| Current Path : /home/etiennec/www/f1f54/ |
| Current File : /home/etiennec/www/f1f54/base.tar |
create.php 0000666 00000013331 15250255012 0006522 0 ustar 00 <?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;
include_spip('inc/acces');
include_spip('base/objets');
include_spip('base/typedoc');
include_spip('base/abstract_sql');
/**
* Determiner le flag autoinc pour une table
* en fonction de si c'est une table principale
*
* @param string $table
* @param array $desc
* @return bool
*/
function base_determine_autoinc($table,$desc=array()){
if ($t=lister_tables_principales() AND isset($t[$table]))
$autoinc = true;
elseif ($t=lister_tables_auxiliaires() AND isset($t[$table]))
$autoinc = false;
else {
// essayer de faire au mieux !
$autoinc = (isset($desc['key']['PRIMARY KEY'])
AND strpos($desc['key']['PRIMARY KEY'],',')===false
AND strpos($desc['field'][$desc['key']['PRIMARY KEY']],'default')===false);
}
return $autoinc;
}
/**
* Creer une table,
* ou ajouter les champs manquants si elle existe deja
*
* http://doc.spip.org/@creer_ou_upgrader_table
*
* @param string $table
* @param array $desc
* @param bool|string $autoinc
* 'auto' pour detecter automatiquement si le champ doit etre autoinc ou non
* en fonction de la table
* @param bool $upgrade
* @param string $serveur
* @return void
*/
function creer_ou_upgrader_table($table,$desc,$autoinc,$upgrade=false,$serveur='') {
#spip_log("creer_ou_upgrader_table table=$table autoinc=$autoinc upgrade=$upgrade","dbinstall"._LOG_INFO_IMPORTANTE);
$sql_desc = $upgrade ? sql_showtable($table,true,$serveur) : false;
#if (!$sql_desc) $sql_desc = false;
#spip_log("table=$table sql_desc:$sql_desc","dbinstall"._LOG_INFO_IMPORTANTE);
if (!$sql_desc) {
if ($autoinc==='auto')
$autoinc = base_determine_autoinc($table,$desc);
#spip_log("sql_create $table autoinc=$autoinc","dbinstall"._LOG_INFO_IMPORTANTE);
sql_create($table, $desc['field'], $desc['key'], $autoinc, false, $serveur);
// verifier la bonne installation de la table (php-fpm es-tu la ?)
$sql_desc = sql_showtable($table,true,$serveur);
#if (!$sql_desc) $sql_desc = false;
#spip_log("Resultat table=$table sql_desc:$sql_desc","dbinstall"._LOG_INFO_IMPORTANTE);
if (!$sql_desc){
// on retente avec un sleep ?
sleep(1);
sql_create($table, $desc['field'], $desc['key'], $autoinc, false, $serveur);
$sql_desc = sql_showtable($table,true,$serveur);
#if (!$sql_desc) $sql_desc = false;
#spip_log("Resultat table=$table sql_desc:$sql_desc","dbinstall"._LOG_INFO_IMPORTANTE);
if (!$sql_desc){
spip_log("Echec creation table $table","maj"._LOG_CRITIQUE);
}
}
}
else {
#spip_log("sql_alter $table ... (on s'en fiche)","dbinstall"._LOG_INFO_IMPORTANTE);
// ajouter les champs manquants
// on ne supprime jamais les champs, car c'est dangereux
// c'est toujours a faire manuellement
$last = '';
foreach($desc['field'] as $field=>$type){
if (!isset($sql_desc['field'][$field]))
sql_alter("TABLE $table ADD $field $type".($last?" AFTER $last":""),$serveur);
$last = $field;
}
foreach($desc['key'] as $key=>$type){
// Ne pas oublier les cas des cles non nommees dans la declaration et qui sont retournees
// par le showtable sous la forme d'un index de tableau "KEY $type" et non "KEY"
if (!isset($sql_desc['key'][$key]) AND !isset($sql_desc['key']["$key $type"]))
sql_alter("TABLE $table ADD $key ($type)",$serveur);
$last = $field;
}
}
}
/**
* Creer ou mettre a jour un ensemble de tables
* en fonction du flag $up
*
* @param array $tables_inc
* tables avec autoincrement sur la cle primaire
* @param $tables_noinc
* tables sans autoincrement sur la cle primaire
* @param bool|array $up
* upgrader (true) ou creer (false)
* si un tableau de table est fournie, seules l'intersection de ces tables
* et des $tables_inc / $tables_noinc seront traitees
* @param string $serveur
* serveur sql
* @return void
*/
function alterer_base($tables_inc, $tables_noinc, $up=false, $serveur='')
{
if ($up === false) {
$old = false;
$up = array();
} else {
$old = true;
if (!is_array($up)) $up = array($up);
}
foreach($tables_inc as $k => $v)
if (!$old OR in_array($k, $up))
creer_ou_upgrader_table($k,$v,true,$old,$serveur);
foreach($tables_noinc as $k => $v)
if (!$old OR in_array($k, $up))
creer_ou_upgrader_table($k,$v,false,$old,$serveur);
}
/**
* Creer une base de donnee
* a partir des tables principales et auxiliaires
*
* http://doc.spip.org/@creer_base
*
* @param string $serveur
* @return void
*/
function creer_base($serveur='') {
// Note: les mises a jour reexecutent ce code pour s'assurer
// de la conformite de la base
// pas de panique sur "already exists" et "duplicate entry" donc.
alterer_base(lister_tables_principales(),
lister_tables_auxiliaires(),
false,
$serveur);
}
/**
* Mettre a jour une liste de tables,
* fonction facilitatrice utilisee pour les maj de base
* dans les plugins
*
* @param array $upgrade_tables
* @param string $serveur
* @return void
*/
function maj_tables($upgrade_tables=array(),$serveur=''){
alterer_base(lister_tables_principales(),
lister_tables_auxiliaires(),
$upgrade_tables,
$serveur);
}
?>
index.php 0000666 00000000002 15250255012 0006355 0 ustar 00 X
auxiliaires.php 0000666 00000002015 15250255012 0007573 0 ustar 00 <?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. *
\***************************************************************************/
/**
* Déclare la liste des tables auxiliaires
*
* @todo
* Nettoyages à faire dans le core : on ne devrait plus appeler
* Ce fichier mais directement base/objets si nécessaire
*
* @package SPIP\SQL\Tables
**/
if (!defined('_ECRIRE_INC_VERSION')) return;
include_spip('base/objets');
lister_tables_objets_sql();
?>
upgrade.php 0000666 00000040175 15250255012 0006714 0 ustar 00 <?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;
/**
* Programme de mise a jour des tables SQL lors d'un chgt de version.
* L'entree dans cette fonction est reservee au maj de SPIP coeur
*
* Marche aussi pour les plugins en appelant directement la fonction maj_plugin
* Pour que ceux-ci profitent aussi de la reprise sur interruption,
* ils doivent simplement indiquer leur numero de version installee dans une meta
* et fournir le tableau maj a la fonction maj_plugin.
* La reprise sur timeout se fait alors par la page admin_plugin et jamais par ici
*
* http://doc.spip.org/@base_upgrade_dist
*
* @param string $titre
* @param string $reprise
* @return
*/
function base_upgrade_dist($titre='', $reprise='')
{
if (!$titre) return; // anti-testeur automatique
if ($GLOBALS['spip_version_base']!=$GLOBALS['meta']['version_installee']) {
if (!is_numeric(_request('reinstall'))) {
include_spip('base/create');
spip_log("recree les tables eventuellement disparues","maj."._LOG_INFO_IMPORTANTE);
creer_base();
}
// quand on rentre par ici, c'est toujours une mise a jour de SPIP
// lancement de l'upgrade SPIP
$res = maj_base();
if ($res) {
// on arrete tout ici !
exit;
}
}
spip_log("Fin de mise a jour SQL. Debut m-a-j acces et config","maj."._LOG_INFO_IMPORTANTE);
// supprimer quelques fichiers temporaires qui peuvent se retrouver invalides
@spip_unlink(_CACHE_RUBRIQUES);
@spip_unlink(_CACHE_PIPELINES);
@spip_unlink(_CACHE_PLUGINS_PATH);
@spip_unlink(_CACHE_PLUGINS_OPT);
@spip_unlink(_CACHE_PLUGINS_FCT);
@spip_unlink(_CACHE_CHEMIN);
@spip_unlink(_DIR_TMP."plugin_xml_cache.gz");
include_spip('inc/auth');
auth_synchroniser_distant();
$config = charger_fonction('config', 'inc');
$config();
}
/**
* MAJ de base de SPIP
*
* http://doc.spip.org/@maj_base
*
* @param int $version_cible
* @param string $redirect
* @return array|bool
*/
function maj_base($version_cible = 0, $redirect = '') {
global $spip_version_base;
$version_installee = @$GLOBALS['meta']['version_installee'];
//
// Si version nulle ou inexistante, c'est une nouvelle installation
// => ne pas passer par le processus de mise a jour.
// De meme en cas de version superieure: ca devait etre un test,
// il y a eu le message d'avertissement il doit savoir ce qu'il fait
//
// version_installee = 1.702; quand on a besoin de forcer une MAJ
spip_log("Version anterieure: $version_installee. Courante: $spip_version_base","maj."._LOG_INFO_IMPORTANTE);
if (!$version_installee OR ($spip_version_base < $version_installee)) {
sql_replace('spip_meta',
array('nom' => 'version_installee',
'valeur' => $spip_version_base,
'impt' => 'non'));
return false;
}
if (!upgrade_test()) return true;
$cible = ($version_cible ? $version_cible : $spip_version_base);
if ($version_installee <= 1.926) {
$n = floor($version_installee * 10);
while ($n < 19) {
$nom = sprintf("v%03d",$n);
$f = charger_fonction($nom, 'maj', true);
if ($f) {
spip_log( "$f repercute les modifications de la version " . ($n/10),"maj."._LOG_INFO_IMPORTANTE);
$f($version_installee, $spip_version_base);
} else spip_log( "pas de fonction pour la maj $n $nom","maj."._LOG_INFO_IMPORTANTE);
$n++;
}
include_spip('maj/v019_pre193');
v019_pre193($version_installee, $version_cible);
}
if ($version_installee < 2000) {
if ($version_installee < 2)
$version_installee = $version_installee*1000;
include_spip('maj/v019');
}
if ($cible < 2)
$cible = $cible*1000;
include_spip('maj/svn10000');
ksort($GLOBALS['maj']);
$res = maj_while($version_installee, $cible, $GLOBALS['maj'], 'version_installee','meta', $redirect, true);
if ($res) {
if (!is_array($res))
spip_log("Pb d'acces SQL a la mise a jour","maj."._LOG_INFO_ERREUR);
else {
echo _T('avis_operation_echec') . ' ' . join(' ', $res);
echo install_fin_html();
}
}
return $res;
}
/**
* Mise à jour d'un plugin de SPIP
*
* Fonction appelée par la fonction de maj d'un plugin.
* On lui fournit un tableau de fonctions élementaires
* dont l'indice est la version
*
* @param string $nom_meta_base_version
* Nom de la meta informant de la version du schéma de données du plugin installé dans SPIP
* @param string $version_cible
* Version du schéma de données dans le plugin (déclaré dans paquet.xml)
* @param array $maj
* Tableau d'actions à faire à l'installation (clé 'create') et pour chaque
* version intermédiaire entre la version actuelle du schéma du plugin dans SPIP
* et la version du schéma déclaré dans le plugin (ex. clé '1.1.0').
*
* Chaque valeur est un tableau contenant une liste de fonctions à exécuter,
* cette liste étant elle-même un tableau avec premier paramètre le nom de la fonction
* et les suivant les paramètres à lui passer
* @example
* array(
* 'create' => array(
* array('maj_tables', array('spip_rubriques', 'spip_articles')),
* array('creer_base)),
* '1.1.0' => array(
* array('sql_alter', 'TABLE spip_articles ADD INDEX truc (truc)'))
* )
* @param string $table_meta
* Nom de la table meta (sans le prefixe spip_) dans laquelle trouver la meta $nom_meta_base_version
* @return void
*/
function maj_plugin($nom_meta_base_version, $version_cible, $maj, $table_meta='meta'){
if ($table_meta!=='meta')
lire_metas($table_meta);
if ( (!isset($GLOBALS[$table_meta][$nom_meta_base_version]) )
|| (!spip_version_compare($current_version = $GLOBALS[$table_meta][$nom_meta_base_version],$version_cible,'='))){
// $maj['create'] contient les directives propres a la premiere creation de base
// c'est une operation derogatoire qui fait aboutir directement dans la version_cible
if (isset($maj['create'])){
if (!isset($GLOBALS[$table_meta][$nom_meta_base_version])){
// installation : on ne fait que l'operation create
$maj = array("init"=>$maj['create']);
// et on lui ajoute un appel a inc/config
// pour creer les metas par defaut
$config = charger_fonction('config','inc');
$maj[$version_cible] = array(array($config));
}
// dans tous les cas enlever cet index du tableau
unset($maj['create']);
}
// si init, deja dans le bon ordre
if (!isset($maj['init'])){
include_spip('inc/plugin'); // pour spip_version_compare
uksort($maj,'spip_version_compare');
}
// la redirection se fait par defaut sur la page d'administration des plugins
// sauf lorsque nous sommes sur l'installation de SPIP
// ou define _REDIRECT_MAJ_PLUGIN
$redirect = (defined('_REDIRECT_MAJ_PLUGIN')?_REDIRECT_MAJ_PLUGIN:generer_url_ecrire('admin_plugin'));
if (defined('_ECRIRE_INSTALL')) {
$redirect = parametre_url(generer_url_ecrire('install'),'etape', _request('etape'));
}
$res = maj_while($current_version, $version_cible, $maj, $nom_meta_base_version, $table_meta, $redirect);
if ($res) {
if (!is_array($res))
spip_log("Pb d'acces SQL a la mise a jour","maj."._LOG_INFO_ERREUR);
else {
echo "<p>"._T('avis_operation_echec') . ' ' . join(' ', $res)."</p>";
}
}
}
}
/**
* Relancer le hit de maj avant timeout
* si pas de redirect fourni, on redirige vers exec=upgrade pour finir
* ce qui doit etre une maj SPIP
*
* @param string $meta
* @param string $table
* @param string $redirect
* @return void
*/
function relance_maj($meta,$table,$redirect=''){
include_spip('inc/headers');
if (!$redirect){
// recuperer la valeur installee en cours
// on la tronque numeriquement, elle ne sert pas reellement
// sauf pour verifier que ce n'est pas oui ou non
// sinon is_numeric va echouer sur un numero de version 1.2.3
$installee = intval($GLOBALS[$table][$meta]);
$redirect = generer_url_ecrire('upgrade',"reinstall=$installee&meta=$meta&table=$table",true);
}
echo redirige_formulaire($redirect);
exit();
}
/**
* Initialiser la page pour l'affichage des progres de l'upgrade
* uniquement si la page n'a pas deja ete initilalisee
*
* @param string $installee
* @param string $meta
* @param string $table
* @return
*/
function maj_debut_page($installee,$meta,$table){
static $done = false;
if ($done) return;
include_spip('inc/minipres');
@ini_set("zlib.output_compression","0"); // pour permettre l'affichage au fur et a mesure
$timeout = _UPGRADE_TIME_OUT*2;
$titre = _T('titre_page_upgrade');
$balise_img = charger_filtre('balise_img');
$titre .= $balise_img(chemin_image('searching.gif'));
echo ( install_debut_html($titre));
// script de rechargement auto sur timeout
$redirect = generer_url_ecrire('upgrade',"reinstall=$installee&meta=$meta&table=$table",true);
echo http_script("window.setTimeout('location.href=\"".$redirect."\";',".($timeout*1000).")");
echo "<div style='text-align: left'>\n";
ob_flush();flush();
$done = true;
}
define('_UPGRADE_TIME_OUT', 20);
/**
* A partir des > 1.926 (i.e SPIP > 1.9.2), cette fonction gere les MAJ.
* Se relancer soi-meme pour eviter l'interruption pendant une operation SQL
* (qu'on espere pas trop longue chacune)
* evidemment en ecrivant dans la meta a quel numero on en est.
*
* Cette fonction peut servir aux plugins qui doivent donner comme arguments:
* 1. le numero de version courant (numero de version 1.2.3 ou entier)
* 2. le numero de version a atteindre (numero de version 1.2.3 ou entier)
* 3. le tableau des instructions de mise a jour a executer
* Pour profiter du mecanisme de reprise sur interruption il faut de plus
* 4. le nom de la meta permettant de retrouver tout ca
* 5. la table des meta ou elle se trouve ($table_prefix . '_meta' par defaut)
* (cf debut de fichier)
* en cas d'echec, cette fonction retourne un tableau (etape,sous-etape)
* sinon elle retourne un tableau vide
*
* les fonctions sql_xx appelees lors des maj sont supposees atomiques et ne sont pas relancees
* en cas de timeout
* mais les fonctions specifiques sont relancees jusqu'a ce qu'elles finissent
* elles doivent donc s'assurer de progresser a chaque reprise
*
* http://doc.spip.org/@maj_while
*
* @param $installee
* @param $cible
* @param $maj
* @param string $meta
* @param string $table
* @param string $redirect
* @param bool $debut_page
* @return array
*/
function maj_while($installee, $cible, $maj, $meta='', $table='meta', $redirect='', $debut_page = false)
{
# inclusions pour que les procedures d'upgrade disposent des fonctions de base
include_spip('base/create');
include_spip('base/abstract_sql');
$trouver_table = charger_fonction('trouver_table','base');
include_spip('inc/plugin'); // pour spip_version_compare
$n = 0;
$time = time();
// definir le timeout qui peut etre utilise dans les fonctions
// de maj qui durent trop longtemps
define('_TIME_OUT',$time+_UPGRADE_TIME_OUT);
reset($maj);
while (list($v,)=each($maj)) {
// si une maj pour cette version
if ($v=='init' OR
(spip_version_compare($v,$installee,'>')
AND spip_version_compare($v,$cible,'<='))) {
if ($debut_page)
maj_debut_page($v,$meta,$table);
echo "MAJ $v";
$etape = serie_alter($v, $maj[$v], $meta, $table, $redirect);
$trouver_table(''); // vider le cache des descriptions de table
# echec sur une etape en cours ?
# on sort
if ($etape) return array($v, $etape);
$n = time() - $time;
spip_log( "$table $meta: $v en $n secondes",'maj.'._LOG_INFO_IMPORTANTE);
if ($meta) ecrire_meta($meta, $installee=$v,'oui', $table);
echo "<br />";
}
if (time() >= _TIME_OUT) {
relance_maj($meta,$table,$redirect);
}
}
$trouver_table(''); // vider le cache des descriptions de table
// indispensable pour les chgt de versions qui n'ecrivent pas en base
// tant pis pour la redondance eventuelle avec ci-dessus
if ($meta) ecrire_meta($meta, $cible,'oui',$table);
spip_log( "MAJ terminee. $meta: $installee",'maj.'._LOG_INFO_IMPORTANTE);
return array();
}
/**
* Appliquer une serie de chgt qui risquent de partir en timeout
* (Alter cree une copie temporaire d'une table, c'est lourd)
*
* http://doc.spip.org/@serie_alter
*
* @param string $serie
* numero de version upgrade
* @param array $q
* tableau des operations pour cette version
* @param string $meta
* nom de la meta qui contient le numero de version
* @param string $table
* nom de la table meta
* @param string $redirect
* url de redirection en cas d'interruption
* @return int
*/
function serie_alter($serie, $q = array(), $meta='', $table='meta', $redirect='') {
$meta2 = $meta . '_maj_' . $serie;
$etape = intval(@$GLOBALS[$table][$meta2]);
foreach ($q as $i => $r) {
if ($i >= $etape) {
$msg = "maj $table $meta2 etape $i";
if (is_array($r)
AND function_exists($f = array_shift($r))) {
spip_log( "$msg: $f " . join(',',$r),'maj.'._LOG_INFO_IMPORTANTE);
// pour les fonctions atomiques sql_xx
// on enregistre le meta avant de lancer la fonction,
// de maniere a eviter de boucler sur timeout
// mais pour les fonctions complexes,
// il faut les rejouer jusqu'a achevement.
// C'est a elle d'assurer qu'elles progressent a chaque rappel
if (strncmp($f,"sql_",4)==0)
ecrire_meta($meta2, $i+1, 'non', $table);
echo " <span title='$i'>.</span>";
call_user_func_array($f, $r);
// si temps imparti depasse, on relance sans ecrire en meta
// car on est peut etre sorti sur timeout si c'est une fonction longue
if (time() >= _TIME_OUT) {
relance_maj($meta,$table,$redirect);
}
ecrire_meta($meta2, $i+1, 'non', $table);
spip_log( "$meta2: ok", 'maj.'._LOG_INFO_IMPORTANTE);
}
else {
if (!is_array($r))
spip_log("maj $i format incorrect","maj."._LOG_ERREUR);
else
spip_log("maj $i fonction $f non definie","maj."._LOG_ERREUR);
// en cas d'erreur serieuse, on s'arrete
// mais on permet de passer par dessus en rechargeant la page.
return $i+1;
}
}
}
effacer_meta($meta2, $table);
return 0;
}
// La fonction a appeler dans le tableau global $maj
// quand on rajoute des types MIME. cf par exemple la 1.953
// http://doc.spip.org/@upgrade_types_documents
function upgrade_types_documents() {
if (include_spip('base/medias')
AND function_exists('creer_base_types_doc'))
creer_base_types_doc();
}
// http://doc.spip.org/@upgrade_test
function upgrade_test() {
sql_drop_table("spip_test", true);
sql_create("spip_test", array('a' => 'int'));
sql_alter("TABLE spip_test ADD b INT");
sql_insertq('spip_test', array('b' => 1), array('field'=>array('b' => 'int')));
$result = sql_select('b', "spip_test");
// ne pas garder le resultat de la requete sinon sqlite3
// ne peut pas supprimer la table spip_test lors du sql_alter qui suit
// car cette table serait alors 'verouillee'
$result = $result?true:false;
sql_alter("TABLE spip_test DROP b");
return $result;
}
// pour versions <= 1.926
// http://doc.spip.org/@maj_version
function maj_version ($version, $test = true) {
if ($test) {
if ($version>=1.922)
ecrire_meta('version_installee', $version, 'oui');
else {
// on le fait manuellement, car ecrire_meta utilise le champs impt qui est absent sur les vieilles versions
$GLOBALS['meta']['version_installee'] = $version;
sql_updateq('spip_meta', array('valeur' => $version), "nom=" . sql_quote('version_installee') );
}
spip_log( "mise a jour de la base en $version","maj."._LOG_INFO_IMPORTANTE);
} else {
echo _T('alerte_maj_impossible', array('version' => $version));
exit;
}
}
// pour versions <= 1.926
// http://doc.spip.org/@upgrade_vers
function upgrade_vers($version, $version_installee, $version_cible = 0){
return ($version_installee<$version
AND (($version_cible>=$version) OR ($version_cible==0))
);
}
?>
repair.php 0000666 00000007474 15250255012 0006554 0 ustar 00 <?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;
// http://doc.spip.org/@base_admin_repair_dist
function base_repair_dist($titre='', $reprise='') {
$res = admin_repair_tables();
if (!$res) {
$res = "<div class='error'>"._T('avis_erreur_mysql').' '.sql_errno().': '.sql_error() ."</div>\n";
} else {
include_spip('inc/rubriques');
calculer_rubriques();
propager_les_secteurs();
}
include_spip('inc/minipres');
$res .= pipeline('base_admin_repair',$res);
echo minipres(_T('texte_tentative_recuperation'),
$res . generer_form_ecrire('accueil', '','',_T('public:accueil_site')));
}
// http://doc.spip.org/@admin_repair_plat
function admin_repair_plat(){
spip_log( "verification des documents joints", _LOG_INFO_IMPORTANTE);
$out = "";
$repertoire = array();
include_spip('inc/getdocument');
$res = sql_select('*','spip_documents',"fichier REGEXP CONCAT('^',extension,'[^/\]') AND distant='non'");
while ($row=sql_fetch($res)){
$ext = $row['extension'];
if (!$ext) {
spip_log("document sans extension: " . $row['id_document'], _LOG_INFO_IMPORTANTE);
continue;
}
if (!isset($repertoire[$ext])){
if (@file_exists($plat = _DIR_IMG. $ext .".plat"))
spip_unlink($plat);
$repertoire[$ext] = creer_repertoire_documents($ext);
if (preg_match(',_$,',$repertoire[$ext]))
$repertoire[$ext] = false;
}
if ($d=$repertoire[$ext]){
$d = substr($d,strlen(_DIR_IMG));
$src = $row['fichier'];
$dest = $d . substr($src,strlen($d));
if (@copy(_DIR_IMG . $src, _DIR_IMG . $dest)
AND file_exists(_DIR_IMG . $dest)) {
sql_updateq('spip_documents',array('fichier'=>$dest),'id_document='.intval($row['id_document']));
spip_unlink(_DIR_IMG . $src);
$out .= "$src => $dest<br />";
}
}
}
return $out;
}
// http://doc.spip.org/@admin_repair_tables
function admin_repair_tables() {
$repair = sql_repair('repair', NULL, 'continue');
// recreer les tables manquantes eventuelles
include_spip('base/create');
creer_base();
$connexion = $GLOBALS['connexions'][0];
$prefixe = $connexion['prefixe'];
$res1 = sql_showbase();
$res = "";
if ($res1) {
while ($r = sql_fetch($res1)) {
$tab = array_shift($r);
$class = "";
$m = "<strong>$tab</strong> ";
spip_log("Repare $tab", _LOG_INFO_IMPORTANTE);
// supprimer la meta avant de lancer la reparation
// car le repair peut etre long ; on ne veut pas boucler
effacer_meta('admin_repair');
if ($repair){
$result_repair = sql_repair($tab);
if (!$result_repair) return false;
}
// essayer de maj la table (creation de champs manquants)
maj_tables($tab);
$count = sql_countsel($tab);
if ($count>1)
$m .= "("._T('texte_compte_elements', array('count' => $count)).")\n";
else if ($count==1)
$m .= "("._T('texte_compte_element', array('count' => $count)).")\n";
else
$m .= "("._T('texte_vide').")\n";
if ($result_repair
AND $msg = join(" ", sql_fetch($result_repair)) . ' '
AND strpos($msg, ' OK ')==FALSE){
$class = " class='notice'";
$m .= "<br /><tt>".spip_htmlentities($msg)."</tt>\n";
}
else
$m .= " "._T('texte_table_ok');
$res .="<div$class>$m</div>";
}
}
return $res;
}
?>
dump.php 0000666 00000061404 15250255012 0006230 0 ustar 00 <?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. *
\***************************************************************************/
/**
*
* Fonctions de base pour la sauvegarde
* Boite a outil commune, sans prejuger de la methode de sauvegarde
*
*/
if (!defined('_ECRIRE_INC_VERSION')) return;
define('_VERSION_ARCHIVE', '1.3');
include_spip('base/serial');
include_spip('base/auxiliaires');
include_spip('public/interfaces'); // pour table_jointures
// NB: Ce fichier peut ajouter des tables (old-style)
// donc il faut l'inclure "en globals"
if ($f = find_in_path('mes_fonctions.php')) {
global $dossier_squelettes;
@include_once (_ROOT_CWD . $f);
}
if (@is_readable(_CACHE_PLUGINS_FCT)){
// chargement optimise precompile
include_once(_CACHE_PLUGINS_FCT);
}
function base_dump_meta_name($rub){
return $meta = "status_dump_{$rub}_" . abs($GLOBALS['visiteur_session']['id_auteur']);
}
function base_dump_dir($meta){
include_spip('inc/documents');
// determine upload va aussi initialiser l'index "restreint"
$maindir = determine_upload();
if (!$GLOBALS['visiteur_session']['restreint'])
$maindir = _DIR_DUMP;
$dir = sous_repertoire($maindir, $meta);
return $dir;
}
/**
* Lister toutes les tables d'un serveur
* en excluant eventuellement une liste fournie
*
* @param string $serveur
* @param array $tables
* @param array $exclude
* @param bool $affiche_vrai_prefixe
* @return array
*/
function base_lister_toutes_tables($serveur='', $tables=array(), $exclude = array(),$affiche_vrai_prefixe=false) {
spip_connect($serveur);
$connexion = $GLOBALS['connexions'][$serveur ? $serveur : 0];
$prefixe = $connexion['prefixe'];
$p = '/^' . $prefixe . '/';
$res = $tables;
foreach(sql_alltable(null,$serveur) as $t) {
if (preg_match($p, $t)) {
$t1 = preg_replace($p, 'spip', $t);
if (!in_array($t1, $tables) AND !in_array($t1, $exclude))
$res[]= ($affiche_vrai_prefixe?$t:$t1);
}
}
sort($res);
return $res;
}
/**
* Retrouver le prefixe des tables
* @param string $serveur
* @return string
*/
function base_prefixe_tables($serveur=''){
spip_connect($serveur);
$connexion = $GLOBALS['connexions'][$serveur ? $serveur : 0];
$prefixe = $connexion['prefixe'];
return $prefixe;
}
/**
* Fabrique la liste a cocher des tables a traiter (copie, delete, sauvegarde)
*
* @param string $name
* @param array $tables
* @param array $exclude
* @param array|null $post
* @param string $serveur
* @return array
*/
function base_saisie_tables($name, $tables, $exclude = array(), $post=null, $serveur='') {
include_spip('inc/filtres');
$res = array();
foreach ($tables as $k => $t) {
// par defaut tout est coche sauf les tables dans $exclude
if (is_null($post))
$check = (in_array($t,$exclude)?false:true);
// mais si on a poste une selection, la reprendre
else
$check = in_array($t,$post);
$res[$k] = "<input type='checkbox' value='$t' name='$name"
. "[]' id='$name$k'"
. ($check ? " checked='checked'" : '')
. "/>\n"
. "<label for='$name$k'>".$t."</label>"
. " ("
. sinon(singulier_ou_pluriel(sql_countsel($t,'','','',$serveur), 'dump:une_donnee', 'dump:nb_donnees'),_T('dump:aucune_donnee'))
. ")";
}
return $res;
}
/**
* Lister les tables non exportables par defaut
* (liste completable par le pipeline lister_tables_noexport
*
* @staticvar array $EXPORT_tables_noexport
* @return array
*/
function lister_tables_noexport(){
// par defaut tout est exporte sauf les tables ci-dessous
static $EXPORT_tables_noexport = null;
if (!is_null($EXPORT_tables_noexport))
return $EXPORT_tables_noexport;
$EXPORT_tables_noexport= array(
'spip_caches', // plugin invalideur
'spip_resultats', // resultats de recherche ... c'est un cache !
'spip_test', // c'est un test !
#'spip_referers',
#'spip_referers_articles',
#'spip_visites',
#'spip_visites_articles',
#'spip_versions',
#'spip_versions_fragments'
);
$EXPORT_tables_noexport = pipeline('lister_tables_noexport',$EXPORT_tables_noexport);
return $EXPORT_tables_noexport;
}
/**
* Lister les tables non importables par defaut
* (liste completable par le pipeline lister_tables_noimport
*
* @staticvar array $IMPORT_tables_noimport
* @return array
*/
function lister_tables_noimport(){
static $IMPORT_tables_noimport=null;
if (!is_null($IMPORT_tables_noimport))
return $IMPORT_tables_noimport;
$IMPORT_tables_noimport = array();
// par defaut tout est importe sauf les tables ci-dessous
// possibiliter de definir cela tables via la meta
// compatibilite
if (isset($GLOBALS['meta']['IMPORT_tables_noimport'])){
$IMPORT_tables_noimport = unserialize($GLOBALS['meta']['IMPORT_tables_noimport']);
if (!is_array($IMPORT_tables_noimport)){
include_spip('inc/meta');
effacer_meta('IMPORT_tables_noimport');
}
}
$IMPORT_tables_noimport = pipeline('lister_tables_noimport',$IMPORT_tables_noimport);
return $IMPORT_tables_noimport;
}
/**
* Lister les tables a ne pas effacer
* (liste completable par le pipeline lister_tables_noerase
*
* @staticvar array $IMPORT_tables_noerase
* @return array
*/
function lister_tables_noerase(){
static $IMPORT_tables_noerase=null;
if (!is_null($IMPORT_tables_noerase))
return $IMPORT_tables_noerase;
$IMPORT_tables_noerase = array(
'spip_meta',
// par defaut on ne vide pas les stats, car elles ne figurent pas dans les dump
// et le cas echeant, un bouton dans l'admin permet de les vider a la main...
'spip_referers',
'spip_referers_articles',
'spip_visites',
'spip_visites_articles'
);
$IMPORT_tables_noerase = pipeline('lister_tables_noerase',$IMPORT_tables_noerase);
return $IMPORT_tables_noerase;
}
/**
* construction de la liste des tables pour le dump :
* toutes les tables principales
* + toutes les tables auxiliaires hors relations
* + les tables relations dont les deux tables liees sont dans la liste
*
* @param array $exclude_tables
* @return array
*/
function base_liste_table_for_dump($exclude_tables = array()){
$tables_for_dump = array();
$tables_pointees = array();
$tables = array();
$tables_principales = $GLOBALS['tables_principales'];
$tables_auxiliaires = $GLOBALS['tables_auxiliaires'];
$tables_jointures = $GLOBALS['tables_jointures'];
if (include_spip('base/objets')
AND function_exists('lister_tables_objets_sql')){
$tables = lister_tables_objets_sql();
foreach($tables as $t=>$infos){
if ($infos['principale'] AND !isset($tables_principales[$t]))
$tables_principales[$t] = true;
if (!$infos['principale'] AND !isset($tables_auxiliaires[$t]))
$tables_auxiliaires[$t] = true;
if (count($infos['tables_jointures']))
$tables_jointures[$t] = array_merge(isset($tables_jointures[$t])?$tables_jointures[$t]:array(),$infos['tables_jointures']);
}
}
// on construit un index des tables de liens
// pour les ajouter SI les deux tables qu'ils connectent sont sauvegardees
$tables_for_link = array();
foreach($tables_jointures as $table => $liste_relations)
if (is_array($liste_relations))
{
$nom = $table;
if (!isset($tables_auxiliaires[$nom])&&!isset($tables_principales[$nom]))
$nom = "spip_$table";
if (isset($tables_auxiliaires[$nom])||isset($tables_principales[$nom])){
foreach($liste_relations as $link_table){
if (isset($tables_auxiliaires[$link_table])/*||isset($tables_principales[$link_table])*/){
$tables_for_link[$link_table][] = $nom;
}
else if (isset($tables_auxiliaires["spip_$link_table"])/*||isset($tables_principales["spip_$link_table"])*/){
$tables_for_link["spip_$link_table"][] = $nom;
}
}
}
}
$liste_tables = array_merge(array_keys($tables_principales),array_keys($tables_auxiliaires),array_keys($tables));
foreach($liste_tables as $table){
// $name = preg_replace("{^spip_}","",$table);
if ( !isset($tables_pointees[$table])
&& !in_array($table,$exclude_tables)
&& !isset($tables_for_link[$table])){
$tables_for_dump[] = $table;
$tables_pointees[$table] = 1;
}
}
foreach ($tables_for_link as $link_table =>$liste){
$connecte = true;
foreach($liste as $connect_table)
if (!in_array($connect_table,$tables_for_dump))
$connecte = false;
if ($connecte)
# on ajoute les liaisons en premier
# si une restauration est interrompue,
# cela se verra mieux si il manque des objets
# que des liens
array_unshift($tables_for_dump,$link_table);
}
return array($tables_for_dump, $tables_for_link);
}
/**
* Vider les tables de la base de destination
* pour la copie dans une base
*
* peut etre utilise pour l'import depuis xml,
* ou la copie de base a base (mysql<->sqlite par exemple)
*
* @param array $tables
* @param array $exclure_tables
* @param string $serveur
*/
function base_vider_tables_destination_copie($tables, $exclure_tables = array(), $serveur=''){
$trouver_table = charger_fonction('trouver_table', 'base');
spip_log('Vider '.count($tables) . " tables sur serveur '$serveur' : " . join(', ', $tables),'base.'._LOG_INFO_IMPORTANTE);
foreach($tables as $table){
if (!in_array($table,$exclure_tables)){
// sur le serveur principal, il ne faut pas supprimer l'auteur loge !
if (($table!='spip_auteurs') OR $serveur!=''){
// regarder si il y a au moins un champ impt='non'
$desc = $trouver_table($table,$serveur);
if (isset($desc['field']['impt'])){
sql_delete($table, "impt='oui'", $serveur);
}
else{
sql_delete($table, "", $serveur);
}
}
}
}
// sur le serveur principal, il ne faut pas supprimer l'auteur loge !
// Bidouille pour garder l'acces admin actuel pendant toute la restauration
if ($serveur==''
AND in_array('spip_auteurs',$tables)
AND !in_array('spip_auteurs',$exclure_tables)) {
base_conserver_copieur(true, $serveur);
sql_delete("spip_auteurs", "id_auteur>0",$serveur);
}
}
/**
* Conserver le copieur si besoin
* @param bool $move
* @param string $serveur
* @return void
*/
function base_conserver_copieur($move = true,$serveur=''){
// s'asurer qu'on a pas deja fait la manip !
if ($GLOBALS['visiteur_session']['id_auteur']>0 AND sql_countsel("spip_auteurs", "id_auteur>0")) {
spip_log('Conserver copieur '.$GLOBALS['visiteur_statut']['id_auteur'] . " dans id_auteur=".$GLOBALS['visiteur_statut']['id_auteur']." pour le serveur '$serveur'",'dump.'._LOG_INFO_IMPORTANTE);
sql_delete("spip_auteurs", "id_auteur<0",$serveur);
if ($move){
sql_updateq('spip_auteurs', array('id_auteur'=>-$GLOBALS['visiteur_session']['id_auteur']), "id_auteur=".intval($GLOBALS['visiteur_session']['id_auteur']),array(),$serveur);
}
else {
$row = sql_fetsel('*','spip_auteurs','id_auteur='.$GLOBALS['visiteur_session']['id_auteur'],'','','','',$serveur);
$row['id_auteur'] = -$GLOBALS['visiteur_session']['id_auteur'];
sql_insertq('spip_auteurs',$row,array(),$serveur);
}
}
}
/**
* Effacement de la bidouille ci-dessus
* Toutefois si la table des auteurs ne contient plus qu'elle
* c'est que la copie etait incomplete et on restaure le compte
* pour garder la connection au site
*
* (mais il doit pas etre bien beau
* et ca ne marche que si l'id_auteur est sur moins de 3 chiffres)
*
* @param string $serveur
*/
function base_detruire_copieur_si_besoin($serveur='')
{
// rien a faire si ce n'est pas le serveur principal !
if ($serveur=='') {
if (sql_countsel("spip_auteurs", "id_auteur>0")) {
spip_log("Detruire copieur id_auteur<0 pour le serveur '$serveur'",'dump.'._LOG_INFO_IMPORTANTE);
sql_delete("spip_auteurs", "id_auteur<0", $serveur);
}
else {
spip_log( "Restaurer copieur id_auteur<0 pour le serveur '$serveur' (aucun autre auteur en base)",'dump.'._LOG_INFO_IMPORTANTE);
sql_update('spip_auteurs', array('id_auteur'=>'-id_auteur'), "id_auteur<0");
}
}
else
spip_log("Pas de destruction copieur sur serveur '$serveur'",'dump.'._LOG_INFO_IMPORTANTE);
}
/**
* Preparer la table dans la base de destination :
* la droper si elle existe (sauf si auteurs ou meta sur le serveur principal)
* la creer si necessaire, ou ajouter simplement les champs manquants
*
* @param string $table
* @param array $desc
* @param string $serveur_dest
* @param bool $init
* @return array
*/
function base_preparer_table_dest($table, $desc, $serveur_dest, $init=false) {
$upgrade = false;
// si la table existe et qu'on est a l'init, la dropper
if ($desc_dest=sql_showtable($table,true,$serveur_dest) AND $init) {
if ($serveur_dest=='' AND in_array($table,array('spip_meta','spip_auteurs'))) {
// ne pas dropper auteurs et meta sur le serveur principal
// faire un simple upgrade a la place
// pour ajouter les champs manquants
$upgrade = true;
// coherence avec le drop sur les autres tables
base_vider_tables_destination_copie(array($table),array(),$serveur_dest);
if ($table=='spip_meta'){
// virer les version base qui vont venir avec l'import
sql_delete($table, "nom like '%_base_version'",$serveur_dest);
// hum casse la base si pas version_installee a l'import ...
sql_delete($table, "nom='version_installee'",$serveur_dest);
}
}
else {
sql_drop_table($table, '', $serveur_dest);
spip_log( "drop table '$table' sur serveur '$serveur_dest'",'dump.'._LOG_INFO_IMPORTANTE);
}
$desc_dest = false;
}
// si la table n'existe pas dans la destination, la creer a l'identique !
if (!$desc_dest) {
spip_log( "creation '$table' sur serveur '$serveur_dest'",'dump.'._LOG_INFO_IMPORTANTE);
include_spip('base/create');
creer_ou_upgrader_table($table, $desc, 'auto', $upgrade,$serveur_dest);
$desc_dest = sql_showtable($table,true,$serveur_dest);
}
if (!$desc_dest){
spip_log( "Erreur creation '$table' sur serveur '$serveur_dest'".var_export($desc,1),'dump.'._LOG_ERREUR);
}
return $desc_dest;
}
/**
* Copier de base a base
*
* @param string $status_file
* nom avec chemin complet du fichier ou est stocke le status courant
* @param array $tables
* liste des tables a copier
* @param string $serveur_source
* @param string $serveur_dest
* @param array $options
* parametres optionnels sous forme de tableau :
* param string $callback_progression
* fonction a appeler pour afficher la progression, avec les arguments (compteur,total,table)
* param int $max_time
* limite de temps au dela de laquelle sortir de la fonction proprement (de la forme time()+15)
* param bool $drop_source
* vider les tables sources apres copie
* param array $no_erase_dest
* liste des tables a ne pas vider systematiquement (ne seront videes que si existent dans la base source)
* param array $where
* liste optionnelle de condition where de selection des donnees pour chaque table
* param string $racine_fonctions_dest
* racine utilisee pour charger_fonction() des operations elementaires sur la base de destination.
* Permet de deleguer vers une autre voie de communication.
* Par defaut on utilise 'base', ce qui route vers les fonctions de ce fichier. Concerne :
* - vider_tables_destination_copie
* - preparer_table_dest
* - detruire_copieur_si_besoin
* - inserer_copie
* param array $fonction_base_inserer
* fonction d'insertion en base. Par defaut "inserer_copie" qui fait un insertq a l'identique.
* Attention, la fonction appelee est prefixee par $racine_fonctions_dest via un charger_fonction()
* Peut etre personalisee pour filtrer, renumeroter....
* param array $desc_tables_dest
* description des tables de destination a utiliser de preference a la description de la table source
* param int data_pool
* nombre de ko de donnees a envoyer d'un coup en insertion dans la table cible (par defaut 1)
* permet des envois groupes pour plus de rapidite, notamment si l'insertion est distante
*
* @return bool
*/
function base_copier_tables($status_file, $tables, $serveur_source, $serveur_dest, $options=array()){
$callback_progression = isset($options['callback_progression'])?$options['callback_progression']:'';
$max_time = isset($options['max_time'])?$options['max_time']:0;
$drop_source = isset($options['drop_source'])?$options['drop_source']:false;
$no_erase_dest = isset($options['no_erase_dest'])?$options['no_erase_dest']:array();
$where = isset($options['where'])?$options['where']:array();
$fonction_base_inserer = isset($options['fonction_base_inserer'])?$options['fonction_base_inserer']:'inserer_copie';
$desc_tables_dest = isset($options['desc_tables_dest'])?$options['desc_tables_dest']:array();
$racine_fonctions = (isset($options['racine_fonctions_dest'])?$options['racine_fonctions_dest']:'base');
$data_pool = (isset($options['data_pool'])?$options['data_pool']:50*1024);
spip_log( "Copier ".count($tables)." tables de '$serveur_source' vers '$serveur_dest'",'dump.'._LOG_INFO_IMPORTANTE);
if (!$inserer_copie = charger_fonction($fonction_base_inserer,$racine_fonctions, true)) {
spip_log( "Fonction '{$racine_fonctions}_$fonction_base_inserer' inconnue. Abandon",'dump.'._LOG_INFO_IMPORTANTE);
return true; // echec mais on a fini, donc true
}
if (!$preparer_table_dest = charger_fonction('preparer_table_dest',$racine_fonctions, true)) {
spip_log( "Fonction '{$racine_fonctions}_$preparer_table_dest' inconnue. Abandon",'dump.'._LOG_INFO_IMPORTANTE);
return true; // echec mais on a fini, donc true
}
if (!lire_fichier($status_file, $status)
OR !$status = unserialize($status))
$status = array();
$status['etape'] = 'basecopie';
// puis relister les tables a importer
// et les vider si besoin, au moment du premier passage ici
$initialisation_copie = (!isset($status["dump_status_copie"])) ? 0 : $status["dump_status_copie"];
// si init pas encore faite, vider les tables du serveur destination
if (!$initialisation_copie) {
if (!$vider_tables_destination_copie = charger_fonction('vider_tables_destination_copie',$racine_fonctions, true)) {
spip_log( "Fonction '{$racine_fonctions}_vider_tables_destination_copie' inconnue. Abandon",'dump.'._LOG_INFO_IMPORTANTE);
return true; // echec mais on a fini, donc true
}
$vider_tables_destination_copie($tables, $no_erase_dest, $serveur_dest);
$status["dump_status_copie"]='ok';
ecrire_fichier($status_file,serialize($status));
}
// les tables auteurs et meta doivent etre copiees en dernier !
if (in_array('spip_auteurs',$tables)){
$tables = array_diff($tables,array('spip_auteurs'));
$tables[] = 'spip_auteurs';
}
if (in_array('spip_meta',$tables)){
$tables = array_diff($tables,array('spip_meta'));
$tables[] = 'spip_meta';
}
spip_log( "Tables a copier :".implode(", ",$tables),'dump.'._LOG_INFO);
$trouver_table = charger_fonction('trouver_table','base');
foreach ($tables as $table){
// si table commence par spip_ c'est une table SPIP, renommer le prefixe si besoin
// sinon chercher la vraie table
$desc_source = false;
if (strncmp($table,"spip_",5)==0){
$desc_source = $trouver_table(preg_replace(",^spip_,","",$table), $serveur_source, true);
}
if (!$desc_source OR !isset($desc_source['exist']) OR !$desc_source['exist'])
$desc_source = $trouver_table($table, $serveur_source, false);
// verifier que la table est presente dans la base source
if ($desc_source){
// $status['tables_copiees'][$table] contient l'avancement
// de la copie pour la $table : 0 a N et -N quand elle est finie (-1 si vide et finie...)
if (!isset($status['tables_copiees'][$table]))
$status['tables_copiees'][$table] = 0;
if (is_numeric($status['tables_copiees'][$table])
AND $status['tables_copiees'][$table]>=0
AND $desc_dest = $preparer_table_dest(
$table,
isset($desc_tables_dest[$table])?$desc_tables_dest[$table]:$desc_source,
$serveur_dest,
$status['tables_copiees'][$table] == 0)){
if ($callback_progression)
$callback_progression($status['tables_copiees'][$table],0,$table);
while (true) {
$n = intval($status['tables_copiees'][$table]);
// on copie par lot de 400
$res = sql_select('*',$table,isset($where[$table])?$where[$table]:'','','',"$n,400",'',$serveur_source);
while ($row = sql_fetch($res,$serveur_source)){
$rows = array($row);
// lire un groupe de donnees si demande en option
// (permet un envoi par lot vers la destination)
if ($data_pool>0){
$s = strlen(serialize($row));
while ($s<$data_pool AND $row = sql_fetch($res,$serveur_source)){
$s += strlen(serialize($row));
$rows[]= $row;
}
}
// si l'enregistrement est deja en base, ca fera un echec ou un doublon
// mais si ca renvoie false c'est une erreur fatale => abandon
if ($inserer_copie($table,$rows,$desc_dest,$serveur_dest)===false) {
// forcer la sortie, charge a l'appelant de gerer l'echec
spip_log("Erreur fatale dans $inserer_copie table $table","dump"._LOG_ERREUR);
$status['errors'][] = "Erreur fatale lors de la copie de la table $table";
ecrire_fichier($status_file,serialize($status));
// copie finie
return true;
}
$status['tables_copiees'][$table]+=count($rows);
if ($max_time AND time()>$max_time)
break;
}
if ($n == $status['tables_copiees'][$table])
break;
spip_log( "recopie $table ".$status['tables_copiees'][$table],'dump.'._LOG_INFO_IMPORTANTE);
if ($callback_progression)
$callback_progression($status['tables_copiees'][$table],0,$table);
ecrire_fichier($status_file,serialize($status));
if ($max_time AND time()>$max_time)
return false; // on a pas fini, mais le temps imparti est ecoule
}
if ($drop_source) {
sql_drop_table($table,'',$serveur_source);
spip_log( "drop $table sur serveur source '$serveur_source'",'dump.'._LOG_INFO_IMPORTANTE);
}
$status['tables_copiees'][$table]=($status['tables_copiees'][$table]?-$status['tables_copiees'][$table]:"zero");
ecrire_fichier($status_file,serialize($status));
spip_log( "tables_recopiees ".implode(',',$status['tables_copiees']),'dump.'._LOG_INFO);
if ($callback_progression)
$callback_progression($status['tables_copiees'][$table],$status['tables_copiees'][$table],$table);
}
else {
if ($status['tables_copiees'][$table]<0)
spip_log("Table $table deja copiee : ".$status['tables_copiees'][$table],"dump."._LOG_INFO);
if ($callback_progression)
$callback_progression(0,$status['tables_copiees'][$table],"$table".((is_numeric($status['tables_copiees'][$table]) AND $status['tables_copiees'][$table]>=0)?"[Echec]":""));
}
}
else {
$status['errors'][] = "Impossible de lire la description de la table $table";
ecrire_fichier($status_file,serialize($status));
spip_log("Impossible de lire la description de la table $table","dump."._LOG_ERREUR);
}
}
// si le nombre de tables envoyees n'est pas egal au nombre de tables demandees
// abandonner
if (count($status['tables_copiees'])<count($tables)){
spip_log("Nombre de tables copiees incorrect : ".count($status['tables_copiees'])."/".count($tables),"dump."._LOG_ERREUR);
$status['errors'][] = "Nombre de tables copiees incorrect : ".count($status['tables_copiees'])."/".count($tables);
ecrire_fichier($status_file,serialize($status));
}
if ($detruire_copieur_si_besoin = charger_fonction('detruire_copieur_si_besoin',$racine_fonctions, true)) {
$detruire_copieur_si_besoin($serveur_dest);
}
else {
spip_log( "Fonction '{$racine_fonctions}_detruire_copieur_si_besoin' inconnue.",'dump.'._LOG_INFO_IMPORTANTE);
}
// OK, copie complete
return true;
}
/**
* fonction d'insertion en base lors de la copie de base a base
*
* @param string $table
* @param array $rows
* @param array $desc_dest
* @param string $serveur_dest
* @return int/bool
*/
function base_inserer_copie($table,$rows,$desc_dest,$serveur_dest){
// verifier le nombre d'insertion
$nb1 = sql_countsel($table,'','','',$serveur_dest);
// si l'enregistrement est deja en base, ca fera un echec ou un doublon
$r = sql_insertq_multi($table,$rows,$desc_dest,$serveur_dest);
$nb = sql_countsel($table,'','','',$serveur_dest);
if ($nb-$nb1<count($rows)){
spip_log("base_inserer_copie : ".($nb-$nb1)." insertions au lieu de ".count($rows).". On retente 1 par 1","dump"._LOG_INFO_IMPORTANTE);
foreach($rows as $row){
// si l'enregistrement est deja en base, ca fera un echec ou un doublon
$r = sql_insertq($table,$row,$desc_dest,$serveur_dest);
}
// on reverifie le total
$r = 0;
$nb = sql_countsel($table,'','','',$serveur_dest);
if ($nb-$nb1<count($rows)){
spip_log("base_inserer_copie : ".($nb-$nb1)." insertions au lieu de ".count($rows)." apres insertion 1 par 1","dump"._LOG_ERREUR);
$r = false;
}
}
return $r;
}
?>
serial.php 0000666 00000002015 15250255012 0006533 0 ustar 00 <?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. *
\***************************************************************************/
/**
* Déclare la liste des tables principales
*
* @todo
* Nettoyages à faire dans le core : on ne devrait plus appeler
* Ce fichier mais directement base/objets si nécessaire
*
* @package SPIP\SQL\Tables
**/
if (!defined('_ECRIRE_INC_VERSION')) return;
include_spip('base/objets');
lister_tables_objets_sql();
?>
connect_sql.php 0000666 00000030612 15250255012 0007570 0 ustar 00 <?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;
include_spip('base/objets');
//
// Utilitaires indispensables autour des serveurs SQL
//
// API d'appel aux bases de donnees:
// on charge le fichier config/$serveur ($serveur='connect' pour le principal)
// qui est cense initaliser la connexion en appelant spip_connect_db
// laquelle met dans la globale db_ok la description de la connexion
// On la memorise dans un tableau pour permettre plusieurs serveurs.
// A l'installation, il faut simuler l'existence de ce fichier
// http://doc.spip.org/@spip_connect
function spip_connect($serveur='', $version='') {
global $connexions, $spip_sql_version;
$serveur = !is_string($serveur) ? '' : strtolower($serveur);
$index = $serveur ? $serveur : 0;
if (!$version) $version = $spip_sql_version;
if (isset($connexions[$index][$version])) return $connexions[$index];
include_spip('base/abstract_sql');
$install = (_request('exec') == 'install');
// Premiere connexion ?
if (!($old = isset($connexions[$index]))) {
$f = (!preg_match('/^[\w\.]*$/', $serveur))
? '' // nom de serveur mal ecrit
: ($serveur ?
( _DIR_CONNECT. $serveur . '.php') // serveur externe
: (_FILE_CONNECT ? _FILE_CONNECT // serveur principal ok
: ($install ? _FILE_CONNECT_TMP // init du serveur principal
: ''))); // installation pas faite
unset($GLOBALS['db_ok']);
unset($GLOBALS['spip_connect_version']);
if ($f) {
if (is_readable($f)) {
include($f);
} elseif ($serveur AND !$install) {
// chercher une declaration de serveur dans le path
// qui pourra un jour servir a declarer des bases sqlite
// par des plugins. Et sert aussi aux boucles POUR.
find_in_path("$serveur.php",'connect/',true);
}
}
if (!isset($GLOBALS['db_ok'])) {
// fera mieux la prochaine fois
if ($install) return false;
if ($f AND is_readable($f))
spip_log("spip_connect: fichier de connexion '$f' OK.", _LOG_INFO_IMPORTANTE);
else
spip_log("spip_connect: fichier de connexion '$f' non trouve", _LOG_INFO_IMPORTANTE);
spip_log("spip_connect: echec connexion ou serveur $index mal defini dans '$f'.", _LOG_HS);
// ne plus reessayer si ce n'est pas l'install
return $connexions[$index]=false;
}
$connexions[$index] = $GLOBALS['db_ok'];
}
// si la connexion a deja ete tentee mais a echoue, le dire!
if (!$connexions[$index]) return false;
// la connexion a reussi ou etait deja faite.
// chargement de la version du jeu de fonctions
// si pas dans le fichier par defaut
$type = $GLOBALS['db_ok']['type'];
$jeu = 'spip_' . $type .'_functions_' . $version;
if (!isset($GLOBALS[$jeu])) {
if (!find_in_path($type . '_' . $version . '.php', 'req/', true)){
spip_log("spip_connect: serveur $index version '$version' non defini pour '$type'", _LOG_HS);
// ne plus reessayer
return $connexions[$index][$version] = array();
}
}
$connexions[$index][$version] = $GLOBALS[$jeu];
if ($old) return $connexions[$index];
$connexions[$index]['spip_connect_version'] = isset($GLOBALS['spip_connect_version']) ? $GLOBALS['spip_connect_version'] : 0;
// initialisation de l'alphabet utilise dans les connexions SQL
// si l'installation l'a determine.
// Celui du serveur principal l'impose aux serveurs secondaires
// s'ils le connaissent
if (!$serveur) {
$charset = spip_connect_main($GLOBALS[$jeu]);
if (!$charset) {
unset($connexions[$index]);
spip_log("spip_connect: absence de charset", _LOG_AVERTISSEMENT);
return false;
}
} else {
// spip_meta n'existe pas toujours dans la base
// C'est le cas d'un dump sqlite par exemple
if ($connexions[$index]['spip_connect_version']
AND sql_showtable('spip_meta', true, $serveur)
AND $r = sql_getfetsel('valeur', 'spip_meta', "nom='charset_sql_connexion'",'','','','',$serveur))
$charset = $r;
else $charset = -1;
}
if ($charset != -1) {
$f = $GLOBALS[$jeu]['set_charset'];
if (function_exists($f))
$f($charset, $serveur);
}
return $connexions[$index];
}
function spip_sql_erreur($serveur='')
{
$connexion = spip_connect($serveur);
$e = sql_errno($serveur);
$t = (isset($connexion['type']) ? $connexion['type'] : 'sql');
$m = "Erreur $e de $t: " . sql_error($serveur) . "\n" . $connexion['last'];
$f = $t . $serveur;
spip_log($m, $f.'.'._LOG_ERREUR);
}
// Cette fonction ne doit etre appelee qu'a travers la fonction sql_serveur
// definie dans base/abstract_sql
// Elle existe en tant que gestionnaire de versions,
// connue seulement des convertisseurs automatiques
// http://doc.spip.org/@spip_connect_sql
function spip_connect_sql($version, $ins='', $serveur='', $cont=false) {
$desc = spip_connect($serveur, $version);
if (function_exists($f = @$desc[$version][$ins])) return $f;
if ($cont) return $desc;
if ($ins)
spip_log("Le serveur '$serveur' version $version n'a pas '$ins'", _LOG_ERREUR);
include_spip('inc/minipres');
echo minipres(_T('info_travaux_titre'), _T('titre_probleme_technique'));
exit;
}
/**
* Fonction appelee par le fichier cree dans config/ a l'instal'.
* Il contient un appel direct a cette fonction avec comme arguments
* les identifants de connexion.
* Si la connexion reussit, la globale db_ok memorise sa description.
* C'est un tableau egalement retourne en valeur, pour les appels a l'install'
*
* http://doc.spip.org/@spip_connect_db
*
* @param string $host
* @param string $port
* @param string $login
* @param string $pass
* @param string $db
* @param string $type
* @param string $prefixe
* @param string $auth
* @return array
*/
function spip_connect_db($host, $port, $login, $pass, $db='', $type='mysql', $prefixe='', $auth='') {
global $db_ok;
// temps avant nouvelle tentative de connexion
// suite a une connection echouee
if (!defined('_CONNECT_RETRY_DELAY'))
define('_CONNECT_RETRY_DELAY',30);
$f = "";
// un fichier de identifiant par combinaison (type,host,port,db)
// pour ne pas declarer tout indisponible d'un coup
// si en cours d'installation ou si db=@test@ on ne pose rien
// car c'est un test de connexion
if (!defined('_ECRIRE_INSTALL') AND !$db=="@test@")
$f = _DIR_TMP . $type . '.' . substr(md5($host.$port.$db),0,8) . '.out';
elseif ($db=='@test@')
$db = '';
if ($f
AND @file_exists($f)
AND (time() - @filemtime($f) < _CONNECT_RETRY_DELAY)) {
spip_log( "Echec : $f recent. Pas de tentative de connexion", _LOG_HS);
return;
}
if (!$prefixe)
$prefixe = isset($GLOBALS['table_prefix'])
? $GLOBALS['table_prefix'] : $db;
$h = charger_fonction($type, 'req', true);
if (!$h) {
spip_log( "les requetes $type ne sont pas fournies", _LOG_HS);
return;
}
if ($g = $h($host, $port, $login, $pass, $db, $prefixe)) {
if (!is_array($auth)) {
// compatibilite version 0.7 initiale
$g['ldap'] = $auth;
$auth = array('ldap' => $auth);
}
$g['authentification'] = $auth;
$g['type'] = $type;
return $db_ok = $g;
}
// En cas d'indisponibilite du serveur, eviter de le bombarder
if ($f) {
@touch($f);
spip_log( "Echec connexion serveur $type : host[$host] port[$port] login[$login] base[$db]", $type.'.'._LOG_HS);
}
}
// Premiere connexion au serveur principal:
// retourner le charset donnee par la table principale
// mais verifier que le fichier de connexion n'est pas trop vieux
// Version courante = 0.7
// La version 0.7 indique un serveur d'authentification comme 8e arg
// La version 0.6 indique le prefixe comme 7e arg
// La version 0.5 indique le serveur comme 6e arg
//
// La version 0.0 (non numerotee) doit etre refaite par un admin
// les autres fonctionnent toujours, meme si :
// - la version 0.1 est moins performante que la 0.2
// - la 0.2 fait un include_ecrire('inc_db_mysql.php3').
// http://doc.spip.org/@spip_connect_main
function spip_connect_main($connexion)
{
if ($GLOBALS['spip_connect_version']< 0.1 AND _DIR_RESTREINT){
include_spip('inc/headers');
redirige_url_ecrire('upgrade', 'reinstall=oui');
}
if (!($f = $connexion['select'])) return false;
// en cas d'erreur select retourne la requette (is_string=true donc)
if (!$r = $f('valeur','spip_meta', "nom='charset_sql_connexion'")
OR is_string($r))
return false;
if (!($f = $connexion['fetch'])) return false;
$r = $f($r);
return ($r['valeur'] ? $r['valeur'] : -1);
}
// compatibilite
function spip_connect_ldap($serveur='') {
include_spip('auth/ldap');
return auth_ldap_connect($serveur);
}
// Echappement d'une valeur (num, string, array) sous forme de chaine PHP
// pour un array(1,'a',"a'") renvoie la chaine "'1','a','a\''"
// Usage sql un peu deprecie, a remplacer par sql_quote()
// http://doc.spip.org/@_q
function _q ($a) {
return (is_numeric($a)) ? strval($a) :
(!is_array($a) ? ("'" . addslashes($a) . "'")
: join(",", array_map('_q', $a)));
}
// Recuperer le nom de la table de jointure xxxx sur l'objet yyyy
// http://doc.spip.org/@table_jointure
function table_jointure($x, $y) {
$trouver_table = charger_fonction('trouver_table', 'base');
$xdesc = $trouver_table(table_objet($x));
$ydesc = $trouver_table(table_objet($y));
$ix = @$xdesc['key']["PRIMARY KEY"];
$iy = @$ydesc['key']["PRIMARY KEY"];
if ($table = $ydesc['tables_jointures'][$ix]) return $table;
if ($table = $xdesc['tables_jointures'][$iy]) return $table;
return '';
}
/**
* Echapper les textes entre ' ' ou " " d'une requete SQL
* avant son pre-traitement
* On renvoi la query sans textes et les textes separes, dans
* leur ordre d'apparition dans la query
*
* @param string $query
* @return array
*/
function query_echappe_textes($query){
static $codeEchappements = array("''"=>"\x1@##@\x1", "\'"=>"\x2@##@\x2", "\\\""=>"\x3@##@\x3");
$query = str_replace(array_keys($codeEchappements), array_values($codeEchappements), $query);
if (preg_match_all("/((['])[^']*(\\2))|(([\"])[^\"]*(\\5))/S",$query,$textes)){
$textes = reset($textes); // indice 0 du match
switch(count($textes)){
case 0:$replace=array();break;
case 1:$replace=array('%1$s');break;
case 2:$replace=array('%1$s','%2$s');break;
case 3:$replace=array('%1$s','%2$s','%3$s');break;
case 4:$replace=array('%1$s','%2$s','%3$s','%4$s');break;
case 5:$replace=array('%1$s','%2$s','%3$s','%4$s','%5$s');break;
default:
$replace = range(1,count($textes));
$replace = '%'.implode('$s,%',$replace).'$s';
$replace = explode(',',$replace);
break;
}
$query = str_replace($textes,$replace,$query);
}
else
$textes = array();
return array($query, $textes);
}
/**
* Reinjecter les textes d'une requete SQL a leur place initiale,
* apres traitement de la requete
*
* @param string $query
* @param array $textes
* @return string
*/
function query_reinjecte_textes($query, $textes){
static $codeEchappements = array("''"=>"\x1@##@\x1", "\'"=>"\x2@##@\x2", "\\\""=>"\x3@##@\x3");
# debug de la substitution
#if (($c1=substr_count($query,"%"))!=($c2=count($textes))){
# spip_log("$c1 ::". $query,"tradquery"._LOG_ERREUR);
# spip_log("$c2 ::". var_export($textes,1),"tradquery"._LOG_ERREUR);
# spip_log("ini ::". $qi,"tradquery"._LOG_ERREUR);
#}
switch (count($textes)){
case 0:break;
case 1:$query=sprintf($query,$textes[0]);break;
case 2:$query=sprintf($query,$textes[0],$textes[1]);break;
case 3:$query=sprintf($query,$textes[0],$textes[1],$textes[2]);break;
case 4:$query=sprintf($query,$textes[0],$textes[1],$textes[2],$textes[3]);break;
case 5:$query=sprintf($query,$textes[0],$textes[1],$textes[2],$textes[3],$textes[4]);break;
default:
array_unshift($textes,$query);
$query = call_user_func_array('sprintf',$textes);
break;
}
$query = str_replace(array_values($codeEchappements), array_keys($codeEchappements), $query);
return $query;
}
// Pour compatibilite. Ne plus utiliser.
// http://doc.spip.org/@spip_query
function spip_query($query, $serveur='') {
global $spip_sql_version;
$f = spip_connect_sql($spip_sql_version, 'query', $serveur, true);
return function_exists($f) ? $f($query, $serveur) : false;
}
?>
abstract_sql.php 0000666 00000123577 15250255012 0007757 0 ustar 00 <?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. *
\***************************************************************************/
/**
* Definition de l'API SQL
*
* Ce fichier definit la couche d'abstraction entre SPIP et ses serveurs SQL.
* Cette version 1 est un ensemble de fonctions ecrites rapidement
* pour generaliser le code strictement MySQL de SPIP <= 1.9.2
* Des retouches sont a prevoir apres l'experience des premiers portages.
* Les symboles sql_* (constantes et nom de fonctions) sont reserves
* a cette interface, sans quoi le gestionnaire de version dysfonctionnera.
*
* @package SPIP\SQL\API
* @version 1
*/
if (!defined('_ECRIRE_INC_VERSION')) return;
/** Version de l'API SQL */
define('sql_ABSTRACT_VERSION', 1);
include_spip('base/connect_sql');
/**
* Charge le serveur de base de donnees
*
* Fonction principale. Elle charge l'interface au serveur de base de donnees
* via la fonction spip_connect_version qui etablira la connexion au besoin.
* Elle retourne la fonction produisant la requete SQL demandee
* Erreur fatale si la fonctionnalite est absente sauf si le 3e arg <> false
*
* @internal Cette fonction de base est appelee par les autres fonctions sql_*
* @param string $ins_sql
* Instruction de l'API SQL demandee (insertq, update, select...)
* @param string $serveur
* Nom du connecteur ('' pour celui par defaut a l'installation de SPIP)
* @param bool $continue
* true pour ne pas generer d'erreur si le serveur SQL ne dispose pas de la fonction demandee
* @return string|array
* Nom de la fonction a appeler pour l'instruction demandee pour le type de serveur SQL correspondant au fichier de connexion.
* Si l'instruction demandee n'existe pas, retourne la liste de toutes les instructions du serveur SQL avec $continue a true.
*
**/
function sql_serveur($ins_sql='', $serveur='', $continue=false) {
static $sql_serveur = array();
if (!isset($sql_serveur[$serveur][$ins_sql])){
$f = spip_connect_sql(sql_ABSTRACT_VERSION, $ins_sql, $serveur, $continue);
if (!is_string($f) OR !$f) return $f;
$sql_serveur[$serveur][$ins_sql] = $f;
}
return $sql_serveur[$serveur][$ins_sql];
}
/**
* Demande si un charset est disponible
*
* Demande si un charset (tel que utf-8) est disponible
* sur le gestionnaire de base de donnees de la connexion utilisee
*
* @api
* @see sql_set_charset() pour utiliser un charset
*
* @param string $charset
* Le charset souhaite
* @param string $serveur
* Le nom du connecteur
* @param bool $option
* Inutilise
* @return string|bool
* Retourne le nom du charset si effectivement trouve, sinon false.
**/
function sql_get_charset($charset, $serveur='', $option=true){
// le nom http du charset differe parfois du nom SQL utf-8 ==> utf8 etc.
$desc = sql_serveur('', $serveur, true,true);
$desc = $desc[sql_ABSTRACT_VERSION];
$c = $desc['charsets'][$charset];
if ($c) {
if (function_exists($f=@$desc['get_charset']))
if ($f($c, $serveur, $option!==false)) return $c;
}
spip_log( "SPIP ne connait pas les Charsets disponibles sur le serveur $serveur. Le serveur choisira seul.", _LOG_AVERTISSEMENT);
return false;
}
/**
* Regler le codage de connexion
*
* Affecte un charset (tel que utf-8) sur la connexion utilisee
* avec le gestionnaire de base de donnees
*
* @api
* @see sql_get_charset() pour tester l'utilisation d'un charset
*
* @param string $charset
* Le charset souhaite
* @param string $serveur
* Le nom du connecteur
* @param bool|string $option
* Peut avoir 2 valeurs :
* - true pour executer la requete.
* - continue pour ne pas echouer en cas de serveur sql indisponible.
*
* @return bool
* Retourne true si elle reussie.
**/
function sql_set_charset($charset,$serveur='', $option=true){
$f = sql_serveur('set_charset', $serveur, $option==='continue' OR $option===false);
if (!is_string($f) OR !$f) return false;
return $f($charset, $serveur, $option!==false);
}
/**
* Effectue une requete de selection
*
* Fonction de selection (SELECT), retournant la ressource interrogeable par sql_fetch.
*
* @api
* @see sql_fetch() Pour boucler sur les resultats de cette fonction
*
* @param array|string $select
* Liste des champs a recuperer (Select)
* @param array|string $from
* Tables a consulter (From)
* @param array|string $where
* Conditions a remplir (Where)
* @param array|string $groupby
* Critere de regroupement (Group by)
* @param array|string $orderby
* Tableau de classement (Order By)
* @param string $limit
* Critere de limite (Limit)
* @param array $having
* Tableau des des post-conditions a remplir (Having)
* @param string $serveur
* Le serveur sollicite (pour retrouver la connexion)
* @param bool|string $option
* Peut avoir 3 valeurs :
* - false -> ne pas l'executer mais la retourner,
* - continue -> ne pas echouer en cas de serveur sql indisponible,
* - true|array -> executer la requete.
* Le cas array est, pour une requete produite par le compilateur,
* un tableau donnnant le contexte afin d'indiquer le lieu de l'erreur au besoin
*
*
* @return mixed
* Ressource SQL
* - Ressource SQL pour sql_fetch, si la requete est correcte
* - false en cas d'erreur
* - Chaine contenant la requete avec $option=false
*
* Retourne false en cas d'erreur, apres l'avoir denoncee.
* Les portages doivent retourner la requete elle-meme en cas d'erreur,
* afin de disposer du texte brut.
*
**/
function sql_select ($select = array(), $from = array(), $where = array(),
$groupby = array(), $orderby = array(), $limit = '', $having = array(),
$serveur='', $option=true) {
$f = sql_serveur('select', $serveur, $option==='continue' OR $option===false);
if (!is_string($f) OR !$f) return false;
$debug = (defined('_VAR_MODE') AND _VAR_MODE == 'debug');
if (($option !== false) AND !$debug) {
$res = $f($select, $from, $where, $groupby, $orderby, $limit, $having, $serveur, is_array($option) ? true : $option);
} else {
$query = $f($select, $from, $where, $groupby, $orderby, $limit, $having, $serveur, false);
if (!$option) return $query;
// le debug, c'est pour ce qui a ete produit par le compilateur
if (isset($GLOBALS['debug']['aucasou'])) {
list($table, $id,) = $GLOBALS['debug']['aucasou'];
$nom = $GLOBALS['debug_objets']['courant'] . $id;
$GLOBALS['debug_objets']['requete'][$nom] = $query;
}
$res = $f($select, $from, $where, $groupby, $orderby, $limit, $having, $serveur, true);
}
// en cas d'erreur
if (!is_string($res)) return $res;
// denoncer l'erreur SQL dans sa version brute
spip_sql_erreur($serveur);
// idem dans sa version squelette (prefixe des tables non substitue)
erreur_squelette(array(sql_errno($serveur), sql_error($serveur), $res), $option);
return false;
}
/**
* Recupere la syntaxe de la requete select sans l'executer
*
* Passe simplement $option a false au lieu de true
* sans obliger a renseigner tous les arguments de sql_select.
* Les autres parametres sont identiques.
*
* @api
* @uses sql_select()
*
* @param array|string $select
* Liste des champs a recuperer (Select)
* @param array|string $from
* Tables a consulter (From)
* @param array|string $where
* Conditions a remplir (Where)
* @param array|string $groupby
* Critere de regroupement (Group by)
* @param array|string $orderby
* Tableau de classement (Order By)
* @param string $limit
* Critere de limite (Limit)
* @param array $having
* Tableau des des post-conditions a remplir (Having)
* @param string $serveur
* Le serveur sollicite (pour retrouver la connexion)
*
* @return mixed
* Chaine contenant la requete
* ou false en cas d'erreur
*
**/
function sql_get_select($select = array(), $from = array(), $where = array(),
$groupby = array(), $orderby = array(), $limit = '', $having = array(),
$serveur='') {
return sql_select ($select, $from, $where, $groupby, $orderby, $limit, $having, $serveur, false);
}
/**
* Retourne le nombre de lignes d'une selection
*
* Ramene seulement et tout de suite le nombre de lignes
* Pas de colonne ni de tri a donner donc.
*
* @api
*
* @param array|string $from
* Tables a consulter (From)
* @param array|string $where
* Conditions a remplir (Where)
* @param array|string $groupby
* Critere de regroupement (Group by)
* @param array $having
* Tableau des des post-conditions a remplir (Having)
* @param string $serveur
* Le serveur sollicite (pour retrouver la connexion)
* @param bool|string $option
* Peut avoir 3 valeurs :
* - false -> ne pas l'executer mais la retourner,
* - continue -> ne pas echouer en cas de serveur sql indisponible,
* - true -> executer la requete.
*
* @return int|bool
* Nombre de lignes de resultat
* ou false en cas d'erreur
*
**/
function sql_countsel($from = array(), $where = array(),
$groupby = array(), $having = array(),
$serveur='', $option=true) {
$f = sql_serveur('countsel', $serveur, $option==='continue' OR $option===false);
if (!is_string($f) OR !$f) return false;
$r = $f($from, $where, $groupby, $having, $serveur, $option!==false);
if ($r===false) spip_sql_erreur($serveur);
return $r;
}
/**
* Modifie la structure de la base de donnees
*
* Effectue une operation ALTER.
*
* @example
* <code>sql_alter('DROP COLUMN supprimer');</code>
*
* @api
* @param string $q
* La requete a executer (sans la preceder de 'ALTER ')
* @param string $serveur
* Le serveur sollicite (pour retrouver la connexion)
* @param bool|string $option
* Peut avoir 2 valeurs :
* - true -> executer la requete
* - continue -> ne pas echouer en cas de serveur sql indisponible
* @return mixed
* 2 possibilites :
* - Incertain en cas d'execution correcte de la requete
* - false en cas de serveur indiponible ou d'erreur
* Ce retour n'est pas pertinent pour savoir si l'operation est correctement realisee.
**/
function sql_alter($q, $serveur='', $option=true) {
$f = sql_serveur('alter', $serveur, $option==='continue' OR $option===false);
if (!is_string($f) OR !$f) return false;
$r = $f($q, $serveur, $option!==false);
if ($r===false) spip_sql_erreur($serveur);
return $r;
}
/**
* Retourne un enregistrement d'une selection
*
* Retourne un resultat d'une ressource obtenue avec sql_select()
*
* @api
* @param mixed
* Ressource retournee par sql_select()
* @param string $serveur
* Le nom du connecteur
* @param bool|string $option
* Peut avoir 2 valeurs :
* - true -> executer la requete
* - continue -> ne pas echouer en cas de serveur sql indisponible
*
* @return array
* Tableau de cles (colonnes SQL ou alias) / valeurs (valeurs dans la colonne de la table ou calculee)
* presentant une ligne de resultat d'une selection
*/
function sql_fetch($res, $serveur='', $option=true) {
$f = sql_serveur('fetch', $serveur, $option==='continue' OR $option===false);
if (!is_string($f) OR !$f) return false;
return $f($res, NULL, $serveur, $option!==false);
}
/**
* Retourne tous les enregistrements d'une selection
*
* Retourne tous les resultats d'une ressource obtenue avec sql_select()
* dans un tableau
*
* @api
* @param mixed
* Ressource retournee par sql_select()
* @param string $serveur
* Le nom du connecteur
* @param bool|string $option
* Peut avoir 2 valeurs :
* - true -> executer la requete
* - continue -> ne pas echouer en cas de serveur sql indisponible
*
* @return array
* Tableau contenant les enregistrements.
* Chaque entree du tableau est un autre tableau
* de cles (colonnes SQL ou alias) / valeurs (valeurs dans la colonne de la table ou calculee)
* presentant une ligne de resultat d'une selection
*/
function sql_fetch_all($res, $serveur='', $option=true){
$rows = array();
if (!$res) return $rows;
$f = sql_serveur('fetch', $serveur, $option==='continue' OR $option===false);
if (!is_string($f) OR !$f) return array();
while ($r = $f($res, NULL, $serveur, $option!==false))
$rows[] = $r;
sql_free($res, $serveur);
return $rows;
}
/**
* Deplace le pointeur d'une ressource de selection
*
* Deplace le pointeur sur un numero de ligne precise
* sur une ressource issue de sql_select, afin que
* le prochain sql_fetch recupere cette ligne.
*
* @api
* @see sql_skip() Pour sauter des enregistrements
*
* @param mixed $res
* Ressource issue de sql_select
* @param int $row_number
* Numero de ligne sur laquelle placer le pointeur
* @param string $serveur
* Le nom du connecteur
* @param bool|string $option
* Peut avoir 2 valeurs :
* - true -> executer la requete
* - continue -> ne pas echouer en cas de serveur sql indisponible
*
* @return bool
* Operation effectuee (true), sinon false.
**/
function sql_seek($res, $row_number, $serveur='', $option=true) {
$f = sql_serveur('seek', $serveur, $option==='continue' OR $option===false);
if (!is_string($f) OR !$f) return false;
$r = $f($res, $row_number, $serveur, $option!==false);
if ($r===false) spip_sql_erreur($serveur);
return $r;
}
/**
* Liste des bases de donnees accessibles
*
* Retourne un tableau du nom de toutes les bases de donnees
* accessibles avec les permissions de l'utilisateur SQL
* de cette connexion.
* Attention on n'a pas toujours les droits !
*
* @api
* @param string $serveur
* Nom du connecteur
* @param bool|string $option
* Peut avoir 2 valeurs :
* - true -> executer la requete
* - continue -> ne pas echouer en cas de serveur sql indisponible
*
* @return array|bool
* Tableau contenant chaque nom de base de donnees.
* False en cas d'erreur.
**/
function sql_listdbs($serveur='', $option=true) {
$f = sql_serveur('listdbs', $serveur, $option==='continue' OR $option===false);
if (!is_string($f) OR !$f) return false;
$r = $f($serveur);
if ($r===false) spip_sql_erreur($serveur);
return $r;
}
/**
* Demande d'utiliser d'une base de donnees
*
* @api
* @param string $nom
* Nom de la base a utiliser
* @param string $serveur
* Nom du connecteur
* @param bool|string $option
* Peut avoir 2 valeurs :
* - true -> executer la requete
* - continue -> ne pas echouer en cas de serveur sql indisponible
*
* @return bool|string
* True ou nom de la base en cas de success.
* False en cas d'erreur.
**/
function sql_selectdb($nom, $serveur='', $option=true)
{
$f = sql_serveur('selectdb', $serveur, $option==='continue' OR $option===false);
if (!is_string($f) OR !$f) return false;
$r = $f($nom, $serveur, $option!==false);
if ($r===false) spip_sql_erreur($serveur);
return $r;
}
// http://doc.spip.org/@sql_count
function sql_count($res, $serveur='', $option=true)
{
$f = sql_serveur('count', $serveur, $option==='continue' OR $option===false);
if (!is_string($f) OR !$f) return false;
$r = $f($res, $serveur, $option!==false);
if ($r===false) spip_sql_erreur($serveur);
return $r;
}
// http://doc.spip.org/@sql_free
function sql_free($res, $serveur='', $option=true)
{
$f = sql_serveur('free', $serveur, $option==='continue' OR $option===false);
if (!is_string($f) OR !$f) return false;
return $f($res);
}
// Cette fonction ne garantit pas une portabilite totale
// ===> lui preferer la suivante.
// Elle est fournie pour permettre l'actualisation de vieux codes
// par un Sed brutal qui peut donner des resultats provisoirement acceptables
// http://doc.spip.org/@sql_insert
function sql_insert($table, $noms, $valeurs, $desc=array(), $serveur='', $option=true)
{
$f = sql_serveur('insert', $serveur, $option==='continue' OR $option===false);
if (!is_string($f) OR !$f) return false;
$r = $f($table, $noms, $valeurs, $desc, $serveur, $option!==false);
if ($r === false) spip_sql_erreur($serveur);
return $r;
}
// http://doc.spip.org/@sql_insertq
function sql_insertq($table, $couples=array(), $desc=array(), $serveur='', $option=true)
{
$f = sql_serveur('insertq', $serveur, $option==='continue' OR $option===false);
if (!is_string($f) OR !$f) return false;
$r = $f($table, $couples, $desc, $serveur, $option!==false);
if ($r === false) spip_sql_erreur($serveur);
return $r;
}
// http://doc.spip.org/@sql_insertq_multi
function sql_insertq_multi($table, $couples=array(), $desc=array(), $serveur='', $option=true)
{
$f = sql_serveur('insertq_multi', $serveur, $option==='continue' OR $option===false);
if (!is_string($f) OR !$f) return false;
$r = $f($table, $couples, $desc, $serveur, $option!==false);
if ($r === false) spip_sql_erreur($serveur);
return $r;
}
// http://doc.spip.org/@sql_update
function sql_update($table, $exp, $where='', $desc=array(), $serveur='', $option=true)
{
$f = sql_serveur('update', $serveur, $option==='continue' OR $option===false);
if (!is_string($f) OR !$f) return false;
$r = $f($table, $exp, $where, $desc, $serveur, $option!==false);
if ($r === false) spip_sql_erreur($serveur);
return $r;
}
// Update est presque toujours appelee sur des constantes ou des dates
// Cette fonction est donc plus utile que la precedente,d'autant qu'elle
// permet de gerer les differences de representation des constantes.
// http://doc.spip.org/@sql_updateq
function sql_updateq($table, $exp, $where='', $desc=array(), $serveur='', $option=true)
{
$f = sql_serveur('updateq', $serveur, $option==='continue' OR $option===false);
if (!is_string($f) OR !$f) return false;
$r = $f($table, $exp, $where, $desc, $serveur, $option!==false);
if ($r === false) spip_sql_erreur($serveur);
return $r;
}
// http://doc.spip.org/@sql_delete
function sql_delete($table, $where='', $serveur='', $option=true)
{
$f = sql_serveur('delete', $serveur, $option==='continue' OR $option===false);
if (!is_string($f) OR !$f) return false;
$r = $f($table, $where, $serveur, $option!==false);
if ($r === false) spip_sql_erreur($serveur);
return $r;
}
// http://doc.spip.org/@sql_replace
function sql_replace($table, $couples, $desc=array(), $serveur='', $option=true)
{
$f = sql_serveur('replace', $serveur, $option==='continue' OR $option===false);
if (!is_string($f) OR !$f) return false;
$r = $f($table, $couples, $desc, $serveur, $option!==false);
if ($r === false) spip_sql_erreur($serveur);
return $r;
}
// http://doc.spip.org/@sql_replace_multi
function sql_replace_multi($table, $tab_couples, $desc=array(), $serveur='', $option=true)
{
$f = sql_serveur('replace_multi', $serveur, $option==='continue' OR $option===false);
if (!is_string($f) OR !$f) return false;
$r = $f($table, $tab_couples, $desc, $serveur, $option!==false);
if ($r === false) spip_sql_erreur($serveur);
return $r;
}
// http://doc.spip.org/@sql_drop_table
function sql_drop_table($table, $exist='', $serveur='', $option=true)
{
$f = sql_serveur('drop_table', $serveur, $option==='continue' OR $option===false);
if (!is_string($f) OR !$f) return false;
$r = $f($table, $exist, $serveur, $option!==false);
if ($r === false) spip_sql_erreur($serveur);
return $r;
}
// supprimer une vue sql
// http://doc.spip.org/@sql_drop_view
function sql_drop_view($table, $exist='', $serveur='', $option=true)
{
$f = sql_serveur('drop_view', $serveur, $option==='continue' OR $option===false);
if (!is_string($f) OR !$f) return false;
$r = $f($table, $exist, $serveur, $option!==false);
if ($r === false) spip_sql_erreur($serveur);
return $r;
}
/**
* Retourne une ressource de la liste des tables de la base de données
*
* @api
* @param string $spip
* Filtre sur tables retournées
* - NULL : retourne les tables SPIP uniquement (tables préfixées avec le préfixe de la connexion)
* - '%' : retourne toutes les tables de la base
* @param string $serveur
* Le nom du connecteur
* @param bool|string $option
* Peut avoir 3 valeurs :
* - false -> ne pas l'executer mais la retourner,
* - continue -> ne pas echouer en cas de serveur sql indisponible,
* - true -> executer la requete.
* @return ressource
* Ressource à utiliser avec sql_fetch()
**/
function sql_showbase($spip=NULL, $serveur='', $option=true)
{
$f = sql_serveur('showbase', $serveur, $option==='continue' OR $option===false);
if (!is_string($f) OR !$f) return false;
// la globale n'est remplie qu'apres l'appel de sql_serveur.
if ($spip == NULL){
$connexion = $GLOBALS['connexions'][$serveur ? strtolower($serveur) : 0];
$spip = $connexion['prefixe'] . '\_%';
}
return $f($spip, $serveur, $option!==false);
}
/**
* Retourne la liste des tables SQL
*
* @api
* @uses sql_showbase()
* @param string $spip
* Filtre sur tables retournées
* - NULL : retourne les tables SPIP uniquement (tables préfixées avec le préfixe de la connexion)
* - '%' : retourne toutes les tables de la base
* @param string $serveur
* Le nom du connecteur
* @param bool|string $option
* Peut avoir 3 valeurs :
* - false -> ne pas l'executer mais la retourner,
* - continue -> ne pas echouer en cas de serveur sql indisponible,
* - true -> executer la requete.
* @return array
* Liste des tables SQL
**/
function sql_alltable($spip=NULL, $serveur='', $option=true)
{
$q = sql_showbase($spip, $serveur, $option);
$r = array();
if ($q) while ($t = sql_fetch($q, $serveur)) { $r[] = array_shift($t);}
return $r;
}
// http://doc.spip.org/@sql_showtable
function sql_showtable($table, $table_spip = false, $serveur='', $option=true)
{
$f = sql_serveur('showtable', $serveur, $option==='continue' OR $option===false);
if (!is_string($f) OR !$f) return false;
// la globale n'est remplie qu'apres l'appel de sql_serveur.
if ($table_spip){
$connexion = $GLOBALS['connexions'][$serveur ? strtolower($serveur) : 0];
$prefixe = $connexion['prefixe'];
$vraie_table = preg_replace('/^spip/', $prefixe, $table);
} else $vraie_table = $table;
$f = $f($vraie_table, $serveur, $option!==false);
if (!$f) return array();
if (isset($GLOBALS['tables_principales'][$table]['join']))
$f['join'] = $GLOBALS['tables_principales'][$table]['join'];
elseif (isset($GLOBALS['tables_auxiliaires'][$table]['join']))
$f['join'] = $GLOBALS['tables_auxiliaires'][$table]['join'];
return $f;
}
// http://doc.spip.org/@sql_create
function sql_create($nom, $champs, $cles=array(), $autoinc=false, $temporary=false, $serveur='', $option=true) {
$f = sql_serveur('create', $serveur, $option==='continue' OR $option===false);
if (!is_string($f) OR !$f) return false;
$r = $f($nom, $champs, $cles, $autoinc, $temporary, $serveur, $option!==false);
if ($r === false) spip_sql_erreur($serveur);
return $r;
}
function sql_create_base($nom, $serveur='', $option=true)
{
$f = sql_serveur('create_base', $serveur, $option==='continue' OR $option===false);
if (!is_string($f) OR !$f) return false;
$r = $f($nom, $serveur, $option!==false);
if ($r === false) spip_sql_erreur($serveur);
return $r;
}
// Fonction pour creer une vue
// nom : nom de la vue,
// select_query : une requete select, idealement cree avec $req = sql_select()
// (en mettant $option du sql_select a false pour recuperer la requete)
// http://doc.spip.org/@sql_create_view
function sql_create_view($nom, $select_query, $serveur='', $option=true) {
$f = sql_serveur('create_view', $serveur, $option==='continue' OR $option===false);
if (!is_string($f) OR !$f) return false;
$r = $f($nom, $select_query, $serveur, $option!==false);
if ($r === false) spip_sql_erreur($serveur);
return $r;
}
// http://doc.spip.org/@sql_multi
function sql_multi($sel, $lang, $serveur='', $option=true)
{
$f = sql_serveur('multi', $serveur, $option==='continue' OR $option===false);
if (!is_string($f) OR !$f) return false;
return $f($sel, $lang);
}
/**
* Retourne la dernière erreur connue
*
* @api
* @param string $serveur
* Nom du connecteur
* @return bool|string
* Description de l'erreur
* False si le serveur est indisponible
*/
function sql_error($serveur='') {
$f = sql_serveur('error', $serveur, 'continue');
if (!is_string($f) OR !$f) return false;
return $f('query inconnue', $serveur);
}
/**
* Retourne le numéro de la derniere erreur connue
*
* @api
* @param string $serveur
* Nom du connecteur
* @return bool|int
* Numéro de l'erreur
* False si le serveur est indisponible
*/
function sql_errno($serveur='') {
$f = sql_serveur('errno', $serveur, 'continue');
if (!is_string($f) OR !$f) return false;
return $f($serveur);
}
// http://doc.spip.org/@sql_explain
function sql_explain($q, $serveur='', $option=true) {
$f = sql_serveur('explain', $serveur, 'continue');
if (!is_string($f) OR !$f) return false;
$r = $f($q, $serveur, $option!==false);
if ($r === false) spip_sql_erreur($serveur);
return $r;
}
// http://doc.spip.org/@sql_optimize
function sql_optimize($table, $serveur='', $option=true) {
$f = sql_serveur('optimize', $serveur, $option==='continue' OR $option===false);
if (!is_string($f) OR !$f) return false;
$r = $f($table, $serveur, $option!==false);
if ($r === false) spip_sql_erreur($serveur);
return $r;
}
// http://doc.spip.org/@sql_repair
function sql_repair($table, $serveur='', $option=true) {
$f = sql_serveur('repair', $serveur, $option==='continue' OR $option===false);
if (!is_string($f) OR !$f) return false;
$r = $f($table, $serveur, $option!==false);
if ($r === false) spip_sql_erreur($serveur);
return $r;
}
// Fonction la plus generale ... et la moins portable
// A n'utiliser qu'en derniere extremite
// http://doc.spip.org/@sql_query
function sql_query($ins, $serveur='', $option=true) {
$f = sql_serveur('query', $serveur, $option==='continue' OR $option===false);
if (!is_string($f) OR !$f) return false;
$r = $f($ins, $serveur, $option!==false);
if ($r === false) spip_sql_erreur($serveur);
return $r;
}
/**
* Retourne la premiere ligne d'une selection
*
* Retourne la premiere ligne de resultat d'une selection
* comme si l'on appelait successivement sql_select() puis sql_fetch()
*
* @example
* <code>
* $art = sql_fetsel(array('id_rubrique','id_secteur'), 'spip_articles', 'id_article='.sql_quote($id_article));
* $id_rubrique = $art['id_rubrique'];
* </code>
*
* @api
* @uses sql_select()
* @uses sql_fetch()
*
* @param array|string $select
* Liste des champs a recuperer (Select)
* @param array|string $from
* Tables a consulter (From)
* @param array|string $where
* Conditions a remplir (Where)
* @param array|string $groupby
* Critere de regroupement (Group by)
* @param array|string $orderby
* Tableau de classement (Order By)
* @param string $limit
* Critere de limite (Limit)
* @param array $having
* Tableau des des post-conditions a remplir (Having)
* @param string $serveur
* Le serveur sollicite (pour retrouver la connexion)
* @param bool|string $option
* Peut avoir 3 valeurs :
* - true -> executer la requete.
* - continue -> ne pas echouer en cas de serveur sql indisponible.
* - false -> ne pas l'executer mais la retourner.
*
* @return array
* Tableau de la premiere ligne de resultat de la selection
* {@example
* <code>array('id_rubrique' => 1, 'id_secteur' => 2)</code>
* }
*
**/
function sql_fetsel($select = array(), $from = array(), $where = array(),
$groupby = array(), $orderby = array(), $limit = '',
$having = array(), $serveur='', $option=true) {
$q = sql_select($select, $from, $where, $groupby, $orderby, $limit, $having, $serveur, $option);
if ($option===false) return $q;
if (!$q) return array();
$r = sql_fetch($q, $serveur, $option);
sql_free($q, $serveur, $option);
return $r;
}
/**
* Retourne le tableau de toutes les lignes d'une selection
*
* Retourne toutes les lignes de resultat d'une selection
* comme si l'on appelait successivement sql_select() puis while(sql_fetch())
*
* @example
* <code>
* $rubs = sql_allfetsel('id_rubrique', 'spip_articles', 'id_secteur='.sql_quote($id_secteur));
* // $rubs = array(array('id_rubrique'=>1), array('id_rubrique'=>3, ...)
* </code>
*
* @api
* @uses sql_select()
* @uses sql_fetch()
*
* @param array|string $select
* Liste des champs a recuperer (Select)
* @param array|string $from
* Tables a consulter (From)
* @param array|string $where
* Conditions a remplir (Where)
* @param array|string $groupby
* Critere de regroupement (Group by)
* @param array|string $orderby
* Tableau de classement (Order By)
* @param string $limit
* Critere de limite (Limit)
* @param array $having
* Tableau des des post-conditions a remplir (Having)
* @param string $serveur
* Le serveur sollicite (pour retrouver la connexion)
* @param bool|string $option
* Peut avoir 3 valeurs :
* - true -> executer la requete.
* - continue -> ne pas echouer en cas de serveur sql indisponible.
* - false -> ne pas l'executer mais la retourner.
*
* @return array
* Tableau de toutes les lignes de resultat de la selection
* Chaque entree contient un tableau des elements demandees dans le SELECT.
* {@example
* <code>
* array(
* array('id_rubrique' => 1, 'id_secteur' => 2)
* array('id_rubrique' => 4, 'id_secteur' => 2)
* ...
* )
* </code>
* }
*
**/
function sql_allfetsel($select = array(), $from = array(), $where = array(),
$groupby = array(), $orderby = array(), $limit = '',
$having = array(), $serveur='', $option=true) {
$q = sql_select($select, $from, $where, $groupby, $orderby, $limit, $having, $serveur, $option);
if ($option===false) return $q;
return sql_fetch_all($q, $serveur, $option);
}
/**
* Retourne un unique champ d'une selection
*
* Retourne dans la premiere ligne de resultat d'une selection
* un unique champ demande
*
* @example
* <code>
* $id_rubrique = sql_getfetsel('id_rubrique', 'spip_articles', 'id_article='.sql_quote($id_article));
* </code>
*
* @api
* @uses sql_fetsel()
*
* @param array|string $select
* Liste des champs a recuperer (Select)
* @param array|string $from
* Tables a consulter (From)
* @param array|string $where
* Conditions a remplir (Where)
* @param array|string $groupby
* Critere de regroupement (Group by)
* @param array|string $orderby
* Tableau de classement (Order By)
* @param string $limit
* Critere de limite (Limit)
* @param array $having
* Tableau des des post-conditions a remplir (Having)
* @param string $serveur
* Le serveur sollicite (pour retrouver la connexion)
* @param bool|string $option
* Peut avoir 3 valeurs :
* - true -> executer la requete.
* - continue -> ne pas echouer en cas de serveur sql indisponible.
* - false -> ne pas l'executer mais la retourner.
*
* @return mixed
* Contenu de l'unique valeur demandee du premier enregistrement retourne
*
**/
function sql_getfetsel($select, $from = array(), $where = array(), $groupby = array(),
$orderby = array(), $limit = '', $having = array(), $serveur='', $option=true) {
if (preg_match('/\s+as\s+(\w+)$/i', $select, $c)) $id = $c[1];
elseif (!preg_match('/\W/', $select)) $id = $select;
else {$id = 'n'; $select .= ' AS n';}
$r = sql_fetsel($select, $from, $where, $groupby, $orderby, $limit, $having, $serveur, $option);
if ($option===false) return $r;
if (!$r) return NULL;
return $r[$id];
}
/**
* Retourne le numero de version du serveur SQL
*
* @api
* @param string $serveur
* Nom du connecteur
* @param bool|string $option
* Peut avoir 2 valeurs :
* - true pour executer la requete.
* - continue pour ne pas echouer en cas de serveur sql indisponible.
*
* @return string
* Numero de version du serveur SQL
**/
function sql_version($serveur='', $option=true) {
$row = sql_fetsel("version() AS n", '','','','','','',$serveur);
return ($row['n']);
}
/**
* Informe si le moteur SQL prefere utiliser des transactions
*
* Cette fonction experimentale est pour l'instant presente pour accelerer certaines
* insertions multiples en SQLite, en les encadrant d'une transaction.
* SQLite ne cree alors qu'un verrou pour l'ensemble des insertions
* et non un pour chaque, ce qui accelere grandement le processus.
* Evidemment, si une des insertions echoue, rien ne sera enregistre.
* Pour ne pas perturber les autres moteurs, cette fonction permet
* de verifier que le moteur prefere utiliser des transactions dans ce cas.
*
* @example
* <code>
* if (sql_preferer_transaction()) {
* sql_demarrer_transaction();
* }
* </code>
*
* @api
* @see sql_demarrer_transaction()
* @see sql_terminer_transaction()
*
* @param string $serveur
* Nom du connecteur
* @param bool|string $option
* Peut avoir 2 valeurs :
* - true pour executer la requete.
* - continue pour ne pas echouer en cas de serveur sql indisponible.
*
* @return bool
* Le serveur SQL prefere t'il des transactions pour les insertions multiples ?
**/
function sql_preferer_transaction($serveur='', $option=true) {
$f = sql_serveur('preferer_transaction', $serveur, 'continue');
if (!is_string($f) OR !$f) return false;
$r = $f($serveur, $option!==false);
if ($r === false) spip_sql_erreur($serveur);
return $r;
};
/**
* Demarre une transaction
*
* @api
* @see sql_terminer_transaction() Pour cloturer la transaction
*
* @param string $serveur
* Nom du connecteur
* @param bool|string $option
* Peut avoir 3 valeurs :
* - true pour executer la requete.
* - continue pour ne pas echouer en cas de serveur sql indisponible.
* - false pour obtenir le code de la requete
*
* @return bool
* true si la transaction est demarree
* false en cas d'erreur
**/
function sql_demarrer_transaction($serveur='', $option=true) {
$f = sql_serveur('demarrer_transaction', $serveur, 'continue');
if (!is_string($f) OR !$f) return false;
$r = $f($serveur, $option!==false);
if ($r === false) spip_sql_erreur($serveur);
return $r;
};
/**
* Termine une transaction
*
* @api
* @see sql_demarrer_transaction() Pour demarrer une transaction
*
* @param string $serveur
* Nom du connecteur
* @param bool|string $option
* Peut avoir 3 valeurs :
* - true pour executer la requete.
* - continue pour ne pas echouer en cas de serveur sql indisponible.
* - false pour obtenir le code de la requete
*
* @return bool
* true si la transaction est demarree
* false en cas d'erreur
**/
function sql_terminer_transaction($serveur='', $option=true) {
$f = sql_serveur('terminer_transaction', $serveur, 'continue');
if (!is_string($f) OR !$f) return false;
$r = $f($serveur, $option!==false);
if ($r === false) spip_sql_erreur($serveur);
return $r;
};
/**
* Prepare une chaine hexadecimale
*
* Prend une chaine sur l'aphabet hexa
* et retourne sa representation numerique attendue par le serveur SQL.
* Par exemple : FF ==> 0xFF en MySQL mais x'FF' en PG
*
* @api
* @param string $val
* Chaine hexadecimale
* @param string $serveur
* Nom du connecteur
* @param bool|string $option
* Peut avoir 2 valeurs :
* - true pour executer la demande.
* - continue pour ne pas echouer en cas de serveur sql indisponible.
* @return string
* Retourne la valeur hexadecimale attendue par le serveur SQL
**/
function sql_hex($val, $serveur='', $option=true)
{
$f = sql_serveur('hex', $serveur, $option==='continue' OR $option===false);
if (!is_string($f) OR !$f) return false;
return $f($val);
}
/**
* Echapper du contenu
*
* Echappe du contenu selon ce qu'attend le type de serveur SQL
* et en fonction du type de contenu.
*
* Cette fonction est automatiquement appelee par les fonctions sql_*q
* tel que sql_instertq ou sql_updateq
*
* @api
* @param string $val
* Chaine a echapper
* @param string $serveur
* Nom du connecteur
* @param string $type
* Peut contenir une declaration de type de champ SQL
* {@example <code>int NOT NULL</code>} qui sert alors aussi a calculer le type d'echappement
* @return string
* La chaine echappee
**/
function sql_quote($val, $serveur='', $type='')
{
$f = sql_serveur('quote', $serveur, true);
if (!is_string($f) OR !$f) $f = '_q';
return $f($val, $type);
}
function sql_date_proche($champ, $interval, $unite, $serveur='', $option=true)
{
$f = sql_serveur('date_proche', $serveur, true);
if (!is_string($f) OR !$f) return false;
return $f($champ, $interval, $unite);
}
/**
* Retourne une expression IN pour le gestionnaire de base de données
*
* Retourne un code à insérer dans une requête SQL pour récupérer
* les éléments d'une colonne qui appartiennent à une liste donnée
*
* @example
* sql_in('id_rubrique', array(3,4,5))
* retourne approximativement «id_rubrique IN (3,4,5)» selon ce qu'attend
* le gestionnaire de base de donnée du connecteur en cours.
*
* @api
* @param string $val
* Colonne SQL sur laquelle appliquer le test
* @param string|array $valeurs
* Liste des valeurs possibles (séparés par des virgules si string)
* @param string $not
* - '' sélectionne les éléments correspondant aux valeurs
* - 'NOT' inverse en sélectionnant les éléments ne correspondant pas aux valeurs
* @param string $serveur
* Nom du connecteur
* @param bool|string $option
* Peut avoir 2 valeurs :
* - continue -> ne pas echouer en cas de serveur sql indisponible
* - true ou false -> retourne l'expression
* @return string
* Expression de requête SQL
**/
function sql_in($val, $valeurs, $not='', $serveur='', $option=true) {
if (is_array($valeurs)) {
$f = sql_serveur('quote', $serveur, true);
if (!is_string($f) OR !$f) return false;
$valeurs = join(',', array_map($f, array_unique($valeurs)));
} elseif (isset($valeurs[0]) AND $valeurs[0]===',') $valeurs = substr($valeurs,1);
if (!strlen(trim($valeurs))) return ($not ? "0=0" : '0=1');
$f = sql_serveur('in', $serveur, $option==='continue' OR $option===false);
if (!is_string($f) OR !$f) return false;
return $f($val, $valeurs, $not, $serveur, $option!==false);
}
// Penser a dire dans la description du serveur
// s'il accepte les requetes imbriquees afin d'optimiser ca
// http://doc.spip.org/@sql_in_select
function sql_in_select($in, $select, $from = array(), $where = array(),
$groupby = array(), $orderby = array(), $limit = '', $having = array(), $serveur='')
{
$liste = array();
$res = sql_select($select, $from, $where, $groupby, $orderby, $limit, $having, $serveur);
while ($r = sql_fetch($res)) {$liste[] = array_shift($r);}
sql_free($res);
return sql_in($in, $liste);
}
/**
* Implementation securisee du saut en avant,
* qui ne depend pas de la disponibilite de la fonction sql_seek
* ne fait rien pour une valeur negative ou nulle de $saut
* retourne la position apres le saut
*
* @see sql_seek()
*
* @param resource $res
* Ressource issue d'une selection sql_select
* @param int $pos
* position courante
* @param int $saut
* saut demande
* @param int $count
* position maximale
* (nombre de resultat de la requete OU position qu'on ne veut pas depasser)
* @param string $serveur
* Nom du connecteur
* @param bool|string $option
* Peut avoir 2 valeurs :
* - true -> executer la requete
* - continue -> ne pas echouer en cas de serveur sql indisponible
*
* @return int
* Position apres le saut.
*/
function sql_skip($res, $pos, $saut, $count, $serveur='', $option=true){
// pas de saut en arriere qu'on ne sait pas faire sans sql_seek
if (($saut=intval($saut))<=0) return $pos;
$seek = $pos + $saut;
// si le saut fait depasser le maxi, on libere la resource
// et on sort
if ($seek>=$count) {sql_free($res, $serveur, $option); return $count;}
if (sql_seek($res, $seek))
$pos = $seek;
else
while ($pos<$seek AND sql_fetch($res, $serveur, $option))
$pos++;
return $pos;
}
// http://doc.spip.org/@sql_test_int
function sql_test_int($type, $serveur='', $option=true)
{
return preg_match('/^(TINYINT|SMALLINT|MEDIUMINT|INT|INTEGER|BIGINT)/i',trim($type));
}
// http://doc.spip.org/@sql_test_date
function sql_test_date($type, $serveur='', $option=true)
{
return preg_match('/^(DATE|DATETIME|TIMESTAMP|TIME)/i',trim($type));
}
/**
* Formate une date
*
* Formater une date Y-m-d H:i:s sans passer par mktime
* qui ne sait pas gerer les dates < 1970
*
* http://doc.spip.org/@format_mysql_date
*
* @param int $annee Annee
* @param int $mois Numero du mois
* @param int $jour Numero du jour dans le mois
* @param int $h Heures
* @param int $m Minutes
* @param int $s Secondes
* @param string $serveur
* Le serveur sollicite (pour retrouver la connexion)
* @return string
* La date formatee
*/
function sql_format_date($annee=0, $mois=0, $jour=0, $h=0, $m=0, $s=0, $serveur=''){
$annee = sprintf("%04s",$annee);
$mois = sprintf("%02s",$mois);
if ($annee == "0000") $mois = 0;
if ($mois == "00") $jour = 0;
return sprintf("%04u",$annee) . '-' . sprintf("%02u",$mois) . '-'
. sprintf("%02u",$jour) . ' ' . sprintf("%02u",$h) . ':'
. sprintf("%02u",$m) . ':' . sprintf("%02u",$s);
}
/**
* Retourne la description de la table SQL
*
* Retrouve la description de la table SQL en privilegiant
* la structure reelle de la base de donnees.
* En absence, ce qui arrive lors de l'installation, la fonction
* s'appuie sur la declaration des tables SQL principales ou auxiliaires.
*
* @internal Cette fonction devrait disparaître
*
* @param string $nom
* Nom de la table dont on souhait la description
* @param string $serveur
* Nom du connecteur
* @return array|bool
* Description de la table ou false si elle n'est pas trouvee ou declaree.
**/
function description_table($nom, $serveur=''){
global $tables_principales, $tables_auxiliaires;
static $trouver_table;
/* toujours utiliser trouver_table
qui renverra la description theorique
car sinon on va se comporter differement selon que la table est declaree
ou non
*/
if (!$trouver_table) $trouver_table = charger_fonction('trouver_table', 'base');
if ($desc = $trouver_table($nom, $serveur))
return $desc;
// sauf a l'installation :
include_spip('base/serial');
if (isset($tables_principales[$nom]))
return $tables_principales[$nom];
include_spip('base/auxiliaires');
if (isset($tables_auxiliaires[$nom]))
return $tables_auxiliaires[$nom];
return false;
}
?>
delete_all.php 0000666 00000002654 15250255012 0007357 0 ustar 00 <?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;
// http://doc.spip.org/@base_delete_all_dist
function base_delete_all_dist($titre)
{
$delete = _request('delete');
$res = array();
if (is_array($delete)) {
foreach ($delete as $table) {
if (sql_drop_table($table))
$res[] = $table;
else spip_log( "SPIP n'a pas pu detruire $table.", _LOG_ERREUR);
}
// un pipeline pour detruire les tables installees par les plugins
pipeline('delete_tables', '');
spip_unlink(_FILE_CONNECT);
spip_unlink(_FILE_CHMOD);
spip_unlink(_FILE_META);
spip_unlink(_ACCESS_FILE_NAME);
spip_unlink(_CACHE_RUBRIQUES);
}
$d = count($delete);
$r = count($res);
spip_log("Tables detruites: $r sur $d: " . join(', ',$res), _LOG_INFO_IMPORTANTE);
}
?>
objets.php 0000666 00000110504 15250255012 0006545 0 ustar 00 <?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. *
\***************************************************************************/
/**
* Fonctions relatives aux objets éditoriaux et SQL
*
* @package SPIP\SQL\Tables
**/
if (!defined('_ECRIRE_INC_VERSION')) return;
/**
* Merge dans un tableau une de ses clés avec une valeur
*
* @param array $table
* Tableau dont on veut compléter une clé
* @param string $index
* Clé du tableau que l'on souhaite compléter
* @param array $valeur
* Sous tableau à merger dans la clé.
* @return void
**/
function array_set_merge(&$table,$index,$valeur){
if (!isset($table[$index]))
$table[$index] = $valeur;
else
$table[$index] = array_merge($table[$index],$valeur);
}
/**
* Lister les infos de toutes les tables sql declarées
*
* Si un argument est fourni, on ne renvoie que les infos de cette table.
* Elle est auto-declarée si inconnue jusqu'alors.
*
* @api
* @param string $table_sql
* table_sql demandee explicitement
* @param array $desc
* description connue de la table sql demandee
* @return array|bool
*/
function lister_tables_objets_sql($table_sql=null, $desc=array()){
static $deja_la = false;
static $infos_tables = null;
static $md5 = null;
static $plugin_hash = null;
// prealablement recuperer les tables_principales
if (is_null($infos_tables)
OR $plugin_hash!==_PLUGINS_HASH){
// pas de reentrance (cas base/serial)
if ($deja_la) {
spip_log ("Re-entrance anormale sur lister_tables_objets_sql :"
. var_export(debug_backtrace(),true),_LOG_CRITIQUE);
return ($table_sql==="::md5"?$md5:array());
}
$deja_la = true;
$plugin_hash = _PLUGINS_HASH; // avant de lancer les pipelines
// recuperer les declarations explicites ancienne mode
// qui servent a completer declarer_tables_objets_sql
base_serial($GLOBALS['tables_principales']);
base_auxiliaires($GLOBALS['tables_auxiliaires']);
$infos_tables = array(
'spip_articles'=> array(
'page'=>'article',
'texte_retour' => 'icone_retour_article',
'texte_modifier' => 'icone_modifier_article',
'texte_creer' => 'icone_ecrire_article',
'texte_objets' => 'public:articles',
'texte_objet' => 'public:article',
'texte_signale_edition' => 'texte_travail_article',
'info_aucun_objet'=> 'info_aucun_article',
'info_1_objet' => 'info_1_article',
'info_nb_objets' => 'info_nb_articles',
'texte_logo_objet' => 'logo_article',
'texte_langue_objet' => 'titre_langue_article',
'texte_definir_comme_traduction_objet' => 'trad_lier',
'titre' => 'titre, lang',
'date' => 'date',
'principale' => 'oui',
'champs_editables' => array('surtitre', 'titre', 'soustitre', 'descriptif','nom_site', 'url_site', 'chapo', 'texte', 'ps','virtuel'),
'champs_versionnes' => array('id_rubrique', 'surtitre', 'titre', 'soustitre', 'jointure_auteurs', 'descriptif', 'nom_site', 'url_site', 'chapo', 'texte', 'ps'),
'field' => array(
"id_article" => "bigint(21) NOT NULL",
"surtitre" => "text DEFAULT '' NOT NULL",
"titre" => "text DEFAULT '' NOT NULL",
"soustitre" => "text DEFAULT '' NOT NULL",
"id_rubrique" => "bigint(21) DEFAULT '0' NOT NULL",
"descriptif" => "text DEFAULT '' NOT NULL",
"chapo" => "mediumtext DEFAULT '' NOT NULL",
"texte" => "longtext DEFAULT '' NOT NULL",
"ps" => "mediumtext DEFAULT '' NOT NULL",
"date" => "datetime DEFAULT '0000-00-00 00:00:00' NOT NULL",
"statut" => "varchar(10) DEFAULT '0' NOT NULL",
"id_secteur" => "bigint(21) DEFAULT '0' NOT NULL",
"maj" => "TIMESTAMP",
"export" => "VARCHAR(10) DEFAULT 'oui'",
"date_redac" => "datetime DEFAULT '0000-00-00 00:00:00' NOT NULL",
"visites" => "integer DEFAULT '0' NOT NULL",
"referers" => "integer DEFAULT '0' NOT NULL",
"popularite" => "DOUBLE DEFAULT '0' NOT NULL",
"accepter_forum" => "CHAR(3) DEFAULT '' NOT NULL",
"date_modif" => "datetime DEFAULT '0000-00-00 00:00:00' NOT NULL",
"lang" => "VARCHAR(10) DEFAULT '' NOT NULL",
"langue_choisie" => "VARCHAR(3) DEFAULT 'non'",
"id_trad" => "bigint(21) DEFAULT '0' NOT NULL",
"nom_site" => "tinytext DEFAULT '' NOT NULL",
"url_site" => "VARCHAR(255) DEFAULT '' NOT NULL",
"virtuel" => "VARCHAR(255) DEFAULT '' NOT NULL",
),
'key' => array(
"PRIMARY KEY" => "id_article",
"KEY id_rubrique" => "id_rubrique",
"KEY id_secteur" => "id_secteur",
"KEY id_trad" => "id_trad",
"KEY lang" => "lang",
"KEY statut" => "statut, date",
),
'join' => array(
"id_article"=>"id_article",
"id_rubrique"=>"id_rubrique"
),
'rechercher_champs' => array(
'surtitre' => 5, 'titre' => 8, 'soustitre' => 5, 'chapo' => 3,
'texte' => 1, 'ps' => 1, 'nom_site' => 1, 'url_site' => 1,
'descriptif' => 4
),
'rechercher_jointures' => array(
'auteur' => array('nom' => 10),
),
'statut'=> array(
array(
'champ' => 'statut',
'publie' => 'publie',
'previsu' => 'publie,prop,prepa/auteur',
'post_date' => 'date',
'exception' => 'statut'
)
),
'statut_titres' => array(
'prepa'=>'info_article_redaction',
'prop'=>'info_article_propose',
'publie'=>'info_article_publie',
'refuse'=>'info_article_refuse',
'poubelle'=>'info_article_supprime'
),
'statut_textes_instituer' => array(
'prepa' => 'texte_statut_en_cours_redaction',
'prop' => 'texte_statut_propose_evaluation',
'publie' => 'texte_statut_publie',
'refuse' => 'texte_statut_refuse',
'poubelle' => 'texte_statut_poubelle',
),
'texte_changer_statut' => 'texte_article_statut',
'aide_changer_statut' => 'artstatut',
'tables_jointures' => array(
'profondeur' => 'rubriques',
#'id_auteur' => 'auteurs_liens' // declaration generique plus bas
),
),
'spip_auteurs' => array(
'page'=>'auteur',
'texte_retour' => 'icone_retour',
'texte_ajouter' => 'titre_ajouter_un_auteur',
'texte_modifier' => 'admin_modifier_auteur',
'texte_objets' => 'icone_auteurs',
'texte_objet' => 'public:auteur',
'info_aucun_objet'=> 'info_aucun_auteur',
'info_1_objet' => 'info_1_auteur',
'info_nb_objets' => 'info_nb_auteurs',
'texte_logo_objet' => 'logo_auteur',
'texte_creer_associer' => 'creer_et_associer_un_auteur',
'titre' => "nom AS titre, '' AS lang",
'date' => 'date',
'principale' => 'oui',
'champs_editables' => array('nom','email','bio','nom_site','url_site','imessage','pgp'),
'champs_versionnes' => array('nom', 'bio', 'email', 'nom_site', 'url_site', 'login'),
'field' => array(
"id_auteur" => "bigint(21) NOT NULL",
"nom" => "text DEFAULT '' NOT NULL",
"bio" => "text DEFAULT '' NOT NULL",
"email" => "tinytext DEFAULT '' NOT NULL",
"nom_site" => "tinytext DEFAULT '' NOT NULL",
"url_site" => "text DEFAULT '' NOT NULL",
"login" => "VARCHAR(255) BINARY",
"pass" => "tinytext DEFAULT '' NOT NULL",
"low_sec" => "tinytext DEFAULT '' NOT NULL",
"statut" => "varchar(255) DEFAULT '0' NOT NULL",
"webmestre" => "varchar(3) DEFAULT 'non' NOT NULL",
"maj" => "TIMESTAMP",
"pgp" => "TEXT DEFAULT '' NOT NULL",
"htpass" => "tinytext DEFAULT '' NOT NULL",
"en_ligne" => "datetime DEFAULT '0000-00-00 00:00:00' NOT NULL",
"alea_actuel" => "tinytext",
"alea_futur" => "tinytext",
"prefs" => "tinytext",
"cookie_oubli" => "tinytext",
"source" => "VARCHAR(10) DEFAULT 'spip' NOT NULL",
"lang" => "VARCHAR(10) DEFAULT '' NOT NULL"
),
'key' => array(
"PRIMARY KEY" => "id_auteur",
"KEY login" => "login",
"KEY statut" => "statut",
"KEY en_ligne" => "en_ligne",
),
'join' => array(
"id_auteur"=>"id_auteur",
"login"=>"login"
),
'rechercher_champs' => array(
'nom' => 5, 'bio' => 1, 'email' => 1, 'nom_site' => 1, 'url_site' => 1, 'login' => 1
),
// 2 conditions pour les auteurs : statut!=poubelle,
// et avoir des articles publies
'statut'=> array(
array(
'champ' => 'statut',
'publie' => '!5poubelle',
'previsu' => '!5poubelle',
'exception' => 'statut'
),
array(
'champ' => array(
array('spip_auteurs_liens', 'id_auteur'),
array(
'spip_articles',
array('id_objet','id_article','objet','article')
),
'statut'
),
'publie' => 'publie',
'previsu' => '!',
'post_date' => 'date',
'exception' => array('statut','lien','tout')
),
),
'statut_images' => array(
'auteur-6forum-16.png',
'0minirezo'=>'auteur-0minirezo-16.png',
'1comite'=>'auteur-1comite-16.png',
'6forum'=>'auteur-6forum-16.png',
'5poubelle'=>'auteur-5poubelle-16.png',
'nouveau'=>''
),
'statut_titres' => array(
'titre_image_visiteur',
'0minirezo'=>'titre_image_administrateur',
'1comite'=>'titre_image_redacteur_02',
'6forum'=>'titre_image_visiteur',
'5poubelle'=>'titre_image_auteur_supprime',
),
'tables_jointures' => array(
#'auteurs_liens' // declaration generique plus bas
),
),
'spip_rubriques' => array(
'page'=>'rubrique',
'url_voir' => 'rubrique',
'url_edit' => 'rubrique_edit',
'texte_retour' => 'icone_retour',
'texte_objets' => 'public:rubriques',
'texte_objet' => 'public:rubrique',
'texte_modifier' => 'icone_modifier_rubrique',
'texte_creer' => 'icone_creer_rubrique',
'texte_ajouter' => 'titre_ajouter_une_rubrique',
'texte_creer_associer' => 'creer_et_associer_une_rubrique',
'info_aucun_objet'=> 'info_aucun_rubrique',
'info_1_objet' => 'info_1_rubrique',
'info_nb_objets' => 'info_nb_rubriques',
'texte_logo_objet' => 'logo_rubrique',
'texte_langue_objet' => 'titre_langue_rubrique',
'titre'=>'titre, lang',
'date' => 'date',
'principale' => 'oui',
'champs_editables' => array('titre', 'texte', 'descriptif', 'extra'),
'champs_versionnes' => array('titre', 'descriptif', 'texte'),
'field' => array(
"id_rubrique" => "bigint(21) NOT NULL",
"id_parent" => "bigint(21) DEFAULT '0' NOT NULL",
"titre" => "text DEFAULT '' NOT NULL",
"descriptif" => "text DEFAULT '' NOT NULL",
"texte" => "longtext DEFAULT '' NOT NULL",
"id_secteur" => "bigint(21) DEFAULT '0' NOT NULL",
"maj" => "TIMESTAMP",
"statut" => "varchar(10) DEFAULT '0' NOT NULL",
"date" => "datetime DEFAULT '0000-00-00 00:00:00' NOT NULL",
"lang" => "VARCHAR(10) DEFAULT '' NOT NULL",
"langue_choisie" => "VARCHAR(3) DEFAULT 'non'",
"statut_tmp" => "varchar(10) DEFAULT '0' NOT NULL",
"date_tmp" => "datetime DEFAULT '0000-00-00 00:00:00' NOT NULL",
"profondeur" => "smallint(5) DEFAULT '0' NOT NULL"
),
'key' => array(
"PRIMARY KEY" => "id_rubrique",
"KEY lang" => "lang",
"KEY id_parent" => "id_parent",
),
'rechercher_champs' => array(
'titre' => 8, 'descriptif' => 5, 'texte' => 1
),
'statut' => array(
array(
'champ' => 'statut',
'publie' => 'publie',
'previsu' => '!',
'exception' => array('statut','tout')
),
),
'tables_jointures' => array(
#'id_auteur' => 'auteurs_liens' // declaration generique plus bas
),
),
// toutes les tables ont le droit a une jointure sur les auteurs
array('tables_jointures'=>array('id_auteur'=>'auteurs_liens'))
);
// avant d'appeller les pipeline qui peuvent generer une reentrance a l'install
// initialiser la signature
$md5 = md5(serialize($infos_tables));
$GLOBALS['tables_principales'] = pipeline('declarer_tables_principales',$GLOBALS['tables_principales']);
$GLOBALS['tables_auxiliaires'] = pipeline('declarer_tables_auxiliaires',$GLOBALS['tables_auxiliaires']);
$infos_tables = pipeline('declarer_tables_objets_sql',$infos_tables);
// completer les informations manquantes ou implicites
$all = array();
foreach(array_keys($infos_tables) as $t) {
// les cles numeriques servent a declarer
// les proprietes applicables a tous les objets
// on les mets de cote
if (is_numeric($t)) {
$all = array_merge_recursive($all,$infos_tables[$t]);
unset($infos_tables[$t]);
}
else
$infos_tables[$t] = renseigner_table_objet_sql($t,$infos_tables[$t]);
}
// repercuter les proprietes generales communes a tous les objets
foreach(array_keys($infos_tables) as $t) {
foreach($all as $i=>$v)
if (in_array($i,array('tables_jointures','champs_versionnes'))){
$add = $all[$i];
// eviter les doublons de declaration de table jointure (ex des mots sur auteurs)
// pour les declarations generiques avec cles numeriques
if ($i=='tables_jointures' AND isset($infos_tables[$t][$i]) AND count($infos_tables[$t][$i])) {
$doublons = array_intersect($infos_tables[$t][$i],$add);
foreach($doublons as $d){
if (is_numeric(array_search($d,$infos_tables[$t][$i]))
AND is_numeric($k=array_search($d,$add)))
unset($add[$k]);
}
}
$infos_tables[$t][$i] = array_merge(isset($infos_tables[$t][$i])?$infos_tables[$t][$i]:array(),$add);
}
else
$infos_tables[$t][$i] = array_merge_recursive(isset($infos_tables[$t][$i])?$infos_tables[$t][$i]:array(),$all[$i]);
}
// completer les tables principales et auxiliaires
// avec celles declarees uniquement dans declarer_table_objets_sql
// pour assurer la compat en transition
foreach($infos_tables as $table=>$infos) {
$principale_ou_auxiliaire = ($infos['principale']?'tables_principales':'tables_auxiliaires');
// memoriser des champs eventuels declares par des plugins dans le pipeline tables_xxx
// qui a ete appelle avant
$mem = (isset($GLOBALS[$principale_ou_auxiliaire][$table])?$GLOBALS[$principale_ou_auxiliaire][$table]:array());
// l'ajouter au tableau
$GLOBALS[$principale_ou_auxiliaire][$table] = array();
if (isset($infos['field']) AND isset($infos['key'])){
foreach(array('field','key','join') as $k)
if (isset($infos_tables[$table][$k]))
$GLOBALS[$principale_ou_auxiliaire][$table][$k] = &$infos_tables[$table][$k];
}
else {
// ici on ne renvoie que les declarations, donc RIEN
// pour avoir la vrai description en base, il faut passer par trouver_table
$GLOBALS[$principale_ou_auxiliaire][$table] = array();
}
if (count($mem)){
foreach(array_keys($mem) as $k)
if (isset($GLOBALS[$principale_ou_auxiliaire][$table][$k]))
$GLOBALS[$principale_ou_auxiliaire][$table][$k] = array_merge($GLOBALS[$principale_ou_auxiliaire][$table][$k],$mem[$k]);
else
$GLOBALS[$principale_ou_auxiliaire][$table][$k] = $mem[$k];
}
}
// recuperer les interfaces (table_titre, table_date)
// on ne le fait que dans un second temps pour que table_objet soit fonctionnel
// dans le pipeline de declarer_tables_interfaces
include_spip('public/interfaces');
foreach(array_keys($infos_tables) as $t) {
$infos_tables[$t] = renseigner_table_objet_interfaces($t,$infos_tables[$t]);
}
$deja_la = false;
// signature
$md5 = md5(serialize($infos_tables));
}
if ($table_sql==="::md5")
return $md5;
if ($table_sql AND !isset($infos_tables[$table_sql])){
#$desc = renseigner_table_objet_sql($table_sql,$desc);
$desc = renseigner_table_objet_interfaces($table_sql,$desc);
return $desc;
}
if ($table_sql)
return isset($infos_tables[$table_sql])?$infos_tables[$table_sql]:array();
return $infos_tables;
}
/**
* Déclare les tables principales du Core
*
* Tables principales, hors objets éditoriaux.
*
* @param array $tables_principales
* Description des tables principales déjà déclarées
* @return void
**/
function base_serial(&$tables_principales){
$spip_jobs = array(
"id_job" => "bigint(21) NOT NULL",
"descriptif" => "text DEFAULT '' NOT NULL",
"fonction" => "varchar(255) NOT NULL", //nom de la fonction
"args"=> "longblob DEFAULT '' NOT NULL", // arguments
"md5args"=> "char(32) NOT NULL default ''", // signature des arguments
"inclure" => "varchar(255) NOT NULL", // fichier a inclure ou path/ pour charger_fonction
"priorite" => "smallint(6) NOT NULL default 0",
"date" => "datetime DEFAULT '0000-00-00 00:00:00' NOT NULL", // date au plus tot
"status" => "tinyint NOT NULL default 1",
);
$spip_jobs_key = array(
"PRIMARY KEY" => "id_job",
"KEY date" => "date",
"KEY status" => "status",
);
/// Attention: mes_fonctions peut avoir deja defini cette variable
/// il faut donc rajouter, mais pas reinitialiser
$tables_principales['spip_jobs'] = array('field' => &$spip_jobs, 'key' => &$spip_jobs_key);
}
/**
* Déclare les tables auxiliaires du Core
*
* @param array $tables_auxiliaires
* Description des tables auxiliaires déjà déclarées
* @return void
**/
function base_auxiliaires(&$tables_auxiliaires){
$spip_resultats = array(
"recherche" => "char(16) DEFAULT '' NOT NULL",
"id" => "INT UNSIGNED NOT NULL",
"points" => "INT UNSIGNED DEFAULT '0' NOT NULL",
"table_objet" => "varchar(30) DEFAULT '' NOT NULL",
"serveur" => "char(16) DEFAULT '' NOT NULL", // hash md5 partiel du serveur de base ('' pour le serveur principal)
"maj" => "TIMESTAMP" );
$spip_resultats_key = array(
// pas de cle ni index, ca fait des insertions plus rapides et les requetes jointes utilisees en recheche ne sont pas plus lentes ...
);
$spip_auteurs_liens = array(
"id_auteur" => "bigint(21) DEFAULT '0' NOT NULL",
"id_objet" => "bigint(21) DEFAULT '0' NOT NULL",
"objet" => "VARCHAR (25) DEFAULT '' NOT NULL",
"vu" => "VARCHAR(6) DEFAULT 'non' NOT NULL");
$spip_auteurs_liens_key = array(
"PRIMARY KEY" => "id_auteur,id_objet,objet",
"KEY id_auteur" => "id_auteur",
"KEY id_objet" => "id_objet",
"KEY objet" => "objet",
);
$spip_meta = array(
"nom" => "VARCHAR (255) NOT NULL",
"valeur" => "text DEFAULT ''",
"impt" => "ENUM('non', 'oui') DEFAULT 'oui' NOT NULL",
"maj" => "TIMESTAMP");
$spip_meta_key = array(
"PRIMARY KEY" => "nom");
$spip_jobs_liens = array(
"id_job" => "bigint(21) DEFAULT '0' NOT NULL",
"id_objet" => "bigint(21) DEFAULT '0' NOT NULL",
"objet" => "VARCHAR (25) DEFAULT '' NOT NULL",
);
$spip_jobs_liens_key = array(
"PRIMARY KEY" => "id_job,id_objet,objet",
"KEY id_job" => "id_job");
$tables_auxiliaires['spip_auteurs_liens'] = array(
'field' => &$spip_auteurs_liens,
'key' => &$spip_auteurs_liens_key);
$tables_auxiliaires['spip_meta'] = array(
'field' => &$spip_meta,
'key' => &$spip_meta_key);
$tables_auxiliaires['spip_resultats'] = array(
'field' => &$spip_resultats,
'key' => &$spip_resultats_key);
$tables_auxiliaires['spip_jobs_liens'] = array(
'field' => &$spip_jobs_liens,
'key' => &$spip_jobs_liens_key);
}
/**
* Auto remplissage des informations non explicites
* sur un objet d'une table sql
*
* - table_objet
* - table_objet_surnoms
* - type
* - type_surnoms
* - url_voir
* - url_edit
* - icone_objet
*
* - texte_retour
* - texte_modifier
* - texte_creer
* - texte_creer_associer
* - texte_ajouter
* - texte_objets
* - texte_objet
*
* - info_aucun_objet
* - info_1_objet
* - info_nb_objets
*
* - texte_logo_objet
* - texte_langue_objet
* - texte_definir_comme_traduction_objet
*
* - principale
* - champs_contenu : utlisé pour générer l'affichage par défaut du contenu
* - editable
* - champs_editables : utilisé pour prendre en compte le post lors de l'édition
*
* - champs_versionnes
*
* statut
* statut_images
* statut_titres
* statut_textes_instituer
* texte_changer_statut
* aide_changer_statut
*
* - modeles : permet de declarer les modeles associes a cet objet
*
* Les infos non renseignées sont auto-déduites par conventions
* ou laissées vides
*
* @param string $table_sql
* @param array $infos
* @return array
*/
function renseigner_table_objet_sql($table_sql,&$infos){
if (!isset($infos['type'])){
// si on arrive de base/trouver_table, on a la cle primaire :
// s'en servir pour extrapoler le type
if (isset($infos['key']["PRIMARY KEY"])){
$primary = $infos['key']["PRIMARY KEY"];
$primary = explode(',',$primary);
$primary = reset($primary);
$infos['type'] = preg_replace(',^spip_|^id_|s$,', '', $primary);
}
else
$infos['type'] = preg_replace(',^spip_|s$,', '', $table_sql);
}
if (!isset($infos['type_surnoms']))
$infos['type_surnoms'] = array();
if (!isset($infos['table_objet']))
$infos['table_objet'] = preg_replace(',^spip_,', '', $table_sql);
if (!isset($infos['table_objet_surnoms']))
$infos['table_objet_surnoms'] = array();
if (!isset($infos['principale']))
$infos['principale'] = (isset($GLOBALS['tables_principales'][$table_sql])?'oui':false);
// normaliser pour pouvoir tester en php $infos['principale']?
// et dans une boucle {principale=oui}
$infos['principale'] = (($infos['principale'] AND $infos['principale']!='non')?'oui':false);
// declarer et normaliser pour pouvoir tester en php $infos['editable']?
// et dans une boucle {editable=oui}
if (!isset($infos['editable'])) $infos['editable'] = 'oui';
$infos['editable'] = (($infos['editable'] AND $infos['editable']!='non')?'oui':false);
// les urls publiques sont par defaut page=type pour les tables principales, et rien pour les autres
// seules les exceptions sont donc a declarer
if (!isset($infos['page']))
$infos['page'] = ($infos['principale']?$infos['type']:'');
if (!isset($infos['url_voir']))
$infos['url_voir'] = $infos['type'];
if (!isset($infos['url_edit']))
$infos['url_edit'] = $infos['url_voir'].($infos['editable']?"_edit":'');
if (!isset($infos['icone_objet']))
$infos['icone_objet'] = $infos['type'];
// chaines de langue
// par defaut : objet:icone_xxx_objet
if (!isset($infos['texte_retour']))
$infos['texte_retour'] = 'icone_retour';
if (!isset($infos['texte_modifier']))
$infos['texte_modifier'] = $infos['type'].':'.'icone_modifier_'.$infos['type'];
if (!isset($infos['texte_creer']))
$infos['texte_creer'] = $infos['type'].':'.'icone_creer_'.$infos['type'];
if (!isset($infos['texte_creer_associer']))
$infos['texte_creer_associer'] = $infos['type'].':'.'texte_creer_associer_'.$infos['type'];
if (!isset($infos['texte_ajouter'])) // Ajouter un X
$infos['texte_ajouter'] = $infos['type'].':'.'texte_ajouter_'.$infos['type'];
if (!isset($infos['texte_objets']))
$infos['texte_objets'] = $infos['type'].':'.'titre_'.$infos['table_objet'];
if (!isset($infos['texte_objet']))
$infos['texte_objet'] = $infos['type'].':'.'titre_'.$infos['type'];
if (!isset($infos['texte_logo_objet'])) // objet:titre_logo_objet "Logo de ce X"
$infos['texte_logo_objet'] = $infos['type'].':'.'titre_logo_'.$infos['type'];
if (!isset($infos['texte_langue_objet'])) // objet:texte_langue_objet "Langue de ce X"
$infos['texte_langue_objet'] = $infos['type'].':'.'titre_langue_'.$infos['type'];
if (!isset($infos['texte_definir_comme_traduction_objet'])) // "Ce X est une traduction du X numéro :"
$infos['texte_definir_comme_traduction_objet'] = $infos['type'].':'.'texte_definir_comme_traduction_'.$infos['type'];
// objet:info_aucun_objet
if (!isset($infos['info_aucun_objet']))
$infos['info_aucun_objet'] = $infos['type'].':'.'info_aucun_'.$infos['type'];
// objet:info_1_objet
if (!isset($infos['info_1_objet']))
$infos['info_1_objet'] = $infos['type'].':'.'info_1_'.$infos['type'];
// objet:info_nb_objets
if (!isset($infos['info_nb_objets']))
$infos['info_nb_objets'] = $infos['type'].':'.'info_nb_'.$infos['table_objet'];
if (!isset($infos['champs_editables']))
$infos['champs_editables'] = array();
if (!isset($infos['champs_versionnes']))
$infos['champs_versionnes'] = array();
if (!isset($infos['rechercher_champs']))
$infos['rechercher_champs'] = array();
if (!isset($infos['rechercher_jointures']))
$infos['rechercher_jointures'] = array();
if (!isset($infos['modeles']))
$infos['modeles'] = array($infos['type']);
return $infos;
}
/**
* Renseigner les infos d'interface compilateur pour les tables objets
* complete la declaration precedente
*
* titre
* date
* statut
* tables_jointures
*
* @param $table_sql
* @param $infos
* @return array
*/
function renseigner_table_objet_interfaces($table_sql,&$infos){
if (!isset($infos['titre'])){
if (isset($infos['table_objet']) AND isset($GLOBALS['table_titre'][$infos['table_objet']]))
$infos['titre'] = $GLOBALS['table_titre'][$infos['table_objet']];
else {
$infos['titre'] = ((isset($infos['field']['titre']))?"titre,":"'' as titre,");
$infos['titre'] .= ((isset($infos['field']['lang']))?"lang":"'' as lang");
}
}
if (!isset($infos['date'])){
if (isset($infos['table_objet']) and isset($GLOBALS['table_date'][$infos['table_objet']]))
$infos['date'] = $GLOBALS['table_date'][$infos['table_objet']];
else
$infos['date'] = ((isset($infos['field']['date']))?"date":'');
}
if (!isset($infos['statut']))
$infos['statut'] = isset($GLOBALS['table_statut'][$table_sql]) ? $GLOBALS['table_statut'][$table_sql] : '';
if (!isset($infos['tables_jointures']))
$infos['tables_jointures'] = array();
if (isset($GLOBALS['tables_jointures'][$table_sql]))
$infos['tables_jointures'] = array_merge($infos['tables_jointures'],$GLOBALS['tables_jointures'][$table_sql]);
return $infos;
}
/**
* Retourne la liste des tables principales et leurs descriptions
*
* @api
* @return array
* Liste et descriptions des tables principales
**/
function lister_tables_principales(){
static $done = false;
if (!$done OR !count($GLOBALS['tables_principales'])){
lister_tables_objets_sql();
$done = true;
}
return $GLOBALS['tables_principales'];
}
/**
* Retourne la liste des tables auxiliaires et leurs descriptions
*
* @api
* @return array
* Liste et descriptions des tables auxiliaires
**/
function lister_tables_auxiliaires(){
static $done = false;
if (!$done OR !count($GLOBALS['tables_auxiliaires'])){
lister_tables_objets_sql();
$done = true;
}
return $GLOBALS['tables_auxiliaires'];
}
/**
* Recenser les surnoms de table_objet
* @return array
*/
function lister_tables_objets_surnoms(){
static $surnoms = null;
static $md5 = null;
if (!$surnoms
OR $md5 != lister_tables_objets_sql('::md5')){
// passer dans un pipeline qui permet aux plugins de declarer leurs exceptions
// pour compatibilite, car il faut dorenavent utiliser
// declarer_table_objets_sql
$surnoms = pipeline('declarer_tables_objets_surnoms',
array(
# pour les modeles
# a enlever ?
'doc' => 'documents',
'img' => 'documents',
'emb' => 'documents',
));
$infos_tables = lister_tables_objets_sql();
foreach($infos_tables as $t=>$infos){
// cas de base type=>table
// et preg_replace(',^spip_|^id_|s$,',table)=>table
if ($infos['table_objet']){ // securite, si la fonction est appelee trop tot, c'est vide
// optimisations pour table_objet
//$surnoms[$infos['type']] = $infos['table_objet'];
$surnoms[preg_replace(',^spip_|^id_|s$,', '', $infos['table_objet'])] = $infos['table_objet'];
$surnoms[preg_replace(',^spip_|^id_|s$,', '', $infos['type'])] = $infos['table_objet'];
if (is_array($infos['table_objet_surnoms']) AND count($infos['table_objet_surnoms']))
foreach($infos['table_objet_surnoms'] as $surnom)
$surnoms[$surnom] = $infos['table_objet'];
}
}
$md5 = lister_tables_objets_sql('::md5');
}
return $surnoms;
}
/**
* Recenser les surnoms de table_objet
* @return array
*/
function lister_types_surnoms(){
static $surnoms = null;
static $md5 = null;
if (!$surnoms
OR $md5 != lister_tables_objets_sql('::md5')){
// passer dans un pipeline qui permet aux plugins de declarer leurs exceptions
// pour compatibilite, car il faut dorenavent utiliser
// declarer_table_objets_sql
$surnoms = pipeline('declarer_type_surnoms', array('racine-site'=>'site'));
$infos_tables = lister_tables_objets_sql();
foreach($infos_tables as $t=>$infos){
if ($infos['type']){ // securite, si la fonction est appelee trop tot, c'est vide
// optimisations pour objet_type
//$surnoms[$infos['type']] = $infos['type'];
$surnoms[preg_replace(',^spip_|^id_|s$,', '', $infos['table_objet'])] = $infos['type'];
$surnoms[preg_replace(',^spip_|^id_|s$,', '', $infos['type'])] = $infos['type'];
// surnoms declares
if (is_array($infos['type_surnoms']) AND count($infos['type_surnoms']))
foreach($infos['type_surnoms'] as $surnom)
$surnoms[$surnom] = $infos['type'];
}
}
$md5 = lister_tables_objets_sql('::md5');
}
return $surnoms;
}
function lister_tables_spip($serveur=''){
static $tables = array();
if (!isset($tables[$serveur])){
$tables[$serveur] = array();
if (!function_exists("sql_alltable"))
include_spip("base/abstract_sql");
$ts = sql_alltable(null,$serveur); // toutes les tables "spip_" (ou prefixe perso)
$connexion = $GLOBALS['connexions'][$serveur ? $serveur : 0];
$spip = $connexion['prefixe'] . '_';
foreach ($ts as $t){
$t = substr($t,strlen($spip));
$tables[$serveur]["spip_$t"] = $t;
}
}
return $tables[$serveur];
}
function lister_toutes_tables($serveur){
static $tables = array();
if (!isset($tables[$serveur])){
$tables[$serveur] = array();
if (!function_exists("sql_alltable"))
include_spip("base/abstract_sql");
$ts = sql_alltable('%',$serveur); // toutes les tables
foreach ($ts as $t){
$tables[$serveur][$t] = $t;
}
}
return $tables[$serveur];
}
/**
* Retrouve le nom d'objet à partir de la table
*
* - spip_articles -> articles
* - id_article -> articles
* - article -> articles
*
* @api
* @param string $type
* Nom de la table SQL (le plus souvent)
* Tolère un nom de clé primaire.
* @param string $serveur
* Nom du connecteur
* @return string
* Nom de l'objet
**/
function table_objet($type,$serveur='') {
$surnoms = lister_tables_objets_surnoms();
$type = preg_replace(',^spip_|^id_|s$,', '', $type);
if (!$type) return;
if (isset($surnoms[$type]))
return $surnoms[$type];
if ($serveur!==false){
$t=lister_tables_spip($serveur);
$trouver_table = charger_fonction('trouver_table', 'base');
$typetrim = rtrim($type,'s')."s";
if (
(isset($t[$typetrim]) OR in_array($typetrim,$t))
AND ($desc = $trouver_table(rtrim($type,'s')."s",$serveur))
)
return $desc['id_table'];
elseif (
(isset($t[$type]) OR in_array($type,$t))
AND ($desc = $trouver_table($type,$serveur))
)
return $desc['id_table'];
spip_log( 'table_objet('.$type.') calculee sans verification');
}
return rtrim($type,'s')."s"; # cas historique ne devant plus servir, sauf si $serveur=false
}
/**
* Retrouve la table sql à partir de l'objet ou du type
*
* - articles -> spip_articles
* - article -> spip_articles
* - id_article -> spip_articles
*
* @api
* @param string $type
* Nom ou type de l'objet
* Tolère un nom de clé primaire.
* @param string $serveur
* Nom du connecteur
* @return string
* Nom de la table SQL
**/
function table_objet_sql($type,$serveur='') {
global $table_des_tables;
$nom = table_objet($type, $serveur);
if (!isset($table_des_tables['articles'])) // eviter de multiples inclusions
include_spip('public/interfaces');
if (isset($table_des_tables[$nom])) {
$nom = $table_des_tables[$nom];
$nom = "spip_$nom";
}
else {
$infos_tables = lister_tables_objets_sql();
if (isset($infos_tables["spip_$nom"]))
$nom = "spip_$nom";
elseif($serveur!==false) {
$t=lister_tables_spip($serveur);
if (isset($t[$nom]) OR in_array($nom,$t)){
$trouver_table = charger_fonction('trouver_table', 'base');
if ($desc = $trouver_table($nom,$serveur))
return $desc['table_sql'];
}
}
}
return $nom ;
}
/**
* Retrouve la clé primaire à partir du nom d'objet ou de table
*
* - articles -> id_article
* - article -> id_article
* - spip_articles -> id_article
*
* @api
* @param string $type
* Nom de la table SQL ou de l'objet
* @param string $serveur
* Nom du connecteur
* @return string
* Nom de la clé primaire
**/
function id_table_objet($type,$serveur='') {
static $trouver_table = null;
$type = objet_type($type,$serveur);
if (!$type) return;
$t = table_objet($type);
if (!$trouver_table)
$trouver_table = charger_fonction('trouver_table', 'base');
$ts=lister_tables_spip($serveur);
if (in_array($t,$ts)
OR in_array($t,lister_toutes_tables($serveur))){
$desc = $trouver_table($t,$serveur);
if (isset($desc['key']['PRIMARY KEY']))
return $desc['key']['PRIMARY KEY'];
if (!$desc OR isset($desc['field']["id_$type"]))
return "id_$type";
// sinon renvoyer le premier champ de la table...
$keys = array_keys($desc['field']);
return array_shift($keys);
}
return "id_$type";
}
/**
* Retrouve le type d'objet à partir du nom d'objet ou de table
*
* - articles -> article
* - spip_articles -> article
* - id_article -> article
*
* @api
* @param string $table_objet
* Nom de l'objet ou de la table SQL
* @param string $serveur
* Nom du connecteur
* @return string
* Type de l'objet
**/
function objet_type($table_objet, $serveur=''){
if (!$table_objet) return;
$surnoms = lister_types_surnoms();
// scenario de base
// le type est decline a partir du nom de la table en enlevant le prefixe eventuel
// et la marque du pluriel
// on accepte id_xx en entree aussi
$type = preg_replace(',^spip_|^id_|s$,', '', $table_objet);
if (isset($surnoms[$type]))
return $surnoms[$type];
// securite : eliminer les caracteres non \w
$type = preg_replace(',[^\w-],','',$type);
// si le type redonne bien la table c'est bon
// oui si table_objet ressemblait deja a un type
if ( $type==$table_objet
OR (table_objet($type,$serveur)==$table_objet)
OR (table_objet_sql($type,$serveur)==$table_objet))
return $type;
// si on ne veut pas chercher en base
if ($serveur===false)
return $type;
// sinon on passe par la cle primaire id_xx pour trouver le type
// car le s a la fin est incertain
// notamment en cas de pluriel derogatoire
// id_jeu/spip_jeux id_journal/spip_journaux qui necessitent tout deux
// une declaration jeu => jeux, journal => journaux
// dans le pipeline declarer_tables_objets_surnoms
$trouver_table = charger_fonction('trouver_table', 'base');
$ts=lister_tables_spip($serveur);
if (in_array($table_objet,$ts))
$desc = $trouver_table($table_objet);
if (!$desc AND in_array($table_objet=table_objet($type,$serveur),$ts))
$desc = $trouver_table($table_objet,$serveur);
// si le type est declare : bingo !
if ($desc AND isset($desc['type']))
return $desc['type'];
// on a fait ce qu'on a pu
return $type;
}
/**
* Determininer si un objet est publie ou non
*
* On se base pour cela sur sa declaration de statut
* pour des cas particuliers non declarables, on permet de fournir une fonction
* base_xxxx_test_si_publie qui sera appele par la fonction
*
* @param string $objet
* @param int $id_objet
* @param string $serveur
* @return bool
*/
function objet_test_si_publie($objet,$id_objet, $serveur=''){
// voir si une fonction est definie pour faire le boulot
// elle a la priorite dans ce cas
if ($f = charger_fonction($objet."_test_si_publie","base",true))
return $f($objet,$id_objet, $serveur);
// sinon on se fie a la declaration de l'objet si presente
$id_table = $table_objet = table_objet($objet);
$id_table_objet = id_table_objet($objet, $serveur);
$trouver_table = charger_fonction('trouver_table', 'base');
if ($desc = $trouver_table($table_objet, $serveur)
AND isset($desc['statut'])
AND $desc['statut']){
$boucle = new Boucle();
$boucle->show = $desc;
$boucle->nom = 'objet_test_si_publie';
$boucle->id_boucle = $id_table;
$boucle->id_table = $id_table;
$boucle->sql_serveur = $serveur;
$boucle->select[] = $id_table_objet;
$boucle->from[$table_objet] = table_objet_sql($objet, $serveur);
$boucle->where[] = $id_table.".".$id_table_objet.'='.intval($id_objet);
include_spip('public/compiler');
include_spip('public/composer');
instituer_boucle($boucle, false, true);
$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);
if (sql_fetch($res))
return true;
return false;
}
// si pas d'info statut ni de fonction : l'objet est publie
return true;
}
trouver_table.php 0000666 00000015131 15250255012 0010134 0 ustar 00 <?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. *
\***************************************************************************/
/**
* Gestion de l'obtention des descriptions de tables SQL
*
* @package SPIP\SQL\Tables
**/
if (!defined('_ECRIRE_INC_VERSION')) return;
include_spip('base/objets');
/**
* Retourne la description d'une table SQL
*
* Cela sert notamment au moment de la compilation des boucles, critères et balise.
*
* Les champs et clés de la tables sont retrouvés prioritairement via le
* gestionnaire de base de données. Les descriptions sont complétées,
* pour les tables éditoriales, des informations déclarées ou construites
* par la déclaration des objets éditoriaux.
*
* @example
* $trouver_table = charger_fonction('trouver_table', 'base');
* $desc = $trouver_table('spip_groupes_mots');
*
* Cette fonction intervient à la compilation, mais aussi pour la balise
* contextuelle EXPOSE ou certains critères.
*
* L'ensemble des descriptions de table d'un serveur est stocké dans un
* fichier cache/sql_desc.txt par soucis de performance. Un appel
* avec $nom vide est une demande explicite de vidange de ce cache
*
* @see lister_tables_objets_sql()
*
* @api
* @param string $nom
* Nom de la table
* Vide '' demande de vider le cache des discriptions
* @param string $serveur
* Nom du connecteur
* @param bool $table_spip
* Indique s'il faut transformer le préfixe de table
* @return array|bool
* false si table introuvable
* tableau de description de la table sinon, en particulier :
* - field : tableau des colonnes SQL et leur description (comme dans serial.php ou objets.php)
* - key : tableau des KEY (comme dans serial.php ou objets.php)
* - table et table_sql : nom de la table (avec spip_ en préfixe)
* - id_table : nom SPIP de la table (type de boucle)
* le compilateur produit FROM $r['table'] AS $r['id_table']
* - Toutes les autres informations des objets éditoriaux si la table est l'un d'eux.
*
*
**/
function base_trouver_table_dist($nom, $serveur='', $table_spip = true){
static $nom_cache_desc_sql=array();
global $tables_principales, $tables_auxiliaires, $table_des_tables;
if (!spip_connect($serveur)
OR !preg_match('/^[a-zA-Z0-9._-]*/',$nom))
return null;
$connexion = &$GLOBALS['connexions'][$serveur ? strtolower($serveur) : 0];
$objets_sql = lister_tables_objets_sql("::md5");
// le nom du cache depend du serveur mais aussi du nom de la db et du prefixe
// ce qui permet une auto invalidation en cas de modif manuelle du fichier
// de connexion, et tout risque d'ambiguite
if (!isset($nom_cache_desc_sql[$serveur][$objets_sql])){
$nom_cache_desc_sql[$serveur][$objets_sql] =
_DIR_CACHE . 'sql_desc_'
. ($serveur ? "{$serveur}_":"")
. substr(md5($connexion['db'].":".$connexion['prefixe'].":$objets_sql"),0,8)
.'.txt';
// nouveau nom de cache = nouvelle version en memoire
unset($connexion['tables']);
}
// un appel avec $nom vide est une demande explicite de vidange du cache des descriptions
if (!$nom){
spip_unlink($nom_cache_desc_sql[$serveur][$objets_sql]);
$connexion['tables'] = array();
return null;
}
$nom_sql = $nom;
if (preg_match('/\.(.*)$/', $nom, $s))
$nom_sql = $s[1];
else
$nom_sql = $nom;
$fdesc = $desc = '';
$connexion = &$GLOBALS['connexions'][$serveur ? $serveur : 0];
// base sous SPIP: gerer les abreviations explicites des noms de table
if ($connexion['spip_connect_version']) {
if ($table_spip AND isset($table_des_tables[$nom])) {
$nom = $table_des_tables[$nom];
$nom_sql = 'spip_' . $nom;
}
}
// si c'est la premiere table qu'on cherche
// et si on est pas explicitement en recalcul
// on essaye de recharger le cache des decriptions de ce serveur
// dans le fichier cache
if (!isset($connexion['tables'][$nom_sql])
AND defined('_VAR_MODE') AND _VAR_MODE!=='recalcul'
AND (!isset($connexion['tables']) OR !$connexion['tables'])) {
if (lire_fichier($nom_cache_desc_sql[$serveur][$objets_sql],$desc_cache)
AND $desc_cache=unserialize($desc_cache))
$connexion['tables'] = $desc_cache;
}
if ($table_spip AND !isset($connexion['tables'][$nom_sql])) {
if (isset($tables_principales[$nom_sql]))
$fdesc = $tables_principales[$nom_sql];
// meme si pas d'abreviation declaree, trouver la table spip_$nom
// si c'est une table principale,
// puisqu'on le fait aussi pour les tables auxiliaires
elseif ($nom_sql==$nom AND isset($tables_principales['spip_' .$nom])){
$nom_sql = 'spip_' . $nom;
$fdesc = &$tables_principales[$nom_sql];
}
elseif (isset($tables_auxiliaires[$n=$nom])
OR isset($tables_auxiliaires[$n='spip_'.$nom])) {
$nom_sql = $n;
$fdesc = &$tables_auxiliaires[$n];
} # table locale a cote de SPIP, comme non SPIP:
}
if (!isset($connexion['tables'][$nom_sql])) {
// La *vraie* base a la priorite
$desc = sql_showtable($nom_sql, $table_spip, $serveur);
if (!$desc OR !$desc['field']) {
if (!$fdesc) {
spip_log("trouver_table: table inconnue '$serveur' '$nom'",_LOG_INFO_IMPORTANTE);
return null;
}
// on ne sait pas lire la structure de la table :
// on retombe sur la description donnee dans les fichiers spip
$desc = $fdesc;
}
else {
$desc['exist'] = true;
}
$desc['table'] = $desc['table_sql'] = $nom_sql;
$desc['connexion']= $serveur;
// charger les infos declarees pour cette table
// en lui passant les infos connues
// $desc est prioritaire pour la description de la table
$desc = array_merge(lister_tables_objets_sql($nom_sql,$desc),$desc);
// si tables_objets_sql est bien fini d'init, on peut cacher
$connexion['tables'][$nom_sql] = $desc;
$res = &$connexion['tables'][$nom_sql];
// une nouvelle table a ete decrite
// mettons donc a jour le cache des descriptions de ce serveur
if (is_writeable(_DIR_CACHE))
ecrire_fichier($nom_cache_desc_sql[$serveur][$objets_sql],serialize($connexion['tables']),true);
}
else
$res = &$connexion['tables'][$nom_sql];
// toujours retourner $nom dans id_table
$res['id_table']=$nom;
return $res;
}
?>
restaurer.php 0000666 00000006467 15250307345 0007316 0 ustar 00 <?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;
include_spip('inc/dump');
include_spip('inc/actions');
function base_restaurer_dist($titre='', $reprise=false) {
$status_file = _DUMP_STATUS_FILE;
$status_file = _DIR_TMP.basename($status_file).".txt";
if (!lire_fichier($status_file, $status)
OR !$status = unserialize($status)) {
}
else {
$redirect = parametre_url(generer_action_auteur('restaurer',_DUMP_STATUS_FILE),"step",intval(_request('step')+1),'&');
$timeout = ini_get('max_execution_time');
// valeur conservatrice si on a pas reussi a lire le max_execution_time
if (!$timeout) $timeout=30; // parions sur une valeur tellement courante ...
$max_time = time()+$timeout/2;
include_spip('inc/minipres');
@ini_set("zlib.output_compression","0"); // pour permettre l'affichage au fur et a mesure
$titre = _T('dump:restauration_en_cours') . " (".count($status['tables']).") ";
$balise_img = chercher_filtre('balise_img');
$titre .= $balise_img(chemin_image('searching.gif'));
echo ( install_debut_html($titre));
// script de rechargement auto sur timeout
echo http_script("window.setTimeout('location.href=\"".$redirect."\";',".($timeout*1000).")");
echo "<div style='text-align: left'>\n";
dump_serveur($status['connect']);
spip_connect('dump');
// au premier coup on ne fait rien sauf afficher l'ecran de sauvegarde
if (_request('step')) {
$options = array(
'callback_progression' => 'dump_afficher_progres',
'max_time' => $max_time,
'no_erase_dest' => lister_tables_noerase(),
'where' => $status['where']?$status['where']:array(),
'desc_tables_dest' => array()
);
if ($desc = sql_getfetsel('valeur','spip_meta',"nom='dump_structure_temp'",'','','','','dump')
AND $desc = unserialize($desc))
$options['desc_tables_dest'] = $desc;
#var_dump(sql_allfetsel('nom,valeur','spip_meta',"",'','','','','dump'));
#die();
$res = base_copier_tables($status_file, $status['tables'], 'dump', '', $options);
}
else {
// mais on en profite pour reparer les version base pour etre sur de ne pas les perdre
sql_updateq("spip_meta",array('impt'=>'oui'),"nom='version_installee'",'','dump');
sql_updateq("spip_meta",array('impt'=>'oui'),"nom LIKE '%_base_version'",'','dump');
}
echo ( "</div>\n");
if (!$res)
echo dump_relance($redirect);
echo (install_fin_html());
ob_end_flush();
flush();
if (!$res)
exit;
// quand on sort de $export avec true c'est qu'on a fini
dump_end(_DUMP_STATUS_FILE,'restaurer');
include_spip('inc/headers');
echo redirige_formulaire(generer_url_ecrire("restaurer",'status='._DUMP_STATUS_FILE,'',true, true));
}
}
?>
forum.php 0000666 00000012607 15250307634 0006424 0 ustar 00 <?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;
/**
* Interfaces de la table forum pour le compilateur
*
* @param array $interfaces
* @return array $interfaces
*/
function forum_declarer_tables_interfaces($interfaces){
$interfaces['table_des_tables']['forums']='forum';
$interfaces['exceptions_des_tables']['forums']['date']='date_heure';
$interfaces['exceptions_des_tables']['forums']['nom']='auteur';
$interfaces['exceptions_des_tables']['forums']['email']='email_auteur';
// il ne faut pas essayer de chercher le forum du mot cle, mais bien le mot cle associe au forum
$interfaces['exceptions_des_jointures']['spip_forum']['id_secteur'] = array('spip_articles','id_secteur');
$interfaces['exceptions_des_jointures']['spip_forum']['id_mot'] = array('spip_mots','id_mot');
$interfaces['exceptions_des_jointures']['spip_forum']['titre_mot'] = array('spip_mots','titre');
$interfaces['exceptions_des_jointures']['spip_forum']['type_mot'] = array('spip_mots','type');
$interfaces['exceptions_des_jointures']['spip_forum']['id_groupe'] = array('spip_mots','id_groupe');
#$interfaces['table_titre']['forums']= "titre, '' AS lang";
#$interfaces['table_date']['forums']='date_heure';
$interfaces['table_statut']['spip_forum'][] = array('champ'=>'statut','publie'=>'publie','previsu'=>'publie,prop','exception'=>'statut');
$interfaces['table_des_traitements']['PARAMETRES_FORUM'][]= 'spip_htmlspecialchars(%s)';
$interfaces['table_des_traitements']['TEXTE']['forums']= "liens_nofollow(safehtml(".str_replace("%s","interdit_html(%s)",_TRAITEMENT_RACCOURCIS)."))";
$interfaces['table_des_traitements']['TITRE']['forums']= "liens_nofollow(safehtml(".str_replace("%s","interdit_html(%s)",_TRAITEMENT_TYPO)."))";
$interfaces['table_des_traitements']['NOTES']['forums']= "liens_nofollow(safehtml(".str_replace("%s","interdit_html(%s)",_TRAITEMENT_RACCOURCIS)."))";
$interfaces['table_des_traitements']['NOM_SITE']['forums']= "liens_nofollow(safehtml(".str_replace("%s","interdit_html(%s)",_TRAITEMENT_TYPO)."))";
$interfaces['table_des_traitements']['URL_SITE']['forums']= 'safehtml(vider_url(%s))';
$interfaces['table_des_traitements']['AUTEUR']['forums']= 'liens_nofollow(safehtml(vider_url(%s)))';
$interfaces['table_des_traitements']['EMAIL_AUTEUR']['forums']= 'safehtml(vider_url(%s))';
return $interfaces;
}
/**
* Déclaration de la table spip_forum et de l'objet forum
*
* @param array $tables Tableau des objets déclarés
* @return array $tables Tableau des objets complété
*/
function forum_declarer_tables_objets_sql($tables){
$tables['spip_forum'] = array(
'table_objet'=>'forums', # ??? hum hum redevient spip_forum par table_objet_sql mais casse par un bete "spip_".table_objet()
'type'=>'forum',
'url_voir'=>'controler_forum',
'url_edit'=>'controler_forum',
'editable'=>'non',
'principale' => 'oui',
'page'=>'', // pas de page editoriale pour un forum
'texte_retour' => 'icone_retour',
'texte_objets' => 'forum:forum',
'texte_objet' => 'forum:forum',
'info_aucun_objet'=> 'forum:aucun_message_forum',
'info_1_objet' => 'forum:info_1_message_forum',
'info_nb_objets' => 'forum:info_nb_messages_forum',
'titre' => "titre, '' AS lang",
'date' => 'date_heure',
'champs_editables' => array('titre', 'texte', 'nom_site', 'url_site'),
'field'=> array(
"id_forum" => "bigint(21) NOT NULL",
"id_objet" => "bigint(21) DEFAULT '0' NOT NULL",
"objet" => "VARCHAR (25) DEFAULT '' NOT NULL",
"id_parent" => "bigint(21) DEFAULT '0' NOT NULL",
"id_thread" => "bigint(21) DEFAULT '0' NOT NULL",
"date_heure" => "datetime DEFAULT '0000-00-00 00:00:00' NOT NULL",
"date_thread" => "datetime DEFAULT '0000-00-00 00:00:00' NOT NULL",
"titre" => "text DEFAULT '' NOT NULL",
"texte" => "mediumtext DEFAULT '' NOT NULL",
"auteur" => "text DEFAULT '' NOT NULL",
"email_auteur" => "text DEFAULT '' NOT NULL",
"nom_site" => "text DEFAULT '' NOT NULL",
"url_site" => "text DEFAULT '' NOT NULL",
"statut" => "varchar(8) DEFAULT '0' NOT NULL",
"ip" => "varchar(40) DEFAULT '' NOT NULL",
"maj" => "TIMESTAMP",
"id_auteur" => "bigint DEFAULT '0' NOT NULL"
),
'key' => array(
"PRIMARY KEY" => "id_forum",
"KEY id_auteur" => "id_auteur",
"KEY id_parent" => "id_parent",
"KEY id_thread" => "id_thread",
"KEY optimal" => "statut,id_parent,id_objet,objet,date_heure"
),
'join' => array(
"id_forum"=>"id_forum",
"id_parent"=>"id_parent",
"id_objet"=>"id_objet",
"objet"=>"objet",
"id_auteur"=>"id_auteur",
),
'rechercher_champs' => array(
'titre' => 3, 'texte' => 1, 'auteur' => 2, 'email_auteur' => 2, 'nom_site' => 1, 'url_site' => 1
),
);
// jointures sur les forum pour tous les objets
$tables[]['tables_jointures'][]= 'forums';
return $tables;
}
?>
medias.php 0000666 00000022552 15250307640 0006533 0 ustar 00 <?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;
/**
* Interfaces des tables breves pour le compilateur
*
* @param array $interfaces
* @return array
*/
function medias_declarer_tables_interfaces($interfaces) {
$interfaces['table_des_tables']['documents']='documents';
$interfaces['table_des_tables']['types_documents']='types_documents';
$interfaces['exceptions_des_tables']['documents']['type_document']=array('types_documents', 'titre');
$interfaces['exceptions_des_tables']['documents']['extension_document']=array('types_documents', 'extension');
$interfaces['exceptions_des_tables']['documents']['mime_type']=array('types_documents', 'mime_type');
$interfaces['exceptions_des_tables']['documents']['media_document']=array('types_documents', 'media');
$interfaces['exceptions_des_jointures']['spip_documents']['id_forum']=array('spip_documents_liens','id_forum');
$interfaces['exceptions_des_jointures']['spip_documents']['vu']=array('spip_documents_liens', 'vu');
$interfaces['table_date']['types_documents']='date';
$interfaces['table_des_traitements']['FICHIER']['documents']= 'get_spip_doc(%s)';
return $interfaces;
}
/**
* Table principale spip_documents et spip_types_documents
*
* @param array $tables_principales
* @return array
*/
function medias_declarer_tables_principales($tables_principales) {
$spip_types_documents = array(
"extension" => "varchar(10) DEFAULT '' NOT NULL",
"titre" => "text DEFAULT '' NOT NULL",
"descriptif" => "text DEFAULT '' NOT NULL",
"mime_type" => "varchar(100) DEFAULT '' NOT NULL",
"inclus" => "ENUM('non', 'image', 'embed') DEFAULT 'non' NOT NULL",
"upload" => "ENUM('oui', 'non') DEFAULT 'oui' NOT NULL",
"media_defaut" => "varchar(10) DEFAULT 'file' NOT NULL",
"maj" => "TIMESTAMP");
$spip_types_documents_key = array(
"PRIMARY KEY" => "extension",
"KEY inclus" => "inclus");
$tables_principales['spip_types_documents'] =
array('field' => &$spip_types_documents, 'key' => &$spip_types_documents_key);
return $tables_principales;
}
/**
* Table des liens documents-objets spip_documents_liens
* @param array $tables_auxiliaires
* @return array
*/
function medias_declarer_tables_auxiliaires($tables_auxiliaires) {
$spip_documents_liens = array(
"id_document" => "bigint(21) DEFAULT '0' NOT NULL",
"id_objet" => "bigint(21) DEFAULT '0' NOT NULL",
"objet" => "VARCHAR (25) DEFAULT '' NOT NULL",
"vu" => "ENUM('non', 'oui') DEFAULT 'non' NOT NULL");
$spip_documents_liens_key = array(
"PRIMARY KEY" => "id_document,id_objet,objet",
"KEY id_document" => "id_document",
"KEY id_objet" => "id_objet",
"KEY objet" => "objet",
);
$tables_auxiliaires['spip_documents_liens'] = array(
'field' => &$spip_documents_liens,
'key' => &$spip_documents_liens_key);
return $tables_auxiliaires;
}
/**
* Declarer le surnom des breves
*
* @param array $surnoms
* @return array
*/
function medias_declarer_tables_objets_surnoms($surnoms) {
$surnoms['type_document'] = "types_documents"; # hum
#$surnoms['extension'] = "types_documents"; # hum
#$surnoms['type'] = "types_documents"; # a ajouter pour id_table_objet('type')=='extension' ?
return $surnoms;
}
function medias_declarer_tables_objets_sql($tables){
$tables['spip_articles']['champs_versionnes'][] = 'jointure_documents';
$tables['spip_documents'] = array(
'table_objet_surnoms'=>array('doc','img','emb'),
'type_surnoms' => array(),
'url_voir' => 'document_edit',
'url_edit' => 'document_edit',
'page'=>'',
'texte_retour' => 'icone_retour',
'texte_objets' => 'medias:objet_documents',
'texte_objet' => 'medias:objet_document',
'texte_modifier' => 'medias:info_modifier_document',
'info_aucun_objet'=> 'medias:aucun_document',
'info_1_objet' => 'medias:un_document',
'info_nb_objets' => 'medias:des_documents',
'titre' => "CASE WHEN length(titre)>0 THEN titre ELSE fichier END as titre, '' AS lang",
'date' => 'date',
'principale'=>'oui',
'field' => array(
"id_document" => "bigint(21) NOT NULL",
"id_vignette" => "bigint(21) DEFAULT '0' NOT NULL",
"extension" => "VARCHAR(10) DEFAULT '' NOT NULL",
"titre" => "text DEFAULT '' NOT NULL",
"date" => "datetime DEFAULT '0000-00-00 00:00:00' NOT NULL",
"descriptif" => "text DEFAULT '' NOT NULL",
"fichier" => "text NOT NULL DEFAULT ''",
"taille" => "bigint",
"largeur" => "integer",
"hauteur" => "integer",
"media" => "varchar(10) DEFAULT 'file' NOT NULL",
"mode" => "varchar(10) DEFAULT 'document' NOT NULL",
"distant" => "VARCHAR(3) DEFAULT 'non'",
"statut" => "varchar(10) DEFAULT '0' NOT NULL",
"credits" => "varchar(255) DEFAULT '' NOT NULL",
"date_publication" => "datetime DEFAULT '0000-00-00 00:00:00' NOT NULL",
"brise" => "tinyint DEFAULT 0",
"maj" => "TIMESTAMP"
),
'key' => array(
"PRIMARY KEY" => "id_document",
"KEY id_vignette" => "id_vignette",
"KEY mode" => "mode",
"KEY extension" => "extension"
),
'join' => array(
"id_document"=>"id_document",
"extension"=>"extension"
),
'statut'=> array(
array(
'champ' => 'statut',
'publie' => 'publie',
'previsu' => 'publie,prop,prepa',
'post_date' => 'date_publication',
'exception' => array('statut','tout')
)
),
'tables_jointures' => array('types_documents'),
'rechercher_champs' => array(
'titre' => 3, 'descriptif' => 1, 'fichier' => 1, 'credits' => 1,
),
'champs_editables' => array('titre', 'descriptif', 'date', 'taille', 'largeur','hauteur','mode','credits','fichier','distant','extension', 'id_vignette', 'media'),
'champs_versionnes' => array('id_vignette', 'titre', 'descriptif', 'hauteur', 'largeur', 'mode','credits','distant'),
'modeles' => array('document','doc','img','emb','image','video','text','audio','application'),
);
// jointures sur les forum pour tous les objets
$tables[]['tables_jointures'][]= 'documents_liens';
// recherche jointe sur les documents pour les articles et rubriques
$tables['spip_articles']['rechercher_jointures']['document'] = array('titre' => 2, 'descriptif' => 1);
$tables['spip_rubriques']['rechercher_jointures']['document'] = array('titre' => 2, 'descriptif' => 1);
return $tables;
}
/**
* Creer la table des types de document
*
* http://code.spip.net/@creer_base_types_doc
*
* @param string $serveur
* @return void
*/
function creer_base_types_doc($serveur='', $champ_media="media_defaut") {
global $tables_images, $tables_sequences, $tables_documents, $tables_mime;
include_spip('base/typedoc');
include_spip('base/abstract_sql');
// charger en memoire tous les types deja definis pour limiter les requettes
$rows = sql_allfetsel('mime_type,titre,inclus,extension,'.$champ_media.',upload,descriptif','spip_types_documents','','','','','',$serveur);
$deja = array();
foreach ($rows as $k=>$row){
$deja[$row['extension']] = &$rows[$k];
}
$insertions = array();
$updates = array();
foreach ($tables_mime as $extension => $type_mime) {
if (isset($tables_images[$extension])) {
$titre = $tables_images[$extension];
$inclus='image';
}
else if (isset($tables_sequences[$extension])) {
$titre = $tables_sequences[$extension];
$inclus='embed';
}
else {
$inclus='non';
if (isset($tables_documents[$extension]))
$titre = $tables_documents[$extension];
else
$titre = '';
}
// type de media
$media = "file";
if (preg_match(",^image/,",$type_mime) OR in_array($type_mime,array('application/illustrator')))
$media = "image";
elseif (preg_match(",^audio/,",$type_mime))
$media = "audio";
elseif (preg_match(",^video/,",$type_mime) OR in_array($type_mime,array('application/ogg','application/x-shockwave-flash','application/mp4')))
$media = "video";
$set = array(
'mime_type' => $type_mime,
'titre' => $titre,
'inclus' => $inclus,
'extension' => $extension,
$champ_media => $media,
'upload' => 'oui',
'descriptif' => '',
);
if (!isset($deja[$extension])){
$insertions[] = $set;
}
elseif (array_diff($deja[$extension],$set)){
$updates[$extension] = $set;
}
}
if (count($updates)){
foreach ($updates as $extension=>$set){
sql_updateq('spip_types_documents',$set,'extension='.sql_quote($extension));
}
}
if ($insertions)
sql_insertq_multi('spip_types_documents', $insertions, '', $serveur);
}
/**
* Optimiser la base de donnee en supprimant les liens orphelins
*
* @param int $n
* @return int
*/
function medias_optimiser_base_disparus($flux){
include_spip('action/editer_liens');
// optimiser les liens morts :
// entre documents vers des objets effaces
// depuis des documents effaces
$flux['data'] += objet_optimiser_liens(array('document'=>'*'),'*');
// on ne nettoie volontairement pas automatiquement les documents orphelins
return $flux;
}
?>