Dotclear

source: plugins/odt/inc/odtPHP0.10/library/odf.php @ 1752

Revision 1752, 10.4 KB checked in by kozlika, 14 years ago (diff)

ODT: typo. Suppression lignes vides en fin de fichiers PHP. Ajout de ?> quand manquants.

Line 
1<?php
2require 'zip/PclZipProxy.php';
3require 'zip/PhpZipProxy.php';
4require 'Segment.php';
5class OdfException extends Exception
6{}
7/**
8 * Templating class for odt file
9 * You need PHP 5.2 at least
10 * You need Zip Extension or PclZip library
11 * Encoding : ISO-8859-1
12 * Last commit by $Author: neveldo $
13 * Date - $Date: 2009-06-06 22:17:14 +0200 (sam., 06 juin 2009) $
14 * SVN Revision - $Rev: 40 $
15 * Id : $Id: odf.php 40 2009-06-06 20:17:14Z neveldo $
16 *
17 * @copyright  GPL License 2008 - Julien Pauli - Cyril PIERRE de GEYER - Anaska (http://www.anaska.com)
18 * @license    http://www.gnu.org/copyleft/gpl.html  GPL License
19 * @version 1.3
20 */
21class Odf
22{
23    protected $config = array(
24     'ZIP_PROXY' => 'PclZipProxy',
25     'DELIMITER_LEFT' => '{',
26     'DELIMITER_RIGHT' => '}'
27     );
28    protected $file;
29    protected $contentXml;
30    protected $tmpfile;
31    protected $images = array();
32    protected $vars = array();
33    protected $segments = array();
34    const PIXEL_TO_CM = 0.026458333;
35    /**
36     * Constructeur de classe
37     *
38     * @param string $filename nom du fichier odt
39     * @throws OdfException
40     */
41    public function __construct($filename, $config = array(), $tmpdir="/tmp")
42    {
43     if (! is_array($config)) {
44          throw new OdfException('Configuration data must be passed as array');
45     }
46     foreach ($config as $configKey => $configValue) {
47          if (array_key_exists($configKey, $this->config)) {
48               $this->config[$configKey] = $configValue;
49          }
50     }
51        if (! class_exists($this->config['ZIP_PROXY'])) {
52            throw new OdfException($this->config['ZIP_PROXY'] . ' class not found - check your php settings');
53        }
54        $zipHandler = $this->config['ZIP_PROXY'];
55        $this->file = new $zipHandler();
56        $this->file->TMP_DIR = $tmpdir;
57        if ($this->file->open($filename) !== true) {
58            throw new OdfException("Error while Opening the file '$filename' - Check your odt file");
59        }
60        if (($this->contentXml = $this->file->getFromName('content.xml')) === false) {
61            throw new OdfException("Nothing to parse - check that the content.xml file is correctly formed");
62        }
63
64        $this->file->close();
65       
66        $tmp = tempnam(null, md5(uniqid()));
67        copy($filename, $tmp);
68        $this->tmpfile = $tmp;
69        $this->_moveRowSegments();
70    }
71    /**
72     * Affecte une variable de template
73     *
74     * @param string $key nom de la variable dans le template
75     * @param string $value valeur de remplacement
76     * @param bool $encode si true, les caractères spéciaux XML seront encodés
77     * @throws OdfException
78     * @return odf
79     */
80    public function setVars($key, $value, $encode = true, $charset = 'ISO-8859')
81    {
82        if (strpos($this->contentXml, $this->config['DELIMITER_LEFT'] . $key . $this->config['DELIMITER_RIGHT']) === false) {
83            throw new OdfException("var $key not found in the document");
84        }
85        $value = $encode ? htmlspecialchars($value) : $value;
86        $value = ($charset == 'ISO-8859') ? utf8_encode($value) : $value;
87        $this->vars[$this->config['DELIMITER_LEFT'] . $key . $this->config['DELIMITER_RIGHT']] = str_replace("\n", "<text:line-break/>", $value);
88        return $this;
89    }
90    /**
91     * Affecte une variable de template en tant qu'image
92     *
93     * @param string $key nom de la variable dans le template
94     * @param string $value chemin vers une image
95     * @throws OdfException
96     * @return odf
97     */
98    public function setImage($key, $value)
99    {
100        $filename = strtok(strrchr($value, '/'), '/.');
101        $file = substr(strrchr($value, '/'), 1);
102        $size = @getimagesize($value);
103        if ($size === false) {
104            throw new OdfException("Invalid image");
105        }
106        list ($width, $height) = $size;
107        $width *= self::PIXEL_TO_CM;
108        $height *= self::PIXEL_TO_CM;
109        $xml = <<<IMG
110<draw:frame draw:style-name="fr1" draw:name="$filename" text:anchor-type="char" svg:width="{$width}cm" svg:height="{$height}cm" draw:z-index="3"><draw:image xlink:href="Pictures/$file" xlink:type="simple" xlink:show="embed" xlink:actuate="onLoad"/></draw:frame>
111IMG;
112        $this->images[$value] = $file;
113        $this->setVars($key, $xml, false);
114        return $this;
115    }
116    /**
117     * Déplace les balises des Segments pour les lignes de tableaux
118     * Appelée automatiquement dans le constructeur
119     *
120     * @return void
121     */   
122    private function _moveRowSegments()
123    {
124     // Search all possible rows in the document
125     $reg1 = "#<table:table-row[^>]*>(.*)</table:table-row>#smU";
126          preg_match_all($reg1, $this->contentXml, $matches);
127          for ($i = 0, $size = count($matches[0]); $i < $size; $i++) {
128               // Check if the current row contains a segment row.*
129               $reg2 = '#\[!--\sBEGIN\s(row.[\S]*)\s--\](.*)\[!--\sEND\s\\1\s--\]#sm';
130               if (preg_match($reg2, $matches[0][$i], $matches2)) {
131                    $balise = str_replace('row.', '', $matches2[1]);
132                    // Move segment tags around the row
133                    $replace = array(
134                         '[!-- BEGIN ' . $matches2[1] . ' --]'   => '',
135                         '[!-- END ' . $matches2[1] . ' --]'          => '',
136                         '<table:table-row'                                => '[!-- BEGIN ' . $balise . ' --]<table:table-row',
137                         '</table:table-row>'                              => '</table:table-row>[!-- END ' . $balise . ' --]'
138                    );
139                    $replacedXML = str_replace(array_keys($replace), array_values($replace), $matches[0][$i]);
140                    $this->contentXml = str_replace($matches[0][$i], $replacedXML, $this->contentXml);
141               }
142          }
143    }
144    /**
145     * Fusionne les variables de template
146     * Appelée automatiquement lors d'une sauvegarde
147     *
148     * @return void
149     */
150    protected function _parse()
151    {
152        $this->contentXml = str_replace(array_keys($this->vars), array_values($this->vars), $this->contentXml);
153    }
154    /**
155     * Rajoute le segment fusionné au document
156     *
157     * @param Segment $segment
158     * @throws OdfException
159     * @return odf
160     */
161    public function mergeSegment(Segment $segment)
162    {
163        if (! array_key_exists($segment->getName(), $this->segments)) {
164            throw new OdfException($segment->getName() . 'cannot be parsed, has it been set yet?');
165        }
166        $string = $segment->getName();
167          // $reg = '@<text:p[^>]*>\[!--\sBEGIN\s' . $string . '\s--\](.*)\[!--.+END\s' . $string . '\s--\]<\/text:p>@smU';
168          $reg = '@\[!--\sBEGIN\s' . $string . '\s--\](.*)\[!--.+END\s' . $string . '\s--\]@smU';
169        $this->contentXml = preg_replace($reg, $segment->getXmlParsed(), $this->contentXml);
170        return $this;
171    }
172    /**
173     * Affiche toutes les variables de templates actuelles
174     *
175     * @return string
176     */
177    public function printVars()
178    {
179        return print_r('<pre>' . print_r($this->vars, true) . '</pre>', true);
180    }
181    /**
182     * Affiche le fichier de contenu xml du document odt
183     * tel qu'il est à cet instant
184     *
185     * @return string
186     */
187    public function __toString()
188    {
189        return $this->contentXml;
190    }
191    /**
192     * Affiche les segments de boucles déclarés avec setSegment()
193     *
194     * @return string
195     */
196    public function printDeclaredSegments()
197    {
198        return '<pre>' . print_r(implode(' ', array_keys($this->segments)), true) . '</pre>';
199    }
200    /**
201     * Déclare un segment pour une utilisation en boucle
202     *
203     * @param string $segment
204     * @throws OdfException
205     * @return Segment
206     */
207    public function setSegment($segment)
208    {
209        if (array_key_exists($segment, $this->segments)) {
210            return $this->segments[$segment];
211        }
212        // $reg = "#\[!--\sBEGIN\s$segment\s--\]<\/text:p>(.*)<text:p\s.*>\[!--\sEND\s$segment\s--\]#sm";
213        $reg = "#\[!--\sBEGIN\s$segment\s--\](.*)\[!--\sEND\s$segment\s--\]#sm";
214        if (preg_match($reg, html_entity_decode($this->contentXml), $m) == 0) {
215            throw new OdfException("'$segment' segment not found in the document");
216        }
217        $this->segments[$segment] = new Segment($segment, $m[1], $this);
218        return $this->segments[$segment];
219    }
220    /**
221     * Sauvegarde le fichier odt sur le disque
222     *
223     * @param string $file nom du fichier désiré
224     * @throws OdfException
225     * @return void
226     */
227    public function saveToDisk($file = null)
228    {
229        if ($file !== null && is_string($file)) {
230          if (file_exists($file) && !(is_file($file) && is_writable($file))) {
231               throw new OdfException('Permission denied : can\'t create ' . $file);
232          }
233            $this->_save();
234            copy($this->tmpfile, $file);     
235        } else {
236            $this->_save();
237        }
238    }
239    /**
240     * Sauvegarde interne
241     *
242     * @throws OdfException
243     * @return void
244     */
245    protected function _save()
246    {
247     $this->file->open($this->tmpfile);
248        $this->_parse();
249        if (! $this->file->addFromString('content.xml', $this->contentXml)) {
250            throw new OdfException('Error during file export');
251        }
252        foreach ($this->images as $imageKey => $imageValue) {
253            $this->file->addFile($imageKey, 'Pictures/' . $imageValue);
254        }
255        $this->file->close(); // seems to bug on windows CLI sometimes
256    }
257    /**
258     * Exporte le fichier en fichier attaché via HTTP
259     *
260     * @param string $name (optionnal)
261     * @throws OdfException
262     * @return void
263     */
264    public function exportAsAttachedFile($name="")
265    {
266        $this->_save();
267        if (headers_sent($filename, $linenum)) {
268            throw new OdfException("headers already sent ($filename at $linenum)");
269        }
270       
271        if( $name == "" )
272        {
273               $name = md5(uniqid()) . ".odt";
274        }
275       
276        header('Content-type: application/vnd.oasis.opendocument.text');
277        header('Content-Disposition: attachment; filename="'.$name.'"');
278        readfile($this->tmpfile);
279    }
280    /**
281     * retourne une variable de configuration
282     *
283     * @return string la  variable de configuration demandée
284     */
285    public function getConfig($configKey)
286    {
287     if (array_key_exists($configKey, $this->config)) {
288          return $this->config[$configKey];
289     }
290     return false;
291    }
292    /**
293     * retourne le fichier temporaire de travail
294     *
295     * @return string le chemin vers le fichier temporaire de travail
296     */
297    public function getTmpfile()
298    {
299     return $this->tmpfile;
300    }
301    /**
302     * Supprime le fichier temporaire à la destruction de l'objet
303     */   
304    public function __destruct() {
305          if (file_exists($this->tmpfile)) {
306          unlink($this->tmpfile);
307        }
308    }
309}
310
311?>
Note: See TracBrowser for help on using the repository browser.

Sites map