1 | <?php |
---|
2 | |
---|
3 | if (!defined("_ECRIRE_INC_VERSION")) return; |
---|
4 | |
---|
5 | // l'actionneur calcule l'ordre des actions |
---|
6 | // et permet de les stocker et de les effectuer. |
---|
7 | |
---|
8 | class Actionneur { |
---|
9 | |
---|
10 | var $decideur; |
---|
11 | |
---|
12 | // loggue t'on ? |
---|
13 | var $log = false; |
---|
14 | |
---|
15 | // actions au debut (avant analyse) |
---|
16 | var $start = array(); |
---|
17 | |
---|
18 | // actions en cours d'analyse |
---|
19 | var $middle = array( |
---|
20 | 'off' => array(), |
---|
21 | 'lib' => array(), |
---|
22 | 'on' => array(), |
---|
23 | 'neutre' => array(), |
---|
24 | ); |
---|
25 | |
---|
26 | // actions a la fin (apres analyse, et dans l'ordre) |
---|
27 | var $end = array(); // a faire... |
---|
28 | var $done = array(); // faites |
---|
29 | var $work = array(); // en cours |
---|
30 | |
---|
31 | function Actionneur(){ |
---|
32 | include_spip('inc/step_decideur'); |
---|
33 | $this->decideur = new Decideur(); |
---|
34 | $this->decideur->start(); |
---|
35 | } |
---|
36 | |
---|
37 | |
---|
38 | function log($quoi) { |
---|
39 | if ($this->log) { |
---|
40 | spip_log($quoi,'actionneur'); |
---|
41 | } |
---|
42 | } |
---|
43 | |
---|
44 | function clear() { |
---|
45 | $this->middle = array( |
---|
46 | 'off' => array(), |
---|
47 | 'lib' => array(), |
---|
48 | 'on' => array(), |
---|
49 | 'neutre' => array(), |
---|
50 | ); |
---|
51 | $this->end = array(); |
---|
52 | $this->done = array(); |
---|
53 | $this->work = array(); |
---|
54 | } |
---|
55 | |
---|
56 | function ajouter_actions($todo) { |
---|
57 | foreach ($todo as $id => $action) { |
---|
58 | $this->start[$id] = $action; |
---|
59 | } |
---|
60 | $this->ordonner_actions(); |
---|
61 | } |
---|
62 | |
---|
63 | |
---|
64 | // ajouter une librairie a installer. |
---|
65 | function add_lib($nom, $source) { |
---|
66 | if (!$this->decideur->est_presente_lib($nom)) { |
---|
67 | if (is_writable(_DIR_LIB)) { |
---|
68 | $this->middle['lib'][$nom] = array( |
---|
69 | 'todo'=>'lib', |
---|
70 | 'n'=>$nom, |
---|
71 | 'p'=>$nom, |
---|
72 | 'v'=>$source, |
---|
73 | 's'=>$source, |
---|
74 | ); |
---|
75 | } else { |
---|
76 | // erreur : impossible d'ecrire dans _DIR_LIB ! |
---|
77 | // TODO : message et retour d'erreur a gerer... |
---|
78 | return false; |
---|
79 | } |
---|
80 | } |
---|
81 | return true; |
---|
82 | } |
---|
83 | |
---|
84 | |
---|
85 | function ordonner_actions() { |
---|
86 | // il faut deja definir quels sont des |
---|
87 | // actions graduellement realisables. |
---|
88 | // Pour tout ce qui est a installer : ordre des dependances |
---|
89 | // Pour tout ce qui est a desinstaller : ordre inverse des dependances. |
---|
90 | |
---|
91 | // on commence par separer |
---|
92 | // - ce qui est a desinstaller. |
---|
93 | // - ce qui est a installe |
---|
94 | // - les actions neutres (get, up sur non actif, kill) |
---|
95 | |
---|
96 | // on commencera par faire ce qui est a desinstaller |
---|
97 | // (il est possible que certains plugins necessitent la desinstallation |
---|
98 | // d'autres present - tel que : 1 seul service d'envoi de mail) |
---|
99 | // puis ce qui est a installer |
---|
100 | // puis les actions neutres |
---|
101 | $this->clear(); |
---|
102 | |
---|
103 | foreach ($this->start as $id=>$action) { |
---|
104 | $i = $this->decideur->infos_courtes_id($id); |
---|
105 | $i = $i['i'][$id]; |
---|
106 | switch ($action) { |
---|
107 | case 'on': |
---|
108 | $this->on($i, $action); |
---|
109 | break; |
---|
110 | case 'up': |
---|
111 | if ($i['a'] == 'oui') { |
---|
112 | $this->on($i, $action); |
---|
113 | } else { |
---|
114 | $this->neutre($i, $action); |
---|
115 | } |
---|
116 | break; |
---|
117 | case 'upon': |
---|
118 | $this->on($i, $action); |
---|
119 | break; |
---|
120 | case 'off': |
---|
121 | case 'stop': |
---|
122 | $this->off($i, $action); |
---|
123 | break; |
---|
124 | case 'get': |
---|
125 | case 'kill': |
---|
126 | $this->neutre($i, $action); |
---|
127 | break; |
---|
128 | } |
---|
129 | } |
---|
130 | |
---|
131 | // c'est termine, on passe tout dans la fin... |
---|
132 | foreach ($this->middle as $acts) { |
---|
133 | $this->end = array_merge($this->end, $acts); |
---|
134 | } |
---|
135 | $this->log("------------"); |
---|
136 | #$$this->log("Fin du tri :"); |
---|
137 | #$this->log($this->end); |
---|
138 | } |
---|
139 | |
---|
140 | |
---|
141 | // a chaque fois qu'une action arrive, |
---|
142 | // on compare avec celles deja presentes |
---|
143 | // pour savoir si on doit la traiter avant ou apres |
---|
144 | |
---|
145 | function on($info, $action) { |
---|
146 | $info['todo'] = $action; |
---|
147 | $p = $info['p']; |
---|
148 | $this->log("ON: $p $action"); |
---|
149 | |
---|
150 | // si dependance, il faut le mettre avant ! |
---|
151 | $in = $out = $deps = $deps_all = array(); |
---|
152 | // raz des cles pour avoir les memes que $out (utile reellement ?) |
---|
153 | $this->middle['on'] = array_values($this->middle['on']); |
---|
154 | // ajout des dependance et des librairies si besion |
---|
155 | foreach ($info['dn'] as $dep) { |
---|
156 | if ($dep['id'] != 'SPIP') { |
---|
157 | if (strpos($dep['id'],'lib:')===0) { |
---|
158 | if ($lib = substr($dep['id'], 4)) { |
---|
159 | // il faudrait gerer un retour d'erreur eventuel ! |
---|
160 | $this->add_lib($lib, $dep['src']); |
---|
161 | } |
---|
162 | } else { |
---|
163 | $in[] = $dep['id']; |
---|
164 | } |
---|
165 | } |
---|
166 | } |
---|
167 | |
---|
168 | // on recupere : tous les prefix de plugin a activer (out) |
---|
169 | // ie. ce plugin peut dependre d'un de ceux la |
---|
170 | // |
---|
171 | // ainsi que les dependences de ces plugins (deps) |
---|
172 | // ie. ces plugins peuvent dependre de ce nouveau a activer. |
---|
173 | foreach ($this->middle['on'] as $inf) { |
---|
174 | $out[] = $inf['p']; |
---|
175 | foreach ($inf['dn'] as $dep) { |
---|
176 | if ($dep['id'] != 'SPIP') { |
---|
177 | if (strpos($dep['id'],'lib:')!==0) { |
---|
178 | $deps[$inf['p']][] = $dep['id']; |
---|
179 | $deps_all[] = $dep['id']; |
---|
180 | } |
---|
181 | } |
---|
182 | } |
---|
183 | } |
---|
184 | |
---|
185 | if (!$in) { |
---|
186 | |
---|
187 | // pas de dependance, on le met en premier ! |
---|
188 | $this->log("- placer $p tout en haut"); |
---|
189 | array_unshift($this->middle['on'], $info); |
---|
190 | |
---|
191 | } else { |
---|
192 | |
---|
193 | // intersection = dependance presente aussi |
---|
194 | // on place notre action juste apres la derniere dependance |
---|
195 | if ($diff = array_intersect($in, $out)) { |
---|
196 | $key = array(); |
---|
197 | foreach($diff as $d) {$key[] = array_search($d, $out);} |
---|
198 | $key = max($key); |
---|
199 | $this->log("- placer $p apres " . $this->middle['on'][$key]['p']); |
---|
200 | if ($key == count($this->middle['on'])) { |
---|
201 | $this->middle['on'][] = $info; |
---|
202 | } else { |
---|
203 | array_splice($this->middle['on'], $key+1, 0, array($info)); |
---|
204 | } |
---|
205 | |
---|
206 | // intersection = plugin dependant de celui-ci |
---|
207 | // on place notre plugin juste avant la premiere dependance a lui trouvee |
---|
208 | } elseif (in_array($p, $deps_all)) { |
---|
209 | foreach ($deps as $prefix=>$dep) { |
---|
210 | if (in_array($p, $dep)) { |
---|
211 | $key = array_search($prefix, $out); |
---|
212 | $this->log("- placer $p avant $prefix qui en depend ($key)"); |
---|
213 | if ($key == 0) { |
---|
214 | array_unshift($this->middle['on'], $info); |
---|
215 | } else { |
---|
216 | array_splice($this->middle['on'], $key, 0, array($info)); |
---|
217 | } |
---|
218 | break; |
---|
219 | } |
---|
220 | } |
---|
221 | |
---|
222 | // rien de particulier, il a des dependances mais les plugins |
---|
223 | // ne sont pas encore la ou les dependances sont deja actives |
---|
224 | // donc on le place tout en bas |
---|
225 | } else { |
---|
226 | $this->log("- placer $p tout en bas"); |
---|
227 | $this->middle['on'][] = $info; |
---|
228 | } |
---|
229 | } |
---|
230 | unset($diff, $in, $out); |
---|
231 | } |
---|
232 | |
---|
233 | |
---|
234 | function neutre($info, $action) { |
---|
235 | $info['todo'] = $action; |
---|
236 | $this->log("NEUTRE: $info[p] $action"); |
---|
237 | $this->middle['neutre'][] = $info; |
---|
238 | } |
---|
239 | |
---|
240 | |
---|
241 | function off($info, $action) { |
---|
242 | $info['todo'] = $action; |
---|
243 | $p = $info['p']; |
---|
244 | $this->log("OFF: $p $action"); |
---|
245 | |
---|
246 | // si dependance, il faut le mettre avant ! |
---|
247 | $in = $out = array(); |
---|
248 | // raz des cles pour avoir les memes que $out (utile reellement ?) |
---|
249 | $this->middle['off'] = array_values($this->middle['off']); |
---|
250 | foreach ($info['dn'] as $dep) { |
---|
251 | if (($dep['id'] != 'SPIP') and (strpos($dep['id'],'lib:')!==0)) { |
---|
252 | $in[] = $dep['id']; |
---|
253 | } |
---|
254 | } |
---|
255 | foreach ($this->middle['off'] as $inf) {$out[] = $inf['p'];} |
---|
256 | |
---|
257 | if (!$in) { |
---|
258 | // pas de dependance, on le met en dernier ! |
---|
259 | $this->log("- placer $p tout en bas"); |
---|
260 | $this->middle['off'][] = $info; |
---|
261 | } else { |
---|
262 | // intersection = dependance presente aussi |
---|
263 | // on place notre action juste avant la premiere dependance |
---|
264 | if ($diff = array_intersect($in, $out)) { |
---|
265 | $key = array(); |
---|
266 | foreach($diff as $d) {$key[] = array_search($d, $out);} |
---|
267 | $key = min($key); |
---|
268 | $this->log("- placer $p avant " . $this->middle['off'][$key]['p']); |
---|
269 | array_splice($this->middle['off'], $key, 0, array($info)); |
---|
270 | } else { |
---|
271 | // pas de dependance, on le met en premier ! |
---|
272 | $this->log("- placer $p tout en haut"); |
---|
273 | array_unshift($this->middle['on'], $info); |
---|
274 | } |
---|
275 | } |
---|
276 | unset($diff, $in, $out); |
---|
277 | } |
---|
278 | |
---|
279 | |
---|
280 | function presenter_actions() { |
---|
281 | $affiche = ""; |
---|
282 | if ($this->end or $this->done) { |
---|
283 | $affiche .= "<ul>"; |
---|
284 | foreach ($this->done as $i) { |
---|
285 | if(is_string($i['done'])){ |
---|
286 | $ajouts_message = "<br />".$i['done']; |
---|
287 | } |
---|
288 | $affiche .= "\t<li>"._T('step:message_action_finale_'.$i['todo'].'_'.($i['done']?'ok':'fail'),array('plugin'=>$i[n],'version'=>$i[v])).$ajouts_message."</li>\n"; |
---|
289 | } |
---|
290 | foreach ($this->end as $i) { |
---|
291 | $affiche .= "\t<li>"._T('step:message_action_'.$i['todo'],array('plugin'=>$i[n],'version'=>$i[v]))."</li>\n"; |
---|
292 | } |
---|
293 | $affiche .= "</ul>\n"; |
---|
294 | } |
---|
295 | return $affiche; |
---|
296 | } |
---|
297 | |
---|
298 | |
---|
299 | function sauver_actions() { |
---|
300 | $contenu = serialize(array( |
---|
301 | 'todo' => $this->end, |
---|
302 | 'done' => $this->done, |
---|
303 | 'work' => $this->work, |
---|
304 | )); |
---|
305 | ecrire_fichier(_DIR_TMP . 'step_actions.txt', $contenu); |
---|
306 | } |
---|
307 | |
---|
308 | |
---|
309 | function get_actions() { |
---|
310 | lire_fichier(_DIR_TMP . 'step_actions.txt', $contenu); |
---|
311 | $infos = unserialize($contenu); |
---|
312 | $this->end = $infos['todo']; |
---|
313 | $this->work = $infos['work']; |
---|
314 | $this->done = $infos['done']; |
---|
315 | } |
---|
316 | |
---|
317 | |
---|
318 | function one_action() { |
---|
319 | if (count($this->end)) { |
---|
320 | $action = $this->work = array_shift($this->end); |
---|
321 | $this->sauver_actions(); |
---|
322 | $this->do_action(); |
---|
323 | return $action; |
---|
324 | } |
---|
325 | return false; |
---|
326 | } |
---|
327 | |
---|
328 | function do_action() { |
---|
329 | if ($do = $this->work) { |
---|
330 | $todo = 'do_' . $do['todo']; |
---|
331 | lire_metas(); // avoir les metas a jour |
---|
332 | $do['done'] = $this->$todo($do); |
---|
333 | $this->done[] = $do; |
---|
334 | $this->work = array(); |
---|
335 | $this->sauver_actions(); |
---|
336 | } |
---|
337 | } |
---|
338 | |
---|
339 | |
---|
340 | // activer un plugin |
---|
341 | // soit il est la... soit il est a telecharger... |
---|
342 | function do_on($info) { |
---|
343 | $i = sql_fetsel('*','spip_plugins','id_plugin='.sql_quote($info['i'])); |
---|
344 | if ($i['id_zone'] > 0) { |
---|
345 | // a telecharger et activer |
---|
346 | if ($dirs = $this->get_paquet_id($i)) { |
---|
347 | $this->activer_plugin_dossier($dirs['dossier'], $i); |
---|
348 | return true; |
---|
349 | } |
---|
350 | } else { |
---|
351 | // a activer uniquement |
---|
352 | // il faudra prendre en compte les autres _DIR_xx |
---|
353 | if (in_array($i['constante'],array('_DIR_PLUGINS','_DIR_PLUGINS_SUPPL'))) { |
---|
354 | $dossier = rtrim($i['dossier'],'/'); |
---|
355 | $this->activer_plugin_dossier($dossier, $i, $i['constante']); |
---|
356 | return true; |
---|
357 | } |
---|
358 | } |
---|
359 | return false; |
---|
360 | } |
---|
361 | |
---|
362 | |
---|
363 | |
---|
364 | // mettre a jour un plugin |
---|
365 | function do_up($info) { |
---|
366 | // ecriture du nouveau |
---|
367 | // suppression de l'ancien (si dans auto, et pas au meme endroit) |
---|
368 | // OU suppression des anciens fichiers |
---|
369 | if (!defined('_DIR_PLUGINS_AUTO') or !_DIR_PLUGINS_AUTO or !is_writable(_DIR_PLUGINS_AUTO)) { |
---|
370 | $this->log("Pas de _DIR_PLUGINS_AUTO defini !"); |
---|
371 | return false; |
---|
372 | } |
---|
373 | |
---|
374 | $i = sql_fetsel('*','spip_plugins','id_plugin='.sql_quote($info['i'])); |
---|
375 | |
---|
376 | // on cherche la mise a jour... |
---|
377 | if ($maj = sql_fetsel('*','spip_plugins',array( |
---|
378 | 'prefixe='.sql_quote($info['p']), |
---|
379 | 'version='.sql_quote($info['maj']), |
---|
380 | 'superieur='.sql_quote('oui')))) { |
---|
381 | if ($dirs = $this->get_paquet_id($maj)) { |
---|
382 | // Si le plugin a jour n'est pas dans le meme dossier que l'ancien... |
---|
383 | // il faut : |
---|
384 | // - activer le plugin sur son nouvel emplacement (uniquement si l'ancien est actif)... |
---|
385 | // - supprimer l'ancien (si faisable) |
---|
386 | if (($dirs['dossier'] . '/') != $i['dossier']) { |
---|
387 | if ($i['actif'] == 'oui') { |
---|
388 | $this->activer_plugin_dossier($dirs['dossier'], $maj); |
---|
389 | } |
---|
390 | |
---|
391 | if (substr($i['dossier'],0,5) == 'auto/') { |
---|
392 | if ($this->deleteDirectory($dirs['dir'])) { |
---|
393 | sql_delete('spip_plugins', 'id_plugin=' . sql_quote($info['i'])); |
---|
394 | } |
---|
395 | } |
---|
396 | } |
---|
397 | |
---|
398 | $this->ajouter_plugin_interessants_meta($dirs['dossier']); |
---|
399 | return $dirs; |
---|
400 | } |
---|
401 | } |
---|
402 | return false; |
---|
403 | } |
---|
404 | |
---|
405 | |
---|
406 | // mettre a jour et activer un plugin |
---|
407 | function do_upon($info) { |
---|
408 | $i = sql_fetsel('*','spip_plugins','id_plugin='.sql_quote($info['i'])); |
---|
409 | if ($dirs = $this->do_up($info)) { |
---|
410 | $this->activer_plugin_dossier($dirs['dossier'], $i, $i['constante']); |
---|
411 | return true; |
---|
412 | } |
---|
413 | return false; |
---|
414 | } |
---|
415 | |
---|
416 | |
---|
417 | // desactiver un plugin |
---|
418 | function do_off($info) { |
---|
419 | $i = sql_fetsel('*','spip_plugins','id_plugin='.sql_quote($info['i'])); |
---|
420 | // il faudra prendre en compte les autres _DIR_xx |
---|
421 | if (in_array($i['constante'],array('_DIR_PLUGINS','_DIR_PLUGINS_SUPPL'))) { |
---|
422 | include_spip('inc/plugin'); |
---|
423 | $dossier = ($i['constante'] == '_DIR_PLUGINS')? $i['dossier'] : '../'.constant($i['constante']).$i['dossier']; |
---|
424 | ecrire_plugin_actifs(array(rtrim($dossier,'/')), false, 'enleve'); |
---|
425 | sql_updateq('spip_plugins', array('actif'=>'non', 'installe'=>'non'), 'id_plugin='.sql_quote($info['i'])); |
---|
426 | $this->actualiser_plugin_interessants(); |
---|
427 | // ce retour est un rien faux... |
---|
428 | // il faudrait que la fonction ecrire_plugin_actifs() |
---|
429 | // retourne au moins d'eventuels message d'erreur ! |
---|
430 | return true; |
---|
431 | } |
---|
432 | return false; |
---|
433 | } |
---|
434 | |
---|
435 | |
---|
436 | // desinstaller un plugin |
---|
437 | function do_stop($info) { |
---|
438 | $i = sql_fetsel('*','spip_plugins','id_plugin='.sql_quote($info['i'])); |
---|
439 | // il faudra prendre en compte les autres _DIR_xx |
---|
440 | if (in_array($i['constante'],array('_DIR_PLUGINS','_DIR_PLUGINS_SUPPL'))) { |
---|
441 | include_spip('inc/plugin'); |
---|
442 | include_spip('inc/step'); |
---|
443 | $dossier = rtrim($i['dossier'],'/'); |
---|
444 | $constante = $i['constante']; |
---|
445 | $plugin_get_infos = charger_fonction('get_infos', 'plugins'); |
---|
446 | if($i['constante'] == '_DIR_PLUGINS_SUPPL') |
---|
447 | $constante = _DIR_RACINE.constant($i['constante']); |
---|
448 | else |
---|
449 | $constante = constant($i['constante']); |
---|
450 | $infos = $plugin_get_infos($dossier,false,$constante); |
---|
451 | |
---|
452 | if (isset($infos['install'])){ |
---|
453 | |
---|
454 | // desinstaller |
---|
455 | $dossier = ($i['constante'] == '_DIR_PLUGINS')? $dossier : '../'.constant($i['constante']).$dossier; |
---|
456 | $etat = desinstalle_un_plugin($dossier, $infos); |
---|
457 | |
---|
458 | // desactiver si il a bien ete desinstalle |
---|
459 | if (!$etat) { |
---|
460 | ecrire_plugin_actifs(array($dossier), false, 'enleve'); |
---|
461 | sql_updateq('spip_plugins', array('actif'=>'non', 'installe'=>'non'), 'id_plugin='.sql_quote($info['i'])); |
---|
462 | return true; |
---|
463 | } |
---|
464 | // echec de la desinstallation |
---|
465 | } |
---|
466 | // pas de desinstallation possible ! |
---|
467 | } |
---|
468 | $this->actualiser_plugin_interessants(); |
---|
469 | return false; |
---|
470 | } |
---|
471 | |
---|
472 | |
---|
473 | // effacer les fichiers d'un plugin |
---|
474 | function do_kill($info) { |
---|
475 | // on reverifie que c'est bien un plugin auto ! |
---|
476 | // il faudrait aussi faire tres attention sur un site mutualise |
---|
477 | // cette option est encore plus delicate que les autres... |
---|
478 | $i = sql_fetsel('*','spip_plugins','id_plugin='.sql_quote($info['i'])); |
---|
479 | |
---|
480 | if (in_array($i['constante'],array('_DIR_PLUGINS','_DIR_PLUGINS_SUPPL')) |
---|
481 | and substr($i['dossier'],0,5) == 'auto/') { |
---|
482 | $dir = constant($i['constante']) . $i['dossier']; |
---|
483 | if ($this->deleteDirectory($dir)) { |
---|
484 | sql_delete('spip_plugins', 'id_plugin=' . sql_quote($info['i'])); |
---|
485 | return true; |
---|
486 | } |
---|
487 | } |
---|
488 | |
---|
489 | return false; |
---|
490 | } |
---|
491 | |
---|
492 | |
---|
493 | // installer une librairie |
---|
494 | function do_lib($info) { |
---|
495 | if (!defined('_DIR_LIB') or !_DIR_LIB or !is_writable(_DIR_LIB)) { |
---|
496 | $this->log("Pas de _DIR_LIB defini !"); |
---|
497 | return false; |
---|
498 | } |
---|
499 | |
---|
500 | $zip = $info['s']; |
---|
501 | if ($files = $this->get_zip($zip, _DIR_LIB)) { |
---|
502 | $dest = $files[0]['stored_filename']; |
---|
503 | $dest = rtrim($dest, '/'); |
---|
504 | $dir = _DIR_LIB . $dest; |
---|
505 | |
---|
506 | $this->log("Suppression des anciens fichiers de $dir"); |
---|
507 | $this->remove_older_files($dir, $files); |
---|
508 | |
---|
509 | return true; |
---|
510 | } |
---|
511 | |
---|
512 | return false; |
---|
513 | } |
---|
514 | |
---|
515 | |
---|
516 | // telecharger un plugin |
---|
517 | function do_get($info) { |
---|
518 | if (!defined('_DIR_PLUGINS_AUTO') or !_DIR_PLUGINS_AUTO or !is_writable(_DIR_PLUGINS_AUTO)) { |
---|
519 | $this->log("Pas de _DIR_PLUGINS_AUTO defini !"); |
---|
520 | return false; |
---|
521 | } |
---|
522 | |
---|
523 | $i = sql_fetsel('*','spip_plugins','id_plugin='.sql_quote($info['i'])); |
---|
524 | if ($i['paquet']) { |
---|
525 | if ($adresse = sql_getfetsel('adresse','spip_zones_plugins','id_zone='.sql_quote($i['id_zone']))) { |
---|
526 | $adresse = dirname($adresse); |
---|
527 | $zip = $adresse . '/' . $i['paquet']; |
---|
528 | if ($files = $this->get_zip($zip, _DIR_PLUGINS_AUTO)) { |
---|
529 | $dest = $files[0]['stored_filename']; |
---|
530 | // rendre obsolete ce paquet distant |
---|
531 | // (ca le fera tout seul au moment d'actualiser les paquets locaux) |
---|
532 | // trouver le nouveau paquet et le mettre dans les interessants... |
---|
533 | $dest = 'auto/' . rtrim($dest, '/'); |
---|
534 | $this->ajouter_plugin_interessants_meta($dest); |
---|
535 | |
---|
536 | // c'est la ou _DIR_PLUGINS_AUTO |
---|
537 | // ne sert pas a grand chose... a ameliorer |
---|
538 | return true; |
---|
539 | } |
---|
540 | } |
---|
541 | } |
---|
542 | |
---|
543 | return false; |
---|
544 | } |
---|
545 | |
---|
546 | |
---|
547 | |
---|
548 | // lancer l'installation d'un plugin |
---|
549 | function do_install($info) { |
---|
550 | include_spip('inc/plugin'); |
---|
551 | $message_install = $this->installe_plugin($info); |
---|
552 | return $message_install; |
---|
553 | } |
---|
554 | |
---|
555 | |
---|
556 | // adresse du dossier, et row SQL du plugin en question |
---|
557 | function activer_plugin_dossier($dossier, $i, $constante='_DIR_PLUGINS') { |
---|
558 | include_spip('inc/plugin'); |
---|
559 | |
---|
560 | //il faut absolument que tous les fichiers de cache |
---|
561 | // soient inclus avant modification, sinon un appel ulterieur risquerait |
---|
562 | // de charger des fichiers deja charges par un autre ! |
---|
563 | // C'est surtout le ficher de fonction le probleme (options et pipelines |
---|
564 | // sont normalement deja charges). |
---|
565 | if (@is_readable(_CACHE_PLUGINS_OPT)) {include_once(_CACHE_PLUGINS_OPT);} |
---|
566 | if (@is_readable(_CACHE_PLUGINS_FCT)) {include_once(_CACHE_PLUGINS_FCT);} |
---|
567 | if (@is_readable(_CACHE_PIPELINES)) {include_once(_CACHE_PIPELINES);} |
---|
568 | |
---|
569 | $dossier = ($constante == '_DIR_PLUGINS')? $dossier : '../'.constant($constante).$dossier; |
---|
570 | ecrire_plugin_actifs(array($dossier), false, 'ajoute'); |
---|
571 | $installe = $i['version_base'] ? 'oui' : 'non'; |
---|
572 | if ($installe == 'oui') { |
---|
573 | if(!$i['constante']) |
---|
574 | $i['constante'] = '_DIR_PLUGINS'; |
---|
575 | // installer le plugin au prochain tour |
---|
576 | $new_action = array_merge($this->work, array( |
---|
577 | 'todo'=>'install', |
---|
578 | 'dossier'=>rtrim($i['dossier'],'/'), |
---|
579 | 'constante'=>$i['constante'] |
---|
580 | )); |
---|
581 | array_unshift($this->end, $new_action); |
---|
582 | #$this->installe_plugin($dossier); |
---|
583 | } |
---|
584 | |
---|
585 | $this->ajouter_plugin_interessants_meta($dossier); |
---|
586 | $this->actualiser_plugin_interessants(); |
---|
587 | } |
---|
588 | |
---|
589 | |
---|
590 | // actualiser les plugins interessants |
---|
591 | function actualiser_plugin_interessants() { |
---|
592 | // Chaque fois que l'on valide des plugins, |
---|
593 | // on memorise la liste de ces plugins comme etant "interessants", |
---|
594 | // avec un score initial, qui sera decremente a chaque tour : |
---|
595 | // ainsi un plugin active pourra reter visible a l'ecran, |
---|
596 | // jusqu'a ce qu'il tombe dans l'oubli. |
---|
597 | $plugins_interessants = @unserialize($GLOBALS['meta']['plugins_interessants']); |
---|
598 | if (!is_array($plugins_interessants)) { |
---|
599 | $plugins_interessants = array(); |
---|
600 | } |
---|
601 | $dossiers = array(); |
---|
602 | foreach($plugins_interessants as $p => $score) { |
---|
603 | if (--$score > 0) { |
---|
604 | $plugins_interessants[$p] = $score; |
---|
605 | $dossiers[$p.'/'] = true; |
---|
606 | } else { |
---|
607 | unset($plugins_interessants[$p]); |
---|
608 | // ATTENTION, il faudra prendre en compte les _DIR_xx |
---|
609 | sql_updateq('spip_plugins',array('recent'=>0),'dossier='.sql_quote($p)); |
---|
610 | } |
---|
611 | } |
---|
612 | |
---|
613 | $plugs = sql_select('dossier','spip_plugins','actif='.sql_quote('oui')); |
---|
614 | |
---|
615 | while ($plug = sql_fetch($plugs)) { |
---|
616 | $dossiers[$plug['dossier']] = true; |
---|
617 | $plugins_interessants[ rtrim($plug['dossier'],'/') ] = 30; // score initial |
---|
618 | } |
---|
619 | |
---|
620 | $plugs = sql_updateq('spip_plugins', array('recent'=>1), sql_in('dossier', array_keys($dossiers))); |
---|
621 | ecrire_meta('plugins_interessants', serialize($plugins_interessants)); |
---|
622 | } |
---|
623 | |
---|
624 | |
---|
625 | |
---|
626 | function ajouter_plugin_interessants_meta($dir) { |
---|
627 | $plugins_interessants = @unserialize($GLOBALS['meta']['plugins_interessants']); |
---|
628 | if (!is_array($plugins_interessants)) { |
---|
629 | $plugins_interessants = array(); |
---|
630 | } |
---|
631 | $plugins_interessants[$dir] = 30; |
---|
632 | ecrire_meta('plugins_interessants', serialize($plugins_interessants)); |
---|
633 | } |
---|
634 | |
---|
635 | |
---|
636 | function installe_plugin($info){ |
---|
637 | $plugin_get_infos = charger_fonction('get_infos', 'plugins'); |
---|
638 | if($info['constante'] == '_DIR_PLUGINS_SUPPL') |
---|
639 | $constante = _DIR_RACINE.constant($info['constante']); |
---|
640 | else |
---|
641 | $constante = constant($info['constante']); |
---|
642 | |
---|
643 | $infos = $plugin_get_infos($info['dossier'],false,$constante); |
---|
644 | if (isset($infos['install'])) { |
---|
645 | ob_start(); |
---|
646 | include_spip('inc/step'); |
---|
647 | $dossier = ($info['constante'] == '_DIR_PLUGINS')? $info['dossier'] : '../'.constant($info['constante']).$info['dossier']; |
---|
648 | if (installe_un_plugin($dossier, $infos)) { |
---|
649 | $meta_plug_installes = @unserialize($GLOBALS['meta']['plugin_installes']); |
---|
650 | if (!$meta_plug_installes) $meta_plug_installes=array(); |
---|
651 | $meta_plug_installes[] = $dossier; |
---|
652 | ecrire_meta('plugin_installes',serialize($meta_plug_installes), 'non'); |
---|
653 | //$messages = preg_replace('/<div.*(install-plugins).*<\/div>/','',ob_get_contents()); |
---|
654 | ob_end_clean(); |
---|
655 | return true; |
---|
656 | } |
---|
657 | ob_end_clean(); |
---|
658 | } |
---|
659 | return false; |
---|
660 | } |
---|
661 | |
---|
662 | |
---|
663 | |
---|
664 | // serait mieux dans inc/flock... |
---|
665 | // necessite PHP 5 |
---|
666 | // vient de http://www.php.net/manual/en/function.rmdir.php#92050 |
---|
667 | function deleteDirectory($dir) { |
---|
668 | if (!file_exists($dir)) return true; |
---|
669 | if (!is_dir($dir) || is_link($dir)) return unlink($dir); |
---|
670 | foreach (scandir($dir) as $item) { |
---|
671 | if ($item == '.' || $item == '..') continue; |
---|
672 | if (!$this->deleteDirectory($dir . "/" . $item)) { |
---|
673 | chmod($dir . "/" . $item, 0777); |
---|
674 | if (!$this->deleteDirectory($dir . "/" . $item)) return false; |
---|
675 | }; |
---|
676 | } |
---|
677 | return rmdir($dir); |
---|
678 | } |
---|
679 | |
---|
680 | |
---|
681 | // telecharge un paquet |
---|
682 | // et supprime les fichiers obsoletes (si presents) |
---|
683 | function get_paquet_id($id_or_row) { |
---|
684 | // on peut passer direct le row sql... |
---|
685 | if (!is_array($id_or_row)) { |
---|
686 | $i = sql_fetsel('*','spip_plugins','id_plugin='.sql_quote($id_or_row)); |
---|
687 | } else { |
---|
688 | $i = $id_or_row; |
---|
689 | } |
---|
690 | unset($id_or_row); |
---|
691 | |
---|
692 | if ($i['paquet']) { |
---|
693 | if ($adresse = sql_getfetsel('adresse','spip_zones_plugins','id_zone='.sql_quote($i['id_zone']))) { |
---|
694 | $adresse = dirname($adresse); |
---|
695 | $zip = $adresse . '/' . $i['paquet']; |
---|
696 | // on recupere la mise a jour... |
---|
697 | if ($files = $this->get_zip($zip, _DIR_PLUGINS_AUTO)) { |
---|
698 | $dest = $files[0]['stored_filename']; |
---|
699 | $dest = 'auto/' . rtrim($dest, '/'); |
---|
700 | $dir = _DIR_PLUGINS . $dest; |
---|
701 | |
---|
702 | // la c'est ennuyant : il faut supprimer les vieux fichiers... |
---|
703 | $this->log("Suppression des anciens fichiers de $dir"); |
---|
704 | $this->remove_older_files($dir, $files); |
---|
705 | |
---|
706 | return array( |
---|
707 | 'dir'=>$dir, |
---|
708 | 'dossier'=>$dest, |
---|
709 | ); |
---|
710 | } |
---|
711 | } |
---|
712 | } |
---|
713 | return false; |
---|
714 | } |
---|
715 | |
---|
716 | |
---|
717 | function get_zip($zip, $dir_dest) { |
---|
718 | |
---|
719 | # si premiere lecture, destination temporaire des fichiers |
---|
720 | $tmp = sous_repertoire(_DIR_CACHE, 'chargeur'); |
---|
721 | |
---|
722 | # $extract = sous_repertoire($tmp, 'extract'); |
---|
723 | $extract = $dir_dest; |
---|
724 | |
---|
725 | $fichier = $tmp . basename($zip); |
---|
726 | include_spip('inc/distant'); |
---|
727 | $contenu = recuperer_page($zip, $fichier, false, _COPIE_LOCALE_MAX_SIZE); |
---|
728 | if (!$contenu) { |
---|
729 | $this->log('Impossible de charger : '. $zip); |
---|
730 | return false; |
---|
731 | } |
---|
732 | |
---|
733 | include_spip('inc/pclzip'); |
---|
734 | $uzip = new PclZip($fichier); |
---|
735 | |
---|
736 | // On extrait, mais dans tmp/ |
---|
737 | $ok = $uzip->extract( |
---|
738 | PCLZIP_OPT_PATH, |
---|
739 | $extract, |
---|
740 | PCLZIP_OPT_SET_CHMOD, |
---|
741 | _SPIP_CHMOD, |
---|
742 | PCLZIP_OPT_REPLACE_NEWER |
---|
743 | ); |
---|
744 | |
---|
745 | if ($uzip->error_code < 0) { |
---|
746 | $this->log('Impossible de decompresser : '. $zip); |
---|
747 | $this->log('> erreur '. $uzip->error_code .' : ' . $uzip->errorName(true)); |
---|
748 | return false; |
---|
749 | } |
---|
750 | |
---|
751 | # spip_log($ok, 'ok'); |
---|
752 | # spip_log($uzip->listContent(), 'ok'); |
---|
753 | // ok contient toute la liste des fichiers installes :) |
---|
754 | // ainsi que leur localisation et quelques infos. |
---|
755 | // [0] est le nom du premier repertoire |
---|
756 | /* |
---|
757 | 0 => |
---|
758 | array ( |
---|
759 | 'filename' => '../plugins/auto/aa/', |
---|
760 | 'stored_filename' => 'aa/', |
---|
761 | 'size' => 0, |
---|
762 | 'compressed_size' => 0, |
---|
763 | 'mtime' => 1262386900, |
---|
764 | 'comment' => '', |
---|
765 | 'folder' => true, |
---|
766 | 'index' => 0, |
---|
767 | 'status' => 'ok', |
---|
768 | ), |
---|
769 | */ |
---|
770 | return $ok; |
---|
771 | } |
---|
772 | |
---|
773 | |
---|
774 | function remove_older_files($dir, $files = array()) { |
---|
775 | static $ok = false; |
---|
776 | if ($ok === false) { |
---|
777 | $ok = array(); |
---|
778 | foreach ($files as $f) { |
---|
779 | $ok[$f['filename']] = true; |
---|
780 | } |
---|
781 | } |
---|
782 | |
---|
783 | if (!file_exists($dir)) return true; |
---|
784 | if (!is_dir($dir) || is_link($dir)) { |
---|
785 | if (!isset($ok[$dir])) { |
---|
786 | $this->log('- supp :' . $dir); |
---|
787 | unlink($dir); |
---|
788 | } |
---|
789 | return true; |
---|
790 | } |
---|
791 | |
---|
792 | $dir = rtrim($dir, '/'); |
---|
793 | foreach (scandir($dir) as $item) { |
---|
794 | if ($item == '.' || $item == '..') continue; |
---|
795 | $this->remove_older_files($dir . "/" . $item); |
---|
796 | } |
---|
797 | |
---|
798 | return true; |
---|
799 | } |
---|
800 | |
---|
801 | } |
---|
802 | |
---|
803 | // scandir pour php4 |
---|
804 | // http://fr2.php.net/manual/fr/function.scandir.php#73062 |
---|
805 | if (!function_exists('scandir')) { |
---|
806 | function scandir($dir, $listDirectories=false, $skipDots=true) { |
---|
807 | $dirArray = array(); |
---|
808 | if ($handle = opendir($dir)) { |
---|
809 | while (false !== ($file = readdir($handle))) { |
---|
810 | if (($file != "." && $file != "..") || $skipDots == true) { |
---|
811 | if($listDirectories == false) { if(is_dir($file)) { continue; } } |
---|
812 | array_push($dirArray,basename($file)); |
---|
813 | } |
---|
814 | } |
---|
815 | closedir($handle); |
---|
816 | } |
---|
817 | return $dirArray; |
---|
818 | } |
---|
819 | } |
---|
820 | |
---|
821 | ?> |
---|