e28d5cc28152b938f8da8158eb0b12dfc1c85d25
[ptitvelo/web/www.git] / www / ecrire / base / objets.php
1 <?php
2
3 /***************************************************************************\
4 * SPIP, Systeme de publication pour l'internet *
5 * *
6 * Copyright (c) 2001-2012 *
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 * Fonctions relatives aux objets éditoriaux et SQL
15 *
16 * @package SPIP\SQL\Tables
17 **/
18
19 if (!defined('_ECRIRE_INC_VERSION')) return;
20
21 /**
22 * Merge dans un tableau une de ses clés avec une valeur
23 *
24 * @param array $table
25 * Tableau dont on veut compléter une clé
26 * @param string $index
27 * Clé du tableau que l'on souhaite compléter
28 * @param array $valeur
29 * Sous tableau à merger dans la clé.
30 * @return void
31 **/
32 function array_set_merge(&$table,$index,$valeur){
33 if (!isset($table[$index]))
34 $table[$index] = $valeur;
35 else
36 $table[$index] = array_merge($table[$index],$valeur);
37 }
38
39 /**
40 * Lister les infos de toutes les tables sql declarées
41 *
42 * Si un argument est fourni, on ne renvoie que les infos de cette table.
43 * Elle est auto-declarée si inconnue jusqu'alors.
44 *
45 * @api
46 * @param string $table_sql
47 * table_sql demandee explicitement
48 * @param array $desc
49 * description connue de la table sql demandee
50 * @return array|bool
51 */
52 function lister_tables_objets_sql($table_sql=null, $desc=array()){
53 static $deja_la = false;
54 static $infos_tables = null;
55 static $md5 = null;
56 static $plugin_hash = null;
57 // prealablement recuperer les tables_principales
58 if (is_null($infos_tables)
59 OR $plugin_hash!==_PLUGINS_HASH){
60 // pas de reentrance (cas base/serial)
61 if ($deja_la) {
62 spip_log ("Re-entrance anormale sur lister_tables_objets_sql :"
63 . var_export(debug_backtrace(),true),_LOG_CRITIQUE);
64 return ($table_sql==="::md5"?$md5:array());
65 }
66 $deja_la = true;
67 $plugin_hash = _PLUGINS_HASH; // avant de lancer les pipelines
68
69 // recuperer les declarations explicites ancienne mode
70 // qui servent a completer declarer_tables_objets_sql
71 base_serial($GLOBALS['tables_principales']);
72 base_auxiliaires($GLOBALS['tables_auxiliaires']);
73 $infos_tables = array(
74 'spip_articles'=> array(
75 'page'=>'article',
76 'texte_retour' => 'icone_retour_article',
77 'texte_modifier' => 'icone_modifier_article',
78 'texte_creer' => 'icone_ecrire_article',
79 'texte_objets' => 'public:articles',
80 'texte_objet' => 'public:article',
81 'texte_signale_edition' => 'texte_travail_article',
82 'info_aucun_objet'=> 'info_aucun_article',
83 'info_1_objet' => 'info_1_article',
84 'info_nb_objets' => 'info_nb_articles',
85 'texte_logo_objet' => 'logo_article',
86 'texte_langue_objet' => 'titre_langue_article',
87 'titre' => 'titre, lang',
88 'date' => 'date',
89 'principale' => 'oui',
90 'champs_editables' => array('surtitre', 'titre', 'soustitre', 'descriptif','nom_site', 'url_site', 'chapo', 'texte', 'ps','virtuel'),
91 'champs_versionnes' => array('id_rubrique', 'surtitre', 'titre', 'soustitre', 'jointure_auteurs', 'descriptif', 'nom_site', 'url_site', 'chapo', 'texte', 'ps'),
92 'field' => array(
93 "id_article" => "bigint(21) NOT NULL",
94 "surtitre" => "text DEFAULT '' NOT NULL",
95 "titre" => "text DEFAULT '' NOT NULL",
96 "soustitre" => "text DEFAULT '' NOT NULL",
97 "id_rubrique" => "bigint(21) DEFAULT '0' NOT NULL",
98 "descriptif" => "text DEFAULT '' NOT NULL",
99 "chapo" => "mediumtext DEFAULT '' NOT NULL",
100 "texte" => "longtext DEFAULT '' NOT NULL",
101 "ps" => "mediumtext DEFAULT '' NOT NULL",
102 "date" => "datetime DEFAULT '0000-00-00 00:00:00' NOT NULL",
103 "statut" => "varchar(10) DEFAULT '0' NOT NULL",
104 "id_secteur" => "bigint(21) DEFAULT '0' NOT NULL",
105 "maj" => "TIMESTAMP",
106 "export" => "VARCHAR(10) DEFAULT 'oui'",
107 "date_redac" => "datetime DEFAULT '0000-00-00 00:00:00' NOT NULL",
108 "visites" => "integer DEFAULT '0' NOT NULL",
109 "referers" => "integer DEFAULT '0' NOT NULL",
110 "popularite" => "DOUBLE DEFAULT '0' NOT NULL",
111 "accepter_forum" => "CHAR(3) DEFAULT '' NOT NULL",
112 "date_modif" => "datetime DEFAULT '0000-00-00 00:00:00' NOT NULL",
113 "lang" => "VARCHAR(10) DEFAULT '' NOT NULL",
114 "langue_choisie" => "VARCHAR(3) DEFAULT 'non'",
115 "id_trad" => "bigint(21) DEFAULT '0' NOT NULL",
116 "nom_site" => "tinytext DEFAULT '' NOT NULL",
117 "url_site" => "VARCHAR(255) DEFAULT '' NOT NULL",
118 "virtuel" => "VARCHAR(255) DEFAULT '' NOT NULL",
119 ),
120 'key' => array(
121 "PRIMARY KEY" => "id_article",
122 "KEY id_rubrique" => "id_rubrique",
123 "KEY id_secteur" => "id_secteur",
124 "KEY id_trad" => "id_trad",
125 "KEY lang" => "lang",
126 "KEY statut" => "statut, date",
127 ),
128 'join' => array(
129 "id_article"=>"id_article",
130 "id_rubrique"=>"id_rubrique"
131 ),
132 'rechercher_champs' => array(
133 'surtitre' => 5, 'titre' => 8, 'soustitre' => 5, 'chapo' => 3,
134 'texte' => 1, 'ps' => 1, 'nom_site' => 1, 'url_site' => 1,
135 'descriptif' => 4
136 ),
137 'rechercher_jointures' => array(
138 'auteur' => array('nom' => 10),
139 ),
140 'statut'=> array(
141 array(
142 'champ' => 'statut',
143 'publie' => 'publie',
144 'previsu' => 'publie,prop,prepa',
145 'post_date' => 'date',
146 'exception' => 'statut'
147 )
148 ),
149 'statut_titres' => array(
150 'prepa'=>'info_article_redaction',
151 'prop'=>'info_article_propose',
152 'publie'=>'info_article_publie',
153 'refuse'=>'info_article_refuse',
154 'poubelle'=>'info_article_supprime'
155 ),
156 'statut_textes_instituer' => array(
157 'prepa' => 'texte_statut_en_cours_redaction',
158 'prop' => 'texte_statut_propose_evaluation',
159 'publie' => 'texte_statut_publie',
160 'refuse' => 'texte_statut_refuse',
161 'poubelle' => 'texte_statut_poubelle',
162 ),
163 'texte_changer_statut' => 'texte_article_statut',
164 'aide_changer_statut' => 'artstatut',
165 'tables_jointures' => array(
166 'profondeur' => 'rubriques',
167 #'id_auteur' => 'auteurs_liens' // declaration generique plus bas
168 ),
169 ),
170 'spip_auteurs' => array(
171 'page'=>'auteur',
172 'texte_retour' => 'icone_retour',
173 'texte_ajouter' => 'titre_ajouter_un_auteur',
174 'texte_modifier' => 'admin_modifier_auteur',
175 'texte_objets' => 'icone_auteurs',
176 'texte_objet' => 'public:auteur',
177 'info_aucun_objet'=> 'info_aucun_auteur',
178 'info_1_objet' => 'info_1_auteur',
179 'info_nb_objets' => 'info_nb_auteurs',
180 'texte_logo_objet' => 'logo_auteur',
181 'texte_creer_associer' => 'creer_et_associer_un_auteur',
182 'titre' => "nom AS titre, '' AS lang",
183 'date' => 'date',
184 'principale' => 'oui',
185 'champs_editables' => array('nom','email','bio','nom_site','url_site','imessage','pgp'),
186 'champs_versionnes' => array('nom', 'bio', 'email', 'nom_site', 'url_site', 'login'),
187 'field' => array(
188 "id_auteur" => "bigint(21) NOT NULL",
189 "nom" => "text DEFAULT '' NOT NULL",
190 "bio" => "text DEFAULT '' NOT NULL",
191 "email" => "tinytext DEFAULT '' NOT NULL",
192 "nom_site" => "tinytext DEFAULT '' NOT NULL",
193 "url_site" => "text DEFAULT '' NOT NULL",
194 "login" => "VARCHAR(255) BINARY",
195 "pass" => "tinytext DEFAULT '' NOT NULL",
196 "low_sec" => "tinytext DEFAULT '' NOT NULL",
197 "statut" => "varchar(255) DEFAULT '0' NOT NULL",
198 "webmestre" => "varchar(3) DEFAULT 'non' NOT NULL",
199 "maj" => "TIMESTAMP",
200 "pgp" => "TEXT DEFAULT '' NOT NULL",
201 "htpass" => "tinytext DEFAULT '' NOT NULL",
202 "en_ligne" => "datetime DEFAULT '0000-00-00 00:00:00' NOT NULL",
203 "alea_actuel" => "tinytext",
204 "alea_futur" => "tinytext",
205 "prefs" => "tinytext",
206 "cookie_oubli" => "tinytext",
207 "source" => "VARCHAR(10) DEFAULT 'spip' NOT NULL",
208 "lang" => "VARCHAR(10) DEFAULT '' NOT NULL"
209 ),
210 'key' => array(
211 "PRIMARY KEY" => "id_auteur",
212 "KEY login" => "login",
213 "KEY statut" => "statut",
214 "KEY en_ligne" => "en_ligne",
215 ),
216 'join' => array(
217 "id_auteur"=>"id_auteur",
218 "login"=>"login"
219 ),
220 'rechercher_champs' => array(
221 'nom' => 5, 'bio' => 1, 'email' => 1, 'nom_site' => 1, 'url_site' => 1, 'login' => 1
222 ),
223 // 2 conditions pour les auteurs : statut!=poubelle,
224 // et avoir des articles publies
225 'statut'=> array(
226 array(
227 'champ' => 'statut',
228 'publie' => '!5poubelle',
229 'previsu' => '!5poubelle',
230 'exception' => 'statut'
231 ),
232 array(
233 'champ' => array(
234 array('spip_auteurs_liens', 'id_auteur'),
235 array(
236 'spip_articles',
237 array('id_objet','id_article','objet','article')
238 ),
239 'statut'
240 ),
241 'publie' => 'publie',
242 'previsu' => '!',
243 'post_date' => 'date',
244 'exception' => array('statut','lien','tout')
245 ),
246 ),
247 'statut_images' => array(
248 'auteur-6forum-16.png',
249 '0minirezo'=>'auteur-0minirezo-16.png',
250 '1comite'=>'auteur-1comite-16.png',
251 '6forum'=>'auteur-6forum-16.png',
252 '5poubelle'=>'auteur-5poubelle-16.png',
253 'nouveau'=>''
254 ),
255 'statut_titres' => array(
256 'titre_image_visiteur',
257 '0minirezo'=>'titre_image_administrateur',
258 '1comite'=>'titre_image_redacteur_02',
259 '6forum'=>'titre_image_visiteur',
260 '5poubelle'=>'titre_image_auteur_supprime',
261 ),
262 'tables_jointures' => array(
263 #'auteurs_liens' // declaration generique plus bas
264 ),
265 ),
266 'spip_rubriques' => array(
267 'page'=>'rubrique',
268 'url_voir' => 'rubrique',
269 'url_edit' => 'rubrique_edit',
270 'texte_retour' => 'icone_retour',
271 'texte_objets' => 'public:rubriques',
272 'texte_objet' => 'public:rubrique',
273 'texte_modifier' => 'icone_modifier_rubrique',
274 'texte_creer' => 'icone_creer_rubrique',
275 'texte_ajouter' => 'titre_ajouter_une_rubrique',
276 'texte_creer_associer' => 'creer_et_associer_une_rubrique',
277 'info_aucun_objet'=> 'info_aucun_rubrique',
278 'info_1_objet' => 'info_1_rubrique',
279 'info_nb_objets' => 'info_nb_rubriques',
280 'texte_logo_objet' => 'logo_rubrique',
281 'texte_langue_objet' => 'titre_langue_rubrique',
282 'titre'=>'titre, lang',
283 'date' => 'date',
284 'principale' => 'oui',
285 'champs_editables' => array('titre', 'texte', 'descriptif', 'extra'),
286 'champs_versionnes' => array('titre', 'descriptif', 'texte'),
287 'field' => array(
288 "id_rubrique" => "bigint(21) NOT NULL",
289 "id_parent" => "bigint(21) DEFAULT '0' NOT NULL",
290 "titre" => "text DEFAULT '' NOT NULL",
291 "descriptif" => "text DEFAULT '' NOT NULL",
292 "texte" => "longtext DEFAULT '' NOT NULL",
293 "id_secteur" => "bigint(21) DEFAULT '0' NOT NULL",
294 "maj" => "TIMESTAMP",
295 "statut" => "varchar(10) DEFAULT '0' NOT NULL",
296 "date" => "datetime DEFAULT '0000-00-00 00:00:00' NOT NULL",
297 "lang" => "VARCHAR(10) DEFAULT '' NOT NULL",
298 "langue_choisie" => "VARCHAR(3) DEFAULT 'non'",
299 "statut_tmp" => "varchar(10) DEFAULT '0' NOT NULL",
300 "date_tmp" => "datetime DEFAULT '0000-00-00 00:00:00' NOT NULL",
301 "profondeur" => "smallint(5) DEFAULT '0' NOT NULL"
302 ),
303 'key' => array(
304 "PRIMARY KEY" => "id_rubrique",
305 "KEY lang" => "lang",
306 "KEY id_parent" => "id_parent",
307 ),
308 'rechercher_champs' => array(
309 'titre' => 8, 'descriptif' => 5, 'texte' => 1
310 ),
311 'statut' => array(
312 array(
313 'champ' => 'statut',
314 'publie' => 'publie',
315 'previsu' => '!',
316 'exception' => array('statut','tout')
317 ),
318 ),
319 'tables_jointures' => array(
320 #'id_auteur' => 'auteurs_liens' // declaration generique plus bas
321 ),
322 ),
323 // toutes les tables ont le droit a une jointure sur les auteurs
324 array('tables_jointures'=>array('id_auteur'=>'auteurs_liens'))
325 );
326
327 // avant d'appeller les pipeline qui peuvent generer une reentrance a l'install
328 // initialiser la signature
329 $md5 = md5(serialize($infos_tables));
330
331 $GLOBALS['tables_principales'] = pipeline('declarer_tables_principales',$GLOBALS['tables_principales']);
332 $GLOBALS['tables_auxiliaires'] = pipeline('declarer_tables_auxiliaires',$GLOBALS['tables_auxiliaires']);
333 $infos_tables = pipeline('declarer_tables_objets_sql',$infos_tables);
334
335 // completer les informations manquantes ou implicites
336 $all = array();
337 foreach(array_keys($infos_tables) as $t) {
338 // les cles numeriques servent a declarer
339 // les proprietes applicables a tous les objets
340 // on les mets de cote
341 if (is_numeric($t)) {
342 $all = array_merge_recursive($all,$infos_tables[$t]);
343 unset($infos_tables[$t]);
344 }
345 else
346 $infos_tables[$t] = renseigner_table_objet_sql($t,$infos_tables[$t]);
347 }
348
349 // repercuter les proprietes generales communes a tous les objets
350 foreach(array_keys($infos_tables) as $t) {
351 foreach($all as $i=>$v)
352 if (in_array($i,array('tables_jointures','champs_versionnes'))){
353 $add = $all[$i];
354 // eviter les doublons de declaration de table jointure (ex des mots sur auteurs)
355 // pour les declarations generiques avec cles numeriques
356 if ($i=='tables_jointures' AND isset($infos_tables[$t][$i]) AND count($infos_tables[$t][$i])) {
357 $doublons = array_intersect($infos_tables[$t][$i],$add);
358 foreach($doublons as $d){
359 if (is_numeric(array_search($d,$infos_tables[$t][$i]))
360 AND is_numeric($k=array_search($d,$add)))
361 unset($add[$k]);
362 }
363 }
364 $infos_tables[$t][$i] = array_merge(isset($infos_tables[$t][$i])?$infos_tables[$t][$i]:array(),$add);
365 }
366 else
367 $infos_tables[$t][$i] = array_merge_recursive(isset($infos_tables[$t][$i])?$infos_tables[$t][$i]:array(),$all[$i]);
368 }
369
370 // completer les tables principales et auxiliaires
371 // avec celles declarees uniquement dans declarer_table_objets_sql
372 // pour assurer la compat en transition
373 foreach($infos_tables as $table=>$infos) {
374 $principale_ou_auxiliaire = ($infos['principale']?'tables_principales':'tables_auxiliaires');
375 // memoriser des champs eventuels declares par des plugins dans le pipeline tables_xxx
376 // qui a ete appelle avant
377 $mem = (isset($GLOBALS[$principale_ou_auxiliaire][$table])?$GLOBALS[$principale_ou_auxiliaire][$table]:array());
378 // l'ajouter au tableau
379 $GLOBALS[$principale_ou_auxiliaire][$table] = array();
380 if (isset($infos['field']) AND isset($infos['key'])){
381 foreach(array('field','key','join') as $k)
382 if (isset($infos_tables[$table][$k]))
383 $GLOBALS[$principale_ou_auxiliaire][$table][$k] = &$infos_tables[$table][$k];
384 }
385 else {
386 // ici on ne renvoie que les declarations, donc RIEN
387 // pour avoir la vrai description en base, il faut passer par trouver_table
388 $GLOBALS[$principale_ou_auxiliaire][$table] = array();
389 }
390 if (count($mem)){
391 foreach(array_keys($mem) as $k)
392 if (isset($GLOBALS[$principale_ou_auxiliaire][$table][$k]))
393 $GLOBALS[$principale_ou_auxiliaire][$table][$k] = array_merge($GLOBALS[$principale_ou_auxiliaire][$table][$k],$mem[$k]);
394 else
395 $GLOBALS[$principale_ou_auxiliaire][$table][$k] = $mem[$k];
396 }
397 }
398
399 // recuperer les interfaces (table_titre, table_date)
400 // on ne le fait que dans un second temps pour que table_objet soit fonctionnel
401 // dans le pipeline de declarer_tables_interfaces
402 include_spip('public/interfaces');
403 foreach(array_keys($infos_tables) as $t) {
404 $infos_tables[$t] = renseigner_table_objet_interfaces($t,$infos_tables[$t]);
405 }
406
407 $deja_la = false;
408 // signature
409 $md5 = md5(serialize($infos_tables));
410 }
411 if ($table_sql==="::md5")
412 return $md5;
413 if ($table_sql AND !isset($infos_tables[$table_sql])){
414 #$desc = renseigner_table_objet_sql($table_sql,$desc);
415 $desc = renseigner_table_objet_interfaces($table_sql,$desc);
416 return $desc;
417 }
418 if ($table_sql)
419 return isset($infos_tables[$table_sql])?$infos_tables[$table_sql]:array();
420
421 return $infos_tables;
422 }
423
424
425 /**
426 * Déclare les tables principales du Core
427 *
428 * Tables principales, hors objets éditoriaux.
429 *
430 * @param array $tables_principales
431 * Description des tables principales déjà déclarées
432 * @return void
433 **/
434 function base_serial(&$tables_principales){
435
436 $spip_jobs = array(
437 "id_job" => "bigint(21) NOT NULL",
438 "descriptif" => "text DEFAULT '' NOT NULL",
439 "fonction" => "varchar(255) NOT NULL", //nom de la fonction
440 "args"=> "longblob DEFAULT '' NOT NULL", // arguments
441 "md5args"=> "char(32) NOT NULL default ''", // signature des arguments
442 "inclure" => "varchar(255) NOT NULL", // fichier a inclure ou path/ pour charger_fonction
443 "priorite" => "smallint(6) NOT NULL default 0",
444 "date" => "datetime DEFAULT '0000-00-00 00:00:00' NOT NULL", // date au plus tot
445 "status" => "tinyint NOT NULL default 1",
446 );
447
448 $spip_jobs_key = array(
449 "PRIMARY KEY" => "id_job",
450 "KEY date" => "date",
451 "KEY status" => "status",
452 );
453
454 /// Attention: mes_fonctions peut avoir deja defini cette variable
455 /// il faut donc rajouter, mais pas reinitialiser
456 $tables_principales['spip_jobs'] = array('field' => &$spip_jobs, 'key' => &$spip_jobs_key);
457 }
458
459
460 /**
461 * Déclare les tables auxiliaires du Core
462 *
463 * @param array $tables_auxiliaires
464 * Description des tables auxiliaires déjà déclarées
465 * @return void
466 **/
467 function base_auxiliaires(&$tables_auxiliaires){
468 $spip_resultats = array(
469 "recherche" => "char(16) DEFAULT '' NOT NULL",
470 "id" => "INT UNSIGNED NOT NULL",
471 "points" => "INT UNSIGNED DEFAULT '0' NOT NULL",
472 "table_objet" => "varchar(30) DEFAULT '' NOT NULL",
473 "serveur" => "char(16) DEFAULT '' NOT NULL", // hash md5 partiel du serveur de base ('' pour le serveur principal)
474 "maj" => "TIMESTAMP" );
475
476 $spip_resultats_key = array(
477 // pas de cle ni index, ca fait des insertions plus rapides et les requetes jointes utilisees en recheche ne sont pas plus lentes ...
478 );
479
480 $spip_auteurs_liens = array(
481 "id_auteur" => "bigint(21) DEFAULT '0' NOT NULL",
482 "id_objet" => "bigint(21) DEFAULT '0' NOT NULL",
483 "objet" => "VARCHAR (25) DEFAULT '' NOT NULL",
484 "vu" => "VARCHAR(6) DEFAULT 'non' NOT NULL");
485
486 $spip_auteurs_liens_key = array(
487 "PRIMARY KEY" => "id_auteur,id_objet,objet",
488 "KEY id_auteur" => "id_auteur",
489 "KEY id_objet" => "id_objet",
490 "KEY objet" => "objet",
491 );
492
493 $spip_meta = array(
494 "nom" => "VARCHAR (255) NOT NULL",
495 "valeur" => "text DEFAULT ''",
496 "impt" => "ENUM('non', 'oui') DEFAULT 'oui' NOT NULL",
497 "maj" => "TIMESTAMP");
498
499 $spip_meta_key = array(
500 "PRIMARY KEY" => "nom");
501
502 $spip_jobs_liens = array(
503 "id_job" => "bigint(21) DEFAULT '0' NOT NULL",
504 "id_objet" => "bigint(21) DEFAULT '0' NOT NULL",
505 "objet" => "VARCHAR (25) DEFAULT '' NOT NULL",
506 );
507
508 $spip_jobs_liens_key = array(
509 "PRIMARY KEY" => "id_job,id_objet,objet",
510 "KEY id_job" => "id_job");
511
512 $tables_auxiliaires['spip_auteurs_liens'] = array(
513 'field' => &$spip_auteurs_liens,
514 'key' => &$spip_auteurs_liens_key);
515
516 $tables_auxiliaires['spip_meta'] = array(
517 'field' => &$spip_meta,
518 'key' => &$spip_meta_key);
519 $tables_auxiliaires['spip_resultats'] = array(
520 'field' => &$spip_resultats,
521 'key' => &$spip_resultats_key);
522 $tables_auxiliaires['spip_jobs_liens'] = array(
523 'field' => &$spip_jobs_liens,
524 'key' => &$spip_jobs_liens_key);
525
526 }
527
528
529 /**
530 * Auto remplissage des informations non explicites
531 * sur un objet d'une table sql
532 *
533 * table_objet
534 * table_objet_surnoms
535 * type
536 * type_surnoms
537 * url_voir
538 * url_edit
539 * icone_objet
540 *
541 * texte_retour
542 * texte_modifier
543 * texte_creer
544 * texte_creer_associer
545 * texte_ajouter
546 * texte_objets
547 * texte_objet
548 *
549 * info_aucun_objet
550 * info_1_objet
551 * info_nb_objets
552 *
553 * texte_logo_objet
554 * texte_langue_objet
555 *
556 * principale
557 * champs_contenu : utlise pour generer l'affichage par defaut du contenu
558 * editable
559 * champs_editables : utilise pour prendre en compte le post lors de l'edition
560 *
561 * champs_versionnes
562 *
563 * statut
564 * statut_images
565 * statut_titres
566 * statut_textes_instituer
567 * texte_changer_statut
568 * aide_changer_statut
569 *
570 * modeles : permet de declarer les modeles associes a cet objet
571 *
572 * les infos non renseignees sont auto deduites par conventions
573 * ou laissees vides
574 *
575 * @param string $table_sql
576 * @param array $infos
577 * @return array
578 */
579 function renseigner_table_objet_sql($table_sql,&$infos){
580 if (!isset($infos['type'])){
581 // si on arrive de base/trouver_table, on a la cle primaire :
582 // s'en servir pour extrapoler le type
583 if (isset($infos['key']["PRIMARY KEY"])){
584 $primary = $infos['key']["PRIMARY KEY"];
585 $primary = explode(',',$primary);
586 $primary = reset($primary);
587 $infos['type'] = preg_replace(',^spip_|^id_|s$,', '', $primary);
588 }
589 else
590 $infos['type'] = preg_replace(',^spip_|s$,', '', $table_sql);
591 }
592 if (!isset($infos['type_surnoms']))
593 $infos['type_surnoms'] = array();
594
595 if (!isset($infos['table_objet']))
596 $infos['table_objet'] = preg_replace(',^spip_,', '', $table_sql);
597 if (!isset($infos['table_objet_surnoms']))
598 $infos['table_objet_surnoms'] = array();
599
600 if (!isset($infos['principale']))
601 $infos['principale'] = (isset($GLOBALS['tables_principales'][$table_sql])?'oui':false);
602
603 // normaliser pour pouvoir tester en php $infos['principale']?
604 // et dans une boucle {principale=oui}
605 $infos['principale'] = (($infos['principale'] AND $infos['principale']!='non')?'oui':false);
606
607 // declarer et normaliser pour pouvoir tester en php $infos['editable']?
608 // et dans une boucle {editable=oui}
609 if (!isset($infos['editable'])) $infos['editable'] = 'oui';
610 $infos['editable'] = (($infos['editable'] AND $infos['editable']!='non')?'oui':false);
611
612 // les urls publiques sont par defaut page=type pour les tables principales, et rien pour les autres
613 // seules les exceptions sont donc a declarer
614 if (!isset($infos['page']))
615 $infos['page'] = ($infos['principale']?$infos['type']:'');
616
617 if (!isset($infos['url_voir']))
618 $infos['url_voir'] = $infos['type'];
619 if (!isset($infos['url_edit']))
620 $infos['url_edit'] = $infos['url_voir'].($infos['editable']?"_edit":'');
621 if (!isset($infos['icone_objet']))
622 $infos['icone_objet'] = $infos['type'];
623
624 // chaines de langue
625 // par defaut : objet:icone_xxx_objet
626 if (!isset($infos['texte_retour']))
627 $infos['texte_retour'] = 'icone_retour';
628 if (!isset($infos['texte_modifier']))
629 $infos['texte_modifier'] = $infos['type'].':'.'icone_modifier_'.$infos['type'];
630 if (!isset($infos['texte_creer']))
631 $infos['texte_creer'] = $infos['type'].':'.'icone_creer_'.$infos['type'];
632 if (!isset($infos['texte_creer_associer']))
633 $infos['texte_creer_associer'] = $infos['type'].':'.'texte_creer_associer_'.$infos['type'];
634 if (!isset($infos['texte_ajouter'])) // Ajouter un X
635 $infos['texte_ajouter'] = $infos['type'].':'.'texte_ajouter_'.$infos['type'];
636 if (!isset($infos['texte_objets']))
637 $infos['texte_objets'] = $infos['type'].':'.'titre_'.$infos['table_objet'];
638 if (!isset($infos['texte_objet']))
639 $infos['texte_objet'] = $infos['type'].':'.'titre_'.$infos['type'];
640 if (!isset($infos['texte_logo_objet'])) // objet:titre_logo_objet "Logo de ce X"
641 $infos['texte_logo_objet'] = $infos['type'].':'.'titre_logo_'.$infos['type'];
642 if (!isset($infos['texte_langue_objet'])) // objet:texte_langue_objet "Langue de ce X"
643 $infos['texte_langue_objet'] = $infos['type'].':'.'titre_langue_'.$infos['type'];
644
645 // objet:info_aucun_objet
646 if (!isset($infos['info_aucun_objet']))
647 $infos['info_aucun_objet'] = $infos['type'].':'.'info_aucun_'.$infos['type'];
648 // objet:info_1_objet
649 if (!isset($infos['info_1_objet']))
650 $infos['info_1_objet'] = $infos['type'].':'.'info_1_'.$infos['type'];
651 // objet:info_nb_objets
652 if (!isset($infos['info_nb_objets']))
653 $infos['info_nb_objets'] = $infos['type'].':'.'info_nb_'.$infos['table_objet'];
654
655
656 if (!isset($infos['champs_editables']))
657 $infos['champs_editables'] = array();
658 if (!isset($infos['champs_versionnes']))
659 $infos['champs_versionnes'] = array();
660 if (!isset($infos['rechercher_champs']))
661 $infos['rechercher_champs'] = array();
662 if (!isset($infos['rechercher_jointures']))
663 $infos['rechercher_jointures'] = array();
664
665 if (!isset($infos['modeles']))
666 $infos['modeles'] = array($infos['type']);
667
668 return $infos;
669 }
670
671 /**
672 * Renseigner les infos d'interface compilateur pour les tables objets
673 * complete la declaration precedente
674 *
675 * titre
676 * date
677 * statut
678 * tables_jointures
679 *
680 * @param $table_sql
681 * @param $infos
682 * @return array
683 */
684 function renseigner_table_objet_interfaces($table_sql,&$infos){
685 if (!isset($infos['titre'])){
686 if (isset($infos['table_objet']) AND isset($GLOBALS['table_titre'][$infos['table_objet']]))
687 $infos['titre'] = $GLOBALS['table_titre'][$infos['table_objet']];
688 else {
689 $infos['titre'] = ((isset($infos['field']['titre']))?"titre,":"'' as titre,");
690 $infos['titre'] .= ((isset($infos['field']['lang']))?"lang":"'' as lang");
691 }
692 }
693 if (!isset($infos['date'])){
694 if (isset($infos['table_objet']) and isset($GLOBALS['table_date'][$infos['table_objet']]))
695 $infos['date'] = $GLOBALS['table_date'][$infos['table_objet']];
696 else
697 $infos['date'] = ((isset($infos['field']['date']))?"date":'');
698 }
699 if (!isset($infos['statut']))
700 $infos['statut'] = isset($GLOBALS['table_statut'][$table_sql]) ? $GLOBALS['table_statut'][$table_sql] : '';
701 if (!isset($infos['tables_jointures']))
702 $infos['tables_jointures'] = array();
703 if (isset($GLOBALS['tables_jointures'][$table_sql]))
704 $infos['tables_jointures'] = array_merge($infos['tables_jointures'],$GLOBALS['tables_jointures'][$table_sql]);
705 return $infos;
706 }
707
708 /**
709 * Retourne la liste des tables principales et leurs descriptions
710 *
711 * @api
712 * @return array
713 * Liste et descriptions des tables principales
714 **/
715 function lister_tables_principales(){
716 static $done = false;
717 if (!$done OR !count($GLOBALS['tables_principales'])){
718 lister_tables_objets_sql();
719 $done = true;
720 }
721 return $GLOBALS['tables_principales'];
722 }
723
724 /**
725 * Retourne la liste des tables auxiliaires et leurs descriptions
726 *
727 * @api
728 * @return array
729 * Liste et descriptions des tables auxiliaires
730 **/
731 function lister_tables_auxiliaires(){
732 static $done = false;
733 if (!$done OR !count($GLOBALS['tables_auxiliaires'])){
734 lister_tables_objets_sql();
735 $done = true;
736 }
737 return $GLOBALS['tables_auxiliaires'];
738 }
739
740 /**
741 * Recenser les surnoms de table_objet
742 * @return array
743 */
744 function lister_tables_objets_surnoms(){
745 static $surnoms = null;
746 static $md5 = null;
747 if (!$surnoms
748 OR $md5 != lister_tables_objets_sql('::md5')){
749 // passer dans un pipeline qui permet aux plugins de declarer leurs exceptions
750 // pour compatibilite, car il faut dorenavent utiliser
751 // declarer_table_objets_sql
752 $surnoms = pipeline('declarer_tables_objets_surnoms',
753 array(
754 # pour les modeles
755 # a enlever ?
756 'doc' => 'documents',
757 'img' => 'documents',
758 'emb' => 'documents',
759 ));
760 $infos_tables = lister_tables_objets_sql();
761 foreach($infos_tables as $t=>$infos){
762 // cas de base type=>table
763 // et preg_replace(',^spip_|^id_|s$,',table)=>table
764 if ($infos['table_objet']){ // securite, si la fonction est appelee trop tot, c'est vide
765 // optimisations pour table_objet
766 //$surnoms[$infos['type']] = $infos['table_objet'];
767 $surnoms[preg_replace(',^spip_|^id_|s$,', '', $infos['table_objet'])] = $infos['table_objet'];
768 $surnoms[preg_replace(',^spip_|^id_|s$,', '', $infos['type'])] = $infos['table_objet'];
769 if (is_array($infos['table_objet_surnoms']) AND count($infos['table_objet_surnoms']))
770 foreach($infos['table_objet_surnoms'] as $surnom)
771 $surnoms[$surnom] = $infos['table_objet'];
772 }
773 }
774 $md5 = lister_tables_objets_sql('::md5');
775 }
776 return $surnoms;
777 }
778
779 /**
780 * Recenser les surnoms de table_objet
781 * @return array
782 */
783 function lister_types_surnoms(){
784 static $surnoms = null;
785 static $md5 = null;
786 if (!$surnoms
787 OR $md5 != lister_tables_objets_sql('::md5')){
788 // passer dans un pipeline qui permet aux plugins de declarer leurs exceptions
789 // pour compatibilite, car il faut dorenavent utiliser
790 // declarer_table_objets_sql
791 $surnoms = pipeline('declarer_type_surnoms', array('racine-site'=>'site'));
792 $infos_tables = lister_tables_objets_sql();
793 foreach($infos_tables as $t=>$infos){
794 if ($infos['type']){ // securite, si la fonction est appelee trop tot, c'est vide
795 // optimisations pour objet_type
796 //$surnoms[$infos['type']] = $infos['type'];
797 $surnoms[preg_replace(',^spip_|^id_|s$,', '', $infos['table_objet'])] = $infos['type'];
798 $surnoms[preg_replace(',^spip_|^id_|s$,', '', $infos['type'])] = $infos['type'];
799 // surnoms declares
800 if (is_array($infos['type_surnoms']) AND count($infos['type_surnoms']))
801 foreach($infos['type_surnoms'] as $surnom)
802 $surnoms[$surnom] = $infos['type'];
803 }
804 }
805 $md5 = lister_tables_objets_sql('::md5');
806 }
807 return $surnoms;
808 }
809
810 function lister_tables_spip($serveur=''){
811 static $tables = array();
812 if (!isset($tables[$serveur])){
813 $tables[$serveur] = array();
814 if (!function_exists("sql_alltable"))
815 include_spip("base/abstract_sql");
816 $ts = sql_alltable(null,$serveur); // toutes les tables "spip_" (ou prefixe perso)
817 $connexion = $GLOBALS['connexions'][$serveur ? $serveur : 0];
818 $spip = $connexion['prefixe'] . '_';
819 foreach ($ts as $t){
820 $t = substr($t,strlen($spip));
821 $tables[$serveur]["spip_$t"] = $t;
822 }
823 }
824 return $tables[$serveur];
825 }
826
827 /**
828 * Retrouve le nom d'objet à partir de la table
829 *
830 * - spip_articles -> articles
831 * - id_article -> articles
832 * - article -> articles
833 *
834 * @api
835 * @param string $type
836 * Nom de la table SQL (le plus souvent)
837 * Tolère un nom de clé primaire.
838 * @param string $serveur
839 * Nom du connecteur
840 * @return string
841 * Nom de l'objet
842 **/
843 function table_objet($type,$serveur='') {
844 $surnoms = lister_tables_objets_surnoms();
845 $type = preg_replace(',^spip_|^id_|s$,', '', $type);
846 if (!$type) return;
847 if (isset($surnoms[$type]))
848 return $surnoms[$type];
849
850 if ($serveur!==false){
851 $t=lister_tables_spip($serveur);
852 $trouver_table = charger_fonction('trouver_table', 'base');
853 $typetrim = rtrim($type,'s')."s";
854 if (
855 (isset($t[$typetrim]) OR in_array($typetrim,$t))
856 AND ($desc = $trouver_table(rtrim($type,'s')."s",$serveur))
857 )
858 return $desc['id_table'];
859 elseif (
860 (isset($t[$type]) OR in_array($type,$t))
861 AND ($desc = $trouver_table($type,$serveur))
862 )
863 return $desc['id_table'];
864
865 spip_log( 'table_objet('.$type.') calculee sans verification');
866 }
867
868 return rtrim($type,'s')."s"; # cas historique ne devant plus servir, sauf si $serveur=false
869 }
870
871 /**
872 * Retrouve la table sql à partir de l'objet ou du type
873 *
874 * - articles -> spip_articles
875 * - article -> spip_articles
876 * - id_article -> spip_articles
877 *
878 * @api
879 * @param string $type
880 * Nom ou type de l'objet
881 * Tolère un nom de clé primaire.
882 * @param string $serveur
883 * Nom du connecteur
884 * @return string
885 * Nom de la table SQL
886 **/
887 function table_objet_sql($type,$serveur='') {
888 global $table_des_tables;
889 $nom = table_objet($type, $serveur);
890 if (!isset($table_des_tables['articles'])) // eviter de multiples inclusions
891 include_spip('public/interfaces');
892 if (isset($table_des_tables[$nom])) {
893 $nom = $table_des_tables[$nom];
894 $nom = "spip_$nom";
895 }
896 else {
897 $infos_tables = lister_tables_objets_sql();
898 if (isset($infos_tables["spip_$nom"]))
899 $nom = "spip_$nom";
900 elseif($serveur!==false) {
901 $t=lister_tables_spip($serveur);
902 if (isset($t[$nom]) OR in_array($nom,$t)){
903 $trouver_table = charger_fonction('trouver_table', 'base');
904 if ($desc = $trouver_table($nom,$serveur))
905 return $desc['table_sql'];
906 }
907 }
908 }
909
910 return $nom ;
911 }
912
913 /**
914 * Retrouve la clé primaire à partir du nom d'objet ou de table
915 *
916 * - articles -> id_article
917 * - article -> id_article
918 * - spip_articles -> id_article
919 *
920 * @api
921 * @param string $type
922 * Nom de la table SQL ou de l'objet
923 * @param string $serveur
924 * Nom du connecteur
925 * @return string
926 * Nom de la clé primaire
927 **/
928 function id_table_objet($type,$serveur='') {
929 static $trouver_table = null;
930 $type = objet_type($type,$serveur);
931 if (!$type) return;
932 $t = table_objet($type);
933 if (!$trouver_table)
934 $trouver_table = charger_fonction('trouver_table', 'base');
935
936 $ts=lister_tables_spip($serveur);
937 if (in_array($t,$ts)){
938 $desc = $trouver_table($t,$serveur);
939 if (isset($desc['key']['PRIMARY KEY']))
940 return $desc['key']['PRIMARY KEY'];
941 if (!$desc OR isset($desc['field']["id_$type"]))
942 return "id_$type";
943 // sinon renvoyer le premier champ de la table...
944 $keys = array_keys($desc['field']);
945 return array_shift($keys);
946 }
947 return "id_$type";
948 }
949
950 /**
951 * Retrouve le type d'objet à partir du nom d'objet ou de table
952 *
953 * - articles -> article
954 * - spip_articles -> article
955 * - id_article -> article
956 *
957 * @api
958 * @param string $table_objet
959 * Nom de l'objet ou de la table SQL
960 * @param string $serveur
961 * Nom du connecteur
962 * @return string
963 * Type de l'objet
964 **/
965 function objet_type($table_objet, $serveur=''){
966 if (!$table_objet) return;
967 $surnoms = lister_types_surnoms();
968
969 // scenario de base
970 // le type est decline a partir du nom de la table en enlevant le prefixe eventuel
971 // et la marque du pluriel
972 // on accepte id_xx en entree aussi
973 $type = preg_replace(',^spip_|^id_|s$,', '', $table_objet);
974 if (isset($surnoms[$type]))
975 return $surnoms[$type];
976
977 // securite : eliminer les caracteres non \w
978 $type = preg_replace(',[^\w-],','',$type);
979
980 // si le type redonne bien la table c'est bon
981 // oui si table_objet ressemblait deja a un type
982 if ( $type==$table_objet
983 OR (table_objet($type,$serveur)==$table_objet)
984 OR (table_objet_sql($type,$serveur)==$table_objet))
985 return $type;
986
987 // si on ne veut pas chercher en base
988 if ($serveur===false)
989 return $type;
990
991 // sinon on passe par la cle primaire id_xx pour trouver le type
992 // car le s a la fin est incertain
993 // notamment en cas de pluriel derogatoire
994 // id_jeu/spip_jeux id_journal/spip_journaux qui necessitent tout deux
995 // une declaration jeu => jeux, journal => journaux
996 // dans le pipeline declarer_tables_objets_surnoms
997 $trouver_table = charger_fonction('trouver_table', 'base');
998 $ts=lister_tables_spip($serveur);
999 if (in_array($table_objet,$ts))
1000 $desc = $trouver_table($table_objet);
1001 if (!$desc AND in_array($table_objet=table_objet($type,$serveur),$ts))
1002 $desc = $trouver_table($table_objet,$serveur);
1003 // si le type est declare : bingo !
1004 if ($desc AND isset($desc['type']))
1005 return $desc['type'];
1006
1007 // on a fait ce qu'on a pu
1008 return $type;
1009 }
1010
1011 /**
1012 * Determininer si un objet est publie ou non
1013 *
1014 * On se base pour cela sur sa declaration de statut
1015 * pour des cas particuliers non declarables, on permet de fournir une fonction
1016 * base_xxxx_test_si_publie qui sera appele par la fonction
1017 *
1018 * @param string $objet
1019 * @param int $id_objet
1020 * @param string $serveur
1021 * @return bool
1022 */
1023 function objet_test_si_publie($objet,$id_objet, $serveur=''){
1024 // voir si une fonction est definie pour faire le boulot
1025 // elle a la priorite dans ce cas
1026 if ($f = charger_fonction($objet."_test_si_publie","base",true))
1027 return $f($objet,$id_objet, $serveur);
1028
1029 // sinon on se fie a la declaration de l'objet si presente
1030 $id_table = $table_objet = table_objet($objet);
1031 $id_table_objet = id_table_objet($objet, $serveur);
1032 $trouver_table = charger_fonction('trouver_table', 'base');
1033 if ($desc = $trouver_table($table_objet, $serveur)
1034 AND isset($desc['statut'])
1035 AND $desc['statut']){
1036 $boucle = new Boucle();
1037 $boucle->show = $desc;
1038 $boucle->nom = 'objet_test_si_publie';
1039 $boucle->id_boucle = $id_table;
1040 $boucle->id_table = $id_table;
1041 $boucle->sql_serveur = $serveur;
1042 $boucle->select[] = $id_table_objet;
1043 $boucle->from[$table_objet] = table_objet_sql($objet, $serveur);
1044 $boucle->where[] = $id_table.".".$id_table_objet.'='.intval($id_objet);
1045
1046 include_spip('public/compiler');
1047 include_spip('public/composer');
1048 instituer_boucle($boucle, false, true);
1049 $res = calculer_select($boucle->select,$boucle->from,$boucle->from_type,$boucle->where,$boucle->join,$boucle->group,$boucle->order,$boucle->limit,$boucle->having,$table_objet,$id_table,$serveur);
1050 if (sql_fetch($res))
1051 return true;
1052 return false;
1053 }
1054
1055 // si pas d'info statut ni de fonction : l'objet est publie
1056 return true;
1057 }