3 /***************************************************************************\
4 * SPIP, Systeme de publication pour l'internet *
6 * Copyright (c) 2001-2019 *
7 * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James *
9 * Ce programme est un logiciel libre distribue sous licence GNU/GPL. *
10 * Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne. *
11 \***************************************************************************/
14 * Fonctions utilitaires pour le stockage et lecture de configuration
16 * @package SPIP\Core\Config
19 if (!defined('_ECRIRE_INC_VERSION')) {
25 * Appliquer les valeurs par défaut pour les options non initialisées
26 * (pour les langues c'est fait)
30 function inc_config_dist() {
31 actualise_metas(liste_metas());
35 * Expliquer une clé de configuration
37 * Analyser la clé de configuration pour déterminer
38 * - la table (ex: spip_metas),
39 * - le casier, la clé principale (ex: dada)
40 * - et le sous-casier éventuel, chemin dans la clé principale (ex: truc/muche)
43 * Clé de configuration, tel que 'dada/truc/muche'
45 * Liste (table, casier, sous_casier)
47 function expliquer_config($cfg) {
48 // par defaut, sur la table des meta
51 $sous_casier = array();
52 $cfg = explode('/', $cfg);
54 // si le premier argument est vide, c'est une syntaxe /table/ ou un appel vide ''
55 if (!reset($cfg) and count($cfg) > 1) {
57 $table = array_shift($cfg);
58 if (!isset($GLOBALS[$table])) {
63 // si on a demande #CONFIG{/meta,'',0}
65 // pas sur un appel vide ''
66 if ('' !== ($c = array_shift($cfg))) {
75 return array($table, $casier, $sous_casier);
79 * Lecture de la configuration
81 * lire_config() permet de recuperer une config depuis le php<br>
82 * memes arguments que la balise (forcement)<br>
83 * $cfg: la config, lire_config('montruc') est un tableau<br>
84 * lire_config('/table/champ') lit le valeur de champ dans la table des meta 'spip_table'<br>
85 * lire_config('montruc/sub') est l'element "sub" de cette config equivalent a lire_config('/meta/montruc/sub')<br>
87 * lire_config('methode::montruc/sub') delegue la lecture a methode_lire_config_dist via un charger_fonction
88 * permet de brancher CFG ou autre outil externe qui etend les methodes de stockage de config
90 * $unserialize est mis par l'histoire
93 * Clé de configuration
96 * @param boolean $unserialize
97 * N'affecte que le dépôt 'meta' :
98 * True pour désérialiser automatiquement la valeur
100 * Contenu de la configuration obtenue
102 function lire_config($cfg = '', $def = null, $unserialize = true) {
103 // lire le stockage sous la forme /table/valeur
104 // ou valeur qui est en fait implicitement /meta/valeur
105 // ou casier/valeur qui est en fait implicitement /meta/casier/valeur
107 // traiter en priorite le cas simple et frequent
108 // de lecture direct $GLOBALS['meta']['truc'], si $cfg ne contient ni / ni :
109 if ($cfg and strpbrk($cfg, '/:') === false) {
110 $r = isset($GLOBALS['meta'][$cfg]) ?
112 // ne pas essayer de deserialiser autre chose qu'une chaine
113 or !is_string($GLOBALS['meta'][$cfg])
114 // ne pas essayer de deserialiser si ce n'est visiblement pas une chaine serializee
115 or strpos($GLOBALS['meta'][$cfg], ':') === false
116 or ($t = @unserialize
($GLOBALS['meta'][$cfg])) === false) ?
$GLOBALS['meta'][$cfg] : $t)
122 // Brancher sur methodes externes si besoin
123 if ($cfg and $p = strpos($cfg, '::')) {
124 $methode = substr($cfg, 0, $p);
125 $lire_config = charger_fonction($methode, 'lire_config');
127 return $lire_config(substr($cfg, $p +
2), $def, $unserialize);
130 list($table, $casier, $sous_casier) = expliquer_config($cfg);
132 if (!isset($GLOBALS[$table])) {
136 $r = $GLOBALS[$table];
138 // si on a demande #CONFIG{/meta,'',0}
140 return $unserialize ?
$r : serialize($r);
143 // casier principal :
144 // le deserializer si demande
147 $r = isset($r[$casier]) ?
$r[$casier] : null;
148 if (($unserialize or count($sous_casier)) and $r and is_string($r)) {
149 $r = (($t = @unserialize
($r)) === false ?
$r : $t);
152 // aller chercher le sous_casier
153 while (!is_null($r) and $casier = array_shift($sous_casier)) {
154 $r = isset($r[$casier]) ?
$r[$casier] : null;
165 * metapack est inclue dans lire_config, mais on traite le cas ou il est explicite
166 * metapack:: dans le $cfg de lire_config.
167 * On renvoie simplement sur lire_config
171 * @param bool $unserialize
174 function lire_config_metapack_dist($cfg = '', $def = null, $unserialize = true) {
175 return lire_config($cfg, $def, $unserialize);
180 * Ecrire une configuration
183 * @param mixed $store
186 function ecrire_config($cfg, $store) {
187 // Brancher sur methodes externes si besoin
188 if ($cfg and $p = strpos($cfg, '::')) {
189 $methode = substr($cfg, 0, $p);
190 $ecrire_config = charger_fonction($methode, 'ecrire_config');
192 return $ecrire_config(substr($cfg, $p +
2), $store);
195 list($table, $casier, $sous_casier) = expliquer_config($cfg);
196 // il faut au moins un casier pour ecrire
201 // trouvons ou creons le pointeur sur le casier
202 $st = isset($GLOBALS[$table][$casier]) ?
$GLOBALS[$table][$casier] : null;
203 if (!is_array($st) and ($sous_casier or is_array($store))) {
204 $st = unserialize($st);
206 // ne rien creer si c'est une demande d'effacement
207 if (is_null($store)) {
214 // si on a affaire a un sous caiser
215 // il faut ecrire au bon endroit sans perdre les autres sous casier freres
216 if ($c = $sous_casier) {
218 $pointeurs = array();
219 while (count($c) and $cc = array_shift($c)) {
220 // creer l'entree si elle n'existe pas
221 if (!isset($sc[$cc])) {
222 // si on essaye d'effacer une config qui n'existe pas
223 // ne rien creer mais sortir
224 if (is_null($store)) {
229 $pointeurs[$cc] = &$sc;
233 // si c'est une demande d'effacement
234 if (is_null($store)) {
236 $sous = array_pop($c);
237 // effacer, et remonter pour effacer les parents vides
239 unset($pointeurs[$sous][$sous]);
240 } while ($sous = array_pop($c) and !count($pointeurs[$sous][$sous]));
242 // si on a vide tous les sous casiers,
243 // et que le casier est vide
244 // vider aussi la meta
245 if (!$sous and !count($st)) {
248 } // dans tous les autres cas, on ecrase
253 // Maintenant que $st est modifiee
254 // reprenons la comme valeur a stocker dans le casier principal
258 if (is_null($store)) {
259 if (is_null($st) and !$sous_casier) {
261 } // la config n'existait deja pas !
262 effacer_meta($casier, $table);
263 if (!count($GLOBALS[$table])
264 or count($GLOBALS[$table]) == 1 and isset($GLOBALS[$table]['charset'])
266 effacer_meta('charset', $table); // enlevons cette meta
267 supprimer_table_meta($table); // supprimons la table (si elle est bien vide)
269 } // les meta ne peuvent etre que des chaines : il faut serializer le reste
271 if (!isset($GLOBALS[$table])) {
272 installer_table_meta($table);
274 // si ce n'est pas une chaine
275 // il faut serializer
276 if (!is_string($store)) {
277 $store = serialize($store);
279 ecrire_meta($casier, $store, null, $table);
282 // verifier que lire_config($cfg)==$store ?
288 * metapack est inclue dans ecrire_config, mais on traite le cas ou il est explicite
289 * metapack:: dans le $cfg de ecrire_config.
290 * On renvoie simplement sur ecrire_config
293 * @param mixed $store
296 function ecrire_config_metapack_dist($cfg, $store) {
297 // cas particulier en metapack::
298 // si on ecrit une chaine deja serializee, il faut la reserializer pour la rendre
299 // intacte en sortie ...
300 if (is_string($store) and strpos($store, ':') and unserialize($store)) {
301 $store = serialize($store);
304 return ecrire_config($cfg, $store);
308 * Effacer une configuration : revient a ecrire une valeur null
313 function effacer_config($cfg) {
314 ecrire_config($cfg, null);
320 * Lister toutes les pages de configuration du site.
322 * Y compris celles fournies par des plugins.
324 * @uses _EXTENSION_SQUELETTES
325 * @uses find_all_in_path()
326 * @uses find_in_theme()
327 * @uses lister_formulaires_configurer()
329 * @param array $exclure
332 function lister_configurer($exclure = array()) {
335 // lister les pages de config deja dans les menus
337 foreach ($exclure as $id => $b) {
338 $url = ($b['url'] ?
$b['url'] : $id);
339 if (!$b['url'] or !isset($exclure[$url])) {
340 if (strncmp($url, 'configurer_', 11) == 0) {
342 } elseif ($b['url'] == 'configurer' and preg_match(',cfg=([a-z0-9_]+),i', $b['args'], $match)) {
343 $deja["configurer_" . $match[1]] = $b;
348 $exclure = $exclure +
$deja;
350 $icone_defaut = "images/configuration-16.png";
355 // trouver toutes les pages configurer_xxx de l'espace prive
356 // et construire un tableau des entrees qui ne sont pas dans $deja
357 $pages = find_all_in_path("prive/squelettes/contenu/", "configurer_.*[.]" . _EXTENSION_SQUELETTES
. '$');
359 foreach ($pages as $page) {
360 $configurer = basename($page, "." . _EXTENSION_SQUELETTES
);
361 if (!isset($exclure[$configurer])) {
362 $liste[$configurer] = array(
363 'parent' => 'bando_configuration',
364 'url' => $configurer,
365 'titre' => _T("configurer:{$configurer}_titre"),
366 'icone' => find_in_theme($i = "images/{$configurer}-16.png") ?
$i : $icone_defaut,
369 $skels[$configurer] = $page;
372 // analyser la liste des $skels pour voir les #FORMULAIRE_CONFIGURER_ inclus
373 foreach ($skels as $file) {
374 $forms = array_merge($forms, lister_formulaires_configurer($file));
376 $forms = array_flip($forms);
378 // trouver tous les formulaires/configurer_
379 // et construire un tableau des entrees
380 $pages = find_all_in_path("formulaires/", "configurer_.*[.]" . _EXTENSION_SQUELETTES
. '$');
381 foreach ($pages as $page) {
382 $configurer = basename($page, "." . _EXTENSION_SQUELETTES
);
383 if (!isset($forms[$configurer])
384 and !isset($liste[$configurer])
385 and !isset($exclure[$configurer])
387 $liste[$configurer] = array(
388 'parent' => 'bando_configuration',
389 'url' => 'configurer',
390 'args' => 'cfg=' . substr($configurer, 11),
391 'titre' => _T("configurer:{$configurer}_titre"),
392 'icone' => find_in_theme($i = "images/{$configurer}-16.png") ?
$i : $icone_defaut,
402 * Retourne la liste des formulaires de configuration
403 * présents dans le fichier dont l'adresse est donnée
405 * @param string $file
408 * Liste des formulaires trouvés
410 function lister_formulaires_configurer($file) {
413 lire_fichier($file, $skel);
414 if (preg_match_all(",#FORMULAIRE_(CONFIGURER_[A-Z0-9_]*),", $skel, $matches, PREG_SET_ORDER
)) {
415 $matches = array_map('end', $matches);
416 $matches = array_map('strtolower', $matches);
417 $forms = array_merge($forms, $matches);
420 // evaluer le fond en lui passant un exec coherent pour que les pipelines le reconnaissent
421 // et reperer les formulaires CVT configurer_xx insereres par les plugins via pipeline
422 $config = basename(substr($file, 0, -strlen("." . _EXTENSION_SQUELETTES
)));
423 spip_log('Calcul de ' . "prive/squelettes/contenu/$config");
424 $fond = recuperer_fond("prive/squelettes/contenu/$config", array("exec" => $config));
426 // passer dans le pipeline affiche_milieu pour que les plugins puissent ajouter leur formulaires...
427 // et donc que l'on puisse les referencer aussi !
428 $fond = pipeline('affiche_milieu', array('args' => array("exec" => $config), 'data' => $fond));
430 // recuperer les noms des formulaires presents.
431 if (is_array($inputs = extraire_balises($fond, "input"))) {
432 foreach ($inputs as $i) {
433 if (extraire_attribut($i, 'name') == 'formulaire_action') {
434 $forms[] = ($c = extraire_attribut($i, 'value'));
444 * Définir les `meta` de configuration
446 * @pipeline_appel configurer_liste_metas
448 * @uses url_de_base()
449 * @uses _DEFAULT_CHARSET
454 * Couples nom de la `meta` => valeur par défaut
456 function liste_metas() {
457 return pipeline('configurer_liste_metas', array(
458 'nom_site' => _T('info_mon_site_spip'),
460 'adresse_site' => preg_replace(",/$,", "", url_de_base()),
461 'descriptif_site' => '',
462 'activer_logos' => 'oui',
463 'activer_logos_survol' => 'non',
464 'articles_surtitre' => 'non',
465 'articles_soustitre' => 'non',
466 'articles_descriptif' => 'non',
467 'articles_chapeau' => 'non',
468 'articles_texte' => 'oui',
469 'articles_ps' => 'non',
470 'articles_redac' => 'non',
471 'post_dates' => 'non',
472 'articles_urlref' => 'non',
473 'articles_redirection' => 'non',
474 'creer_preview' => 'non',
475 'taille_preview' => 150,
476 'articles_modif' => 'non',
478 'rubriques_descriptif' => 'non',
479 'rubriques_texte' => 'oui',
481 'accepter_inscriptions' => 'non',
482 'accepter_visiteurs' => 'non',
483 'prevenir_auteurs' => 'non',
484 'suivi_edito' => 'non',
485 'adresse_suivi' => '',
486 'adresse_suivi_inscription' => '',
487 'adresse_neuf' => '',
489 'quoi_de_neuf' => 'non',
490 'preview' => ',0minirezo,1comite,',
492 'syndication_integrale' => 'oui',
493 'charset' => _DEFAULT_CHARSET
,
494 'dir_img' => substr(_DIR_IMG
, strlen(_DIR_RACINE
)),
496 'multi_rubriques' => 'non',
497 'multi_secteurs' => 'non',
498 'gerer_trad' => 'non',
499 'langues_multilingue' => '',
501 'version_html_max' => 'html4',
503 'type_urls' => 'page',
506 'email_webmaster' => '',
507 'auto_compress_http' => 'non',
512 * Mets les `meta` à des valeurs conventionnelles quand elles sont vides
513 * et recalcule les langues
515 * @param array $liste_meta
518 function actualise_metas($liste_meta) {
523 'alea_ephemere_ancien',
525 'alea_ephemere_date',
528 'date_calcul_rubriques',
539 'formats_graphiques',
544 // verifier le impt=non
545 sql_updateq('spip_meta', array('impt' => 'non'), sql_in('nom', $meta_serveur));
547 while (list($nom, $valeur) = each($liste_meta)) {
548 if (!isset($GLOBALS['meta'][$nom]) or !$GLOBALS['meta'][$nom]) {
549 ecrire_meta($nom, $valeur);
553 include_spip('inc/rubriques');
554 $langues = calculer_langues_utilisees();
555 ecrire_meta('langues_utilisees', $langues);
560 // Gestion des modifs
564 * Appliquer les modifications apportées aux `metas`
566 * Si `$purger_skel` est à `true`, on purge le répertoire de cache des squelettes
568 * @uses liste_metas()
569 * @uses ecrire_meta()
570 * @uses purger_repertoire()
572 * @param bool $purger_skel
575 function appliquer_modifs_config($purger_skel = false) {
577 foreach (liste_metas() as $i => $v) {
578 if (($x = _request($i)) !== null) {
580 } elseif (!isset($GLOBALS['meta'][$i])) {
586 include_spip('inc/invalideur');
587 purger_repertoire(_DIR_SKELS
);
592 * Mettre à jour l'adresse du site à partir d'une valeur saisie
593 * (ou auto détection si vide)
595 * @param string $adresse_site
598 function appliquer_adresse_site($adresse_site) {
599 if ($adresse_site !== null) {
600 if (!strlen($adresse_site)) {
601 $GLOBALS['profondeur_url'] = _DIR_RESTREINT ?
0 : 1;
602 $adresse_site = url_de_base();
604 $adresse_site = preg_replace(",/?\s*$,", "", $adresse_site);
606 if (!tester_url_absolue($adresse_site)) {
607 $adresse_site = "http://$adresse_site";
610 ecrire_meta('adresse_site', $adresse_site);
613 return $adresse_site;