source: spip-zone/_plugins_/step/inc/step_actionneur.php @ 52860

Last change on this file since 52860 was 52860, checked in by kent1@…, 9 years ago

if (!defined("_ECRIRE_INC_VERSION")) return; sur tout fichier PHP pour sécurité future principalement

File size: 23.1 KB
Line 
1<?php
2
3if (!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
8class 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
805if (!function_exists('scandir')) {
806function 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?>
Note: See TracBrowser for help on using the repository browser.