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