ryxeo-glpi-git / plugins / anet_epacks / front / lib / odf.php @ 15ef2b99
Historique | Voir | Annoter | Télécharger (10,4 ko)
1 |
<?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 |
copy($this->tmpfile, $file); |
234 |
} 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 |
//erics 20100818 ca deconne ici print "Error during file export";
|
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 |
?>
|