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

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

Coding rules (indentation, guillemets etc)

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