[SPIP] ~v3.0.20-->v3.0.25
[lhc/web/clavette_www.git] / www / ecrire / base / trouver_table.php
1 <?php
2
3 /***************************************************************************\
4 * SPIP, Systeme de publication pour l'internet *
5 * *
6 * Copyright (c) 2001-2016 *
7 * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James *
8 * *
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 \***************************************************************************/
12
13 /**
14 * Gestion de l'obtention des descriptions de tables SQL
15 *
16 * @package SPIP\SQL\Tables
17 **/
18 if (!defined('_ECRIRE_INC_VERSION')) return;
19 include_spip('base/objets');
20
21 /**
22 * Retourne la description d'une table SQL
23 *
24 * Cela sert notamment au moment de la compilation des boucles, critères et balise.
25 *
26 * Les champs et clés de la tables sont retrouvés prioritairement via le
27 * gestionnaire de base de données. Les descriptions sont complétées,
28 * pour les tables éditoriales, des informations déclarées ou construites
29 * par la déclaration des objets éditoriaux.
30 *
31 * @example
32 * $trouver_table = charger_fonction('trouver_table', 'base');
33 * $desc = $trouver_table('spip_groupes_mots');
34 *
35 * Cette fonction intervient à la compilation, mais aussi pour la balise
36 * contextuelle EXPOSE ou certains critères.
37 *
38 * L'ensemble des descriptions de table d'un serveur est stocké dans un
39 * fichier cache/sql_desc.txt par soucis de performance. Un appel
40 * avec $nom vide est une demande explicite de vidange de ce cache
41 *
42 * @see lister_tables_objets_sql()
43 *
44 * @api
45 * @param string $nom
46 * Nom de la table
47 * Vide '' demande de vider le cache des discriptions
48 * @param string $serveur
49 * Nom du connecteur
50 * @param bool $table_spip
51 * Indique s'il faut transformer le préfixe de table
52 * @return array|bool
53 * false si table introuvable
54 * tableau de description de la table sinon, en particulier :
55 * - field : tableau des colonnes SQL et leur description (comme dans serial.php ou objets.php)
56 * - key : tableau des KEY (comme dans serial.php ou objets.php)
57 * - table et table_sql : nom de la table (avec spip_ en préfixe)
58 * - id_table : nom SPIP de la table (type de boucle)
59 * le compilateur produit FROM $r['table'] AS $r['id_table']
60 * - Toutes les autres informations des objets éditoriaux si la table est l'un d'eux.
61 *
62 *
63 **/
64 function base_trouver_table_dist($nom, $serveur='', $table_spip = true){
65 static $nom_cache_desc_sql=array();
66 global $tables_principales, $tables_auxiliaires, $table_des_tables;
67
68 if (!spip_connect($serveur)
69 OR !preg_match('/^[a-zA-Z0-9._-]*/',$nom))
70 return null;
71
72 $connexion = &$GLOBALS['connexions'][$serveur ? strtolower($serveur) : 0];
73 $objets_sql = lister_tables_objets_sql("::md5");
74
75 // le nom du cache depend du serveur mais aussi du nom de la db et du prefixe
76 // ce qui permet une auto invalidation en cas de modif manuelle du fichier
77 // de connexion, et tout risque d'ambiguite
78 if (!isset($nom_cache_desc_sql[$serveur][$objets_sql])){
79 $nom_cache_desc_sql[$serveur][$objets_sql] =
80 _DIR_CACHE . 'sql_desc_'
81 . ($serveur ? "{$serveur}_":"")
82 . substr(md5($connexion['db'].":".$connexion['prefixe'].":$objets_sql"),0,8)
83 .'.txt';
84 // nouveau nom de cache = nouvelle version en memoire
85 unset($connexion['tables']);
86 }
87
88 // un appel avec $nom vide est une demande explicite de vidange du cache des descriptions
89 if (!$nom){
90 spip_unlink($nom_cache_desc_sql[$serveur][$objets_sql]);
91 $connexion['tables'] = array();
92 return null;
93 }
94
95 $nom_sql = $nom;
96 if (preg_match('/\.(.*)$/', $nom, $s))
97 $nom_sql = $s[1];
98 else
99 $nom_sql = $nom;
100
101 $fdesc = $desc = '';
102 $connexion = &$GLOBALS['connexions'][$serveur ? $serveur : 0];
103
104 // base sous SPIP: gerer les abreviations explicites des noms de table
105 if ($connexion['spip_connect_version']) {
106 if ($table_spip AND isset($table_des_tables[$nom])) {
107 $nom = $table_des_tables[$nom];
108 $nom_sql = 'spip_' . $nom;
109 }
110 }
111
112 // si c'est la premiere table qu'on cherche
113 // et si on est pas explicitement en recalcul
114 // on essaye de recharger le cache des decriptions de ce serveur
115 // dans le fichier cache
116 if (!isset($connexion['tables'][$nom_sql])
117 AND defined('_VAR_MODE') AND _VAR_MODE!=='recalcul'
118 AND (!isset($connexion['tables']) OR !$connexion['tables'])) {
119 if (lire_fichier($nom_cache_desc_sql[$serveur][$objets_sql],$desc_cache)
120 AND $desc_cache=unserialize($desc_cache))
121 $connexion['tables'] = $desc_cache;
122 }
123 if ($table_spip AND !isset($connexion['tables'][$nom_sql])) {
124
125 if (isset($tables_principales[$nom_sql]))
126 $fdesc = $tables_principales[$nom_sql];
127 // meme si pas d'abreviation declaree, trouver la table spip_$nom
128 // si c'est une table principale,
129 // puisqu'on le fait aussi pour les tables auxiliaires
130 elseif ($nom_sql==$nom AND isset($tables_principales['spip_' .$nom])){
131 $nom_sql = 'spip_' . $nom;
132 $fdesc = &$tables_principales[$nom_sql];
133 }
134 elseif (isset($tables_auxiliaires[$n=$nom])
135 OR isset($tables_auxiliaires[$n='spip_'.$nom])) {
136 $nom_sql = $n;
137 $fdesc = &$tables_auxiliaires[$n];
138 } # table locale a cote de SPIP, comme non SPIP:
139 }
140 if (!isset($connexion['tables'][$nom_sql])) {
141
142 // La *vraie* base a la priorite
143 $desc = sql_showtable($nom_sql, $table_spip, $serveur);
144 if (!$desc OR !$desc['field']) {
145 if (!$fdesc) {
146 spip_log("trouver_table: table inconnue '$serveur' '$nom'",_LOG_INFO_IMPORTANTE);
147 return null;
148 }
149 // on ne sait pas lire la structure de la table :
150 // on retombe sur la description donnee dans les fichiers spip
151 $desc = $fdesc;
152 }
153 else {
154 $desc['exist'] = true;
155 }
156
157 $desc['table'] = $desc['table_sql'] = $nom_sql;
158 $desc['connexion']= $serveur;
159
160 // charger les infos declarees pour cette table
161 // en lui passant les infos connues
162 // $desc est prioritaire pour la description de la table
163 $desc = array_merge(lister_tables_objets_sql($nom_sql,$desc),$desc);
164
165 // si tables_objets_sql est bien fini d'init, on peut cacher
166 $connexion['tables'][$nom_sql] = $desc;
167 $res = &$connexion['tables'][$nom_sql];
168 // une nouvelle table a ete decrite
169 // mettons donc a jour le cache des descriptions de ce serveur
170 if (is_writeable(_DIR_CACHE))
171 ecrire_fichier($nom_cache_desc_sql[$serveur][$objets_sql],serialize($connexion['tables']),true);
172 }
173 else
174 $res = &$connexion['tables'][$nom_sql];
175
176 // toujours retourner $nom dans id_table
177 $res['id_table']=$nom;
178
179 return $res;
180 }
181 ?>