1
0
Fork 0
mirror of https://github.com/YunoHost-Apps/spip_ynh.git synced 2024-09-03 20:25:59 +02:00
spip_ynh/sources/ecrire/inc/plugin.php
2015-04-28 17:10:23 +02:00

789 lines
27 KiB
PHP

<?php
/***************************************************************************\
* SPIP, Systeme de publication pour l'internet *
* *
* Copyright (c) 2001-2014 *
* 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. *
\***************************************************************************/
if (!defined('_ECRIRE_INC_VERSION')) return;
// l'adresse du repertoire de telechargement et de decompactage des plugins
define('_DIR_PLUGINS_AUTO', _DIR_PLUGINS.'auto/');
#include_spip('inc/texte'); // ????? Appelle public/parametrer trop tot avant la reconstruction du chemin des plugins.
include_spip('plugins/installer');
// lecture des sous repertoire plugin existants
// $dir_plugins pour forcer un repertoire (ex: _DIR_PLUGINS_DIST)
// _DIR_PLUGINS_SUPPL pour aller en chercher ailleurs
// (chemins relatifs a la racine du site, separes par des ":")
// http://doc.spip.org/@liste_plugin_files
function liste_plugin_files($dir_plugins = null){
static $plugin_files=array();
if (is_null($dir_plugins))
$dir_plugins = _DIR_PLUGINS;
if (!isset($plugin_files[$dir_plugins])
OR count($plugin_files[$dir_plugins]) == 0){
$plugin_files[$dir_plugins] = array();
foreach (fast_find_plugin_dirs($dir_plugins) as $plugin) {
$plugin_files[$dir_plugins][] = substr($plugin,strlen($dir_plugins));
}
sort($plugin_files[$dir_plugins]);
// et on lit le XML de tous les plugins pour le mettre en cache
// et en profiter pour nettoyer ceux qui n'existent plus du cache
$get_infos = charger_fonction('get_infos','plugins');
$get_infos($plugin_files[$dir_plugins],false,$dir_plugins,true);
}
return $plugin_files[$dir_plugins];
}
function fast_find_plugin_dirs($dir, $max_prof=100) {
$fichiers = array();
// revenir au repertoire racine si on a recu dossier/truc
// pour regarder dossier/truc/ ne pas oublier le / final
$dir = preg_replace(',/[^/]*$,', '', $dir);
if ($dir == '') $dir = '.';
if (!is_dir($dir))
return $fichiers;
if (is_plugin_dir($dir,'')) {
$fichiers[] = $dir;
return $fichiers;
}
if ($max_prof<=0)
return $fichiers;
$subdirs = array();
if (@is_dir($dir) AND is_readable($dir) AND $d = @opendir($dir)) {
while (($f = readdir($d)) !== false) {
if ($f[0] != '.' # ignorer . .. .svn etc
AND $f != 'CVS'
AND is_dir($f = "$dir/$f"))
$subdirs[] = $f;
}
closedir($d);
}
foreach($subdirs as $d){
$fichiers = array_merge($fichiers,fast_find_plugin_dirs("$d/",$max_prof-1));
}
return $fichiers;
}
function is_plugin_dir($dir,$dir_plugins = null){
if (is_array($dir)){
foreach($dir as $k=>$d){
if (!is_plugin_dir($d,$dir_plugins))
unset($dir[$k]);
}
return $dir;
}
if (is_null($dir_plugins))
$dir_plugins = _DIR_PLUGINS;
$search = array("$dir_plugins$dir/plugin.xml","$dir_plugins$dir/paquet.xml");
foreach($search as $s){
if (file_exists($s)){
return $dir;
}
}
return '';
}
// Regexp d'extraction des informations d'un intervalle de compatibilité
define('_EXTRAIRE_INTERVALLE', ',^[\[\(\]]([0-9.a-zRC\s\-]*)[;]([0-9.a-zRC\s\-\*]*)[\]\)\[]$,');
/**
* Teste si le numéro de version d'un plugin est dans un intervalle donné.
*
* Cette fonction peut être volontairement trompée (phase de développement) :
* voir commentaire infra sur l'utilisation de la constante _DEV_PLUGINS
*
* @param string $intervalle
* Un intervalle entre 2 versions. ex: [2.0.0-dev;2.1.*]
* @param string $version
* Un numéro de version. ex: 3.1.99]
* @param string $avec_quoi
* Ce avec quoi est testée la compatibilité. par défaut ('')
* avec un plugin (cas des 'necessite'), parfois ('spip')
* avec SPIP.
* @return bool
* True si dans l'intervalle, false sinon.
**/
function plugin_version_compatible($intervalle, $version, $avec_quoi = '') {
if (!strlen($intervalle)) return true;
if (!preg_match(_EXTRAIRE_INTERVALLE,$intervalle,$regs)) return false;
// Extraction des bornes et traitement de * pour la borne sup :
// -- on autorise uniquement les ecritures 3.0.*, 3.*
$minimum = $regs[1];
$maximum = $regs[2];
// si une borne de compatibilité supérieure a été définie (dans
// mes_options.php, sous la forme : define('_DEV_PLUGINS', '3.1.99');
// on l'utilise (phase de dev, de test...) mais *que* en cas de comparaison
// avec la version de SPIP (ne nuit donc pas aux tests de necessite
// entre plugins)
if (defined('_DEV_PLUGINS') && $avec_quoi == 'spip') {
$maximum = _DEV_PLUGINS.']';
}
$minimum_inc = $intervalle{0}=="[";
$maximum_inc = substr($intervalle,-1)=="]";
if (strlen($minimum)){
if ($minimum_inc AND spip_version_compare($version,$minimum,'<')) return false;
if (!$minimum_inc AND spip_version_compare($version,$minimum,'<=')) return false;
}
if (strlen($maximum)){
if ($maximum_inc AND spip_version_compare($version,$maximum,'>')) return false;
if (!$maximum_inc AND spip_version_compare($version,$maximum,'>=')) return false;
}
return true;
}
// Construire la liste des infos strictement necessaires aux plugins a activer
// afin de les memoriser dans une meta pas trop grosse
// http://doc.spip.org/@liste_plugin_valides
function liste_plugin_valides($liste_plug, $force = false)
{
$liste_ext = liste_plugin_files(_DIR_PLUGINS_DIST);
$get_infos = charger_fonction('get_infos','plugins');
$infos = array(
// lister les extensions qui sont automatiquement actives
'_DIR_PLUGINS_DIST' => $get_infos($liste_ext, $force, _DIR_PLUGINS_DIST),
'_DIR_PLUGINS' => $get_infos($liste_plug, $force, _DIR_PLUGINS)
);
// creer une premiere liste non ordonnee mais qui ne retient
// que les plugins valides, et dans leur derniere version en cas de doublon
$infos['_DIR_RESTREINT'][''] = $get_infos('./',$force,_DIR_RESTREINT);
$infos['_DIR_RESTREINT']['SPIP']['version'] = $GLOBALS['spip_version_branche'];
$infos['_DIR_RESTREINT']['SPIP']['chemin'] = array();
$liste_non_classee = array('SPIP'=>array(
'nom' => 'SPIP',
'etat' => 'stable',
'version' => $GLOBALS['spip_version_branche'],
'dir_type' => '_DIR_RESTREINT',
'dir'=> '',
)
);
foreach($liste_ext as $plug){
if (isset($infos['_DIR_PLUGINS_DIST'][$plug]))
plugin_valide_resume($liste_non_classee, $plug, $infos, '_DIR_PLUGINS_DIST');
}
foreach($liste_plug as $plug) {
if (isset($infos['_DIR_PLUGINS'][$plug]))
plugin_valide_resume($liste_non_classee, $plug, $infos, '_DIR_PLUGINS');
}
if (defined('_DIR_PLUGINS_SUPPL') and _DIR_PLUGINS_SUPPL) {
$infos['_DIR_PLUGINS_SUPPL'] = $get_infos($liste_plug, false, _DIR_PLUGINS_SUPPL);
foreach($liste_plug as $plug) {
if (isset($infos['_DIR_PLUGINS_SUPPL'][$plug]))
plugin_valide_resume($liste_non_classee, $plug, $infos, '_DIR_PLUGINS_SUPPL');
}
}
// les procure de core.xml sont consideres comme des plugins proposes,
// mais surchargeables (on peut activer un plugin qui procure ca pour l'ameliorer,
// donc avec le meme prefixe)
foreach($infos['_DIR_RESTREINT']['']['procure'] as $procure) {
$p = strtoupper($procure['nom']);
if (!isset($liste_non_classee[$p])){
$procure['etat'] = '?';
$procure['dir_type'] = '_DIR_RESTREINT';
$procure['dir'] = '';
$liste_non_classee[$p] = $procure;
}
}
return array($infos, $liste_non_classee);
}
// Ne retenir un plugin que s'il est valide
// et dans leur plus recente version compatible
// avec la version presente de SPIP
function plugin_valide_resume(&$liste, $plug, $infos, $dir)
{
$i = $infos[$dir][$plug];
if (isset($i['erreur']) AND $i['erreur'])
return;
if (!plugin_version_compatible($i['compatibilite'], $GLOBALS['spip_version_branche'],'spip'))
return;
$p = strtoupper($i['prefix']);
if (!isset($liste[$p])
OR spip_version_compare($i['version'],$liste[$p]['version'],'>')) {
$liste[$p] = array(
'nom' => $i['nom'],
'etat' => $i['etat'],
'version'=> $i['version'],
'dir'=> $plug,
'dir_type' => $dir
);
}
}
/**
* extrait les chemins d'une liste de plugin
* selectionne au passage ceux qui sont dans $dir_plugins uniquement
* si valeur non vide
*
* @param array $liste
* @param string $dir_plugins
* @return array
*/
function liste_chemin_plugin($liste, $dir_plugins=_DIR_PLUGINS){
foreach ($liste as $prefix=>$infos) {
if (!$dir_plugins
OR (
defined($infos['dir_type'])
AND constant($infos['dir_type'])==$dir_plugins))
$liste[$prefix] = $infos['dir'];
else
unset($liste[$prefix]);
}
return $liste;
}
/**
* Liste les chemins vers les plugins actifs du dossier fourni en argument
* a partir d'une liste d'elelements construits par plugin_valide_resume
*
* @return array
*/
// http://doc.spip.org/@liste_chemin_plugin_actifs
function liste_chemin_plugin_actifs($dir_plugins=_DIR_PLUGINS){
include_spip('plugins/installer');
return liste_chemin_plugin(liste_plugin_actifs(), $dir_plugins);
}
// Pour tester utilise, il faut connaitre tous les plugins
// qui seront forcement pas la a la fin,
// car absent de la liste des plugins actifs.
// Il faut donc construire une liste ordonnee
// Cette fonction detecte des dependances circulaires,
// avec un doute sur un "utilise" qu'on peut ignorer.
// Mais ne pas inserer silencieusement et risquer un bug sournois latent
function plugin_trier($infos, $liste_non_classee)
{
$toute_la_liste = $liste_non_classee;
$liste = $ordre = array();
$count = 0;
while ($c=count($liste_non_classee) AND $c!=$count){ // tant qu'il reste des plugins a classer, et qu'on ne stagne pas
#echo "tour::";var_dump($liste_non_classee);
$count = $c;
foreach($liste_non_classee as $p=>$resume) {
$plug = $resume['dir'];
$dir_type = $resume['dir_type'];
$info1 = $infos[$dir_type][$plug];
// si des plugins sont necessaires,
// on ne peut inserer qu'apres eux
foreach($info1['necessite'] as $need){
$nom = strtoupper($need['nom']);
$compat = isset($need['compatibilite']) ? $need['compatibilite'] : '';
if (!isset($liste[$nom]) OR !plugin_version_compatible($compat,$liste[$nom]['version'])) {
$info1 = false;
break;
}
}
if (!$info1) continue;
// idem si des plugins sont utiles,
// sauf si ils sont de toute facon absents de la liste
foreach($info1['utilise'] as $need){
$nom = strtoupper($need['nom']);
$compat = isset($need['compatibilite']) ? $need['compatibilite'] : '';
if (isset($toute_la_liste[$nom])) {
if (!isset($liste[$nom]) OR
!plugin_version_compatible($compat, $liste[$nom]['version'])) {
$info1 = false;
break;
}
}
}
if ($info1) {
$ordre[$p] = $info1;
$liste[$p] = $liste_non_classee[$p];
unset($liste_non_classee[$p]);
}
}
}
return array($liste, $ordre, $liste_non_classee);
}
// Collecte les erreurs dans la meta
function plugins_erreurs($liste_non_classee, $liste, $infos, $msg=array())
{
static $erreurs = array();
foreach($liste_non_classee as $p=>$resume){
$dir_type = $resume['dir_type'];
$plug = $resume['dir'];
$k = $infos[$dir_type][$plug];
$plug = constant($dir_type) . $plug;
if (!isset($msg[$p])) {
if (!$msg[$p] = plugin_necessite($k['necessite'], $liste))
$msg[$p] = plugin_necessite($k['utilise'], $liste);
} else {
foreach($msg[$p] as $c => $l)
$msg[$p][$c] = plugin_controler_lib($l['nom'], $l['lien']);
}
$erreurs[$plug] = $msg[$p];
}
ecrire_meta('plugin_erreur_activation', serialize($erreurs));
}
function plugin_donne_erreurs($raw=false, $raz=true) {
if (!isset($GLOBALS['meta']['plugin_erreur_activation'])) return $raw?array():'';
$list = @unserialize($GLOBALS['meta']['plugin_erreur_activation']);
// Compat ancienne version
if (!$list)
$list = $raw?array():$GLOBALS['meta']['plugin_erreur_activation'];
elseif(!$raw) {
foreach($list as $plug => $msg)
$list[$plug] = "<li>" . _T('plugin_impossible_activer', array('plugin' => $plug))
. "<ul><li>" . implode("</li><li>", $msg) . "</li></ul></li>";
$list ="<ul>" . join("\n", $list) . "</ul>";
}
if ($raz)
effacer_meta('plugin_erreur_activation');
return $list;
}
/**
* Teste des dependances
* Et verifie que chaque dependance est presente
* dans la liste de plugins donnee
*
* @param array $n
* Tableau de dependances dont on souhaite verifier leur presence
* @param array $liste
* Tableau des plugins presents
* @return array
* Tableau des messages d'erreurs recus. Il sera vide si tout va bien.
*
**/
function plugin_necessite($n, $liste) {
$msg = array();
foreach($n as $need){
$id = strtoupper($need['nom']);
if ($r = plugin_controler_necessite($liste, $id, $need['compatibilite'])) {
$msg[] = $r;
}
}
return $msg;
}
/**
* Verifie qu'une dependance (plugin) est bien presente.
*
* @param $liste
* Liste de description des plugins
* @param $nom
* Le plugin donc on cherche la presence
* @param $version
* L'éventuelle intervalle de compatibilité de la dependance. ex: [1.1.0;]
* @return string.
* Vide si ok,
* Message d'erreur lorsque la dependance est absente.
**/
function plugin_controler_necessite($liste, $nom, $version)
{
if (isset($liste[$nom]) AND plugin_version_compatible($version,$liste[$nom]['version'])) {
return '';
}
// retrouver le minimum
if (preg_match(_EXTRAIRE_INTERVALLE, $version, $regs)) {
$minimum = $regs[1];
if ($minimum) {
return _T('plugin_necessite_plugin', array(
'plugin' => $nom,
'version' => $minimum));
}
}
return _T('plugin_necessite_plugin_sans_version', array('plugin' => $nom));
}
function plugin_controler_lib($lib, $url)
{
/* Feature sortie du core, voir STP
* if ($url) {
include_spip('inc/charger_plugin');
$url = '<br />' . bouton_telechargement_plugin($url, 'lib');
}*/
return _T('plugin_necessite_lib', array('lib'=>$lib)) . " <a href='$url'>$url</a>";
}
// Pour compatibilite et lisibilite du code
function actualise_plugins_actifs($pipe_recherche = false){
return ecrire_plugin_actifs('', $pipe_recherche, 'force');
}
// mise a jour du meta en fonction de l'etat du repertoire
// Les ecrire_meta() doivent en principe aussi initialiser la valeur a vide
// si elle n'existe pas
// risque de pb en php5 a cause du typage ou de null (verifier dans la doc php)
// @return true/false si il y a du nouveau
// http://doc.spip.org/@ecrire_plugin_actifs
function ecrire_plugin_actifs($plugin,$pipe_recherche=false,$operation='raz') {
// creer le repertoire cache/ si necessaire ! (installation notamment)
sous_repertoire(_DIR_CACHE, '', false,true);
if (!spip_connect()) return false;
if ($operation!='raz') {
$plugin_valides = liste_chemin_plugin_actifs();
$plugin_valides = is_plugin_dir($plugin_valides);
if(defined('_DIR_PLUGINS_SUPPL') && _DIR_PLUGINS_SUPPL){
$plugin_valides_supp = liste_chemin_plugin_actifs(_DIR_PLUGINS_SUPPL);
$plugin_valides_supp = is_plugin_dir($plugin_valides_supp,_DIR_PLUGINS_SUPPL);
$plugin_valides = array_merge($plugin_valides,$plugin_valides_supp);
}
// si des plugins sont en attentes (coches mais impossible a activer)
// on les reinjecte ici
if (isset($GLOBALS['meta']['plugin_attente'])
AND $a = unserialize($GLOBALS['meta']['plugin_attente']))
$plugin_valides = $plugin_valides + liste_chemin_plugin($a);
if ($operation=='ajoute')
$plugin = array_merge($plugin_valides,$plugin);
elseif ($operation=='enleve')
$plugin = array_diff($plugin_valides,$plugin);
else $plugin = $plugin_valides;
}
$actifs_avant = $GLOBALS['meta']['plugin'];
// si une fonction de gestion de dependances existe, l'appeler ici
if ($ajouter_dependances = charger_fonction("ajouter_dependances","plugins",true)){
$plugin = $ajouter_dependances($plugin);
}
// recharger le xml des plugins a activer
// on forcer le reload ici, meme si le fichier xml n'a pas change
// pour ne pas rater l'ajout ou la suppression d'un fichier fonctions/options/administrations
// pourra etre evite quand on ne supportera plus les plugin.xml
// en deplacant la detection de ces fichiers dans la compilation ci dessous
list($infos,$liste) = liste_plugin_valides($plugin,true);
// trouver l'ordre d'activation
list($plugin_valides,$ordre,$reste) = plugin_trier($infos, $liste);
if ($reste) plugins_erreurs($reste, $liste, $infos);
// Ignorer les plugins necessitant une lib absente
// et preparer la meta d'entete Http
$err = $msg = $header = array();
foreach($plugin_valides as $p => $resume) {
$header[]= $p.($resume['version']?"(".$resume['version'].")":"");
if ($resume['dir']){
foreach($infos[$resume['dir_type']][$resume['dir']]['lib'] as $l) {
if (!find_in_path($l['nom'], 'lib/')) {
$err[$p] = $resume;
$msg[$p][] = $l;
unset($plugin_valides[$p]);
}
}
}
}
if ($err) plugins_erreurs($err, '', $infos, $msg);
if (isset($GLOBALS['meta']['message_crash_plugins']))
effacer_meta('message_crash_plugins');
ecrire_meta('plugin',serialize($plugin_valides));
$liste = array_diff_key($liste,$plugin_valides);
ecrire_meta('plugin_attente',serialize($liste));
$header = strtolower(implode(",",$header));
ecrire_meta('plugin_header',substr($header,0,900));
if (!isset($GLOBALS['spip_header_silencieux']) OR !$GLOBALS['spip_header_silencieux'])
ecrire_fichier(_DIR_VAR."config.txt", (defined('_HEADER_COMPOSED_BY') ? _HEADER_COMPOSED_BY:"Composed-By: SPIP") . ' '. $GLOBALS['spip_version_affichee'] . " @ www.spip.net + " . $header);
else
@unlink(_DIR_VAR."config.txt");
// generer charger_plugins_chemin.php
plugins_precompile_chemin($plugin_valides, $ordre);
// generer les fichiers
// charger_plugins_options.php
// charger_plugins_fonctions.php
// et retourner les fichiers a verifier
plugins_precompile_xxxtions($plugin_valides, $ordre);
// mise a jour de la matrice des pipelines
pipeline_matrice_precompile($plugin_valides, $ordre, $pipe_recherche);
// generer le fichier _CACHE_PIPELINE
pipeline_precompile();
// lancer et initialiser les nouveaux crons !
include_spip('inc/genie');
genie_queue_watch_dist();
return ($GLOBALS['meta']['plugin'] != $actifs_avant);
}
function plugins_precompile_chemin($plugin_valides, $ordre)
{
$chemins = array();
$contenu = "";
foreach($ordre as $p => $info){
// $ordre peur contenir des plugins en attente et non valides pour ce hit
if (isset($plugin_valides[$p])){
$dir_type = $plugin_valides[$p]['dir_type'];
$plug = $plugin_valides[$p]['dir'];
// definir le plugin, donc le path avant l'include du fichier options
// permet de faire des include_spip pour attraper un inc_ du plugin
$dir = $dir_type.".'" . $plug ."/'";
$prefix = strtoupper(preg_replace(',\W,','_',$info['prefix']));
if ($prefix!=="SPIP"){
$contenu .= "define('_DIR_PLUGIN_$prefix',$dir);\n";
foreach($info['chemin'] as $chemin){
if (!isset($chemin['version']) OR plugin_version_compatible($chemin['version'],$GLOBALS['spip_version_branche'],'spip')){
$dir = $chemin['path'];
if (strlen($dir) AND $dir{0}=="/") $dir = substr($dir,1);
if (strlen($dir) AND $dir=="./") $dir = '';
if (strlen($dir)) $dir = rtrim($dir,'/').'/';
if (!isset($chemin['type']) OR $chemin['type']=='public')
$chemins['public'][]="_DIR_PLUGIN_$prefix".(strlen($dir)?".'$dir'":"");
if (!isset($chemin['type']) OR $chemin['type']=='prive')
$chemins['prive'][]="_DIR_PLUGIN_$prefix".(strlen($dir)?".'$dir'":"");
}
}
}
}
}
if (count($chemins)){
$contenu .= "if (_DIR_RESTREINT) _chemin(implode(':',array(".implode(',',array_reverse($chemins['public'])).")));\n"
. "else _chemin(implode(':',array(".implode(',',array_reverse($chemins['prive'])).")));\n";
}
ecrire_fichier_php(_CACHE_PLUGINS_PATH, $contenu);
}
function plugins_precompile_xxxtions($plugin_valides, $ordre)
{
$contenu = array('options' => '', 'fonctions' =>'');
$boutons = array();
$onglets = array();
$sign = "";
foreach($ordre as $p => $info){
// $ordre peur contenir des plugins en attente et non valides pour ce hit
if (isset($plugin_valides[$p])){
$dir_type = $plugin_valides[$p]['dir_type'];
$plug = $plugin_valides[$p]['dir'];
$dir = constant($dir_type);
$root_dir_type = str_replace('_DIR_','_ROOT_',$dir_type);
if ($info['menu'])
$boutons = array_merge($boutons,$info['menu']);
if ($info['onglet'])
$onglets = array_merge($onglets,$info['onglet']);
foreach($contenu as $charge => $v){
// si pas declare/detecte a la lecture du paquet.xml,
// detecer a nouveau ici puisque son ajout ne provoque pas une modif du paquet.xml
// donc ni sa relecture, ni sa detection
if (!isset($info[$charge])
AND $dir // exclure le cas du plugin "SPIP"
AND file_exists("$dir$plug/paquet.xml") // uniquement pour les paquet.xml
){
if (is_readable("$dir$plug/".($file=$info['prefix']."_".$charge.".php"))){
$info[$charge] = array($file);
}
}
if (isset($info[$charge])){
$files = $info[$charge];
foreach($files as $k=>$file){
// on genere un if file_exists devant chaque include
// pour pouvoir garder le meme niveau d'erreur general
$file = trim($file);
if (!is_readable("$dir$plug/$file")
// uniquement pour les paquet.xml
AND file_exists("$dir$plug/paquet.xml")){
unset($info[$charge][$k]);
}
else {
$_file = $root_dir_type . ".'$plug/$file'";
$contenu[$charge] .= "include_once_check($_file);\n";
}
}
}
}
$sign .= md5(serialize($info));
}
}
$contenu['options'] = "define('_PLUGINS_HASH','".md5($sign)."');\n" . $contenu['options'];
$contenu['fonctions'] .= plugin_ongletbouton("boutons_plugins", $boutons)
. plugin_ongletbouton("onglets_plugins", $onglets);
ecrire_fichier_php(_CACHE_PLUGINS_OPT, $contenu['options']);
ecrire_fichier_php(_CACHE_PLUGINS_FCT, $contenu['fonctions']);
}
function plugin_ongletbouton($nom, $val)
{
if (!$val) $val = array();
define("_UPDATED_$nom",$val = serialize($val));
define("_UPDATED_md5_$nom",$md5=md5($val));
$val = "unserialize('".str_replace("'","\'",$val)."')";
return
"if (!function_exists('$nom')) {\n"
."function $nom(){return defined('_UPDATED_$nom')?unserialize(_UPDATED_$nom):$val;}\n"
."function md5_$nom(){return defined('_UPDATED_md5_$nom')?_UPDATED_md5_$nom:'".$md5."';}\n"
."}\n";
}
// creer le fichier CACHE_PLUGIN_VERIF a partir de
// $GLOBALS['spip_pipeline']
// $GLOBALS['spip_matrice']
function pipeline_matrice_precompile($plugin_valides, $ordre, $pipe_recherche)
{
static $liste_pipe_manquants=array();
if (($pipe_recherche)&&(!in_array($pipe_recherche,$liste_pipe_manquants)))
$liste_pipe_manquants[]=$pipe_recherche;
foreach($ordre as $p => $info){
// $ordre peur contenir des plugins en attente et non valides pour ce hit
if (isset($plugin_valides[$p])){
$dir_type = $plugin_valides[$p]['dir_type'];
$root_dir_type = str_replace('_DIR_','_ROOT_',$dir_type);
$plug = $plugin_valides[$p]['dir'];
$prefix = (($info['prefix']=="spip")?"":$info['prefix']."_");
if (isset($info['pipeline']) AND is_array($info['pipeline'])){
foreach($info['pipeline'] as $pipe){
$nom = $pipe['nom'];
if (isset($pipe['action']))
$action = $pipe['action'];
else
$action = $nom;
$nomlower = strtolower($nom);
if ($nomlower!=$nom
AND isset($GLOBALS['spip_pipeline'][$nom])
AND !isset($GLOBALS['spip_pipeline'][$nomlower])){
$GLOBALS['spip_pipeline'][$nomlower] = $GLOBALS['spip_pipeline'][$nom];
unset($GLOBALS['spip_pipeline'][$nom]);
}
$nom = $nomlower;
// une action vide est une declaration qui ne doit pas etre compilee !
if (!isset($GLOBALS['spip_pipeline'][$nom])) // creer le pipeline eventuel
$GLOBALS['spip_pipeline'][$nom]="";
if ($action){
if (strpos($GLOBALS['spip_pipeline'][$nom],"|$prefix$action")===FALSE)
$GLOBALS['spip_pipeline'][$nom] = preg_replace(",(\|\||$),","|$prefix$action\\1",$GLOBALS['spip_pipeline'][$nom],1);
if (isset($pipe['inclure'])){
$GLOBALS['spip_matrice']["$prefix$action"] =
"$root_dir_type:$plug/".$pipe['inclure'];
}
}
}
}
}
}
// on charge les fichiers d'options qui peuvent completer
// la globale spip_pipeline egalement
if (@is_readable(_CACHE_PLUGINS_PATH))
include_once(_CACHE_PLUGINS_PATH); // securite : a priori n'a pu etre fait plus tot
if (@is_readable(_CACHE_PLUGINS_OPT)) {
include_once(_CACHE_PLUGINS_OPT);
} else {
spip_log("pipelines desactives: impossible de produire " . _CACHE_PLUGINS_OPT);
}
// on ajoute les pipe qui ont ete recenses manquants
foreach($liste_pipe_manquants as $add_pipe)
if (!isset($GLOBALS['spip_pipeline'][$add_pipe]))
$GLOBALS['spip_pipeline'][$add_pipe]= '';
}
// precompilation des pipelines
// http://doc.spip.org/@pipeline_precompile
function pipeline_precompile(){
global $spip_pipeline, $spip_matrice;
$content = "";
foreach($spip_pipeline as $action=>$pipeline){
$s_inc = "";
$s_call = "";
$pipe = array_filter(explode('|',$pipeline));
// Eclater le pipeline en filtres et appliquer chaque filtre
foreach ($pipe as $fonc) {
$fonc = trim($fonc);
$s_call .= '$val = minipipe(\''.$fonc.'\', $val);'."\n";
if (isset($spip_matrice[$fonc])){
$file = $spip_matrice[$fonc];
$file = "'$file'";
// si un _DIR_XXX: est dans la chaine, on extrait la constante
if (preg_match(",(_(DIR|ROOT)_[A-Z_]+):,Ums",$file,$regs)){
$dir = $regs[1];
$root_dir = str_replace('_DIR_','_ROOT_',$dir);
if (defined($root_dir))
$dir = $root_dir;
$file = str_replace($regs[0],"'.".$dir.".'",$file);
$file = str_replace("''.","",$file);
$file = str_replace(constant($dir), '', $file);
}
$s_inc .= "include_once_check($file);\n";
}
}
if (strlen($s_inc))
$s_inc = "static \$inc=null;\nif (!\$inc){\n$s_inc\$inc=true;\n}\n";
$content .= "// Pipeline $action \n"
. "function execute_pipeline_$action(&\$val){\n"
. $s_inc
. $s_call
. "return \$val;\n}\n";
}
ecrire_fichier_php(_CACHE_PIPELINES, $content);
clear_path_cache();
}
// http://doc.spip.org/@plugin_est_installe
function plugin_est_installe($plug_path){
$plugin_installes = isset($GLOBALS['meta']['plugin_installes'])?unserialize($GLOBALS['meta']['plugin_installes']):array();
if (!$plugin_installes) return false;
return in_array($plug_path,$plugin_installes);
}
function plugin_installes_meta()
{
$installer_plugins = charger_fonction('installer', 'plugins');
$meta_plug_installes = array();
foreach (unserialize($GLOBALS['meta']['plugin']) as $prefix=>$resume) {
if ($plug = $resume['dir']){
$infos = $installer_plugins($plug, 'install', $resume['dir_type']);
if ($infos){
if (!is_array($infos) OR $infos['install_test'][0])
$meta_plug_installes[] = $plug;
if (is_array($infos)){
list($ok, $trace) = $infos['install_test'];
include_spip('inc/filtres_boites');
echo "<div class='install-plugins svp_retour'>"
.boite_ouvrir(_T('plugin_titre_installation', array('plugin' => typo($infos['nom']))), ($ok ? 'success' : 'error'))
.$trace
."<div class='result'>"
.($ok ? ((isset($infos['upgrade']) && $infos['upgrade']) ? _T("plugin_info_upgrade_ok") : _T("plugin_info_install_ok")) : _T("avis_operation_echec"))
."</div>"
.boite_fermer()
."</div>";
}
}
}
}
ecrire_meta('plugin_installes',serialize($meta_plug_installes),'non');
}
function ecrire_fichier_php($nom, $contenu, $comment='')
{
ecrire_fichier($nom,
'<'.'?php' . "\n" . $comment ."\nif (defined('_ECRIRE_INC_VERSION')) {\n". $contenu . "}\n?".'>');
}
?>