X-Git-Url: http://git.cyclocoop.org/?a=blobdiff_plain;f=www%2Fplugins-dist%2Fsvp%2Finc%2Fsvp_actionner.php;fp=www%2Fplugins-dist%2Fsvp%2Finc%2Fsvp_actionner.php;h=07a0c148e55dd0f07cf4e81d0656443ad1a4ba1f;hb=4f443dce95ff6f8221c189880a70c74ce1c1f238;hp=cf4e7a63d91181f8119d070ba4c3e7046e1dbdfb;hpb=4a628e9b277d3617535f99d663ca79fa2e891177;p=lhc%2Fweb%2Fwww.git diff --git a/www/plugins-dist/svp/inc/svp_actionner.php b/www/plugins-dist/svp/inc/svp_actionner.php index cf4e7a63..07a0c148 100644 --- a/www/plugins-dist/svp/inc/svp_actionner.php +++ b/www/plugins-dist/svp/inc/svp_actionner.php @@ -1,14 +1,16 @@ type d'action */ - var $start = array(); + public $start = array(); /** * Actions en cours d'analyse @@ -47,14 +53,14 @@ class Actionneur { * * Chaque sous-tableau est composé d'une description courte du paquet * auquel est ajouté dans l'index 'todo' le type d'action à faire. - * + * * @var array * Index 'off' : les paquets à désactiver (ordre inverse des dépendances) * Index 'lib' : les librairies à installer * Index 'on' : les paquets à activer (ordre des dépendances) * Index 'neutre' : autres actions dont l'ordre a peu d'importance. */ - var $middle = array( + public $middle = array( 'off' => array(), 'lib' => array(), 'on' => array(), @@ -65,53 +71,61 @@ class Actionneur { /** * Liste des actions à faire - * + * * Liste de description courtes des paquets + index 'todo' indiquant l'action - * @var array */ - var $end = array(); + * + * @var array + */ + public $end = array(); /** * Liste des actions faites * Liste de description courtes des paquets + index 'todo' indiquant l'action - * @var array */ - var $done = array(); // faites + * + * @var array + */ + public $done = array(); // faites /** * Actions en cours * Description courte du paquet + index 'todo' indiquant l'action - * @var array */ - var $work = array(); + * + * @var array + */ + public $work = array(); /** * Liste des erreurs - * - * @var array Liste des erreurs */ - var $err = array(); + * + * @var array Liste des erreurs + */ + public $err = array(); /** * Verrou. * Le verrou est posé au moment de passer à l'action. + * * @var array * Index 'id_auteur' : Identifiant de l'auteur ayant déclenché des actions * Indix 'time' : timestamp de l'heure de déclenchement de l'action */ - var $lock = array('id_auteur'=>0, 'time'=>''); + public $lock = array('id_auteur' => 0, 'time' => ''); /** * SVP (ce plugin) est-il à désactiver dans une des actions ? * * Dans ce cas, on tente de le désactiver après d'autres plugins à désactiver * sinon l'ensemble des actions suivantes échoueraient. - * + * * @var bool * false si SVP n'est pas à désactiver, true sinon */ - var $svp_off = false; + public $svp_off = false; /** * Constructeur * * Détermine si les logs sont activés et instancie un décideur. */ - function Actionneur(){ + public function __construct() { include_spip('inc/config'); $this->log = (lire_config('svp/mode_log_verbeux') == 'oui'); @@ -131,23 +145,23 @@ class Actionneur { * * @param mixed $quoi * La chose à logguer (souvent un texte) - **/ - function log($quoi) { + **/ + public function log($quoi) { if ($this->log) { - spip_log($quoi,'actionneur'); + spip_log($quoi, 'actionneur'); } } /** * Ajoute une erreur - * + * * Ajoute une erreur à la liste des erreurs présentées au moment * de traiter les actions. * * @param string $erreur * Le texte de l'erreur - **/ - function err($erreur) { + **/ + public function err($erreur) { if ($erreur) { $this->err[] = $erreur; } @@ -156,7 +170,7 @@ class Actionneur { /** * Remet à zéro les tableaux d'actions */ - function clear() { + public function clear() { $this->middle = array( 'off' => array(), 'lib' => array(), @@ -169,14 +183,16 @@ class Actionneur { } /** - * Ajoute les actions à faire dans l'actionneur + * Ajoute les actions à faire dans l'actionneur * * @param array $todo * Tableau des actions à faire (identifiant de paquet => type d'action) - **/ - function ajouter_actions($todo) { - foreach ($todo as $id => $action) { - $this->start[$id] = $action; + **/ + public function ajouter_actions($todo) { + if ($todo) { + foreach ($todo as $id => $action) { + $this->start[$id] = $action; + } } $this->ordonner_actions(); } @@ -192,15 +208,15 @@ class Actionneur { * @param string $nom Nom de la librairie * @param string $source URL pour obtenir la librairie */ - function add_lib($nom, $source) { + public function add_lib($nom, $source) { if (!$this->decideur->est_presente_lib($nom)) { if (is_writable(_DIR_LIB)) { $this->middle['lib'][$nom] = array( - 'todo'=>'getlib', - 'n'=>$nom, - 'p'=>$nom, - 'v'=>$source, - 's'=>$source, + 'todo' => 'getlib', + 'n' => $nom, + 'p' => $nom, + 'v' => $source, + 's' => $source, ); } else { // erreur : impossible d'ecrire dans _DIR_LIB ! @@ -208,6 +224,7 @@ class Actionneur { return false; } } + return true; } @@ -231,13 +248,31 @@ class Actionneur { * - puis ce qui est a installer (à commencer par les librairies, puis paquets), * - puis les actions neutres */ - function ordonner_actions() { + public function ordonner_actions() { + $this->log("Ordonner les actions à réaliser"); // nettoyer le terrain $this->clear(); - foreach ($this->start as $id=>$action) { - $i = $this->decideur->infos_courtes_id($id); - $i = $i['i'][$id]; + // récupérer les descriptions de chaque paquet + $this->log("> Récupérer les descriptions des paquets concernés"); + $infos = array(); + foreach ($this->start as $id => $action) { + // seulement les identifiants de paquets (pas les librairies) + if (is_int($id)) { + $info = $this->decideur->infos_courtes_id($id); + $infos[$id] = $info['i'][$id]; + } + } + + // Calculer les dépendances (nécessite) profondes pour chaque paquet, + // si les plugins en questions sont parmis ceux actionnés + // (ie A dépend de B qui dépend de C => a dépend de B et C). + $infos = $this->calculer_necessites_complets($infos); + + foreach ($this->start as $id => $action) { + // infos du paquet. Ne s'applique pas sur librairie ($id = md5) + $i = is_int($id) ? $infos[$id] : array(); + switch ($action) { case 'getlib': // le plugin en ayant besoin le fera @@ -249,7 +284,7 @@ class Actionneur { break; case 'up': // si le plugin est actif - if ($i['a'] == 'oui') { + if ($i['a'] == 'oui') { $this->on($i, $action); } else { $this->neutre($i, $action); @@ -287,7 +322,7 @@ class Actionneur { } } } - + $this->log("------------"); #$this->log("Fin du tri :"); #$this->log($this->end); @@ -295,7 +330,110 @@ class Actionneur { /** - * Ajoute un paquet à activer + * Complète les infos des paquets actionnés pour qu'ils contiennent + * en plus de leurs 'necessite' directs, tous les nécessite des + * plugins dont ils dépendent, si ceux ci sont aussi actionnés. + * + * Ie: si A indique dépendre de B, et B de C, la clé + * 'dp' (dépendances prefixes). indiquera les préfixes + * des plugins B et C + * + * On ne s'occupe pas des versions de compatibilité ici + * + * @param array $infos (identifiant => description courte du plugin) + * @return array $infos + **/ + public function calculer_necessites_complets($infos) { + $this->log("> Calculer les dépendances nécessités sur paquets concernés"); + + // prefixe => array(prefixes) + $necessites = array(); + + // 1) déjà les préfixes directement nécessités + foreach ($infos as $i => $info) { + if (!empty($info['dn'])) { + # à remplacer par array_column($info['dn'], 'nom') un jour + $necessites[$info['p']] = array(); + foreach ($info['dn'] as $n) { + $necessites[$info['p']][] = $n['nom']; + } + } + // préparer la clé dp (dépendances préfixes) et 'dmp' (dépendent de moi) vide + $infos[$i]['dp'] = array(); + $infos[$i]['dmp'] = array(); + } + + if ($nb = count($necessites)) { + $this->log(">- $nb plugins ont des nécessités"); + // 2) ensuite leurs dépendances, récursivement + $necessites = $this->calculer_necessites_complets_rec($necessites); + + // 3) intégrer le résultat + foreach ($infos as $i => $info) { + if (!empty($necessites[$info['p']])) { + $infos[$i]['dp'] = $necessites[$info['p']]; + } + } + + // 4) calculer une clé 'dmp' : liste des paquets actionnés qui dépendent de moi + foreach ($infos as $i => $info) { + $dmp = array(); + foreach ($necessites as $prefixe => $liste) { + if (in_array($info['p'], $liste)) { + $dmp[] = $prefixe; + } + } + $infos[$i]['dmp'] = $dmp; + } + } + + # $this->log($infos); + + return $infos; + } + + /** + * Fonction récursive pour calculer la liste de tous les préfixes + * de plugins nécessités par un autre. + * + * Avec une liste fermée connue d'avance des possibilités de plugins + * (ceux qui seront actionnés) + * + * @param array prefixe => liste de prefixe dont il dépend + * @param bool $profondeur + * @return array prefixe => liste de prefixe dont il dépend + **/ + public function calculer_necessites_complets_rec($necessites, $profondeur = 0) { + $changement = false; + foreach ($necessites as $prefixe => $liste) { + $n = count($liste); + foreach ($liste as $prefixe_necessite) { + // si un des plugins dépendants fait partie des plugins actionnés, + // il faut aussi lui ajouter ses dépendances… + if (isset($necessites[$prefixe_necessite])) { + $liste = array_unique(array_merge($liste, $necessites[$prefixe_necessite])); + } + } + $necessites[$prefixe] = $liste; + if ($n !== count($liste)) { + $changement = true; + } + } + + // limiter à 10 les successions de dépendances ! + if ($changement and $profondeur <= 10) { + $necessites = $this->calculer_necessites_complets_rec($necessites, $profondeur++); + } + + if ($changement and $profondeur > 10) { + $this->log("! Problème de calcul de dépendances complètes : récursion probable. On stoppe."); + } + + return $necessites; + } + + /** + * Ajoute un paquet à activer * * À chaque fois qu'un nouveau paquet arrive ici, on le compare * avec ceux déjà présents pour savoir si on doit le traiter avant @@ -308,26 +446,31 @@ class Actionneur { * librairies seront téléchargées avant l'activation des plugins, * le plugin aura donc sa librairie lorsqu'il sera activé) * - * + * * @param array $info * Description du paquet * @param string $action * Action à réaliser (on, upon) * @return void - **/ - function on($info, $action) { + **/ + public function on($info, $action) { $info['todo'] = $action; $p = $info['p']; $this->log("ON: $p $action"); // si dependance, il faut le mettre avant ! - $in = $out = $deps = $deps_all = array(); + $in = $out = $prov = $deps = $deps_all = array(); // raz des cles pour avoir les memes que $out (utile reellement ?) $this->middle['on'] = array_values($this->middle['on']); - // ajout des dependance - foreach ($info['dn'] as $dep) { - $in[] = $dep['nom']; + // ajout des dependances + $in = $info['dp']; + // $info fourni ses procure + if (isset($info['procure']) and $info['procure']) { + $prov = array_keys($info['procure']); } + // et se fournit lui meme evidemment + array_unshift($prov, $p); + // ajout des librairies foreach ($info['dl'] as $lib) { // il faudrait gerer un retour d'erreur eventuel ! @@ -339,12 +482,18 @@ class Actionneur { // // ainsi que les dependences de ces plugins (deps) // ie. ces plugins peuvent dependre de ce nouveau a activer. - foreach ($this->middle['on'] as $inf) { - $out[] = $inf['p']; - foreach ($inf['dn'] as $dep) { - $deps[$inf['p']][] = $dep['nom']; - $deps_all[] = $dep['nom']; + foreach ($this->middle['on'] as $k => $inf) { + $out["$k:0"] = $inf['p']; + if (isset($inf['procure']) and $inf['procure']) { + $i = 1; + foreach ($inf['procure'] as $procure => $v) { + $out["$k:$i"] = $inf['p']; + $i++; + } } + + $deps[$inf['p']] = $inf['dp']; + $deps_all = array_merge($deps_all, $inf['dp']); } @@ -360,21 +509,30 @@ class Actionneur { // on place notre action juste apres la derniere dependance if ($diff = array_intersect($in, $out)) { $key = array(); - foreach($diff as $d) {$key[] = array_search($d, $out);} + foreach ($diff as $d) { + $k = array_search($d, $out); + $k = explode(":", $k); + $key[] = reset($k); + } $key = max($key); $this->log("- placer $p apres " . $this->middle['on'][$key]['p']); if ($key == count($this->middle['on'])) { $this->middle['on'][] = $info; } else { - array_splice($this->middle['on'], $key+1, 0, array($info)); + array_splice($this->middle['on'], $key + 1, 0, array($info)); } - // intersection = plugin dependant de celui-ci - // on place notre plugin juste avant la premiere dependance a lui trouvee - } elseif (in_array($p, $deps_all)) { - foreach ($deps as $prefix=>$dep) { - if (in_array($p, $dep)) { - $key = array_search($prefix, $out); + // intersection = plugin dependant de celui-ci + // on place notre plugin juste avant la premiere dependance a lui trouvee + } elseif (array_intersect($prov, $deps_all)) { + foreach ($deps as $prefix => $dep) { + if ($diff = array_intersect($prov, $deps_all)) { + foreach ($diff as $d) { + $k = array_search($d, $out); + $k = explode(":", $k); + $key[] = reset($k); + } + $key = min($key); $this->log("- placer $p avant $prefix qui en depend ($key)"); if ($key == 0) { array_unshift($this->middle['on'], $info); @@ -385,9 +543,9 @@ class Actionneur { } } - // rien de particulier, il a des dependances mais les plugins - // ne sont pas encore la ou les dependances sont deja actives - // donc on le place tout en bas + // rien de particulier, il a des dependances mais les plugins + // ne sont pas encore la ou les dependances sont deja actives + // donc on le place tout en bas } else { $this->log("- placer $p tout en bas"); $this->middle['on'][] = $info; @@ -398,18 +556,18 @@ class Actionneur { /** - * Ajoute un paquet avec une action neutre + * Ajoute un paquet avec une action neutre * * Ces actions seront traitées en dernier, et peu importe leur * ordre car elles n'entrent pas en conflit avec des dépendances. - * + * * @param array $info * Description du paquet * @param string $action * Action à réaliser (kill, get, up (sur plugin inactif)) * @return void - **/ - function neutre($info, $action) { + **/ + public function neutre($info, $action) { $info['todo'] = $action; $this->log("NEUTRE: $info[p] $action"); $this->middle['neutre'][] = $info; @@ -426,14 +584,14 @@ class Actionneur { * * Si le paquet est une dépendance d'un autre plugin, il faut le mettre * après (pour désactiver avant celui qui en dépend). - * + * * @param array $info * Description du paquet * @param string $action * Action à réaliser (kill, get, up (sur plugin inactif)) * @return void - **/ - function off($info, $action) { + **/ + public function off($info, $action) { $info['todo'] = $action; $p = $info['p']; $this->log("OFF: $p $action"); @@ -442,45 +600,89 @@ class Actionneur { if ($p == 'SVP') { $this->svp_off = true; } - + // si dependance, il faut le mettre avant ! $in = $out = array(); // raz des cles pour avoir les memes que $out (utile reellement ?) $this->middle['off'] = array_values($this->middle['off']); - foreach ($info['dn'] as $dep) { - $in[] = $dep['nom']; - } - foreach ($this->middle['off'] as $inf) { + // in : si un plugin en dépend, il faudra désactiver celui là avant. + $in = $info['dp']; + + foreach ($this->middle['off'] as $inf) { $out[] = $inf['p']; } - if (!$in) { + if (!$info['dn']) { // ce plugin n'a pas de dependance, on le met en dernier ! $this->log("- placer $p tout en bas"); $this->middle['off'][] = $info; } else { // ce plugin a des dependances, // on le desactive juste avant elles. - + // intersection = dependance presente aussi // on place notre action juste avant la premiere dependance if ($diff = array_intersect($in, $out)) { $key = array(); - foreach($diff as $d) {$key[] = array_search($d, $out);} + foreach ($diff as $d) { + $key[] = array_search($d, $out); + } $key = min($key); $this->log("- placer $p avant " . $this->middle['off'][$key]['p']); array_splice($this->middle['off'], $key, 0, array($info)); + // inversement des plugins dépendants de ce plugin sont présents… + // on le met juste après le dernier + } elseif ($diff = array_intersect($info['dmp'], $out)) { + $key = array(); + foreach ($diff as $d) { + $key[] = array_search($d, $out); + } + $key = max($key); + $this->log("- placer $p apres " . $this->middle['off'][$key]['p']); + if ($key == count($this->middle['off'])) { + $this->middle['off'][] = $info; + } else { + array_splice($this->middle['off'], $key + 1, 0, array($info)); + } } else { // aucune des dependances n'est a desactiver // (du moins à ce tour ci), // on le met en premier ! $this->log("- placer $p tout en haut"); - array_unshift($this->middle['off'], $info); // etait ->middle['on'] ?? ... + array_unshift($this->middle['off'], $info); } } unset($diff, $in, $out); } + /** + * Retourne le texte qui présente la dernière action qui vient d'être réalisée + * + * @return string + **/ + public function presenter_derniere_action() { + $i = end($this->done); + reset($this->done); + $texte = ''; + if ($i) { + $ok = ($i['done'] ? true : false); + $oks = &$ok; + $ok_texte = $ok ? 'ok' : 'fail'; + $cle_t = 'svp:message_action_finale_' . $i['todo'] . '_' . $ok_texte; + $trads = array( + 'plugin' => $i['n'], + 'version' => denormaliser_version($i['v']), + ); + if (isset($i['maj'])) { + $trads['version_maj'] = denormaliser_version($i['maj']); + } + $texte = _T($cle_t, $trads); + if (is_string($i['done'])) { + $texte .= " $i[done]"; + } + } + return $texte; + } /** * Retourne un bilan, texte HTML, des actions qui ont été faites @@ -488,23 +690,23 @@ class Actionneur { * Si c'est un affichage du bilan de fin, et qu'il reste des actions * à faire, un lien est proposé pour faire supprimer ces actions restantes * et le verrou qui va avec. - * + * * @param bool $fin * Est-ce un affichage intermédiaire (false) ou le tout dernier (true). * @return string * Bilan des actions au format HTML - **/ - function presenter_actions($fin = false) { + **/ + public function presenter_actions($fin = false) { $affiche = ""; include_spip('inc/filtres_boites'); - + if (count($this->err)) { $erreurs = ""; + $erreurs .= ""; $affiche .= boite_ouvrir(_T('svp:actions_en_erreur'), 'error') . $erreurs . boite_fermer(); } @@ -516,14 +718,33 @@ class Actionneur { $oks = &$ok; $ok_texte = $ok ? 'ok' : 'fail'; $cle_t = 'svp:message_action_finale_' . $i['todo'] . '_' . $ok_texte; - $texte = _T($cle_t, array( + $trads = array( 'plugin' => $i['n'], 'version' => denormaliser_version($i['v']), - 'version_maj' => denormaliser_version($i['maj']))); + ); + if (isset($i['maj'])) { + $trads['version_maj'] = denormaliser_version($i['maj']); + } + $texte = _T($cle_t, $trads); if (is_string($i['done'])) { $texte .= " $i[done]"; } - $done .= "\t
  • $texte
  • \n"; + // si le plugin a ete active dans le meme lot, on remplace le message 'active' par le message 'installe' + if ($i['todo'] == 'install' and $ok_texte == 'ok') { + $cle_t = 'svp:message_action_finale_' . 'on' . '_' . $ok_texte; + $texte_on = _T($cle_t, array( + 'plugin' => $i['n'], + 'version' => denormaliser_version($i['v']), + 'version_maj' => denormaliser_version($i['maj']) + )); + if (strpos($done, $texte_on) !== false) { + $done = str_replace($texte_on, $texte, $done); + $texte = ""; + } + } + if ($texte) { + $done .= "\t
  • $texte
  • \n"; + } } $done .= ""; $affiche .= boite_ouvrir(_T('svp:actions_realises'), ($oks ? 'success' : 'notice')) . $done . boite_fermer(); @@ -532,10 +753,11 @@ class Actionneur { if (count($this->end)) { $todo = "\n"; $titre = ($fin ? _T('svp:actions_non_traitees') : _T('svp:actions_a_faire')); @@ -554,10 +776,11 @@ class Actionneur { $date = date('Y-m-d H:i:s', $time); $todo .= "
    \n"; $todo .= "

    " . _T('svp:erreur_actions_non_traitees', array( - 'auteur' => sql_getfetsel('nom', 'spip_auteurs', 'id_auteur=' . sql_quote($this->lock['id_auteur'])), - 'date' => affdate_heure($date) - )) . "

    \n"; - $todo .= "" . _T('svp:nettoyer_actions') . "\n"; + 'auteur' => sql_getfetsel('nom', 'spip_auteurs', 'id_auteur=' . sql_quote($this->lock['id_auteur'])), + 'date' => affdate_heure($date) + )) . "

    \n"; + $todo .= "" . _T('svp:nettoyer_actions') . "\n"; } $affiche .= boite_ouvrir($titre, 'notice') . $todo . boite_fermer(); } @@ -566,27 +789,39 @@ class Actionneur { include_spip('inc/filtres'); $affiche = wrap($affiche, "
    "); } - + return $affiche; } + /** + * Retourne le pourcentage de progression des actions + * @return int|float + */ + public function progression() { + if (count($this->done)) { + return count($this->done) / (count($this->done) + count($this->end)); + } + return 0; + } + /** * Teste l'existance d'un verrou par un auteur ? * * Si un id_auteur est transmis, teste que c'est cet auteur * précis qui a posé le verrou. * - * @see Actionneur::verouiller() - * + * @see Actionneur::verrouiller() + * * @param int|string $id_auteur * Identifiant de l'auteur, ou vide * @return bool * true si un verrou est là, false sinon - **/ - function est_verrouille($id_auteur = '') { + **/ + public function est_verrouille($id_auteur = '') { if ($id_auteur == '') { return ($this->lock['id_auteur'] ? true : false); } + return ($this->lock['id_auteur'] == $id_auteur); } @@ -601,10 +836,10 @@ class Actionneur { * Le verrou est signé par l'id_auteur de l'auteur actuellement identifié. * * Le verrou sera sauvegardé en fichier avec la liste des actions - * + * * @see Actionneur::sauver_actions() - **/ - function verrouiller() { + **/ + public function verrouiller() { $this->lock = array( 'id_auteur' => $GLOBALS['visiteur_session']['id_auteur'], 'time' => time(), @@ -613,8 +848,8 @@ class Actionneur { /** * Enlève le verrou - **/ - function deverrouiller() { + **/ + public function deverrouiller() { $this->lock = array( 'id_auteur' => 0, 'time' => '', @@ -629,15 +864,15 @@ class Actionneur { * les erreurs générées, et le verrouillage. * * Le cache peut être lu avec la méthode get_actions() - * + * * @see Actionneur::get_actions() - **/ - function sauver_actions() { + **/ + public function sauver_actions() { $contenu = serialize(array( 'todo' => $this->end, 'done' => $this->done, 'work' => $this->work, - 'err' => $this->err, + 'err' => $this->err, 'lock' => $this->lock, )); ecrire_fichier(_DIR_TMP . 'stp_actions.txt', $contenu); @@ -648,16 +883,16 @@ class Actionneur { * * Restaure les informations contenues dans le fichier de cache * et écrites avec la méthode sauver_actions(). - * + * * @see Actionneur::sauver_actions() - **/ - function get_actions() { + **/ + public function get_actions() { lire_fichier(_DIR_TMP . 'stp_actions.txt', $contenu); $infos = unserialize($contenu); - $this->end = $infos['todo']; + $this->end = $infos['todo']; $this->work = $infos['work']; $this->done = $infos['done']; - $this->err = $infos['err']; + $this->err = $infos['err']; $this->lock = $infos['lock']; } @@ -665,12 +900,12 @@ class Actionneur { * Nettoyage des actions et verrou * * Remet tout à zéro pour pouvoir repartir d'un bon pied. - **/ - function nettoyer_actions() { + **/ + public function nettoyer_actions() { $this->todo = array(); $this->done = array(); $this->work = array(); - $this->err = array(); + $this->err = array(); $this->deverrouiller(); $this->sauver_actions(); } @@ -685,12 +920,12 @@ class Actionneur { * @return bool|array * False si aucune action à faire, * sinon tableau de description courte du paquet + index 'todo' indiquant l'action - **/ - function one_action() { + **/ + public function one_action() { // s'il reste des actions, on en prend une, et on la fait // de meme si une action est en cours mais pas terminee (timeout) // on tente de la refaire... - if (count($this->end) OR $this->work) { + if (count($this->end) or $this->work) { // on verrouille avec l'auteur en cours pour // que seul lui puisse effectuer des actions a ce moment la if (!$this->est_verrouille()) { @@ -718,6 +953,7 @@ class Actionneur { $this->deverrouiller(); $this->sauver_actions(); } + return $action; } else { // on ne devrait normalement plus tomber sur un cas de verrouillage ici @@ -727,6 +963,7 @@ class Actionneur { $this->sauver_actions(); } } + return false; } @@ -739,8 +976,8 @@ class Actionneur { * Place dans la clé 'done' de description courte du paquet * le résultat de l'action (un booléen indiquant si elle s'est bien * déroulée). - **/ - function do_action() { + **/ + public function do_action() { if ($do = $this->work) { $todo = 'do_' . $do['todo']; lire_metas(); // avoir les metas a jour @@ -761,17 +998,19 @@ class Actionneur { * @return bool * false si erreur, true sinon. */ - function do_geton($info) { + public function do_geton($info) { if (!$this->tester_repertoire_plugins_auto()) { return false; } - $i = sql_fetsel('*','spip_paquets','id_paquet='.sql_quote($info['i'])); + $i = sql_fetsel('*', 'spip_paquets', 'id_paquet=' . sql_quote($info['i'])); if ($dirs = $this->get_paquet_id($i)) { $this->activer_plugin_dossier($dirs['dossier'], $i); + return true; } - - $this->log("GetOn : Erreur de chargement du paquet " .$info['n']); + + $this->log("GetOn : Erreur de chargement du paquet " . $info['n']); + return false; } @@ -785,21 +1024,22 @@ class Actionneur { * @return bool * false si erreur, true sinon. */ - function do_on($info) { - $i = sql_fetsel('*','spip_paquets','id_paquet='.sql_quote($info['i'])); + public function do_on($info) { + $i = sql_fetsel('*', 'spip_paquets', 'id_paquet=' . sql_quote($info['i'])); // à télécharger ? - if ($i['id_zone'] > 0) { + if (isset($i['id_zone']) and $i['id_zone'] > 0) { return $this->do_geton($info); } - + // a activer uniquement // il faudra prendre en compte les autres _DIR_xx - if (in_array($i['constante'], array('_DIR_PLUGINS','_DIR_PLUGINS_SUPPL'))) { + if (in_array($i['constante'], array('_DIR_PLUGINS', '_DIR_PLUGINS_SUPPL'))) { $dossier = rtrim($i['src_archive'], '/'); $this->activer_plugin_dossier($dossier, $i, $i['constante']); + return true; } - + return false; } @@ -813,7 +1053,7 @@ class Actionneur { * false si erreur, * description courte du nouveau plugin sinon. */ - function do_up($info) { + public function do_up($info) { // ecriture du nouveau // suppression de l'ancien (si dans auto, et pas au meme endroit) // OU suppression des anciens fichiers @@ -823,21 +1063,29 @@ class Actionneur { // $i est le paquet a mettre à jour (donc present) // $maj est le paquet a telecharger qui est a jour (donc distant) - - $i = sql_fetsel('*','spip_paquets','id_paquet='.sql_quote($info['i'])); + + $i = sql_fetsel('*', 'spip_paquets', 'id_paquet=' . sql_quote($info['i'])); // on cherche la mise a jour... // c'est a dire le paquet source que l'on met a jour. if ($maj = sql_fetsel('pa.*', array('spip_paquets AS pa', 'spip_plugins AS pl'), array( - 'pl.prefixe='.sql_quote($info['p']), - 'pa.version='.sql_quote($info['maj']), - 'pa.id_plugin = pl.id_plugin', - 'pa.id_depot>'.sql_quote(0)), - '', 'pa.etatnum DESC', '0,1')) { + 'pl.prefixe=' . sql_quote($info['p']), + 'pa.version=' . sql_quote($info['maj']), + 'pa.id_plugin = pl.id_plugin', + 'pa.id_depot>' . sql_quote(0) + ), + '', 'pa.etatnum DESC', '0,1') + ) { + + // si dans auto, on autorise à mettre à jour depuis auto pour les VCS + $dir_actuel_dans_auto = ''; + if (substr($i['src_archive'], 0, 5) == 'auto/') { + $dir_actuel_dans_auto = substr($i['src_archive'], 5); + } - if ($dirs = $this->get_paquet_id($maj)) { + if ($dirs = $this->get_paquet_id($maj, $dir_actuel_dans_auto)) { // Si le plugin a jour n'est pas dans le meme dossier que l'ancien... // il faut : // - activer le plugin sur son nouvel emplacement (uniquement si l'ancien est actif)... @@ -851,16 +1099,18 @@ class Actionneur { // alors que le nouveau est auto/X/Y ... // il faut prendre en compte ce cas particulier et ne pas ecraser auto/X ! if (substr($i['src_archive'], 0, 5) == 'auto/' and (false === strpos($dirs['dossier'], $i['src_archive']))) { - if (supprimer_repertoire( constant($i['constante']) . $i['src_archive']) ) { + if (supprimer_repertoire(constant($i['constante']) . $i['src_archive'])) { sql_delete('spip_paquets', 'id_paquet=' . sql_quote($info['i'])); } } } $this->ajouter_plugin_interessants_meta($dirs['dossier']); + return $dirs; } } + return false; } @@ -873,12 +1123,14 @@ class Actionneur { * @return bool * false si erreur, true sinon */ - function do_upon($info) { - $i = sql_fetsel('*', 'spip_paquets', 'id_paquet='.sql_quote($info['i'])); + public function do_upon($info) { + $i = sql_fetsel('*', 'spip_paquets', 'id_paquet=' . sql_quote($info['i'])); if ($dirs = $this->do_up($info)) { $this->activer_plugin_dossier($dirs['dossier'], $i, $i['constante']); + return true; } + return false; } @@ -891,20 +1143,21 @@ class Actionneur { * @return bool * false si erreur, true sinon */ - function do_off($info) { - $i = sql_fetsel('*','spip_paquets','id_paquet='.sql_quote($info['i'])); + public function do_off($info) { + $i = sql_fetsel('*', 'spip_paquets', 'id_paquet=' . sql_quote($info['i'])); // il faudra prendre en compte les autres _DIR_xx - if (in_array($i['constante'], array('_DIR_PLUGINS','_DIR_PLUGINS_SUPPL'))) { + if (in_array($i['constante'], array('_DIR_PLUGINS', '_DIR_PLUGINS_SUPPL'))) { include_spip('inc/plugin'); $dossier = rtrim($i['src_archive'], '/'); - ecrire_plugin_actifs(array(rtrim($dossier,'/')), false, 'enleve'); - sql_updateq('spip_paquets', array('actif'=>'non', 'installe'=>'non'), 'id_paquet='.sql_quote($info['i'])); + ecrire_plugin_actifs(array(rtrim($dossier, '/')), false, 'enleve'); + sql_updateq('spip_paquets', array('actif' => 'non', 'installe' => 'non'), 'id_paquet=' . sql_quote($info['i'])); $this->actualiser_plugin_interessants(); // ce retour est un rien faux... // il faudrait que la fonction ecrire_plugin_actifs() // retourne au moins d'eventuels message d'erreur ! return true; } + return false; } @@ -917,23 +1170,24 @@ class Actionneur { * @return bool * false si erreur, true sinon */ - function do_stop($info) { - $i = sql_fetsel('*','spip_paquets','id_paquet=' . sql_quote($info['i'])); + public function do_stop($info) { + $i = sql_fetsel('*', 'spip_paquets', 'id_paquet=' . sql_quote($info['i'])); // il faudra prendre en compte les autres _DIR_xx - if (in_array($i['constante'], array('_DIR_PLUGINS','_DIR_PLUGINS_SUPPL'))) { + if (in_array($i['constante'], array('_DIR_PLUGINS', '_DIR_PLUGINS_SUPPL'))) { include_spip('inc/plugin'); - $dossier = rtrim($i['src_archive'],'/'); + $dossier = rtrim($i['src_archive'], '/'); $installer_plugins = charger_fonction('installer', 'plugins'); // retourne : // - false : pas de procedure d'install/desinstalle // - true : operation deja faite // - tableau : operation faite ce tour ci. - $infos = $installer_plugins($dossier, 'uninstall'); - if (is_bool($infos) OR !$infos['install_test'][0]) { + $infos = $installer_plugins($dossier, 'uninstall', $i['constante']); + if (is_bool($infos) or !$infos['install_test'][0]) { include_spip('inc/plugin'); ecrire_plugin_actifs(array($dossier), false, 'enleve'); - sql_updateq('spip_paquets', array('actif'=>'non', 'installe'=>'non'), 'id_paquet='.sql_quote($info['i'])); + sql_updateq('spip_paquets', array('actif' => 'non', 'installe' => 'non'), 'id_paquet=' . sql_quote($info['i'])); + return true; } else { // echec @@ -941,6 +1195,7 @@ class Actionneur { } } $this->actualiser_plugin_interessants(); + return false; } @@ -953,15 +1208,16 @@ class Actionneur { * @return bool * false si erreur, true sinon */ - function do_kill($info) { + public function do_kill($info) { // on reverifie que c'est bien un plugin auto ! // il faudrait aussi faire tres attention sur un site mutualise // cette option est encore plus delicate que les autres... - $i = sql_fetsel('*','spip_paquets','id_paquet='.sql_quote($info['i'])); + $i = sql_fetsel('*', 'spip_paquets', 'id_paquet=' . sql_quote($info['i'])); + + if (in_array($i['constante'], array('_DIR_PLUGINS', '_DIR_PLUGINS_SUPPL')) + and substr($i['src_archive'], 0, 5) == 'auto/' + ) { - if (in_array($i['constante'], array('_DIR_PLUGINS','_DIR_PLUGINS_SUPPL')) - and substr($i['src_archive'], 0, 5) == 'auto/') { - $dir = constant($i['constante']) . $i['src_archive']; if (supprimer_repertoire($dir)) { $id_plugin = sql_getfetsel('id_plugin', 'spip_paquets', 'id_paquet=' . sql_quote($info['i'])); @@ -1010,6 +1266,7 @@ class Actionneur { } array_pop($chemins); } + return true; } } @@ -1026,24 +1283,27 @@ class Actionneur { * @return bool * false si erreur, true sinon */ - function do_getlib($info) { + public function do_getlib($info) { if (!defined('_DIR_LIB') or !_DIR_LIB) { $this->err(_T('svp:erreur_dir_dib_indefini')); $this->log("/!\ Pas de _DIR_LIB defini !"); + return false; } if (!is_writable(_DIR_LIB)) { - $this->err(_T('svp:erreur_dir_dib_ecriture', array('dir' => _DIR_LIB ))); + $this->err(_T('svp:erreur_dir_dib_ecriture', array('dir' => _DIR_LIB))); $this->log("/!\ Ne peut pas écrire dans _DIR_LIB !"); + return false; } - if(!autoriser('plugins_ajouter')){ + if (!autoriser('plugins_ajouter')) { $this->err(_T('svp:erreur_auth_plugins_ajouter_lib')); $this->log("/!\ Pas autorisé à ajouter des libs !"); + return false; } - $this->log("Recuperer la librairie : " . $info['n'] ); + $this->log("Recuperer la librairie : " . $info['n']); // on recupere la mise a jour... include_spip('action/teleporter'); @@ -1052,9 +1312,10 @@ class Actionneur { if ($ok === true) { return true; } - + $this->err($ok); $this->log("Téléporteur en erreur : " . $ok); + return false; } @@ -1067,15 +1328,16 @@ class Actionneur { * @return bool * false si erreur, true sinon */ - function do_get($info) { + public function do_get($info) { if (!$this->tester_repertoire_plugins_auto()) { return false; } $i = sql_fetsel('*', 'spip_paquets', 'id_paquet=' . sql_quote($info['i'])); - + if ($dirs = $this->get_paquet_id($info['i'])) { $this->ajouter_plugin_interessants_meta($dirs['dossier']); + return true; } @@ -1091,13 +1353,13 @@ class Actionneur { * @return bool * false si erreur, true sinon */ - function do_install($info) { + public function do_install($info) { return $this->installer_plugin($info); } /** - * Activer un plugin + * Activer un plugin * * @param string $dossier * Chemin du répertoire du plugin @@ -1106,32 +1368,39 @@ class Actionneur { * @param string $constante * Constante indiquant le chemin de base du plugin (_DIR_PLUGINS, _DIR_PLUGINS_SUPPL, _DIR_PLUGINS_DIST) * @return void - **/ - function activer_plugin_dossier($dossier, $i, $constante='_DIR_PLUGINS') { + **/ + public function activer_plugin_dossier($dossier, $i, $constante = '_DIR_PLUGINS') { include_spip('inc/plugin'); $this->log("Demande d'activation de : " . $dossier); - + //il faut absolument que tous les fichiers de cache // soient inclus avant modification, sinon un appel ulterieur risquerait // de charger des fichiers deja charges par un autre ! // C'est surtout le ficher de fonction le probleme (options et pipelines // sont normalement deja charges). - if (@is_readable(_CACHE_PLUGINS_OPT)) {include_once(_CACHE_PLUGINS_OPT);} - if (@is_readable(_CACHE_PLUGINS_FCT)) {include_once(_CACHE_PLUGINS_FCT);} - if (@is_readable(_CACHE_PIPELINES)) {include_once(_CACHE_PIPELINES);} + if (@is_readable(_CACHE_PLUGINS_OPT)) { + include_once(_CACHE_PLUGINS_OPT); + } + if (@is_readable(_CACHE_PLUGINS_FCT)) { + include_once(_CACHE_PLUGINS_FCT); + } + if (@is_readable(_CACHE_PIPELINES)) { + include_once(_CACHE_PIPELINES); + } include_spip('inc/plugin'); ecrire_plugin_actifs(array($dossier), false, 'ajoute'); $installe = $i['version_base'] ? 'oui' : 'non'; if ($installe == 'oui') { - if(!$i['constante']) + if (!$i['constante']) { $i['constante'] = '_DIR_PLUGINS'; + } // installer le plugin au prochain tour $new_action = array_merge($this->work, array( - 'todo'=>'install', - 'dossier'=>rtrim($dossier,'/'), - 'constante'=>$i['constante'], - 'v'=>$i['version'], // pas forcement la meme version qu'avant lors d'une mise a jour. + 'todo' => 'install', + 'dossier' => rtrim($dossier, '/'), + 'constante' => $i['constante'], + 'v' => $i['version'], // pas forcement la meme version qu'avant lors d'une mise a jour. )); array_unshift($this->end, $new_action); $this->log("Demande d'installation de $dossier"); @@ -1149,10 +1418,10 @@ class Actionneur { * Décrémente chaque score de plugin présent dans la méta * 'plugins_interessants' et signifiant que ces plugins * ont été utilisés récemment. - * + * * Les plugins atteignant un score de zéro sont évacués ce la liste. */ - function actualiser_plugin_interessants() { + public function actualiser_plugin_interessants() { // Chaque fois que l'on valide des plugins, // on memorise la liste de ces plugins comme etant "interessants", // avec un score initial, qui sera decremente a chaque tour : @@ -1162,33 +1431,33 @@ class Actionneur { if (!is_array($plugins_interessants)) { $plugins_interessants = array(); } - + $dossiers = array(); $dossiers_old = array(); - foreach($plugins_interessants as $p => $score) { + foreach ($plugins_interessants as $p => $score) { if (--$score > 0) { $plugins_interessants[$p] = $score; - $dossiers[$p.'/'] = true; + $dossiers[$p . '/'] = true; } else { unset($plugins_interessants[$p]); - $dossiers_old[$p.'/'] = true; + $dossiers_old[$p . '/'] = true; } } // enlever les anciens if ($dossiers_old) { // ATTENTION, il faudra prendre en compte les _DIR_xx - sql_updateq('spip_paquets', array('recent'=>0), sql_in('src_archive', array_keys($dossiers_old))); + sql_updateq('spip_paquets', array('recent' => 0), sql_in('src_archive', array_keys($dossiers_old))); } - $plugs = sql_allfetsel('src_archive','spip_paquets', 'actif='.sql_quote('oui')); + $plugs = sql_allfetsel('src_archive', 'spip_paquets', 'actif=' . sql_quote('oui')); $plugs = array_map('array_shift', $plugs); foreach ($plugs as $dossier) { $dossiers[$dossier] = true; - $plugins_interessants[ rtrim($dossier, '/') ] = 30; // score initial + $plugins_interessants[rtrim($dossier, '/')] = 30; // score initial } - $plugs = sql_updateq('spip_paquets', array('recent'=>1), sql_in('src_archive', array_keys($dossiers))); + $plugs = sql_updateq('spip_paquets', array('recent' => 1), sql_in('src_archive', array_keys($dossiers))); ecrire_meta('plugins_interessants', serialize($plugins_interessants)); } @@ -1202,7 +1471,7 @@ class Actionneur { * @param string $dir * Chemin du répertoire du plugin */ - function ajouter_plugin_interessants_meta($dir) { + public function ajouter_plugin_interessants_meta($dir) { $plugins_interessants = @unserialize($GLOBALS['meta']['plugins_interessants']); if (!is_array($plugins_interessants)) { $plugins_interessants = array(); @@ -1219,25 +1488,25 @@ class Actionneur { * @return bool * false si erreur, true sinon */ - function installer_plugin($info){ + public function installer_plugin($info) { // il faut info['dossier'] et info['constante'] pour installer if ($plug = $info['dossier']) { $installer_plugins = charger_fonction('installer', 'plugins'); $infos = $installer_plugins($plug, 'install', $info['constante']); if ($infos) { // en absence d'erreur, on met a jour la liste des plugins installes... - if (!is_array($infos) OR $infos['install_test'][0]) { + if (!is_array($infos) or $infos['install_test'][0]) { $meta_plug_installes = @unserialize($GLOBALS['meta']['plugin_installes']); if (!$meta_plug_installes) { - $meta_plug_installes=array(); + $meta_plug_installes = array(); } $meta_plug_installes[] = $plug; - ecrire_meta('plugin_installes',serialize($meta_plug_installes),'non'); + ecrire_meta('plugin_installes', serialize($meta_plug_installes), 'non'); } if (!is_array($infos)) { // l'installation avait deja ete faite un autre jour - return true; + return true; } else { // l'installation est neuve list($ok, $trace) = $infos['install_test']; @@ -1246,40 +1515,47 @@ class Actionneur { } // l'installation est en erreur $this->err(_T('svp:message_action_finale_install_fail', - array('plugin' => $info['n'], 'version'=>denormaliser_version($info['v']))) . "
    " . $trace); + array('plugin' => $info['n'], 'version' => denormaliser_version($info['v']))) . "
    " . $trace); } } } + return false; } /** * Télécharge un paquet - * + * * Supprime les fichiers obsolètes (si présents) * * @param int|array $id_or_row * Identifiant du paquet ou description ligne SQL du paquet + * @param string $dest_ancien + * Chemin vers l'ancien répertoire (pour les mises à jour par VCS) * @return bool|array * False si erreur. * Tableau de 2 index sinon : * - dir : Chemin du paquet téléchargé depuis la racine * - dossier : Chemin du paquet téléchargé, depuis _DIR_PLUGINS */ - function get_paquet_id($id_or_row) { + public function get_paquet_id($id_or_row, $dest_ancien = "") { // on peut passer direct le row sql... if (!is_array($id_or_row)) { - $i = sql_fetsel('*','spip_paquets','id_paquet='.sql_quote($id_or_row)); + $i = sql_fetsel('*', 'spip_paquets', 'id_paquet=' . sql_quote($id_or_row)); } else { $i = $id_or_row; } unset($id_or_row); if ($i['nom_archive'] and $i['id_depot']) { - $this->log("Recuperer l'archive : " . $i['nom_archive'] ); - if ($adresse = sql_getfetsel('url_archives', 'spip_depots', 'id_depot='.sql_quote($i['id_depot']))) { - $zip = $adresse . '/' . $i['nom_archive']; + $this->log("Recuperer l'archive : " . $i['nom_archive']); + // on récupère les informations intéressantes du dépot : + // - url des archives + // - éventuellement : type de serveur (svn, git) et url de la racine serveur (svn://..../) + $adresses = sql_fetsel(array('url_archives', 'type', 'url_serveur'), 'spip_depots', + 'id_depot=' . sql_quote($i['id_depot'])); + if ($adresses and $adresse = $adresses['url_archives']) { // destination : auto/prefixe/version (sinon auto/nom_archive/version) $prefixe = sql_getfetsel('pl.prefixe', @@ -1287,51 +1563,48 @@ class Actionneur { array('pa.id_plugin = pl.id_plugin', 'pa.id_paquet=' . sql_quote($i['id_paquet']))); // prefixe - $base = ($prefixe ? strtolower($prefixe) : substr($i['nom_archive'], 0, -4) ); // enlever .zip ... + $base = ($prefixe ? strtolower($prefixe) : substr($i['nom_archive'], 0, -4)); // enlever .zip ... // prefixe/version - $dest = $base . '/v' . denormaliser_version($i['version']); - - // si on tombe sur un auto/X ayant des fichiers (et pas uniquement des dossiers) - // ou un dossier qui ne commence pas par 'v' - // c'est que auto/X n'était pas chargé avec SVP - // ce qui peut arriver lorsqu'on migre de SPIP 2.1 à 3.0 - // dans ce cas, on supprime auto X pour mettre notre nouveau paquet. - $ecraser_base = false; - if (is_dir(_DIR_PLUGINS_AUTO . $base)) { - $base_files = scandir(_DIR_PLUGINS_AUTO . $base); - if (is_array($base_files)) { - $base_files = array_diff($base_files, array('.', '..')); - foreach ($base_files as $f) { - if (($f[0] != '.' and $f[0] != 'v') // commence pas par v - OR ($f[0] != '.' and !is_dir(_DIR_PLUGINS_AUTO . $base . '/' . $f))) { // commence par v mais pas repertoire - $ecraser_base = true; - break; - } - } - } - } - if ($ecraser_base) { + $dest_future = $base . '/v' . denormaliser_version($i['version']); + + // Nettoyer les vieux formats dans auto/ + if ($this->tester_repertoire_destination_ancien_format(_DIR_PLUGINS_AUTO . $base)) { supprimer_repertoire(_DIR_PLUGINS_AUTO . $base); } + // l'url est différente en fonction du téléporteur + $teleporteur = $this->choisir_teleporteur($adresses['type']); + if ($teleporteur == 'http') { + $url = $adresse . '/' . $i['nom_archive']; + $dest = $dest_future; + } else { + $url = $adresses['url_serveur'] . '/' . $i['src_archive']; + $dest = $dest_ancien ? $dest_ancien : $dest_future; + } // on recupere la mise a jour... include_spip('action/teleporter'); $teleporter_composant = charger_fonction('teleporter_composant', 'action'); - $ok = $teleporter_composant('http', $zip, _DIR_PLUGINS_AUTO . $dest); + $ok = $teleporter_composant($teleporteur, $url, _DIR_PLUGINS_AUTO . $dest); if ($ok === true) { + // pour une mise à jour via VCS, il faut rebasculer sur le nouveau nom de repertoire + if ($dest != $dest_future) { + rename(_DIR_PLUGINS_AUTO . $dest, _DIR_PLUGINS_AUTO . $dest_future); + } + return array( - 'dir'=> _DIR_PLUGINS_AUTO . $dest, + 'dir' => _DIR_PLUGINS_AUTO . $dest, 'dossier' => 'auto/' . $dest, // c'est depuis _DIR_PLUGINS ... pas bien en dur... ); } $this->err($ok); $this->log("Téléporteur en erreur : " . $ok); } else { - $this->log("Aucune adresse pour le dépot " . $i['id_depot'] ); + $this->log("Aucune adresse pour le dépot " . $i['id_depot']); } } + return false; } @@ -1342,46 +1615,115 @@ class Actionneur { * * @return bool * True si on peut écrire dedans, false sinon - **/ - function tester_repertoire_plugins_auto() { + **/ + public function tester_repertoire_plugins_auto() { include_spip('inc/plugin'); // pour _DIR_PLUGINS_AUTO if (!defined('_DIR_PLUGINS_AUTO') or !_DIR_PLUGINS_AUTO) { $this->err(_T('svp:erreur_dir_plugins_auto_indefini')); $this->log("/!\ Pas de _DIR_PLUGINS_AUTO defini !"); + return false; } if (!is_writable(_DIR_PLUGINS_AUTO)) { - $this->err(_T('svp:erreur_dir_plugins_auto_ecriture', array('dir'=>_DIR_PLUGINS_AUTO))); + $this->err(_T('svp:erreur_dir_plugins_auto_ecriture', array('dir' => _DIR_PLUGINS_AUTO))); $this->log("/!\ Ne peut pas écrire dans _DIR_PLUGINS_AUTO !"); + return false; } + return true; } + /** + * Teste si un répertoire du plugin auto, contenant un plugin + * est dans un ancien format auto/prefixe/ (qui doit alors être supprimé) + * ou dans un format normal auto/prefixe/vx.y.z + * + * @example + * $this->tester_repertoire_destination_ancien_format(_DIR_PLUGINS_AUTO . $base); + * + * @param string $dir_dans_auto + * Chemin du répertoire à tester + * @return bool + * true si le répertoire est dans un ancien format + */ + public function tester_repertoire_destination_ancien_format($dir_dans_auto) { + // si on tombe sur un auto/X ayant des fichiers (et pas uniquement des dossiers) + // ou un dossier qui ne commence pas par 'v' + // c'est que auto/X n'était pas chargé avec SVP + // ce qui peut arriver lorsqu'on migre de SPIP 2.1 à 3.0 + // dans ce cas, on supprime auto X pour mettre notre nouveau paquet. + if (is_dir($dir_dans_auto)) { + $base_files = scandir($dir_dans_auto); + if (is_array($base_files)) { + $base_files = array_diff($base_files, array('.', '..')); + foreach ($base_files as $f) { + if (($f[0] != '.' and $f[0] != 'v') // commence pas par v + or ($f[0] != '.' and !is_dir($dir_dans_auto . '/' . $f)) + ) { // commence par v mais pas repertoire + return true; + } + } + } + } + + return false; + } + + + /** + * Teste s'il est possible d'utiliser un téléporteur particulier, + * sinon retourne le nom du téléporteur par défaut + * + * @param string $teleporteur Téléporteur VCS à tester + * @param string $defaut Téléporteur par défaut + * + * @return string Nom du téléporteur à utiliser + **/ + public function choisir_teleporteur($teleporteur, $defaut = 'http') { + // Utiliser un teleporteur vcs si possible si demandé + if (defined('SVP_PREFERER_TELECHARGEMENT_PAR_VCS') and SVP_PREFERER_TELECHARGEMENT_PAR_VCS) { + if ($teleporteur) { + include_spip('teleporter/' . $teleporteur); + $tester_teleporteur = "teleporter_{$teleporteur}_tester"; + if (function_exists($tester_teleporteur)) { + if ($tester_teleporteur()) { + return $teleporteur; + } + } + } + } + + return $defaut; + } + + /** * Teste si le plugin SVP (celui-ci donc) a - * été désinstallé / désactivé dans les actions réalisées + * été désinstallé / désactivé dans les actions réalisées * * @note * On ne peut tester sa désactivation que dans le hit où la désinstallation * est réalisée, puisque après, s'il a été désactivé, au prochain hit * on ne connaîtra plus ce fichier ! - * + * * @return bool * true si SVP a été désactivé, false sinon - **/ - function tester_si_svp_desactive() { + **/ + public function tester_si_svp_desactive() { foreach ($this->done as $d) { if ($d['p'] == 'SVP' - AND $d['done'] == true - AND in_array($d['todo'], array('off', 'stop'))) { + and $d['done'] == true + and in_array($d['todo'], array('off', 'stop')) + ) { return true; } } + return false; } - + } @@ -1395,16 +1737,15 @@ class Actionneur { * @param string $redirect * URL de retour * @return void -**/ -function svp_actionner_traiter_actions_demandees($actions, &$retour,$redirect=null) { - $actionneur = new Actionneur(); - $actionneur->ajouter_actions($actions); - $actionneur->verrouiller(); - $actionneur->sauver_actions(); - - $redirect = $redirect ? $redirect : generer_url_ecrire('admin_plugin'); - $retour['redirect'] = generer_url_action('actionner', 'redirect='.urlencode($redirect)); - set_request('_todo', ''); - $retour['message_ok'] = _T("svp:action_patienter"); + **/ +function svp_actionner_traiter_actions_demandees($actions, &$retour, $redirect = null) { + $actionneur = new Actionneur(); + $actionneur->ajouter_actions($actions); + $actionneur->verrouiller(); + $actionneur->sauver_actions(); + + $redirect = $redirect ? $redirect : generer_url_ecrire('admin_plugin'); + $retour['redirect'] = generer_url_action('actionner', 'redirect=' . urlencode($redirect)); + set_request('_todo', ''); + $retour['message_ok'] = _T("svp:action_patienter"); } -?>