source: spip-zone/_plugins_/spipdf/branches/v0.2/spipdf_fonctions.php @ 82819

Last change on this file since 82819 was 82819, checked in by cedric@…, 7 years ago

Le plugin supprimait toutes les puces en les remplacant par un li au lieu de ne traiter ce probleme que pour le seul PDF. On ne touche plus aux puces dans pre_typo, et on les remplace par le - de bon aloi dans le PDF uniquement
+ le fichier fonctions est un fichier fonctions, bien le declarer dans le xml

File size: 13.2 KB
Line 
1<?php
2
3/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4 ff=unix fenc=utf8: */
4
5/**
6 * Génération d'article SPIP au format PDF
7 *
8 * @package      spiPDF
9 * @author       Yves Tannier [grafactory.net]
10 * @copyright    2010 Yves Tannier
11 * @link         http://www.spip-contrib.net/spiPDF-generer-des-contenus-sur-mesure-en-PDF
12 * @link         http://zone.spip.org/trac/spip-zone/browser/_plugins_/spipdf
13 * @link         http://www.grafactory.net/
14 * @license      GPL Gnu Public Licence
15 * @version      0.2
16 */
17
18// Options pour les marges des PDF, valables seulement pour la librairie mPDF
19// définissez vos options par défaut directement dans votre mes_options.php
20if (!defined('_SPIPDF_FORMAT')){
21        define('_SPIPDF_FORMAT', 'A4');
22}
23if (!defined('_SPIPDF_MARGIN_TOP')){
24        define('_SPIPDF_MARGIN_TOP', 20);
25}
26if (!defined('_SPIPDF_MARGIN_RIGHT')){
27        define('_SPIPDF_MARGIN_RIGHT', 20);
28}
29if (!defined('_SPIPDF_MARGIN_BOTTOM')){
30        define('_SPIPDF_MARGIN_BOTTOM', 15);
31}
32if (!defined('_SPIPDF_MARGIN_LEFT')){
33        define('_SPIPDF_MARGIN_LEFT', 15);
34}
35if (!defined('_SPIPDF_MARGIN_HEADER')){
36        define('_SPIPDF_MARGIN_HEADER', 2);
37}
38if (!defined('_SPIPDF_MARGIN_FOOTER')){
39        define('_SPIPDF_MARGIN_FOOTER', 2);
40}
41
42// Charset (qui peut être défini dans un fichier d'options
43if (!defined('SPIPDF_CHARSET')){
44        define('SPIPDF_CHARSET', 'UTF-8');
45        //define('SPIPDF_CHARSET', 'ISO-8859-15');
46}
47
48// utilisé pour le constructeur de HTML2PDF
49if (SPIPDF_CHARSET=='UTF-8'){
50        define('SPIPDF_UNICODE', true);
51} else {
52        define('SPIPDF_UNICODE', false);
53}
54
55// les librairies necessaires doivent-être dans "lib". A la racine ou dans le répertoire du plugin
56if (!defined('_DIR_LIB')){
57        define('_DIR_LIB', _DIR_RACINE . 'lib/');
58}
59
60// pour les function unicode2charset
61include_spip('inc/charsets');
62
63// repris dans le plugin article_pdf => a modifier
64// http://zone.spip.org/trac/spip-zone/browser/_plugins_/article_pdf
65function spipdf_first_clean($texte){
66
67        // supprimer les remarques HTML (du Couteau Suisse ?)
68        $texte = preg_replace(',<!-- .* -->,msU', '', $texte);
69
70        $trans = array();
71        $trans["<br />\n"] = '<BR>'; // Pour éviter que le \n ne se tranforme en espace dans les <DIV class=spip_code> (TT, tag SPIP : code)
72
73        // gestion d'un encodage latin1
74        if (SPIPDF_CHARSET=='ISO-8859-15' || SPIPDF_CHARSET=='iso-8859-15'){
75                $trans['&#176;'] = '°';
76                $trans["&#339;"] = 'oe';
77                $trans["&#8211;"] = '-';
78                $trans["&#8216;"] = '\'';
79                $trans["&#8217;"] = '\'';
80                $trans["&#8220;"] = '"';
81                $trans["&#8221;"] = '"';
82                $trans["&#8230;"] = '...';
83                $trans["&#8364;"] = 'Euros';
84                $trans["&ucirc;"] = "û";
85                $trans['->'] = '-»';
86                $trans['<-'] = '«-';
87                $trans['&mdash;'] = '-';
88                $trans['&deg;'] = '°';
89                $trans['œ'] = 'oe';
90                $trans['Œ'] = 'OE';
91                $trans['…'] = '...';
92                $trans['&euro;'] = 'Euros';
93                $trans['€'] = 'Euros';
94                $trans['&copy;'] = '©';
95        }
96        // pas d'insécable
97        $trans['&nbsp;'] = ' ';
98
99        // certains titles font paniquer l'analyse
100        // TODO : a peaufiner car ils sont necessaires pour les signets
101        // <bookmark title="Compatibilité" level="0" ></bookmark>
102        // http://wiki.spipu.net/doku.php?id=html2pdf:fr:v4:bookmark
103        //$texte = preg_replace(',title=".*",msU', 'title=""', $texte);
104
105        $texte = strtr($texte, $trans);
106        if (SPIPDF_CHARSET=='UTF-8'){
107                $texte = charset2unicode($texte);
108        } else {
109                $texte = unicode2charset(charset2unicode($texte), SPIPDF_CHARSET); // Repasser tout dans le charset demandé
110        }
111
112        // Décoder les codes HTML dans le charset final
113        $texte = html_entity_decode($texte, ENT_NOQUOTES, SPIPDF_CHARSET);
114
115        return $texte;
116}
117
118
119//function spipdf_remplaceSpan($matches) { return str_replace('img', 'img style="padding:5px;" style="float:'.$matches[1].'"', $matches[2]); }
120function spipdf_remplaceSpan_wfloat($matches){
121        return str_replace('img', 'img style="padding:5px;" class="pdf_img_float_' . $matches[1] . '"', $matches[2]);
122}
123
124function spipdf_remplaceSpan($matches){
125        return str_replace('img', 'img style="padding:5px;" align="' . $matches[1] . '"', $matches[2]);
126}
127
128function spipdf_remplaceSpanCenter($matches){
129        return $matches[1];
130}
131
132//function spipdf_remplaceDt($matches) { return str_replace('img', 'img style="padding:5px;" style="float:'.$matches[1].'"', $matches[2]); }
133function spipdf_remplaceDt_wfloat($matches){
134        return str_replace('img', 'img style="padding:5px;" class="pdf_img_float_' . $matches[1] . '"', $matches[2]);
135}
136
137function spipdf_remplaceDt($matches){
138        return str_replace('img', 'img style="padding:5px;" align="' . $matches[1] . '"', $matches[2]);
139}
140
141function spipdf_remplaceIdParName($matches){
142        return str_replace('id=\'', 'name=\'', $matches[0]);
143}
144
145function spipdf_remplaceFloatPuce($matches){
146        return str_replace('style=\'', 'style=\'float:left;', $matches[0]);
147}
148
149function spipdf_remplaceDtCenter($matches){
150        return $matches[1];
151}
152
153function spipdf_remplaceCaption($matches){
154        $table = '<table style="border:none;"' . $matches[1] . '<tr><td style="text-align: center;border:none;">' . $matches[2] . '</td></tr>';
155        $table .= '<tr><td style="border:none;">';
156        $table .= '<table' . $matches[1] . $matches[3] . '</table>';
157        $table .= '</td></tr></table>';
158        return $table;
159}
160
161function spipdf_nettoyer_html($html, $params_pdf = array()){
162        // supprimer les spans autour des images et récupérer le placement
163        $patterns_float = '/<span class=\'spip_document_.*spip_documents.*float:(.*);.*>(.*)<\/span>/iUms';
164        $html = preg_replace_callback($patterns_float, !empty($params_pdf['float']) ? 'spipdf_remplaceSpan' : 'spipdf_remplaceSpan_wfloat', $html);
165
166        // supprimer les spans autour des images
167        $patterns_float = '/<span class=\'spip_document_.*spip_documents.*>(.*)<\/span>/iUms';
168        $html = preg_replace_callback($patterns_float, 'spipdf_remplaceSpanCenter', $html);
169
170        // supprimer les dl autour des images et récupérer le placement
171        $patterns_float = '/<dl class=\'spip_document_.*spip_documents.*float:(.*);.*<dt>(.*)<\/dt>.*<\/dl>/iUms';
172        $html = preg_replace_callback($patterns_float, !empty($params_pdf['float']) ? 'spipdf_remplaceDt' : 'spipdf_remplaceDt_wfloat', $html);
173
174        // replacer id par name pour les notes
175        $patterns_note = '/<a.*href.*class=\'spip_note\'.*>/iUms';
176        $html = preg_replace_callback($patterns_note, 'spipdf_remplaceIdParName', $html);
177
178        // float sur les puces graphiques
179        $patterns_puce = '/<img[^>]*class="puce" alt="-"[^>]*>/iUms';
180        $html = preg_replace($patterns_puce, '-', $html);
181
182        // supprimer les dl autour des images centrer
183        $patterns_float = '/<dl class=\'spip_document_.*spip_documents.*<dt>(.*)<\/dt>.*<\/dl>/iUms';
184        $html = preg_replace_callback($patterns_float, 'spipdf_remplaceDtCenter', $html);
185
186        // remplacer les captions
187        if (!empty($params_pdf['caption'])){
188                $patterns_caption = '/<table(.*)<caption>(.*)<\/caption>(.*)<\/table>/iUms';
189                $html = preg_replace_callback($patterns_caption, 'spipdf_remplaceCaption', $html);
190        }
191
192        // tableaux centré
193        $html = preg_replace('/<table/iUms', '<table align="center"', $html);
194
195        // gestion des caractères spéciaux et de charset
196        $html = spipdf_first_clean($html);
197
198        return $html;
199
200}
201
202// traiter la balise page
203function traite_balise_page($html){
204
205        // on teste la balise page
206        if (preg_match('/<page(.*)>/iUms', $html, $matches)){
207                // on crée un tableau avec (beurk) Global pour accèder aux valeurs de pages
208                if (!empty($matches[1])){
209                        $balise_page = $matches[1];
210                        $pattern = '/(.*)="(.*)"/iUms';
211                        function getBalise($matches){
212                                $matches[2] = str_replace('mm', '', $matches[2]);
213                                $GLOBALS['valeurs_page'][trim($matches[1])] = trim($matches[2]);
214                        }
215
216                        $balise_page = preg_replace_callback($pattern, 'getBalise', $balise_page);
217
218                        // supprimer <page> et </page>
219                        $html = preg_replace('/<\/?page(.*)>/iUms', '', $html);
220
221                        return $html;
222                }
223
224        } else {
225                return $html;
226        }
227
228}
229
230
231// traitement principal. avec ce pipeline, le PDF est mis en cache et recalculé "normalement"
232function spipdf_html2pdf($html){
233
234        // les librairies possibles
235        $possible_librairies = array(
236                'mpdf' => array( // gére le float d'image mais pas les captions de tableau
237                        'float' => true,
238                        'caption' => true,
239                        'traite_balise_page' => true
240                ),
241                'html2pdf' => array( // ne gére pas le float d'image et les captions
242                        'float' => false,
243                        'caption' => true
244                ),
245                'dompdf' => array( // domPDF beta 0.6 EXPERIMENTAL
246                        'float' => false,
247                        'caption' => true,
248                        'traite_balise_page' => true
249                ),
250        );
251
252        // choix de la classe de génération via la balise <page lib>
253        if (preg_match('/\<page*.lib_pdf=["|\'](.*)["|\']/iUms', $html, $match_librairie)
254                && !empty($match_librairie[1])
255                && array_key_exists(strtolower($match_librairie[1]), $possible_librairies)
256        ){
257                $librairie_pdf = strtolower($match_librairie[1]);
258        } else {
259                $librairie_pdf = 'mpdf';
260        }
261
262        // tester si la librairie est dans /lib à la racine du spip ou dans le répertoire du plugin
263        if (is_dir(_DIR_LIB . $librairie_pdf)){
264                $dir_librairie_pdf = _DIR_LIB . $librairie_pdf . '/';
265        } elseif (is_dir(dirname(__FILE__) . '/lib/' . $librairie_pdf)) {
266                $dir_librairie_pdf = dirname(__FILE__) . '/lib/' . $librairie_pdf . '/';
267        } else {
268                die('Impossible de trouver la librairie de génération de PDF ' . $librairie_pdf . '. vérifiez que vous l\'avez bien téléchargée et installée dans /lib');
269        }
270
271        // nettoyer le HTML et gérer les placements d'image en fonction de la librairie utilisée
272        $html = spipdf_nettoyer_html($html, $possible_librairies[$librairie_pdf]);
273
274        // Debug = voir le html sans génération de PDF
275        if (isset($_GET['debug_spipdf'])){
276                echo $html;
277                exit;
278        }
279
280        // du A4 par defaut
281        $format_page = _SPIPDF_FORMAT;
282
283        // traiter la balise page pour les librairies qui ne la comprennent pas
284        if (!empty($possible_librairies[$librairie_pdf]['traite_balise_page'])){
285
286                $html = traite_balise_page($html);
287
288                // dans balise_page, on ne récupère que quelques possibilité dont le format
289                if (!empty($GLOBALS['valeurs_page'])){
290                        if (!empty($GLOBALS['valeurs_page']['format']))
291                                $format_page = $GLOBALS['valeurs_page']['format'];
292                        if (!empty($GLOBALS['valeurs_page']['backtop']))
293                                $backtop = $GLOBALS['valeurs_page']['backtop'];
294                        else
295                                $backtop = _SPIPDF_MARGIN_TOP;
296                        if (!empty($GLOBALS['valeurs_page']['backbottom']))
297                                $backbottom = $GLOBALS['valeurs_page']['backbottom'];
298                        else
299                                $backbottom = _SPIPDF_MARGIN_BOTTOM;
300                        if (!empty($GLOBALS['valeurs_page']['backleft']))
301                                $backleft = $GLOBALS['valeurs_page']['backleft'];
302                        else
303                                $backleft = _SPIPDF_MARGIN_LEFT;
304                        if (!empty($GLOBALS['valeurs_page']['backright']))
305                                $backright = $GLOBALS['valeurs_page']['backright'];
306                        else
307                                $backright = _SPIPDF_MARGIN_RIGHT;
308                        if (!empty($GLOBALS['valeurs_page']['margin_header']))
309                                $margin_header = $GLOBALS['valeurs_page']['margin_header'];
310                        else
311                                $margin_header = _SPIPDF_MARGIN_HEADER;
312                        if (!empty($GLOBALS['valeurs_page']['margin_footer']))
313                                $margin_footer = $GLOBALS['valeurs_page']['margin_footer'];
314                        else
315                                $margin_footer = _SPIPDF_MARGIN_FOOTER;
316                }
317        }
318
319        if ($librairie_pdf=='mpdf'){ // la librairie mPDF
320
321                // si il y a des options dans la balise page
322                // http://mpdf1.com/manual/index.php?tid=307
323
324                // le chemin relatif vers mPDF
325                define('_MPDF_PATH', $dir_librairie_pdf);
326                include_once(_MPDF_PATH . 'mpdf.php');
327
328                // la classe mPDF
329                $mpdf = new mPDF(SPIPDF_CHARSET, $format_page, 0, "", $backleft, $backright, $backtop, $backbottom, $margin_header, $margin_footer);
330                $mpdf->WriteHTML($html);
331
332                $html = $mpdf->Output('', 'S'); // envoyer le code binaire du PDF dans le flux
333                $echap_special_pdf_chars = true;
334
335        } elseif ($librairie_pdf=='dompdf') { // la librairie dompdf beta 0.6 // EXPERIMENTAL
336
337                // le chemin relatif vers mPDF
338                require_once(_DIR_LIB . 'dompdf/dompdf_config.inc.php');
339
340                $dompdf = new DOMPDF();
341                $dompdf->load_html($html, SPIPDF_CHARSET);
342                $dompdf->set_paper($format_page);
343                $dompdf->render();
344
345                $html = $dompdf->output(); // envoyer le code binaire du PDF dans le flux
346                $echap_special_pdf_chars = true;
347
348        } else { // la librairie HTML2PDF par défaut
349
350                // appel de la classe HTML2pdf
351                require_once($dir_librairie_pdf . 'html2pdf.class.php');
352                try {
353                        // les paramétres d'orientation et de format son écrasé par ceux défini dans la balise <page> du squelette
354                        $html2pdf = new HTML2PDF('P', $format_page, $flux['args']['contexte']['lang'], SPIPDF_UNICODE, SPIPDF_CHARSET);
355
356                        // mode debug de HTML2PDF
357                        if (defined('SPIPDF_DEBUG_HTML2PDF')){
358                                $html2pdf->setModeDebug();
359                        }
360                        // police différente selon unicode ou latin
361                        if (SPIPDF_UNICODE){
362                                $police_caractere = 'FreeSans';
363                        } else {
364                                $police_caractere = 'Arial';
365                        }
366                        $html2pdf->setDefaultFont($police_caractere);
367                        $html2pdf->writeHTML($html);
368
369                        $html = $html2pdf->Output('', true); // envoyer le code binaire du PDF dans le flux
370                        $echap_special_pdf_chars = true;
371                } catch (HTML2PDF_exception $e) {
372                        echo $e;
373                }
374
375        }
376
377        // On échappe les suites de caractères <? pour éviter des erreurs d'évaluation PHP (seront remis en place avec affichage_final)
378        // l'erreur d'évaluation est liée à la directive short_open_tag=On dans la configuration de PHP
379        if (!empty($echap_special_pdf_chars)
380                AND strpos($html, "<" . "?")!==false
381        ){
382                $html = str_replace("<" . "?", "<\2\2?", $html);
383        }
384
385        return $html;
386
387}
388
389/**
390 * On rétablit les <? du code PDF si necessaire
391 * on n'agit que sur les pages non html
392 *
393 * @param string $texte
394 * @return string
395 */
396function spipdf_affichage_final($texte){
397        if ($GLOBALS['html']==false
398                AND strpos($texte, "<\2\2?")!==false
399        ){
400                $texte = str_replace("<\2\2?", "<" . "?", $texte);
401        }
402        return $texte;
403}
404
405?>
Note: See TracBrowser for help on using the repository browser.