Projet

Général

Profil

Paste
Statistiques
| Branche: | Révision:

ryxeo-glpi-git / plugins / anet_epacks / front / lib / odf.php @ 15ef2b99

Historique | Voir | Annoter | Télécharger (10,4 ko)

1 b67d8923 Eric Seigne
<?php
2
require 'zip/PclZipProxy.php';
3
require 'zip/PhpZipProxy.php';
4
require 'Segment.php';
5
class 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
 */
21
class 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())
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
        if ($this->file->open($filename) !== true) {
57
            throw new OdfException("Error while Opening the file '$filename' - Check your odt file");
58
        }
59
        if (($this->contentXml = $this->file->getFromName('content.xml')) === false) {
60
            throw new OdfException("Nothing to parse - check that the content.xml file is correctly formed");
61
        }
62
63
        $this->file->close();
64
        
65
        $tmp = tempnam(null, md5(uniqid()));
66
        copy($filename, $tmp);
67
        $this->tmpfile = $tmp;
68
        $this->_moveRowSegments();
69
    }
70
    /**
71
     * Affecte une variable de template
72
     *
73
     * @param string $key nom de la variable dans le template
74
     * @param string $value valeur de remplacement
75
     * @param bool $encode si true, les caractères spéciaux XML seront encodés
76
     * @throws OdfException
77
     * @return odf
78
     */
79
    public function setVars($key, $value, $encode = true, $charset = 'ISO-8859')
80
    {
81
        if (strpos($this->contentXml, $this->config['DELIMITER_LEFT'] . $key . $this->config['DELIMITER_RIGHT']) === false) {
82
            throw new OdfException("var $key not found in the document");
83
        }
84
        $value = $encode ? htmlspecialchars($value) : $value;
85
        $value = ($charset == 'ISO-8859') ? utf8_encode($value) : $value;
86
        $this->vars[$this->config['DELIMITER_LEFT'] . $key . $this->config['DELIMITER_RIGHT']] = str_replace("\n", "<text:line-break/>", $value);
87
        return $this;
88
    }
89
    /**
90
     * Affecte une variable de template en tant qu'image
91
     *
92
     * @param string $key nom de la variable dans le template
93
     * @param string $value chemin vers une image
94
     * @throws OdfException
95
     * @return odf
96
     */
97
    public function setImage($key, $value)
98
    {
99
        $filename = strtok(strrchr($value, '/'), '/.');
100
        $file = substr(strrchr($value, '/'), 1);
101
        $size = @getimagesize($value);
102
        if ($size === false) {
103
            throw new OdfException("Invalid image");
104
        }
105
        list ($width, $height) = $size;
106
        $width *= self::PIXEL_TO_CM;
107
        $height *= self::PIXEL_TO_CM;
108
        $xml = <<<IMG
109
<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>
110
IMG;
111
        $this->images[$value] = $file;
112
        $this->setVars($key, $xml, false);
113
        return $this;
114
    }
115
    /**
116
     * Déplace les balises des Segments pour les lignes de tableaux
117
     * Appelée automatiquement dans le constructeur
118
     *
119
     * @return void
120
     */    
121
    private function _moveRowSegments()
122
    {
123
            // Search all possible rows in the document
124
            $reg1 = "#<table:table-row[^>]*>(.*)</table:table-row>#smU";
125
                preg_match_all($reg1, $this->contentXml, $matches);
126
                for ($i = 0, $size = count($matches[0]); $i < $size; $i++) {
127
                        // Check if the current row contains a segment row.*
128
                        $reg2 = '#\[!--\sBEGIN\s(row.[\S]*)\s--\](.*)\[!--\sEND\s\\1\s--\]#sm';
129
                        if (preg_match($reg2, $matches[0][$i], $matches2)) {
130
                                $balise = str_replace('row.', '', $matches2[1]);
131
                                // Move segment tags around the row
132
                                $replace = array(
133
                                        '[!-- BEGIN ' . $matches2[1] . ' --]'        => '',
134
                                        '[!-- END ' . $matches2[1] . ' --]'                => '',
135
                                        '<table:table-row'                                                        => '[!-- BEGIN ' . $balise . ' --]<table:table-row',
136
                                        '</table:table-row>'                                                => '</table:table-row>[!-- END ' . $balise . ' --]'
137
                                );
138
                                $replacedXML = str_replace(array_keys($replace), array_values($replace), $matches[0][$i]);
139
                                $this->contentXml = str_replace($matches[0][$i], $replacedXML, $this->contentXml);
140
                        }
141
                }
142
    }
143
    /**
144
     * Fusionne les variables de template
145
     * Appelée automatiquement lors d'une sauvegarde
146
     *
147
     * @return void
148
     */
149
    private function _parse()
150
    {
151
        $this->contentXml = str_replace(array_keys($this->vars), array_values($this->vars), $this->contentXml);
152
    }
153
    /**
154
     * Rajoute le segment fusionné au document
155
     *
156
     * @param Segment $segment
157
     * @throws OdfException
158
     * @return odf
159
     */
160
    public function mergeSegment(Segment $segment)
161
    {
162
        if (! array_key_exists($segment->getName(), $this->segments)) {
163
            throw new OdfException($segment->getName() . 'cannot be parsed, has it been set yet ?');
164
        }
165
        $string = $segment->getName();
166
                // $reg = '@<text:p[^>]*>\[!--\sBEGIN\s' . $string . '\s--\](.*)\[!--.+END\s' . $string . '\s--\]<\/text:p>@smU';
167
                $reg = '@\[!--\sBEGIN\s' . $string . '\s--\](.*)\[!--.+END\s' . $string . '\s--\]@smU';
168
        $this->contentXml = preg_replace($reg, $segment->getXmlParsed(), $this->contentXml);
169
        return $this;
170
    }
171
    /**
172
     * Affiche toutes les variables de templates actuelles
173
     * 
174
     * @return string
175
     */
176
    public function printVars()
177
    {
178
        return print_r('<pre>' . print_r($this->vars, true) . '</pre>', true);
179
    }
180
    /**
181
     * Affiche le fichier de contenu xml du document odt
182
     * tel qu'il est à cet instant
183
     *
184
     * @return string
185
     */
186
    public function __toString()
187
    {
188
        return $this->contentXml;
189
    }
190
    /**
191
     * Affiche les segments de boucles déclarés avec setSegment()
192
     * 
193
     * @return string
194
     */
195
    public function printDeclaredSegments()
196
    {
197
        return '<pre>' . print_r(implode(' ', array_keys($this->segments)), true) . '</pre>';
198
    }
199
    /**
200
     * Déclare un segment pour une utilisation en boucle
201
     *
202
     * @param string $segment
203
     * @throws OdfException
204
     * @return Segment
205
     */
206
    public function setSegment($segment)
207
    {
208
        if (array_key_exists($segment, $this->segments)) {
209
            return $this->segments[$segment];
210
        }
211
        // $reg = "#\[!--\sBEGIN\s$segment\s--\]<\/text:p>(.*)<text:p\s.*>\[!--\sEND\s$segment\s--\]#sm";
212
        $reg = "#\[!--\sBEGIN\s$segment\s--\](.*)\[!--\sEND\s$segment\s--\]#sm";
213
        if (preg_match($reg, html_entity_decode($this->contentXml), $m) == 0) {
214
            throw new OdfException("'$segment' segment not found in the document");
215
        }
216
        $this->segments[$segment] = new Segment($segment, $m[1], $this);
217
        return $this->segments[$segment];
218
    }
219
    /**
220
     * Sauvegarde le fichier odt sur le disque
221
     * 
222
     * @param string $file nom du fichier désiré
223
     * @throws OdfException
224
     * @return void
225
     */
226
    public function saveToDisk($file = null)
227
    {
228
        if ($file !== null && is_string($file)) {
229
                if (file_exists($file) && !(is_file($file) && is_writable($file))) {
230
                    throw new OdfException('Permission denied : can\'t create ' . $file);
231
                }
232
            $this->_save();
233 15ef2b99 Eric Seigne
            copy($this->tmpfile, $file);
234 b67d8923 Eric Seigne
        } else {
235
            $this->_save();
236
        }
237
    }
238
    /**
239
     * Sauvegarde interne
240
     *
241
     * @throws OdfException
242
     * @return void
243
     */
244
    private function _save()
245
    {
246
            $this->file->open($this->tmpfile);
247
        $this->_parse();
248
        if (! $this->file->addFromString('content.xml', $this->contentXml)) {
249 15ef2b99 Eric Seigne
          //erics 20100818 ca deconne ici print "Error during file export";
250 b67d8923 Eric Seigne
            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
?>
Redmine Appliance - Powered by TurnKey Linux