spip_nursit/ecrire/plugins/installer.php
2023-06-01 17:30:12 +02:00

237 lines
7.3 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/***************************************************************************\
* SPIP, Systeme de publication pour l'internet *
* *
* Copyright (c) 2001-2019 *
* Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James *
* *
* Ce programme est un logiciel libre distribue sous licence GNU/GPL. *
* Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne. *
\***************************************************************************/
/**
* Gestion de l'installation des plugins
*
* @package SPIP\Core\Plugins
**/
if (!defined('_ECRIRE_INC_VERSION')) {
return;
}
/**
* Installe ou retire un plugin
*
* Permet d'installer ou retirer un plugin en incluant les fichiers
* associés et en lançant les fonctions spécifiques.
*
* 1. d'abord sur l'argument `test`,
* 2. ensuite sur l'action demandée si le test repond `false`
* 3. enfin sur l'argument `test` à nouveau.
*
* L'index `install_test` du tableau résultat est un tableau formé :
*
* - du résultat 3
* - des echo de l'étape 2
*
* @note
* La fonction quitte (retourne false) si le plugin
* n'a pas de version d'installation définie
* (information `version_base` dans le paquet.xml)
*
* @param string $plug
* Nom du plugin
* @param string $action
* Nom de l'action (install|uninstall)
* @param string $dir_type
* Répertoire du plugin
* @return array|bool
* - False si le plugin n'a pas d'installation,
* - true si déjà installé,
* - le tableau de get_infos sinon
*/
function plugins_installer_dist($plug, $action, $dir_type = '_DIR_PLUGINS') {
$get_infos = charger_fonction('get_infos', 'plugins');
$infos = $get_infos($plug, false, constant($dir_type));
if (!isset($infos['install']) or !$infos['install']) {
return false;
}
// passer en chemin absolu si possible, c'est plus efficace
$dir = str_replace('_DIR_', '_ROOT_', $dir_type);
if (!defined($dir)) {
$dir = $dir_type;
}
$dir = constant($dir);
foreach ($infos['install'] as $file) {
$file = $dir . $plug . "/" . trim($file);
if (file_exists($file)) {
include_once($file);
}
}
$version = isset($infos['schema']) ? $infos['schema'] : '';
$arg = $infos;
$f = $infos['prefix'] . "_install";
if (!function_exists($f)) {
$f = isset($infos['schema']) ? 'spip_plugin_install' : '';
} else {
$arg = $infos['prefix'];
} // stupide: info deja dans le nom
if (!$f) {
// installation sans operation particuliere
$infos['install_test'] = array(true, '');
return $infos;
}
$test = $f('test', $arg, $version);
if ($action == 'uninstall') {
$test = !$test;
}
// Si deja fait, on ne dit rien
if ($test) {
return true;
}
// Si install et que l'on a la meta d'installation, c'est un upgrade
if ($action == 'install' && !is_null(lire_meta($infos['prefix'] . '_base_version'))) {
$infos['upgrade'] = true;
}
// executer l'installation ou l'inverse
// et renvoyer la trace (mais il faudrait passer en AJAX plutot)
ob_start();
$f($action, $arg, $version);
$aff = ob_get_contents();
ob_end_clean();
// vider le cache des descriptions de tables a chaque (de)installation
$trouver_table = charger_fonction('trouver_table', 'base');
$trouver_table('');
$infos['install_test'] = array($f('test', $arg, $version), $aff);
return $infos;
}
// Fonction par defaut pour install/desinstall
// http://code.spip.net/@spip_plugin_install
function spip_plugin_install($action, $infos, $version_cible) {
$prefix = $infos['prefix'];
if (isset($infos['meta']) and (($table = $infos['meta']) !== 'meta')) {
$nom_meta = "base_version";
} else {
$nom_meta = $prefix . "_base_version";
$table = 'meta';
}
switch ($action) {
case 'test':
return (isset($GLOBALS[$table])
and isset($GLOBALS[$table][$nom_meta])
and spip_version_compare($GLOBALS[$table][$nom_meta], $version_cible, '>='));
break;
case 'install':
if (function_exists($upgrade = $prefix . "_upgrade")) {
$upgrade($nom_meta, $version_cible, $table);
}
break;
case 'uninstall':
if (function_exists($vider_tables = $prefix . "_vider_tables")) {
$vider_tables($nom_meta, $table);
}
break;
}
}
/**
* Compare 2 numéros de version entre elles.
*
* Cette fonction est identique (arguments et retours) a la fonction PHP
* version_compare() qu'elle appelle. Cependant, cette fonction reformate
* les numeros de versions pour ameliorer certains usages dans SPIP ou bugs
* dans PHP. On permet ainsi de comparer 3.0.4 à 3.0.* par exemple.
*
* @param string $v1
* Numero de version servant de base a la comparaison.
* Ce numero ne peut pas comporter d'etoile.
* @param string $v2
* Numero de version a comparer.
* Il peut posseder des etoiles tel que 3.0.*
* @param string $op
* Un operateur eventuel (<, >, <=, >=, =, == ...)
* @return int|bool
* Sans operateur : int. -1 pour inferieur, 0 pour egal, 1 pour superieur
* Avec operateur : bool.
**/
function spip_version_compare($v1, $v2, $op = null) {
$v1 = strtolower(preg_replace(',([0-9])[\s.-]?(dev|alpha|a|beta|b|rc|pl|p),i', '\\1.\\2', $v1));
$v2 = strtolower(preg_replace(',([0-9])[\s.-]?(dev|alpha|a|beta|b|rc|pl|p),i', '\\1.\\2', $v2));
$v1 = str_replace('rc', 'RC', $v1); // certaines versions de PHP ne comprennent RC qu'en majuscule
$v2 = str_replace('rc', 'RC', $v2); // certaines versions de PHP ne comprennent RC qu'en majuscule
$v1 = explode('.', $v1);
$v2 = explode('.', $v2);
// $v1 est toujours une version, donc sans etoile
while (count($v1) < count($v2)) {
$v1[] = '0';
}
// $v2 peut etre une borne, donc accepte l'etoile
$etoile = false;
foreach ($v1 as $k => $v) {
if (!isset($v2[$k])) {
$v2[] = ($etoile and (is_numeric($v) or $v == 'pl' or $v == 'p')) ? $v : '0';
} else {
if ($v2[$k] == '*') {
$etoile = true;
$v2[$k] = $v;
}
}
}
$v1 = implode('.', $v1);
$v2 = implode('.', $v2);
return $op ? version_compare($v1, $v2, $op) : version_compare($v1, $v2);
}
/**
* Retourne un tableau des plugins activés sur le site
*
* Retourne la meta `plugin` désérialisée.
* Chaque élément du tableau est lui-même un tableau contenant
* les détails du plugin en question : répertoire et version.
*
* @note
* Si le contenu de la meta nest pas un tableau, cette fonction transforme
* lancien format en tableau sérialisé pour être conforme au nouveau fonctionnement (SPIP >= 1.9.2)
*
* @return array Tableau des plugins actifs
**/
function liste_plugin_actifs() {
$liste = isset($GLOBALS['meta']['plugin']) ? $GLOBALS['meta']['plugin'] : '';
if (!$liste) {
return array();
}
if (!is_array($liste = unserialize($liste))) {
// compatibilite pre 1.9.2, mettre a jour la meta
spip_log("MAJ meta plugin vieille version : $liste", "plugin");
$new = true;
list(, $liste) = liste_plugin_valides(explode(",", $liste));
} else {
$new = false;
// compat au moment d'une migration depuis version anterieure
// si pas de dir_type, alors c'est _DIR_PLUGINS
foreach ($liste as $prefix => $infos) {
if (!isset($infos['dir_type'])) {
$liste[$prefix]['dir_type'] = "_DIR_PLUGINS";
$new = true;
}
}
}
if ($new) {
ecrire_meta('plugin', serialize($liste));
}
return $liste;
}