source: spip-zone/_plugins_/odt2spip/version_0.1_stable/action/odt2spip_importe.php @ 29008

Last change on this file since 29008 was 29008, checked in by cy_altern@…, 12 years ago

Passage en version 0.14: utilisation de _DIR_TEMP pour le chemin du repertoire /odt2spip histoire d'etre compatible avec la mutualisation (mais pourquoi n'y ai je pas pense plus tot???)

File size: 15.3 KB
Line 
1<?php
2
3function action_odt2spip_importe() {
4    global $auteur_session, $spip_version_code;;
5    $id_auteur = $auteur_session['id_auteur'];
6    $arg = _request('arg');
7    $args = explode(":",$arg);
8  // le 1er element de _request('arg') est id_rubrique=XXX
9    $Targs = explode("=", $args[0]);
10    $id_rubrique = $Targs[1];
11    $hash = _request('hash');
12    $redirect = _request('redirect');
13    if ($redirect==NULL) $redirect="";
14    include_spip("inc/securiser_action");
15   
16    if (!autoriser('creerarticledans', 'rubrique', $id_rubrique)) die(_T('avis_non_acces_page'));
17               
18  // les chemins à utiliser
19    $rep_IMG = "../"._NOM_PERMANENTS_ACCESSIBLES;
20   
21  // ss-rep temporaire specifique de l'auteur en cours: tmp/odt2spip/id_auteur/ => le creer si il n'existe pas
22    $base_dezip = _DIR_TMP."odt2spip/";   // avec / final
23    if (!is_dir($base_dezip)) if (!mkdir($base_dezip,0777)) die (_T('odtspip:err_repertoire_tmp')); 
24    $rep_dezip = $base_dezip.$id_auteur.'/';
25    if (!is_dir($rep_dezip)) if (!mkdir($rep_dezip,0777)) die (_T('odtspip:err_repertoire_tmp')); 
26   
27    $rep_pictures = $rep_dezip."Pictures/";
28   
29  // paramètres de conversion de taille des images : cm -> px (en 96 dpi puisque c'est ce que semble utiliser Writer)
30    $conversion_image = 96/2.54;
31   
32  // traitement d'un fichier odt envoyé par $_POST
33    $fichier_zip = addslashes($_FILES['fichier_odt']['name']);
34    if ($_FILES['fichier_odt']['name'] == '' 
35        OR $_FILES['fichier_odt']['error'] != 0
36        OR !move_uploaded_file($_FILES['fichier_odt']['tmp_name'], $rep_dezip.$fichier_zip)
37       )  die(_T('odtspip:err_telechargement_fichier'));
38
39  // dézipper le fichier odt à la mode SPIP
40    include_spip("inc/pclzip");
41    $zip = new PclZip($rep_dezip.$fichier_zip);
42          $ok = $zip->extract(
43        PCLZIP_OPT_PATH, $rep_dezip,
44        PCLZIP_OPT_SET_CHMOD, _SPIP_CHMOD,
45        PCLZIP_OPT_REPLACE_NEWER
46          );
47          if ($zip->error_code < 0) {
48                    spip_log('charger_decompresser erreur zip ' . $zip->error_code .' pour fichier ' . $rep_dezip.$fichier_zip);
49                    die($zip->errorName(true));  //$zip->error_code
50          }
51//die();   
52  // variables en dur pour xml en entrée et xslt utilisée
53//    $xml_entre = $rep_dezip.'content.xml';  // chemin du fichier xml à lire  !!! ce chemin absolu ne fonctionne pas pour PHP4 !!!
54    $xml_entre = _DIR_TMP.'odt2spip/'.$id_auteur.'/content.xml';  // chemin du fichier xml à lire
55    $xslt_texte = _DIR_PLUGIN_ODT2SPIP.'inc/odt2spip.xsl'; //'inc/odt2spip_texte.xsl';  // chemin de la xslt à utiliser pour le texte
56   
57  // fichier de sortie
58    $fichier_sortie = $rep_dezip.'snippet_odt2spip.xml';
59
60  // determiner si le plugin enluminure_typo ou intertitres_enrichis est present & actif
61    include_spip('inc/plugin');
62    $Tplugins = liste_plugin_actifs();
63    $intertitres_riches = ((array_key_exists('TYPOENLUMINEE', $Tplugins) OR array_key_exists('INTERTITRESTDM', $Tplugins)) ? 'oui' : 'non'); 
64   
65  // faut il mettre les images en mode document?
66    $type = (_request('mode_image') AND _request('mode_image') == 'document') ? 'document' : ($spip_version_code > 2 ? 'image' : 'vignette');
67    $ModeImages = ($type == 'document' ? 'doc' : 'img');
68   
69  // récupérer la langue de publication + verifier la valeur envoyée
70    $Tlangues = explode(',', $GLOBALS['meta']['langues_proposees']);
71    $LanguePublication = (in_array(_request('lang_publi'), $Tlangues) ? _request('lang_publi') : $GLOBALS['meta']['langue_site']);
72   
73   
74  // appliquer la transformation XSLT sur le fichier content.xml
75    // déterminer les fonctions xslt à utiliser (php 4 ou php 5)
76    if (!class_exists('XSLTProcessor')) {
77      // on est en php4 : utiliser l'extension et les fonction xslt de Sablotron
78      // vérifier que l'extension xslt est active
79        if (!function_exists('xslt_create')) die(_T('odtspip:err_extension_xslt'));
80     
81      // Crée le processeur XSLT
82        $xh = xslt_create();
83      // si on est sur un serveur Windows utiliser xslt_set_base avec le préfixe file://
84        if (strpos($_SERVER['SERVER_SOFTWARE'], 'Win') !== false) xslt_set_base($xh, 'file://' . getcwd () . '/');
85//        else xslt_set_base($xh, getcwd () . '/');
86     
87      // definition de l'array des parametres a passer a la xslt
88        $params = array('IntertitresRiches' => $intertitres_riches, 
89                        'ModeImages' => $ModeImages,
90                        'LanguePublication' => $LanguePublication
91                        );
92       
93      // lancer le parseur
94        $xml_sortie = xslt_process($xh, $xml_entre, $xslt_texte, NULL, array(), $params);
95        if (!$xml_sortie) die(_T('odtspip:err_transformation_xslt'));
96     
97      // Détruit le processeur XSLT
98        xslt_free($xh);
99    }
100    else {
101      // on est php5: utiliser les fonctions de la classe XSLTProcessor
102        $proc = new XSLTProcessor();
103
104      // passage des parametres a la xslt
105        $proc->setParameter(null, 'IntertitresRiches', $intertitres_riches);
106        $proc->setParameter(null, 'ModeImages', $ModeImages);
107        $proc->setParameter(null, 'LanguePublication', $LanguePublication);
108       
109        $xml = new DOMDocument();
110        $xml->load($xml_entre);
111        $xsl = new DOMDocument();
112        $xsl->load($xslt_texte);
113        $proc->importStylesheet($xsl); // attachement des règles xsl
114       
115      // lancer le parseur
116        if (!$xml_sortie = $proc->transformToXml($xml)) die(_T('odtspip:err_transformation_xslt'));
117    }
118
119  // traitements complémentaires du flux de sortie
120    // remplacer les &gt; et &lt;
121    $a_remplacer = array('&#60;','&#62;','&lt;','&gt;', '"', "<date/>");
122    $remplace = array('<','>','<','>', "'", '<date>'.(date("Y-m-d H:i:s")).'</date>');
123    $xml_sortie = str_replace($a_remplacer, $remplace, $xml_sortie);
124   
125    // gerer la conversion des <math>Object X</math> => on delegue a /inc/odt2spip_traiter_mathml.php
126    if (preg_match_all('/<math>(.*?)<\/math>/', $xml_sortie, $match, PREG_PATTERN_ORDER) > 0) {
127        include_spip('inc/odt2spip_traiter_mathml');
128        foreach ($match[1] as $balise) {
129            $fic_content = $rep_dezip.$balise.'/content.xml';
130          // si le fichier /Object X/content.xml ne contient pas du mathML, virer la balise <math>
131            if (substr_count(file_get_contents($fic_content), '<!DOCTYPE math:math') < 1) {
132                $xml_sortie = str_replace('<math>'.$balise.'</math>', '', $xml_sortie);
133                continue;
134            }
135          // sinon faire la transfo xsl du contenu du fichier pour obtenir le LateX qu'on place dans la balise
136            $xml_sortie = str_replace($balise, odt2spip_traiter_mathml($fic_content), $xml_sortie);
137        }
138    }
139   
140    // virer les sauts de ligne multiples
141    $xml_sortie = preg_replace('/([\r\n]{2})[ \r\n]*/m', "$1", $xml_sortie);
142   
143    // si malgré toutes les magouille xslt la balise  <titre> est vide, mettre le nom du fichier odt
144    if(preg_match('/<titre>([ ]*?)<\/titre>/', $xml_sortie, $match) == 1)
145        $xml_sortie = preg_replace('/<titre>[ ]*?<\/titre>/', 
146                                   '<titre>'.str_replace(array('_','-','.odt'), array(' ',' ',''), $fichier_zip).'</titre>', 
147                                   $xml_sortie);   
148
149    // traiter les images: dans tous les cas il faut les intégrer dans la table documents
150    // en 1.9.2 c'est mode vignette + il faut les intégrer dans la table de liaison
151    // en 2.0 c'est mode image + les fonctions de snippets font la liaison => on bloque la liaison en filant un id_article vide
152    $id_article_tmp = ($spip_version_code > 2 ? '' : 100000);   
153    preg_match_all('/<'.$ModeImages.'([;a-zA-Z0-9\.]*)/', $xml_sortie, $match, PREG_PATTERN_ORDER);
154    if (@count($match) > 0) {
155        include_spip('inc/ajouter_document');
156        $T_images = array();
157        foreach($match[1] as $ch) {
158            $Tdims = explode(';;;', $ch);
159            $img = $Tdims[0];
160            if (file_exists($rep_pictures.$img)) {
161              // retailler l'image en fct des parametres ;;;largeur;;;hauteur;;;
162                $largeur = round($Tdims[1]*$conversion_image);
163                $hauteur = round($Tdims[2]*$conversion_image);
164                odt2spip_retailler_img($rep_pictures.$img, $largeur, $hauteur);
165              // intégrer l'image comme document spip
166                // la y'a un bogue super-bizarre avec la fonction spip_abstract_insert() qui est donnee comme absente lors de l'appel de ajouter_document()
167                if (!function_exists('spip_abstract_insert')) include_spip('base/abstract_sql');
168                $ajouter_documents = charger_fonction('ajouter_documents','inc');
169//                $type = ($spip_version_code > 2 ? 'image' : 'vignette');
170                if ($id_document = $ajouter_documents($rep_pictures.$img, $img, "article", $id_article_tmp, $type, 0, $toto='')) { 
171                  // uniformiser la sortie: si on est en 1.9.2 inc_ajouter_documents_dist() retourne le type de fichier (extension) alors qu'en 2.0 c'est l'id_document
172                    if (!is_numeric($id_document)) {
173                        $Ttmp = explode('.', $img);
174                        $nom_fic = $Ttmp[0];
175                        $data = spip_fetch_array(spip_query("SELECT id_document FROM spip_documents WHERE fichier LIKE '%$nom_fic%' ORDER BY maj DESC LIMIT 1"));
176                        $id_document = $data['id_document'];
177                    }
178                    $xml_sortie = str_replace($ch, $id_document, $xml_sortie);
179                    $T_images[] = $id_document;
180                };
181            }
182        }
183    }
184   
185  // finalement enregistrer le contenu dans /tmp/odt2spip/id_auteur/snippet_odt2spip.xml
186    if (function_exists('file_put_contents')) {
187        if (!file_put_contents($fichier_sortie, $xml_sortie)) die(_T('odtspip:err_enregistrement_fichier_sortie').$fichier_sortie);
188    }
189    else {  // php4
190        $fic = fopen($fichier_sortie, 'wb');
191        if (!fwrite($fic, $xml_sortie)) die(_T('odtspip:err_enregistrement_fichier_sortie').$fichier_sortie);
192        fclose($fic);
193    }
194/* die;  */ 
195  // générer l'article à partir du fichier xml de sortie (code pompé sur plugins/snippets/action/snippet_importe.php)
196    include_spip('inc/snippets');
197                $table = $id = 'articles';
198                $contexte = $args[0];
199                $source = $fichier_sortie;
200    if (!$f = snippets_fonction_importer($table)) die(_T('odtspip:err_import_snippet'));
201    include_spip('inc/xml');
202    $arbre = spip_xml_load($source, false);
203    $translations = $f($id,$arbre,$contexte);
204    snippets_translate_raccourcis_modeles($translations);
205    $id_article = $translations[0][2]; 
206  // si on est en 1.9.2 mettre à jour l'id_article auquel sont liees les images
207    if ($spip_version_code < 2) spip_query("UPDATE spip_documents_articles SET id_article = $id_article WHERE id_document IN (".implode(',',$T_images).")");
208
209  // passer le statut de l'article en prepa (bizarre que snippets respecte pas le <statut>prop</statut> ???)
210    if ($spip_version_code > 2) sql_updateq('spip_articles', array('statut' => 'prop'), 'id_article='.$id_article);
211    else spip_query("UPDATE spip_articles SET statut = 'prop' WHERE id_article = $id_article LIMIT 1");
212   
213  // si necessaire attacher le fichier odt original à l'article et lui mettre un titre signifiant
214    if (_request('attacher_odt') == '1') {
215      // recuperer le titre
216        preg_match('/<titre>(.*?)<\/titre>/', $xml_sortie, $match);
217        $titre = $match[1];
218        if (!isset($ajouter_documents)) $ajouter_documents = charger_fonction('ajouter_documents','inc');
219        $id_doc_odt = $ajouter_documents($rep_dezip.$fichier_zip, $fichier_zip, "article", $id_article, 'document', 0, $toto='');
220        if (!is_numeric($id_doc_odt)) {
221            $Tfic = explode('.', $fichier_zip);
222            $fichier_zip_av_extension = $Tfic[0];
223            $data = spip_fetch_array(spip_query("SELECT id_document FROM spip_documents WHERE fichier LIKE '%$fichier_zip_av_extension%' ORDER BY maj DESC LIMIT 1"));
224            $id_doc_odt = $data['id_document'];
225        }
226        if (function_exists('sql_updateq')) sql_updateq('spip_documents', array('titre' => $titre, 'descriptif' => _T('odtspip:cet_article_version_odt')), 'id_document='.$id_doc_odt);
227        else spip_query("UPDATE spip_documents SET titre = '".$titre."', descriptif = '"._T('odtspip:cet_article_version_odt')."' WHERE id_document=".$id_doc_odt." LIMIT 1");
228    }
229   
230  // vider le contenu du rep de dezippage
231    if ($spip_version_code >= 12691) {
232        if (!function_exists('effacer_repertoire_temporaire')) include_spip('inc/getdocument');
233        effacer_repertoire_temporaire($rep_dezip);
234    }
235    else odt2spip_effacer_repzip($rep_dezip);
236   
237  // aller sur la page de l'article qui vient d'être créé
238    redirige_par_entete(str_replace("&amp;","&",urldecode($redirect.$id_article)));
239}   
240
241// Efface le repertoire de dezippage de maniere recursive !
242// reprise de http://doc.spip.org/@effacer_repertoire_temporaire + correctif closedir()
243// cette fonction n'est plus utile à partir de spip 2.0.5 [12691] puisque le correctif à été intégré
244function odt2spip_effacer_repzip($nom) {
245        $d = opendir($nom);
246        while (($f = readdir($d)) !== false) {
247                if (is_file("$nom/$f")) @unlink("$nom/$f");
248                else if ($f <> '.' AND $f <> '..' AND is_dir("$nom/$f"))
249                        odt2spip_effacer_repzip("$nom/$f");
250        }
251        closedir($d);
252  @rmdir($nom);
253}
254
255// retailler une image : (ne gère que les images GIF, JPG et PNG)
256//      $img_ini = CHEMIN+NOM_FICHIER de l'img initiale, $l et $h = largeur et hauteur max de l'image finale
257// gestion de la transparence des PNG : code de matt1walsh@gmail.com sur http://fr2.php.net/manual/fr/function.imagecopyresampled.php
258function odt2spip_retailler_img($img_ini, $l = '', $h = 400) {
259    if (!file_exists($img_ini)) return 'Le fichier '.$img_ini.' n\'existe pas';
260  // déterminer le type de fonction de création d'image à utiliser
261    $param_img = getimagesize($img_ini);
262    $type_img = $param_img[2];
263    switch ($type_img) {
264        case 1 :
265            $fct_creation_ext = 'imagecreatefromgif';
266            $fct_ecrire = 'imagegif';
267        break;
268        case 2 :
269            $fct_creation_ext = 'imagecreatefromjpeg';
270            $fct_ecrire = 'imagejpeg';
271        break;
272        case 3 :
273            $fct_creation_ext = 'imagecreatefrompng';
274            $fct_ecrire = 'imagepng';
275        break;
276        default :
277            return;
278        break;
279    } 
280  // calculer le ratio à appliquer aux dimensions initiales
281    $l_ini = $param_img[0];
282    $h_ini = $param_img[1];
283    $ratio = ($l != '' ? (abs($l_ini - $l) >= abs($h_ini - $h) ? $l/$l_ini : $h/$h_ini) : $h/$h_ini); 
284    $img_nv = imagecreatetruecolor($l_ini*$ratio, $h_ini*$ratio); 
285    $img_acopier = $fct_creation_ext($img_ini);
286  // gérer la transparence pour les images PNG (le mec qui a trouvé ce code est génial! :-)
287    if ($type_img == 3) {
288        imagecolortransparent($img_nv, imagecolorallocate($img_nv, 0, 0, 0));
289        imagealphablending($img_nv, false);
290        imagesavealpha($img_nv, true);
291    }
292    imagecopyresampled($img_nv, $img_acopier, 0, 0, 0, 0, $l_ini*$ratio, $h_ini*$ratio, $l_ini, $h_ini);                     
293  // sauvegarder l'image et éventuellement détruire le fichier image initial
294    $fct_ecrire($img_nv, $img_ini);
295    imagedestroy($img_nv);
296    imagedestroy($img_acopier);
297}
298
299
300?>
Note: See TracBrowser for help on using the repository browser.