[SPIP] ~2.1.12 -->2.1.25
[velocampus/web/www.git] / www / ecrire / inc / plugin.php
1 <?php
2
3 /***************************************************************************\
4 * SPIP, Systeme de publication pour l'internet *
5 * *
6 * Copyright (c) 2001-2014 *
7 * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James *
8 * *
9 * Ce programme est un logiciel libre distribue sous licence GNU/GPL. *
10 * Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne. *
11 \***************************************************************************/
12
13 if (!defined('_ECRIRE_INC_VERSION')) return;
14
15 // librairie pour parametrage plugin
16 //
17 define('_FILE_PLUGIN_CONFIG', "plugin.xml");
18 # l'adresse du repertoire de telechargement et de decompactage des plugins
19 define('_DIR_PLUGINS_AUTO', _DIR_PLUGINS.'auto/');
20
21 // besoin de inc_meta
22 include_spip('inc/texte');
23
24 function spip_version_compare($v1,$v2,$op){
25 $v1 = strtolower(preg_replace(',([0-9])[\s-.]?(dev|alpha|a|beta|b|rc|pl|p),i','\\1.\\2',$v1));
26 $v2 = strtolower(preg_replace(',([0-9])[\s-.]?(dev|alpha|a|beta|b|rc|pl|p),i','\\1.\\2',$v2));
27 $v1 = str_replace('rc','RC',$v1); // certaines versions de PHP ne comprennent RC qu'en majuscule
28 $v2 = str_replace('rc','RC',$v2); // certaines versions de PHP ne comprennent RC qu'en majuscule
29 $v1 = explode('.',$v1);
30 $v2 = explode('.',$v2);
31 while (count($v1)<count($v2))
32 $v1[] = '0';
33 while (count($v2)<count($v1))
34 $v2[] = '0';
35 $v1 = implode('.',$v1);
36 $v2 = implode('.',$v2);
37
38 return version_compare($v1, $v2,$op);
39 }
40
41 // lecture des sous repertoire plugin existants
42 // $dir_plugins pour forcer un repertoire (ex: _DIR_EXTENSIONS)
43 // _DIR_PLUGINS_SUPPL pour aller en chercher ailleurs (separes par des ":")
44 // http://doc.spip.org/@liste_plugin_files
45 function liste_plugin_files($dir_plugins = null){
46 static $plugin_files=array();
47
48 if (is_null($dir_plugins)) {
49 $dir_plugins = _DIR_PLUGINS;
50 if (defined('_DIR_PLUGINS_SUPPL'))
51 $dir_plugins_suppl = array_filter(explode(':',_DIR_PLUGINS_SUPPL));
52 }
53
54 if (!isset($plugin_files[$dir_plugins])
55 OR count($plugin_files[$dir_plugins]) == 0){
56 $plugin_files[$dir_plugins] = array();
57 foreach (preg_files($dir_plugins, '/plugin[.]xml$') as $plugin) {
58 $plugin_files[$dir_plugins][] = substr(dirname($plugin),strlen($dir_plugins));
59 }
60 sort($plugin_files[$dir_plugins]);
61
62 // hack affreux pour avoir le bon chemin pour les repertoires
63 // supplementaires ; chemin calcule par rapport a _DIR_PLUGINS.
64 if (isset($dir_plugins_suppl)) {
65 foreach($dir_plugins_suppl as $suppl) {
66 foreach (preg_files(_DIR_RACINE.$suppl, 'plugin[.]xml$') as $plugin) {
67 $plugin_files[$dir_plugins][] = (_DIR_RACINE? '':'../').dirname($plugin);
68 }
69 }
70 }
71 }
72
73 return $plugin_files[$dir_plugins];
74 }
75
76 // http://doc.spip.org/@plugin_version_compatible
77 function plugin_version_compatible($intervalle,$version){
78 if (!strlen($intervalle)) return true;
79 if (!preg_match(',^[\[\(]([0-9.a-zRC\s\-]*)[;]([0-9.a-zRC\s\-]*)[\]\)]$,',$intervalle,$regs)) return false;
80 #var_dump("$version::$intervalle");
81 $minimum = $regs[1];
82 $maximum = $regs[2];
83 $minimum_inc = $intervalle{0}=="[";
84 $maximum_inc = substr($intervalle,-1)=="]";
85 #var_dump("$version::$minimum_inc::$minimum::$maximum::$maximum_inc");
86 #var_dump(spip_version_compare($version,$minimum,'<'));
87 if (strlen($minimum)){
88 if ($minimum_inc AND spip_version_compare($version,$minimum,'<')) return false;
89 if (!$minimum_inc AND spip_version_compare($version,$minimum,'<=')) return false;
90 }
91 if (strlen($maximum)){
92 if ($maximum_inc AND spip_version_compare($version,$maximum,'>')) return false;
93 if (!$maximum_inc AND spip_version_compare($version,$maximum,'>=')) return false;
94 }
95 return true;
96 }
97
98
99
100 /**
101 * Faire la liste des librairies disponibles
102 * retourne un array ( nom de la lib => repertoire , ... )
103 *
104 * @return array
105 */
106 // http://doc.spip.org/@liste_librairies
107 function plugins_liste_librairies() {
108 $libs = array();
109 foreach (array_reverse(creer_chemin()) as $d) {
110 if (is_dir($dir = $d.'lib/')
111 AND $t = @opendir($dir)) {
112 while (($f = readdir($t)) !== false) {
113 if ($f[0] != '.'
114 AND is_dir("$dir/$f"))
115 $libs[$f] = $dir;
116 }
117 }
118 }
119 return $libs;
120 }
121
122 // Prend comme argument le tableau des <necessite> et retourne un tableau vide
123 // si tout est bon, et un tableau avec une entree par erreur sinon
124 // http://doc.spip.org/@erreur_necessite
125 function erreur_necessite($n, $liste) {
126 if (!is_array($n) OR !count($n)) {
127 return array();
128 }
129
130 $msg = array();
131 foreach($n as $need){
132 $id = strtoupper($need['id']);
133
134 // Necessite SPIP version x ?
135 if ($id=='SPIP') {
136 if (!plugin_version_compatible($need['version'],
137 $GLOBALS['spip_version_branche'])) {
138 $msg[] = _T('plugin_necessite_spip', array(
139 'version' => $need['version']
140 ));
141 }
142 }
143
144 // Necessite une librairie ?
145 else if (preg_match(',^(lib):(.*),i', $need['id'], $r)) {
146 $lib = trim($r[2]);
147 if (!find_in_path('lib/'.$lib)) {
148 $lien_download = '';
149 if (isset($need['src'])) {
150 $url = $need['src'];
151 include_spip('inc/charger_plugin');
152 $lien_download = '<br />'
153 .bouton_telechargement_plugin($url, strtolower($r[1]));
154 }
155 $msg[] = _T('plugin_necessite_lib', array('lib'=>$lib)) . $lien_download;
156 }
157 }
158
159 // Necessite un autre plugin version x ?
160 else if (!isset($liste[$id])
161 OR !plugin_version_compatible($need['version'],$liste[$id]['version'])
162 ) {
163 $msg[] = _T('plugin_necessite_plugin', array(
164 'plugin' => $id,
165 'version' => $need['version']));
166 }
167 }
168
169 return $msg;
170 }
171
172
173 // http://doc.spip.org/@liste_plugin_valides
174 function liste_plugin_valides($liste_plug, $force = false){
175 $liste = array();
176 $ordre = array();
177 $infos = array();
178
179 // lister les extensions qui sont automatiquement actives
180 $liste_extensions = liste_plugin_files(_DIR_EXTENSIONS);
181 $listes = array(
182 '_DIR_EXTENSIONS'=>$liste_extensions,
183 '_DIR_PLUGINS'=>$liste_plug
184 );
185 // creer une premiere liste non ordonnee mais qui ne retient
186 // que les plugins valides, et dans leur derniere version en cas de doublon
187 $liste_non_classee = array();
188
189 $get_infos = charger_fonction('get_infos','plugins');
190
191 foreach($listes as $dir_type=>$l){
192 foreach($l as $k=>$plug) {
193 // renseigner ce plugin
194 $infos[$dir_type][$plug] = $get_infos($plug,$force,constant($dir_type));
195 // si il n'y a pas d'erreur
196 if ($infos[$dir_type][$plug] AND !isset($infos[$dir_type][$plug]['erreur'])) {
197 // regarder si on a pas deja selectionne le meme plugin dans une autre version
198 $version = isset($infos[$dir_type][$plug]['version'])?$infos[$dir_type][$plug]['version']:NULL;
199 if (isset($liste_non_classee[$p=strtoupper($infos[$dir_type][$plug]['prefix'])])){
200 // prendre le plus recent
201 if (spip_version_compare($version,$liste_non_classee[$p]['version'],'>'))
202 unset($liste_non_classee[$p]);
203 else{
204 continue;
205 }
206 }
207 // ok, le memoriser
208 $liste_non_classee[$p] = array(
209 'nom' => $infos[$dir_type][$plug]['nom'],
210 'etat' => $infos[$dir_type][$plug]['etat'],
211 'dir_type' => $dir_type, // extensions ou plugins
212 'dir'=>$plug,
213 'version'=>isset($infos[$dir_type][$plug]['version'])?$infos[$dir_type][$plug]['version']:NULL
214 );
215 }
216 }
217 }
218
219 // il y a des plugins a trier
220 if (is_array($liste_non_classee)){
221 // pour tester utilise, il faut connaitre tous les plugins
222 // qui seront forcement pas la a la fin,
223 // car absent de la liste des plugins actifs
224 $toute_la_liste = $liste_non_classee;
225
226 // construire une liste ordonnee des plugins
227 $count = 0;
228 while ($c=count($liste_non_classee) AND $c!=$count){ // tant qu'il reste des plugins a classer, et qu'on ne stagne pas
229 #echo "tour::";var_dump($liste_non_classee);
230 $count = $c;
231 foreach($liste_non_classee as $p=>$resume) {
232 $plug = $resume['dir'];
233 $dir_type = $resume['dir_type'];
234 // si des plugins sont necessaire, on ne peut inserer qu'apres eux
235 $necessite_ok = !erreur_necessite($infos[$dir_type][$plug]['necessite'], $liste);
236 // si des plugins sont utiles, on ne peut inserer qu'apres eux,
237 // sauf si ils sont de toute facon absents de la liste
238 $utilise_ok = true;
239 // tous les plugins "utilise" absents
240 $nb_utilise_absents_toleres = count(erreur_necessite($infos[$dir_type][$plug]['utilise'], $toute_la_liste));
241 // tous les plugins "utilise" absents de la liste deja trie
242 $nb_utilise_absents_tries = count(erreur_necessite($infos[$dir_type][$plug]['utilise'], $liste));
243 if (abs($nb_utilise_absents_tries - $nb_utilise_absents_toleres) > 0) {
244 $utilise_ok = false;
245 }
246
247 if ($necessite_ok AND $utilise_ok){
248 $liste[$p] = $liste_non_classee[$p];
249 $ordre[] = $p;
250 unset($liste_non_classee[$p]);
251 }
252 }
253 }
254 if (count($liste_non_classee)) {
255 include_spip('inc/lang');
256 utiliser_langue_visiteur();
257 $erreurs = "";
258 foreach($liste_non_classee as $p=>$resume){
259 $plug = $resume['dir'];
260 $dir_type = $resume['dir_type'];
261 if ($n = erreur_necessite($infos[$dir_type][$plug]['necessite'], $liste)){
262 $erreurs .= "<li>" . _T('plugin_impossible_activer',
263 array('plugin' => constant($dir_type). $plug)
264 ) . "<ul><li>" . implode("</li><li>", $n) . "</li></ul></li>";
265 }
266 else {
267 // dependance circulaire, ou utilise qu'on peut ignorer ?
268 // dans le doute on fait une erreur quand meme
269 // plutot que d'inserer silencieusement et de risquer un bug sournois latent
270 $necessite = erreur_necessite($infos[$dir_type][$plug]['utilise'], $liste);
271 $erreurs .= "<li>" . _T('plugin_impossible_activer',
272 array('plugin' => constant($dir_type). $plug)
273 ) . "<ul><li>" . implode("</li><li>", $necessite) . "</li></ul></li>";
274 }
275 }
276 ecrire_meta('plugin_erreur_activation',
277 "<ul>$erreurs</ul>");
278 }
279 }
280
281 return array($liste,$ordre,$infos);
282 }
283
284 // A utiliser pour initialiser ma variable globale $plugin
285 // http://doc.spip.org/@liste_plugin_actifs
286 function liste_plugin_actifs(){
287 $meta_plugin = isset($GLOBALS['meta']['plugin'])?$GLOBALS['meta']['plugin']:'';
288 if (strlen($meta_plugin)>0){
289 if (is_array($t=unserialize($meta_plugin)))
290 return $t;
291 else{ // compatibilite pre 1.9.2, mettre a jour la meta
292 spip_log("MAJ meta plugin vieille version : $meta_plugin","plugin");
293 $t = explode(",",$meta_plugin);
294 list($liste,,) = liste_plugin_valides($t);
295 include_spip('inc/meta');
296 ecrire_meta('plugin',serialize($liste));
297 return $liste;
298 }
299 }
300 else
301 return array();
302 }
303
304 /**
305 * Lister les chemins vers les plugins actifs d'un dossier plugins/
306 *
307 * @return unknown
308 */
309 // http://doc.spip.org/@liste_chemin_plugin_actifs
310 function liste_chemin_plugin_actifs($dir_plugins=_DIR_PLUGINS){
311 $liste = liste_plugin_actifs();
312 foreach ($liste as $prefix=>$infos) {
313 // compat au moment d'une migration depuis version anterieure
314 // si pas de dir_type, alors c'est _DIR_PLUGINS
315 if (!isset($infos['dir_type']))
316 $infos['dir_type'] = "_DIR_PLUGINS";
317 if (defined($infos['dir_type'])
318 AND constant($infos['dir_type'])==$dir_plugins)
319 $liste[$prefix] = $infos['dir'];
320 else
321 unset($liste[$prefix]);
322 }
323 return $liste;
324 }
325
326 // http://doc.spip.org/@ecrire_plugin_actifs
327 function ecrire_plugin_actifs($plugin,$pipe_recherche=false,$operation='raz') {
328 static $liste_pipe_manquants=array();
329
330 // creer le repertoire cache/ si necessaire ! (installation notamment)
331 sous_repertoire(_DIR_CACHE, '', false,true);
332
333 $liste_fichier_verif = array();
334 if (($pipe_recherche)&&(!in_array($pipe_recherche,$liste_pipe_manquants)))
335 $liste_pipe_manquants[]=$pipe_recherche;
336
337 if ($operation!='raz'){
338 $plugin_actifs = liste_chemin_plugin_actifs();
339 $plugin_liste = liste_plugin_files();
340 $plugin_valides = array_intersect($plugin_actifs,$plugin_liste);
341 if ($operation=='ajoute')
342 $plugin = array_merge($plugin_valides,$plugin);
343 if ($operation=='enleve')
344 $plugin = array_diff($plugin_valides,$plugin);
345 }
346
347 // recharger le xml des plugins a activer
348 list($plugin_valides,$ordre,$infos) = liste_plugin_valides($plugin,true);
349
350 ecrire_meta('plugin',serialize($plugin_valides));
351 effacer_meta('message_crash_plugins'); // baisser ce flag !
352 $plugin_header_info = array();
353 foreach($plugin_valides as $p=>$resume){
354 $plugin_header_info[]= $p.($resume['version']?"(".$resume['version'].")":"");
355 }
356 ecrire_meta('plugin_header',substr(strtolower(implode(",",$plugin_header_info)),0,900));
357
358 $start_file = "<"."?php\nif (defined('_ECRIRE_INC_VERSION')) {\n";
359 $end_file = "}\n?".">";
360
361 if (is_array($infos)){
362 // construire tableaux de boutons et onglets
363 $liste_boutons = array();
364 $liste_onglets = array();
365 foreach($ordre as $p){
366 $dir_type = $plugin_valides[$p]['dir_type'];
367 $plug = $plugin_valides[$p]['dir'];
368 $info = $infos[$dir_type][$plug];
369 if (isset($info['bouton'])){
370 $liste_boutons = array_merge($liste_boutons,$info['bouton']);
371 }
372 if (isset($info['onglet'])){
373 $liste_onglets = array_merge($liste_onglets,$info['onglet']);
374 }
375 }
376 }
377
378 // generer les fichier
379 // charger_plugins_options.php
380 // charger_plugins_fonctions.php
381 if (defined('_DIR_PLUGINS_SUPPL'))
382 $dir_plugins_suppl = implode(array_filter(explode(':',_DIR_PLUGINS_SUPPL)),'|');
383
384 foreach(array('chemins'=>_CACHE_PLUGINS_PATH,'options'=>_CACHE_PLUGINS_OPT,'fonctions'=>_CACHE_PLUGINS_FCT) as $charge=>$fileconf){
385 $s = "";
386 $splugs = "";
387 $chemins = array();
388 if (is_array($infos)){
389 foreach($ordre as $p){
390 $dir_type = $plugin_valides[$p]['dir_type'];
391 $plug = $plugin_valides[$p]['dir'];
392 $info = $infos[$dir_type][$plug];
393 if($dir_plugins_suppl && preg_match(',('.$dir_plugins_suppl.'),',$plugin_valides[$p]['dir'])){
394 //$plugin_valides[$p]['dir_type'] = '_DIR_RACINE';
395 $dir_type = '_DIR_RACINE';
396 //if(!test_espace_prive())
397 $plug = str_replace('../','',$plug);
398 }
399 $root_dir_type = str_replace('_DIR_','_ROOT_',$dir_type);
400 $dir = $dir_type.".'" . $plug ."/'";
401 // definir le plugin, donc le path avant l'include du fichier options
402 // permet de faire des include_spip pour attraper un inc_ du plugin
403 if ($charge=='chemins'){
404 $prefix = strtoupper(preg_replace(',\W,','_',$info['prefix']));
405 $splugs .= "define('_DIR_PLUGIN_$prefix',$dir);\n";
406 foreach($info['path'] as $chemin){
407 if (!isset($chemin['version']) OR plugin_version_compatible($chemin['version'],$GLOBALS['spip_version_branche'])){
408 $dir = $chemin['dir'];
409 if (strlen($dir) AND $dir{0}=="/") $dir = substr($dir,1);
410 if (!isset($chemin['type']) OR $chemin['type']=='public')
411 $chemins['public'][]="_DIR_PLUGIN_$prefix".(strlen($dir)?".'$dir'":"");
412 if (!isset($chemin['type']) OR $chemin['type']=='prive')
413 $chemins['prive'][]="_DIR_PLUGIN_$prefix".(strlen($dir)?".'$dir'":"");
414 #$splugs .= "if (".(($chemin['type']=='public')?"":"!")."_DIR_RESTREINT) ";
415 #$splugs .= "_chemin(_DIR_PLUGIN_$prefix".(strlen($dir)?".'$dir'":"").");\n";
416 }
417 }
418 }
419 // concerne uniquement options et fonctions
420 if (isset($info[$charge])){
421 foreach($info[$charge] as $file){
422 // on genere un if file_exists devant chaque include pour pouvoir garder le meme niveau d'erreur general
423 $file = trim($file);
424
425 if (strlen(constant($dir_type)) && (strpos($plug, constant($dir_type)) === 0)) {
426 $dir = str_replace("'".constant($dir_type), $root_dir_type.".'", "'$plug/'");
427 }
428 if($root_dir_type == '_ROOT_RACINE'){
429 $plug = str_replace('../','',$plug);
430 }
431 else
432 $dir = $root_dir_type.".'$plug/'";
433 $s .= "if (file_exists(\$f=$dir.'".trim($file)."')){ include_once \$f;}\n";
434 $liste_fichier_verif[] = "$root_dir_type:$plug/".trim($file);
435 }
436 }
437 }
438 }
439 if ($charge=='chemins'){
440 if (count($chemins)){
441 $splugs .= "if (_DIR_RESTREINT) _chemin(implode(':',array(".implode(',',array_reverse($chemins['public'])).")));\n";
442 $splugs .= "else _chemin(implode(':',array(".implode(',',array_reverse($chemins['prive'])).")));\n";
443 }
444 }
445 if ($charge=='options'){
446 $s .= "if (!function_exists('boutons_plugins')){function boutons_plugins(){return unserialize('".str_replace("'","\'",serialize($liste_boutons))."');}}\n";
447 $s .= "if (!function_exists('onglets_plugins')){function onglets_plugins(){return unserialize('".str_replace("'","\'",serialize($liste_onglets))."');}}\n";
448 }
449 ecrire_fichier($fileconf, $start_file . $splugs . $s . $end_file);
450 }
451
452 if (is_array($infos)){
453 // construire tableaux de pipelines et matrices et boutons
454 // $GLOBALS['spip_pipeline']
455 // $GLOBALS['spip_matrice']
456 $liste_boutons = array();
457 foreach($ordre as $p){
458 $dir_type = $plugin_valides[$p]['dir_type'];
459 $root_dir_type = str_replace('_DIR_','_ROOT_',$dir_type);
460 $plug = $plugin_valides[$p]['dir'];
461 $info = $infos[$dir_type][$plug];
462 $prefix = "";
463 $prefix = $info['prefix']."_";
464 if (isset($info['pipeline']) AND is_array($info['pipeline'])){
465 foreach($info['pipeline'] as $pipe){
466 $nom = $pipe['nom'];
467 if (isset($pipe['action']))
468 $action = $pipe['action'];
469 else
470 $action = $nom;
471 $nomlower = strtolower($nom);
472 if ($nomlower!=$nom
473 AND isset($GLOBALS['spip_pipeline'][$nom])
474 AND !isset($GLOBALS['spip_pipeline'][$nomlower])){
475 $GLOBALS['spip_pipeline'][$nomlower] = $GLOBALS['spip_pipeline'][$nom];
476 unset($GLOBALS['spip_pipeline'][$nom]);
477 }
478 $nom = $nomlower;
479 if (!isset($GLOBALS['spip_pipeline'][$nom])) // creer le pipeline eventuel
480 $GLOBALS['spip_pipeline'][$nom]="";
481 if (strpos($GLOBALS['spip_pipeline'][$nom],"|$prefix$action")===FALSE)
482 $GLOBALS['spip_pipeline'][$nom] = preg_replace(",(\|\||$),","|$prefix$action\\1",$GLOBALS['spip_pipeline'][$nom],1);
483 if (isset($pipe['inclure'])){
484 $GLOBALS['spip_matrice']["$prefix$action"] =
485 "$root_dir_type:$plug/".$pipe['inclure'];
486 }
487 }
488 }
489 }
490 }
491
492 // on charge les fichiers d'options qui peuvent completer
493 // la globale spip_pipeline egalement
494 if (@is_readable(_CACHE_PLUGINS_PATH))
495 include_once(_CACHE_PLUGINS_PATH); // securite : a priori n'a pu etre fait plus tot
496 if (@is_readable(_CACHE_PLUGINS_OPT)) {
497 include_once(_CACHE_PLUGINS_OPT);
498 } else {
499 spip_log("pipelines desactives: impossible de produire " . _CACHE_PLUGINS_OPT);
500 }
501
502 // on ajoute les pipe qui ont ete recenses manquants
503 foreach($liste_pipe_manquants as $add_pipe)
504 if (!isset($GLOBALS['spip_pipeline'][$add_pipe]))
505 $GLOBALS['spip_pipeline'][$add_pipe]= '';
506
507 $liste_fichier_verif2 = pipeline_precompile();
508 $liste_fichier_verif = array_merge($liste_fichier_verif,$liste_fichier_verif2);
509
510 // on note dans tmp la liste des fichiers qui doivent etre presents,
511 // pour les verifier "souvent"
512 // ils ne sont verifies que depuis l'espace prive, mais peuvent etre reconstruit depuis l'espace public
513 // dans le cas d'un plugin non declare, spip etant mis devant le fait accompli
514 // hackons donc avec un "../" en dur dans ce cas, qui ne manquera pas de nous embeter un jour...
515 foreach ($liste_fichier_verif as $k => $f){
516 // si un _DIR_XXX: est dans la chaine, on extrait la constante
517 if (preg_match(",(_(DIR|ROOT)_[A-Z_]+):,Ums",$f,$regs))
518 $f = str_replace($regs[0],$regs[2]=="ROOT"?constant($regs[1]):(_DIR_RACINE?"":"../").constant($regs[1]),$f);
519 $liste_fichier_verif[$k] = $f;
520 }
521 ecrire_fichier(_CACHE_PLUGINS_VERIF,
522 serialize($liste_fichier_verif));
523 clear_path_cache();
524 }
525
526 // precompilation des pipelines
527 // http://doc.spip.org/@pipeline_precompile
528 function pipeline_precompile(){
529 global $spip_pipeline, $spip_matrice;
530 $liste_fichier_verif = array();
531
532 $start_file = "<"."?php\nif (defined('_ECRIRE_INC_VERSION')) {\n";
533 $end_file = "}\n?".">";
534 $content = "";
535 foreach($spip_pipeline as $action=>$pipeline){
536 $s_inc = "";
537 $s_call = "";
538 $pipe = array_filter(explode('|',$pipeline));
539 // Eclater le pipeline en filtres et appliquer chaque filtre
540 foreach ($pipe as $fonc) {
541 $fonc = trim($fonc);
542 $s_call .= '$val = minipipe(\''.$fonc.'\', $val);'."\n";
543 if (isset($spip_matrice[$fonc])){
544 $file = $spip_matrice[$fonc];
545 $liste_fichier_verif[] = $file;
546 $s_inc .= 'if (file_exists($f=';
547 $file = "'$file'";
548 // si un _DIR_XXX: est dans la chaine, on extrait la constante
549 if (preg_match(",(_(DIR|ROOT)_[A-Z_]+):,Ums",$file,$regs)){
550 $dir = $regs[1];
551 $root_dir = str_replace('_DIR_','_ROOT_',$dir);
552 if (defined($root_dir))
553 $dir = $root_dir;
554 $file = str_replace($regs[0],"'.".$dir.".'",$file);
555 $file = str_replace("''.","",$file);
556 $file = str_replace(constant($dir), '', $file);
557 }
558 $s_inc .= $file . ')){include_once($f);}'."\n";
559 }
560 }
561 $content .= "// Pipeline $action \n";
562 $content .= "function execute_pipeline_$action(&\$val){\n";
563 $content .= $s_inc;
564 $content .= $s_call;
565 $content .= "return \$val;\n}\n\n";
566 }
567 ecrire_fichier(_CACHE_PIPELINES, $start_file . $content . $end_file);
568 return $liste_fichier_verif;
569 }
570
571 // pas sur que ca serve...
572 // http://doc.spip.org/@liste_plugin_inactifs
573 function liste_plugin_inactifs(){
574 return array_diff (liste_plugin_files(),liste_chemin_plugin_actifs());
575 }
576
577 // mise a jour du meta en fonction de l'etat du repertoire
578 // Les ecrire_meta() doivent en principe aussi initialiser la valeur a vide
579 // si elle n'existe pas
580 // risque de pb en php5 a cause du typage ou de null (verifier dans la doc php)
581 function actualise_plugins_actifs($pipe_recherche = false){
582 if (!spip_connect()) return false;
583 $plugin_actifs = liste_chemin_plugin_actifs();
584 $plugin_liste = liste_plugin_files();
585 $plugin_new = array_intersect($plugin_actifs,$plugin_liste);
586 $actifs_avant = $GLOBALS['meta']['plugin'];
587 ecrire_plugin_actifs($plugin_new,$pipe_recherche);
588 // retourner -1 si la liste des plugins actifs a change
589 return (strcmp($GLOBALS['meta']['plugin'],$actifs_avant)==0) ? 1 : -1;
590 }
591
592 // http://doc.spip.org/@spip_plugin_install
593 function spip_plugin_install($action, $infos){
594 $prefix = $infos['prefix'];
595 $version_cible = $infos['version_base'];
596 if (isset($infos['meta']) AND (($table = $infos['meta']) !== 'meta'))
597 $nom_meta = "base_version";
598 else {
599 $nom_meta = $prefix."_base_version";
600 $table = 'meta';
601 }
602 switch ($action){
603 case 'test':
604 return (isset($GLOBALS[$table])
605 AND isset($GLOBALS[$table][$nom_meta])
606 AND spip_version_compare($GLOBALS[$table][$nom_meta],$version_cible,'>='));
607 break;
608 case 'install':
609 if (function_exists($upgrade = $prefix."_upgrade"))
610 $upgrade($nom_meta, $version_cible, $table);
611 break;
612 case 'uninstall':
613 if (function_exists($vider_tables = $prefix."_vider_tables"))
614 $vider_tables($nom_meta, $table);
615 break;
616 }
617 }
618
619 // http://doc.spip.org/@desinstalle_un_plugin
620 function desinstalle_un_plugin($plug,$infos){
621 // faire les include qui vont bien
622 charge_instal_plugin($plug, $infos);
623 $version_cible = isset($infos['version_base'])?$infos['version_base']:'';
624 $prefix_install = $infos['prefix']."_install";
625 if (function_exists($prefix_install)){
626 $prefix_install('uninstall',$infos['prefix'],$version_cible);
627 $ok = $prefix_install('test',$infos['prefix'],$version_cible);
628 return $ok;
629 }
630 if (isset($infos['version_base'])){
631 spip_plugin_install('uninstall',$infos);
632 $ok = spip_plugin_install('test',$infos);
633 return $ok;
634 }
635
636 return false;
637 }
638
639 function charge_instal_plugin($plug,$infos,$dir_plugins = '_DIR_PLUGINS'){
640 // passer en chemin absolu si possible
641 $dir = str_replace('_DIR_','_ROOT_',$dir_plugins);
642 if (!defined($dir))
643 $dir = $dir_plugins;
644
645 // faire les include qui vont bien
646 foreach($infos['install'] as $file){
647 $file = trim($file);
648 if (file_exists($f=constant($dir)."$plug/$file")){
649 include_once($f);
650 }
651 }
652 }
653
654 function installe_un_plugin($plug,$infos,$dir_plugins = '_DIR_PLUGINS'){
655
656 charge_instal_plugin($plug, $infos, $dir_plugins);
657
658 $version_cible = isset($infos['version_base'])?$infos['version_base']:'';
659 $prefix_install = $infos['prefix']."_install";
660 // cas de la fonction install fournie par le plugin
661 if (function_exists($prefix_install)){
662 // voir si on a besoin de faire l'install
663 $ok = $prefix_install('test',$infos['prefix'],$version_cible);
664 if (!$ok) {
665 echo "<div class='install-plugins'>";
666 echo _T('plugin_titre_installation',array('plugin'=>typo($infos['nom'])))."<br />";
667 $prefix_install('install',$infos['prefix'],$version_cible);
668 $ok = $prefix_install('test',$infos['prefix'],$version_cible);
669 // vider le cache des definitions des tables
670 $trouver_table = charger_fonction('trouver_table','base');
671 $trouver_table(false);
672 echo "<span class='".($ok?'ok':'erreur')."'>".($ok ? _L("OK"):_L("Echec"))."</span>";
673 echo "</div>";
674 }
675 return $ok; // le plugin est deja installe et ok
676 }
677 // pas de fonction instal fournie, mais une version_base dans le plugin
678 // on utilise la fonction par defaut
679 if (isset($infos['version_base'])){
680 $ok = spip_plugin_install('test',$infos);
681 if (!$ok) {
682 echo "<div class='install-plugins'>";
683 echo _T('plugin_titre_installation',array('plugin'=>typo($infos['nom'])))."<br />";
684 spip_plugin_install('install',$infos);
685 $ok = spip_plugin_install('test',$infos);
686 // vider le cache des definitions des tables
687 $trouver_table = charger_fonction('trouver_table','base');
688 $trouver_table(false);
689 echo "<span class='".($ok?'ok':'erreur')."'>".($ok ? _L("OK"):_L("Echec"))."</span>";
690 echo "</div>";
691 }
692 return $ok; // le plugin est deja installe et ok
693 }
694 return false;
695 }
696
697 // http://doc.spip.org/@installe_plugins
698 function installe_plugins($test = false){
699 $meta_plug_installes = array();
700
701 // vider le cache des descriptions de tables avant installation
702 $trouver_table = charger_fonction('trouver_table', 'base');
703 $trouver_table('');
704
705 $liste = liste_plugin_actifs();
706 $get_infos = charger_fonction('get_infos','plugins');
707
708 foreach ($liste as $prefix=>$resume) {
709 $plug = $resume['dir'];
710 $dir_type = $resume['dir_type'];
711 $infos = $get_infos($plug,false,constant($dir_type));
712 if ($infos AND isset($infos['install'])){
713 if ($test) return true; // il y a des installations a faire
714 $ok = installe_un_plugin($plug,$infos,$dir_type);
715 // on peut enregistrer le chemin ici car il est mis a jour juste avant l'affichage
716 // du panneau -> cela suivra si le plugin demenage
717 if ($ok)
718 $meta_plug_installes[] = $plug;
719 // vider le cache des descriptions de tables apres chaque installation
720 $trouver_table('');
721 }
722 }
723 ecrire_meta('plugin_installes',serialize($meta_plug_installes),'non');
724 if ($test) return false; // il n'y a pas d'installations a faire
725 return true; // succes
726 }
727
728 // http://doc.spip.org/@plugin_est_installe
729 function plugin_est_installe($plug_path){
730 $plugin_installes = isset($GLOBALS['meta']['plugin_installes'])?unserialize($GLOBALS['meta']['plugin_installes']):array();
731 if (!$plugin_installes) return false;
732 return in_array($plug_path,$plugin_installes);
733 }
734
735 // http://doc.spip.org/@verifie_include_plugins
736 function verifie_include_plugins() {
737 include_spip('inc/meta');
738 ecrire_meta('message_crash_plugins', 1);
739
740 /* if (_request('exec')!="admin_plugin"
741 AND $_SERVER['X-Requested-With'] != 'XMLHttpRequest'){
742 if (@is_readable(_DIR_PLUGINS)) {
743 include_spip('inc/headers');
744 redirige_url_ecrire("admin_plugin");
745 }
746 // plus de repertoire plugin existant, le menu n'existe plus
747 // on fait une mise a jour silencieuse
748 // generer les fichiers php precompiles
749 // de chargement des plugins et des pipelines
750 actualise_plugins_actifs();
751 spip_log("desactivation des plugins suite a suppression du repertoire");
752 }
753 */
754 }
755
756
757 // http://doc.spip.org/@message_crash_plugins
758 function message_crash_plugins() {
759 if (autoriser('configurer')
760 AND lire_fichier(_CACHE_PLUGINS_VERIF,$l)
761 AND $l = @unserialize($l)) {
762 $err = array();
763 foreach ($l as $fichier) {
764 if (!@is_readable($fichier)) {
765 spip_log("Verification plugin: echec sur $fichier !");
766 $err[] = $fichier;
767 }
768 }
769
770 if ($err) {
771 $err = array_map('joli_repertoire', array_unique($err));
772 return "<a href='".generer_url_ecrire('admin_plugin')."'>"
773 ._T('plugins_erreur',
774 array('plugins' => join(', ', $err)))
775 .'</a>';
776 }
777 }
778 }
779
780
781
782 ?>