[SPIP][PLUGINS] v3.0-->v3.2
[lhc/web/www.git] / www / ecrire / req / sqlite_generique.php
index e194bc7..7840615 100644 (file)
@@ -3,7 +3,7 @@
 /* *************************************************************************\
  *  SPIP, Systeme de publication pour l'internet                           *
  *                                                                         *
- *  Copyright (c) 2001-2016                                                *
+ *  Copyright (c) 2001-2017                                                *
  *  Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James  *
  *                                                                         *
  *  Ce programme est un logiciel libre distribue sous licence GNU/GPL.     *
 \***************************************************************************/
 
 /**
- * Ce fichier contient les fonctions gerant
+ * Ce fichier contient les fonctions gérant
  * les instructions SQL pour Sqlite
  *
- * @package SPIP\SQL\SQLite
+ * @package SPIP\Core\SQL\SQLite
  */
-if (!defined('_ECRIRE_INC_VERSION')) return;
+
+if (!defined('_ECRIRE_INC_VERSION')) {
+       return;
+}
 
 // TODO: get/set_caracteres ?
 
 
 /*
- * 
  * regroupe le maximum de fonctions qui peuvent cohabiter
  * D'abord les fonctions d'abstractions de SPIP
- * 
  */
-// http://doc.spip.org/@req_sqlite_dist
-function req_sqlite_dist($addr, $port, $login, $pass, $db = '', $prefixe = '', $sqlite_version = ''){
+
+/**
+ * Connecteur à une base SQLite
+ *
+ * @param string $addr
+ * @param int $port
+ * @param string $login
+ * @param string $pass
+ * @param string $db
+ * @param string $prefixe
+ * @param string $sqlite_version
+ * @return array|bool
+ */
+function req_sqlite_dist($addr, $port, $login, $pass, $db = '', $prefixe = '', $sqlite_version = '') {
        static $last_connect = array();
 
        // si provient de selectdb
        // un code pour etre sur que l'on vient de select_db()
-       if (strpos($db, $code = '@selectdb@')!==false){
-               foreach (array('addr', 'port', 'login', 'pass', 'prefixe') as $a){
+       if (strpos($db, $code = '@selectdb@') !== false) {
+               foreach (array('addr', 'port', 'login', 'pass', 'prefixe') as $a) {
                        $$a = $last_connect[$a];
                }
                $db = str_replace($code, '', $db);
@@ -51,35 +63,38 @@ function req_sqlite_dist($addr, $port, $login, $pass, $db = '', $prefixe = '', $
 
        // determiner le dossier de la base : $addr ou _DIR_DB
        $f = _DIR_DB;
-       if ($addr AND strpos($addr, '/')!==false)
-               $f = rtrim($addr, '/').'/';
+       if ($addr and strpos($addr, '/') !== false) {
+               $f = rtrim($addr, '/') . '/';
+       }
 
        // un nom de base demande et impossible d'obtenir la base, on s'en va :
        // il faut que la base existe ou que le repertoire parent soit writable
-       if ($db AND !is_file($f .= $db.'.sqlite') AND !is_writable(dirname($f))){
-               spip_log("base $f non trouvee ou droits en ecriture manquants", 'sqlite.'._LOG_HS);
+       if ($db and !is_file($f .= $db . '.sqlite') and !is_writable(dirname($f))) {
+               spip_log("base $f non trouvee ou droits en ecriture manquants", 'sqlite.' . _LOG_HS);
+
                return false;
        }
 
        // charger les modules sqlite au besoin
-       if (!_sqlite_charger_version($sqlite_version)){
-               spip_log("Impossible de trouver/charger le module SQLite ($sqlite_version)!", 'sqlite.'._LOG_HS);
+       if (!_sqlite_charger_version($sqlite_version)) {
+               spip_log("Impossible de trouver/charger le module SQLite ($sqlite_version)!", 'sqlite.' . _LOG_HS);
+
                return false;
        }
 
        // chargement des constantes
        // il ne faut pas definir les constantes avant d'avoir charge les modules sqlite
-       $define = "spip_sqlite".$sqlite_version."_constantes";
+       $define = "spip_sqlite" . $sqlite_version . "_constantes";
        $define();
 
        $ok = false;
-       if (!$db){
+       if (!$db) {
                // si pas de db ->
                // base temporaire tant qu'on ne connait pas son vrai nom
                // pour tester la connexion
-               $db = "_sqlite".$sqlite_version."_install";
-               $tmp = _DIR_DB.$db.".sqlite";
-               if ($sqlite_version==3){
+               $db = "_sqlite" . $sqlite_version . "_install";
+               $tmp = _DIR_DB . $db . ".sqlite";
+               if ($sqlite_version == 3) {
                        $ok = $link = new PDO("sqlite:$tmp");
                } else {
                        $ok = $link = sqlite_open($tmp, _SQLITE_CHMOD, $err);
@@ -87,20 +102,21 @@ function req_sqlite_dist($addr, $port, $login, $pass, $db = '', $prefixe = '', $
        } else {
                // Ouvrir (eventuellement creer la base)
                // si pas de version fourni, on essaie la 3, sinon la 2
-               if ($sqlite_version==3){
+               if ($sqlite_version == 3) {
                        $ok = $link = new PDO("sqlite:$f");
                } else {
                        $ok = $link = sqlite_open($f, _SQLITE_CHMOD, $err);
                }
        }
 
-       if (!$ok){
+       if (!$ok) {
                $e = sqlite_last_error($db);
-               spip_log("Impossible d'ouvrir la base SQLite($sqlite_version) $f : $e", 'sqlite.'._LOG_HS);
+               spip_log("Impossible d'ouvrir la base SQLite($sqlite_version) $f : $e", 'sqlite.' . _LOG_HS);
+
                return false;
        }
 
-       if ($link){
+       if ($link) {
                $last_connect = array(
                        'addr' => $addr,
                        'port' => $port,
@@ -118,6 +134,7 @@ function req_sqlite_dist($addr, $port, $login, $pass, $db = '', $prefixe = '', $
                'db' => $db,
                'prefixe' => $prefixe ? $prefixe : $db,
                'link' => $link,
+               'total_requetes' => 0,
        );
 }
 
@@ -126,29 +143,40 @@ function req_sqlite_dist($addr, $port, $login, $pass, $db = '', $prefixe = '', $
  * Fonction de requete generale, munie d'une trace a la demande
  *
  * @param string $query
- *             Requete a executer
+ *    Requete a executer
  * @param string $serveur
- *             Nom du connecteur
+ *    Nom du connecteur
  * @param bool $requeter
- *             Effectuer la requete ?
- *             - true pour executer
- *             - false pour retourner le texte de la requete
+ *    Effectuer la requete ?
+ *    - true pour executer
+ *    - false pour retourner le texte de la requete
  * @return bool|SQLiteResult|string
- *             Resultat de la requete
+ *    Resultat de la requete
  */
-function spip_sqlite_query($query, $serveur = '', $requeter = true){
+function spip_sqlite_query($query, $serveur = '', $requeter = true) {
        #spip_log("spip_sqlite_query() > $query",'sqlite.'._LOG_DEBUG);
        #_sqlite_init(); // fait la premiere fois dans spip_sqlite
        $query = spip_sqlite::traduire_requete($query, $serveur);
-       if (!$requeter) return $query;
+       if (!$requeter) {
+               return $query;
+       }
+
        return spip_sqlite::executer_requete($query, $serveur);
 }
 
 
 /* ordre alphabetique pour les autres */
 
-// http://doc.spip.org/@spip_sqlite_alter
-function spip_sqlite_alter($query, $serveur = '', $requeter = true){
+/**
+ * Modifie une structure de table SQLite
+ *
+ * @param string $query Requête SQL (sans 'ALTER ')
+ * @param string $serveur Nom de la connexion
+ * @param bool $requeter inutilisé
+ * @return bool
+ *     False si erreur dans l'exécution, true sinon
+ */
+function spip_sqlite_alter($query, $serveur = '', $requeter = true) {
 
        $query = spip_sqlite_query("ALTER $query", $serveur, false);
        // traduire la requete pour recuperer les bons noms de table
@@ -164,12 +192,13 @@ function spip_sqlite_alter($query, $serveur = '', $requeter = true){
                 */
 
        // 1
-       if (preg_match("/\s*(ALTER(\s*IGNORE)?\s*TABLE\s*([^\s]*))\s*(.*)?/is", $query, $regs)){
+       if (preg_match("/\s*(ALTER(\s*IGNORE)?\s*TABLE\s*([^\s]*))\s*(.*)?/is", $query, $regs)) {
                $debut = $regs[1];
                $table = $regs[3];
                $suite = $regs[4];
        } else {
-               spip_log("SQLite : Probleme de ALTER TABLE mal forme dans $query", 'sqlite.'._LOG_ERREUR);
+               spip_log("SQLite : Probleme de ALTER TABLE mal forme dans $query", 'sqlite.' . _LOG_ERREUR);
+
                return false;
        }
 
@@ -184,25 +213,33 @@ function spip_sqlite_alter($query, $serveur = '', $requeter = true){
        $todo2 = array();
        $i = 0;
        $ouverte = false;
-       while ($do = array_shift($todo)){
-               $todo2[$i] = isset($todo2[$i]) ? $todo2[$i].",".$do : $do;
-               $o = (false!==strpos($do, "("));
-               $f = (false!==strpos($do, ")"));
-               if ($o AND !$f) $ouverte = true;
-               elseif ($f) $ouverte = false;
-               if (!$ouverte) $i++;
+       while ($do = array_shift($todo)) {
+               $todo2[$i] = isset($todo2[$i]) ? $todo2[$i] . "," . $do : $do;
+               $o = (false !== strpos($do, "("));
+               $f = (false !== strpos($do, ")"));
+               if ($o and !$f) {
+                       $ouverte = true;
+               } elseif ($f) {
+                       $ouverte = false;
+               }
+               if (!$ouverte) {
+                       $i++;
+               }
        }
 
-       // 3    
+       // 3
        $resultats = array();
-       foreach ($todo2 as $do){
+       foreach ($todo2 as $do) {
                $do = trim($do);
                if (!preg_match('/(DROP PRIMARY KEY|DROP KEY|DROP INDEX|DROP COLUMN|DROP'
-                               .'|CHANGE COLUMN|CHANGE|MODIFY|RENAME TO|RENAME'
-                               .'|ADD PRIMARY KEY|ADD KEY|ADD INDEX|ADD UNIQUE KEY|ADD UNIQUE'
-                               .'|ADD COLUMN|ADD'
-                               .')\s*([^\s]*)\s*(.*)?/i', $do, $matches)){
-                       spip_log("SQLite : Probleme de ALTER TABLE, utilisation non reconnue dans : $do \n(requete d'origine : $query)", 'sqlite.'._LOG_ERREUR);
+                       . '|CHANGE COLUMN|CHANGE|MODIFY|RENAME TO|RENAME'
+                       . '|ADD PRIMARY KEY|ADD KEY|ADD INDEX|ADD UNIQUE KEY|ADD UNIQUE'
+                       . '|ADD COLUMN|ADD'
+                       . ')\s*([^\s]*)\s*(.*)?/i', $do, $matches)
+               ) {
+                       spip_log("SQLite : Probleme de ALTER TABLE, utilisation non reconnue dans : $do \n(requete d'origine : $query)",
+                               'sqlite.' . _LOG_ERREUR);
+
                        return false;
                }
 
@@ -236,7 +273,8 @@ function spip_sqlite_alter($query, $serveur = '', $requeter = true){
                                        $table,
                                        $colonne_origine,
                                        array('key' => array('PRIMARY KEY' => '')),
-                                       $serveur)){
+                                       $serveur)
+                               ) {
                                        return false;
                                }
                                break;
@@ -247,7 +285,8 @@ function spip_sqlite_alter($query, $serveur = '', $requeter = true){
                                        $table,
                                        array($colonne_origine => ""),
                                        '',
-                                       $serveur)){
+                                       $serveur)
+                               ) {
                                        return false;
                                }
                                break;
@@ -255,47 +294,51 @@ function spip_sqlite_alter($query, $serveur = '', $requeter = true){
                        case 'CHANGE COLUMN':
                        case 'CHANGE':
                                // recuperer le nom de la future colonne
-                         // on reprend la def d'origine car _sqlite_modifier_table va refaire la translation
-                         // en tenant compte de la cle primaire (ce qui est mieux)
+                               // on reprend la def d'origine car _sqlite_modifier_table va refaire la translation
+                               // en tenant compte de la cle primaire (ce qui est mieux)
                                $def = trim($defo);
                                $colonne_destination = substr($def, 0, strpos($def, ' '));
-                               $def = substr($def, strlen($colonne_destination)+1);
+                               $def = substr($def, strlen($colonne_destination) + 1);
 
                                if (!_sqlite_modifier_table(
                                        $table,
                                        array($colonne_origine => $colonne_destination),
                                        array('field' => array($colonne_destination => $def)),
-                                       $serveur)){
+                                       $serveur)
+                               ) {
                                        return false;
                                }
                                break;
 
                        case 'MODIFY':
-                         // on reprend la def d'origine car _sqlite_modifier_table va refaire la translation
-                         // en tenant compte de la cle primaire (ce qui est mieux)
+                               // on reprend la def d'origine car _sqlite_modifier_table va refaire la translation
+                               // en tenant compte de la cle primaire (ce qui est mieux)
                                if (!_sqlite_modifier_table(
                                        $table,
                                        $colonne_origine,
                                        array('field' => array($colonne_origine => $defo)),
-                                       $serveur)){
+                                       $serveur)
+                               ) {
                                        return false;
                                }
                                break;
 
                        // pas geres en sqlite2
                        case 'RENAME':
-                               $do = "RENAME TO".substr($do, 6);
+                               $do = "RENAME TO" . substr($do, 6);
                        case 'RENAME TO':
-                               if (_sqlite_is_version(3, '', $serveur)){
-                                       if (!spip_sqlite::executer_requete("$debut $do", $serveur)){
-                                               spip_log("SQLite : Erreur ALTER TABLE / RENAME : $query", 'sqlite.'._LOG_ERREUR);
+                               if (_sqlite_is_version(3, '', $serveur)) {
+                                       if (!spip_sqlite::executer_requete("$debut $do", $serveur)) {
+                                               spip_log("SQLite : Erreur ALTER TABLE / RENAME : $query", 'sqlite.' . _LOG_ERREUR);
+
                                                return false;
                                        }
                                        // artillerie lourde pour sqlite2 !
                                } else {
                                        $table_dest = trim(substr($do, 9));
-                                       if (!_sqlite_modifier_table(array($table => $table_dest), '', '', $serveur)){
-                                               spip_log("SQLite : Erreur ALTER TABLE / RENAME : $query", 'sqlite.'._LOG_ERREUR);
+                                       if (!_sqlite_modifier_table(array($table => $table_dest), '', '', $serveur)) {
+                                               spip_log("SQLite : Erreur ALTER TABLE / RENAME : $query", 'sqlite.' . _LOG_ERREUR);
+
                                                return false;
                                        }
                                }
@@ -304,42 +347,44 @@ function spip_sqlite_alter($query, $serveur = '', $requeter = true){
                        // ajout d'une pk
                        case 'ADD PRIMARY KEY':
                                $pk = trim(substr($do, 16));
-                               $pk = ($pk[0]=='(') ? substr($pk, 1, -1) : $pk;
+                               $pk = ($pk[0] == '(') ? substr($pk, 1, -1) : $pk;
                                if (!_sqlite_modifier_table(
                                        $table,
                                        $colonne_origine,
                                        array('key' => array('PRIMARY KEY' => $pk)),
-                                       $serveur)){
+                                       $serveur)
+                               ) {
                                        return false;
                                }
                                break;
                        // ajout d'un index
                        case 'ADD UNIQUE KEY':
                        case 'ADD UNIQUE':
-                               $unique=true;
+                               $unique = true;
                        case 'ADD INDEX':
                        case 'ADD KEY':
+                               if (!isset($unique)) {
+                                       $unique = false;
+                               }
                                // peut etre "(colonne)" ou "nom_index (colonnes)"
                                // bug potentiel si qqn met "(colonne, colonne)"
                                //
                                // nom_index (colonnes)
-                               if ($def){
+                               if ($def) {
                                        $colonnes = substr($def, 1, -1);
                                        $nom_index = $colonne_origine;
-                               }
-                               else {
+                               } else {
                                        // (colonne)
-                                       if ($colonne_origine[0]=="("){
+                                       if ($colonne_origine[0] == "(") {
                                                $colonnes = substr($colonne_origine, 1, -1);
-                                               if (false!==strpos(",", $colonnes)){
+                                               if (false !== strpos(",", $colonnes)) {
                                                        spip_log(_LOG_GRAVITE_ERREUR, "SQLite : Erreur, impossible de creer un index sur plusieurs colonnes"
-                                                                                     ." sans qu'il ait de nom ($table, ($colonnes))", 'sqlite');
+                                                               " sans qu'il ait de nom ($table, ($colonnes))", 'sqlite');
                                                        break;
                                                } else {
                                                        $nom_index = $colonnes;
                                                }
-                                       }
-                                               // nom_index
+                                       } // nom_index
                                        else {
                                                $nom_index = $colonnes = $colonne_origine;
                                        }
@@ -349,12 +394,13 @@ function spip_sqlite_alter($query, $serveur = '', $requeter = true){
 
                        // pas geres en sqlite2
                        case 'ADD COLUMN':
-                               $do = "ADD".substr($do, 10);
+                               $do = "ADD" . substr($do, 10);
                        case 'ADD':
                        default:
-                               if (_sqlite_is_version(3, '', $serveur) AND !preg_match(',primary\s+key,i',$do)){
-                                       if (!spip_sqlite::executer_requete("$debut $do", $serveur)){
-                                               spip_log("SQLite : Erreur ALTER TABLE / ADD : $query", 'sqlite.'._LOG_ERREUR);
+                               if (_sqlite_is_version(3, '', $serveur) and !preg_match(',primary\s+key,i', $do)) {
+                                       if (!spip_sqlite::executer_requete("$debut $do", $serveur)) {
+                                               spip_log("SQLite : Erreur ALTER TABLE / ADD : $query", 'sqlite.' . _LOG_ERREUR);
+
                                                return false;
                                        }
                                        break;
@@ -367,201 +413,249 @@ function spip_sqlite_alter($query, $serveur = '', $requeter = true){
                                else {
                                        $def = trim(substr($do, 3));
                                        $colonne_ajoutee = substr($def, 0, strpos($def, ' '));
-                                       $def = substr($def, strlen($colonne_ajoutee)+1);
+                                       $def = substr($def, strlen($colonne_ajoutee) + 1);
                                        $opts = array();
-                                       if (preg_match(',primary\s+key,i',$def)){
+                                       if (preg_match(',primary\s+key,i', $def)) {
                                                $opts['key'] = array('PRIMARY KEY' => $colonne_ajoutee);
-                                               $def = preg_replace(',primary\s+key,i','',$def);
+                                               $def = preg_replace(',primary\s+key,i', '', $def);
                                        }
                                        $opts['field'] = array($colonne_ajoutee => $def);
-                                       if (!_sqlite_modifier_table($table, array($colonne_ajoutee), $opts, $serveur)){
-                                               spip_log("SQLite : Erreur ALTER TABLE / ADD : $query", 'sqlite.'._LOG_ERREUR);
+                                       if (!_sqlite_modifier_table($table, array($colonne_ajoutee), $opts, $serveur)) {
+                                               spip_log("SQLite : Erreur ALTER TABLE / ADD : $query", 'sqlite.' . _LOG_ERREUR);
+
                                                return false;
                                        }
                                }
                                break;
                }
                // tout est bon, ouf !
-               spip_log("SQLite ($serveur) : Changements OK : $debut $do", 'sqlite.'._LOG_INFO);
+               spip_log("SQLite ($serveur) : Changements OK : $debut $do", 'sqlite.' . _LOG_INFO);
        }
 
-       spip_log("SQLite ($serveur) : fin ALTER TABLE OK !", 'sqlite.'._LOG_INFO);
+       spip_log("SQLite ($serveur) : fin ALTER TABLE OK !", 'sqlite.' . _LOG_INFO);
+
        return true;
 }
 
 
 /**
- * Fonction de creation d'une table SQL nommee $nom
- * http://doc.spip.org/@spip_sqlite_create
+ * Crée une table SQL
  *
- * @param string $nom
- * @param array $champs
- * @param array $cles
- * @param bool $autoinc
- * @param bool $temporary
- * @param string $serveur
- * @param bool $requeter
- * @return bool|SQLiteResult|string
+ * Crée une table SQL nommee `$nom` à partir des 2 tableaux `$champs` et `$cles`
+ *
+ * @note Le nom des caches doit être inferieur à 64 caractères
+ *
+ * @param string $nom Nom de la table SQL
+ * @param array $champs Couples (champ => description SQL)
+ * @param array $cles Couples (type de clé => champ(s) de la clé)
+ * @param bool $autoinc True pour ajouter un auto-incrément sur la Primary Key
+ * @param bool $temporary True pour créer une table temporaire
+ * @param string $serveur Nom de la connexion
+ * @param bool $requeter Exécuter la requête, sinon la retourner
+ * @return array|null|resource|string
+ *     - string Texte de la requête si demandée
+ *     - true si la requête réussie, false sinon.
  */
-function spip_sqlite_create($nom, $champs, $cles, $autoinc = false, $temporary = false, $serveur = '', $requeter = true){
+function spip_sqlite_create(
+       $nom,
+       $champs,
+       $cles,
+       $autoinc = false,
+       $temporary = false,
+       $serveur = '',
+       $requeter = true
+) {
        $query = _sqlite_requete_create($nom, $champs, $cles, $autoinc, $temporary, $ifnotexists = true, $serveur, $requeter);
-       if (!$query) return false;
+       if (!$query) {
+               return false;
+       }
        $res = spip_sqlite_query($query, $serveur, $requeter);
 
        // SQLite ne cree pas les KEY sur les requetes CREATE TABLE
        // il faut donc les faire creer ensuite
-       if (!$requeter) return $res;
+       if (!$requeter) {
+               return $res;
+       }
 
        $ok = $res ? true : false;
-       if ($ok){
-               foreach ($cles as $k => $v){
-                       if (preg_match(',^(KEY|UNIQUE)\s,i',$k,$m)){
-                               $index = trim(substr($k,strlen($m[1])));
-                               $unique = (strlen($m[1])>3);
+       if ($ok) {
+               foreach ($cles as $k => $v) {
+                       if (preg_match(',^(KEY|UNIQUE)\s,i', $k, $m)) {
+                               $index = trim(substr($k, strlen($m[1])));
+                               $unique = (strlen($m[1]) > 3);
                                $ok &= spip_sqlite_create_index($index, $nom, $v, $unique, $serveur);
                        }
                }
        }
+
        return $ok ? true : false;
 }
 
 /**
- * Fonction pour creer une base de donnees SQLite
+ * Crée une base de données SQLite
  *
- * @param string $nom le nom de la base (sans l'extension de fichier)
- * @param string $serveur le nom de la connexion
- * @param string $option options
+ * @param string $nom Nom de la base (sans l'extension de fichier)
+ * @param string $serveur Nom de la connexion
+ * @param string $option Options
  *
- * @return bool true si la base est creee.
+ * @return bool true si la base est créee.
  **/
-function spip_sqlite_create_base($nom, $serveur = '', $option = true){
-       $f = $nom.'.sqlite';
-       if (strpos($nom, "/")===false)
-               $f = _DIR_DB.$f;
-       if (_sqlite_is_version(2, '', $serveur)){
+function spip_sqlite_create_base($nom, $serveur = '', $option = true) {
+       $f = $nom . '.sqlite';
+       if (strpos($nom, "/") === false) {
+               $f = _DIR_DB . $f;
+       }
+       if (_sqlite_is_version(2, '', $serveur)) {
                $ok = sqlite_open($f, _SQLITE_CHMOD, $err);
        } else {
                $ok = new PDO("sqlite:$f");
        }
-       if ($ok){
+       if ($ok) {
                unset($ok);
+
                return true;
        }
        unset($ok);
+
        return false;
 }
 
 
 /**
- * Fonction de creation d'une vue SQL nommee $nom
- * http://doc.spip.org/@spip_sqlite_create_view
+ * Crée une vue SQL nommée `$nom`
  *
  * @param string $nom
- *             Nom de la vue a creer
+ *    Nom de la vue a creer
  * @param string $query_select
- *             Texte de la requete de selection servant de base a la vue
+ *     Texte de la requête de sélection servant de base à la vue
  * @param string $serveur
- *             Nom du connecteur
+ *     Nom du connecteur
  * @param bool $requeter
- *             Effectuer la requete ?
- *             - true pour executer
- *             - false pour retourner le texte de la requete
+ *     Effectuer la requete, sinon la retourner
  * @return bool|SQLiteResult|string
- *             Resultat de la requete ou
- *             - false si erreur ou si la vue existe deja
- *             - string texte de la requete si $requeter vaut false
+ *     - true si la vue est créée
+ *     - false si erreur ou si la vue existe déja
+ *     - string texte de la requête si $requeter vaut false
  */
-function spip_sqlite_create_view($nom, $query_select, $serveur = '', $requeter = true){
-       if (!$query_select) return false;
+function spip_sqlite_create_view($nom, $query_select, $serveur = '', $requeter = true) {
+       if (!$query_select) {
+               return false;
+       }
        // vue deja presente
-       if (sql_showtable($nom, false, $serveur)){
-               spip_log("Echec creation d'une vue sql ($nom) car celle-ci existe deja (serveur:$serveur)", 'sqlite.'._LOG_ERREUR);
+       if (sql_showtable($nom, false, $serveur)) {
+               spip_log("Echec creation d'une vue sql ($nom) car celle-ci existe deja (serveur:$serveur)",
+                       'sqlite.' . _LOG_ERREUR);
+
                return false;
        }
 
-       $query = "CREATE VIEW $nom AS ".$query_select;
+       $query = "CREATE VIEW $nom AS " . $query_select;
+
        return spip_sqlite_query($query, $serveur, $requeter);
 }
 
 /**
- * Fonction de creation d'un INDEX
+ * Fonction de création d'un INDEX
  *
- * @param string $nom : nom de l'index
- * @param string $table : table sql de l'index
- * @param string/array $champs : liste de champs sur lesquels s'applique l'index
- * @param string $serveur : nom de la connexion sql utilisee
- * @param bool $requeter : true pour executer la requete ou false pour retourner le texte de la requete
- *
- * @return bool ou requete
+ * @param string $nom
+ *     Nom de l'index
+ * @param string $table
+ *     Table SQL de l'index
+ * @param string|array $champs
+ *     Liste de champs sur lesquels s'applique l'index
+ * @param string|bool $unique
+ *     Créer un index UNIQUE ?
+ * @param string $serveur
+ *     Nom de la connexion sql utilisee
+ * @param bool $requeter
+ *     true pour executer la requête ou false pour retourner le texte de la requête
+ * @return bool|string
+ *    string : requête, false si erreur, true sinon.
  */
-function spip_sqlite_create_index($nom, $table, $champs, $unique='', $serveur = '', $requeter = true){
-       if (!($nom OR $table OR $champs)){
-               spip_log("Champ manquant pour creer un index sqlite ($nom, $table, (".join(',', $champs)."))", 'sqlite.'._LOG_ERREUR);
+function spip_sqlite_create_index($nom, $table, $champs, $unique = '', $serveur = '', $requeter = true) {
+       if (!($nom or $table or $champs)) {
+               spip_log("Champ manquant pour creer un index sqlite ($nom, $table, (" . join(',', $champs) . "))",
+                       'sqlite.' . _LOG_ERREUR);
+
                return false;
        }
 
        // SQLite ne differentie pas noms des index en fonction des tables
        // il faut donc creer des noms uniques d'index pour une base sqlite
-       $nom = $table.'_'.$nom;
+       $nom = $table . '_' . $nom;
        // enlever d'eventuelles parentheses deja presentes sur champs
-       if (!is_array($champs)){
-               if ($champs[0]=="(") $champs = substr($champs, 1, -1);
+       if (!is_array($champs)) {
+               if ($champs[0] == "(") {
+                       $champs = substr($champs, 1, -1);
+               }
                $champs = array($champs);
                // supprimer l'info de longueur d'index mysql en fin de champ
-               $champs = preg_replace(",\(\d+\)$,","",$champs);
+               $champs = preg_replace(",\(\d+\)$,", "", $champs);
        }
 
        $ifnotexists = "";
-       $version = spip_sqlite_fetch(spip_sqlite_query("select sqlite_version() AS sqlite_version",$serveur),'',$serveur);
-       if (!function_exists('spip_version_compare')) include_spip('plugins/installer');
+       $version = spip_sqlite_fetch(spip_sqlite_query("select sqlite_version() AS sqlite_version", $serveur), '', $serveur);
+       if (!function_exists('spip_version_compare')) {
+               include_spip('plugins/installer');
+       }
 
-       if ($version AND spip_version_compare($version['sqlite_version'],'3.3.0','>=')) {
+       if ($version and spip_version_compare($version['sqlite_version'], '3.3.0', '>=')) {
                $ifnotexists = ' IF NOT EXISTS';
        } else {
                /* simuler le IF EXISTS - version 2 et sqlite < 3.3a */
                $a = spip_sqlite_showtable($table, $serveur);
-               if (isset($a['key']['KEY '.$nom])) return true;
+               if (isset($a['key']['KEY ' . $nom])) {
+                       return true;
+               }
        }
 
-       $query = "CREATE ".($unique?"UNIQUE ":"")."INDEX$ifnotexists $nom ON $table (".join(',', $champs).")";
+       $query = "CREATE " . ($unique ? "UNIQUE " : "") . "INDEX$ifnotexists $nom ON $table (" . join(',', $champs) . ")";
        $res = spip_sqlite_query($query, $serveur, $requeter);
-       if (!$requeter) return $res;
-       if ($res)
+       if (!$requeter) {
+               return $res;
+       }
+       if ($res) {
                return true;
-       else
+       } else {
                return false;
+       }
 }
 
 /**
- * en PDO/sqlite3, il faut calculer le count par une requete count(*)
+ * Retourne le nombre de lignes d’une ressource de sélection obtenue
+ * avec `sql_select()`
+ *
+ * En PDO/sqlite3, il faut calculer le count par une requete count(*)
  * pour les resultats de SELECT
  * cela est fait sans spip_sqlite_query()
- * http://doc.spip.org/@spip_sqlite_count
  *
- * @param  $r
- * @param string $serveur
- * @param bool $requeter
- * @return int
+ * @param Ressource|Object $r Ressource de résultat
+ * @param string $serveur Nom de la connexion
+ * @param bool $requeter Inutilisé
+ * @return int                 Nombre de lignes
  */
-function spip_sqlite_count($r, $serveur = '', $requeter = true){
-       if (!$r) return 0;
+function spip_sqlite_count($r, $serveur = '', $requeter = true) {
+       if (!$r) {
+               return 0;
+       }
 
-       if (_sqlite_is_version(3, '', $serveur)){
+       if (_sqlite_is_version(3, '', $serveur)) {
                // select ou autre (insert, update,...) ?
 
                // (link,requete) a compter
-               if (is_array($r->spipSqliteRowCount)){
-                       list($link,$query) = $r->spipSqliteRowCount;
+               if (is_array($r->spipSqliteRowCount)) {
+                       list($link, $query) = $r->spipSqliteRowCount;
                        // amelioration possible a tester intensivement : pas de order by pour compter !
                        // $query = preg_replace(",ORDER BY .+(LIMIT\s|HAVING\s|GROUP BY\s|$),Uims","\\1",$query);
                        $query = "SELECT count(*) as zzzzsqlitecount FROM ($query)";
                        $l = $link->query($query);
                        $i = 0;
-                       if ($l AND $z = $l->fetch())
+                       if ($l and $z = $l->fetch()) {
                                $i = $z['zzzzsqlitecount'];
+                       }
                        $r->spipSqliteRowCount = $i;
                }
-               if (isset($r->spipSqliteRowCount)){
+               if (isset($r->spipSqliteRowCount)) {
                        // Ce compte est faux s'il y a des limit dans la requete :(
                        // il retourne le nombre d'enregistrements sans le limit
                        return $r->spipSqliteRowCount;
@@ -574,79 +668,134 @@ function spip_sqlite_count($r, $serveur = '', $requeter = true){
 }
 
 
-// http://doc.spip.org/@spip_sqlite_countsel
-function spip_sqlite_countsel($from = array(), $where = array(), $groupby = '', $having = array(), $serveur = '', $requeter = true){
-       $c = !$groupby ? '*' : ('DISTINCT '.(is_string($groupby) ? $groupby : join(',', $groupby)));
+/**
+ * Retourne le nombre de lignes d'une sélection
+ *
+ * @param array|string $from Tables à consulter (From)
+ * @param array|string $where Conditions a remplir (Where)
+ * @param array|string $groupby Critère de regroupement (Group by)
+ * @param array $having Tableau des des post-conditions à remplir (Having)
+ * @param string $serveur Nom de la connexion
+ * @param bool $requeter Exécuter la requête, sinon la retourner
+ * @return int|bool|string
+ *     - String Texte de la requête si demandé
+ *     - int Nombre de lignes
+ *     - false si la requête a échouée
+ **/
+function spip_sqlite_countsel(
+       $from = array(),
+       $where = array(),
+       $groupby = '',
+       $having = array(),
+       $serveur = '',
+       $requeter = true
+) {
+       $c = !$groupby ? '*' : ('DISTINCT ' . (is_string($groupby) ? $groupby : join(',', $groupby)));
        $r = spip_sqlite_select("COUNT($c)", $from, $where, '', '', '',
-                               $having, $serveur, $requeter);
-       if ((is_resource($r) or is_object($r)) && $requeter){ // ressource : sqlite2, object : sqlite3
-               if (_sqlite_is_version(3, '', $serveur)){
+               $having, $serveur, $requeter);
+       if ((is_resource($r) or is_object($r)) && $requeter) { // ressource : sqlite2, object : sqlite3
+               if (_sqlite_is_version(3, '', $serveur)) {
                        list($r) = spip_sqlite_fetch($r, SPIP_SQLITE3_NUM, $serveur);
                } else {
                        list($r) = spip_sqlite_fetch($r, SPIP_SQLITE2_NUM, $serveur);
                }
 
        }
+
        return $r;
 }
 
 
-// http://doc.spip.org/@spip_sqlite_delete
-function spip_sqlite_delete($table, $where = '', $serveur = '', $requeter = true){
+/**
+ * Supprime des enregistrements d'une table
+ *
+ * @param string $table Nom de la table SQL
+ * @param string|array $where Conditions à vérifier
+ * @param string $serveur Nom du connecteur
+ * @param bool $requeter Exécuter la requête, sinon la retourner
+ * @return bool|string
+ *     - int : nombre de suppressions réalisées,
+ *     - Texte de la requête si demandé,
+ *     - False en cas d'erreur.
+ **/
+function spip_sqlite_delete($table, $where = '', $serveur = '', $requeter = true) {
        $res = spip_sqlite_query(
                _sqlite_calculer_expression('DELETE FROM', $table, ',')
-               ._sqlite_calculer_expression('WHERE', $where),
+               . _sqlite_calculer_expression('WHERE', $where),
                $serveur, $requeter);
 
        // renvoyer la requete inerte si demandee
-       if (!$requeter) return $res;
+       if (!$requeter) {
+               return $res;
+       }
 
-       if ($res){
+       if ($res) {
                $link = _sqlite_link($serveur);
-               if (_sqlite_is_version(3, $link)){
+               if (_sqlite_is_version(3, $link)) {
                        return $res->rowCount();
                } else {
                        return sqlite_changes($link);
                }
-       }
-       else
+       } else {
                return false;
+       }
 }
 
 
-// http://doc.spip.org/@spip_sqlite_drop_table
-function spip_sqlite_drop_table($table, $exist = '', $serveur = '', $requeter = true){
-       if ($exist) $exist = " IF EXISTS";
+/**
+ * Supprime une table SQL
+ *
+ * @param string $table Nom de la table SQL
+ * @param string $exist True pour ajouter un test d'existence avant de supprimer
+ * @param string $serveur Nom de la connexion
+ * @param bool $requeter Exécuter la requête, sinon la retourner
+ * @return bool|string
+ *     - string Texte de la requête si demandé
+ *     - true si la requête a réussie, false sinon
+ */
+function spip_sqlite_drop_table($table, $exist = '', $serveur = '', $requeter = true) {
+       if ($exist) {
+               $exist = " IF EXISTS";
+       }
 
        /* simuler le IF EXISTS - version 2 */
-       if ($exist && _sqlite_is_version(2, '', $serveur)){
+       if ($exist && _sqlite_is_version(2, '', $serveur)) {
                $a = spip_sqlite_showtable($table, $serveur);
-               if (!$a) return true;
+               if (!$a) {
+                       return true;
+               }
                $exist = '';
        }
-       if (spip_sqlite_query("DROP TABLE$exist $table", $serveur, $requeter))
+       if (spip_sqlite_query("DROP TABLE$exist $table", $serveur, $requeter)) {
                return true;
-       else
+       } else {
                return false;
+       }
 }
 
+
 /**
- * supprime une vue
- * http://doc.spip.org/@spip_sqlite_drop_view
+ * Supprime une vue SQL
  *
- * @param  $view
- * @param string $exist
- * @param string $serveur
- * @param bool $requeter
- * @return bool|SQLiteResult|string
+ * @param string $view Nom de la vue SQL
+ * @param string $exist True pour ajouter un test d'existence avant de supprimer
+ * @param string $serveur Nom de la connexion
+ * @param bool $requeter Exécuter la requête, sinon la retourner
+ * @return bool|string
+ *     - string Texte de la requête si demandé
+ *     - true si la requête a réussie, false sinon
  */
-function spip_sqlite_drop_view($view, $exist = '', $serveur = '', $requeter = true){
-       if ($exist) $exist = " IF EXISTS";
+function spip_sqlite_drop_view($view, $exist = '', $serveur = '', $requeter = true) {
+       if ($exist) {
+               $exist = " IF EXISTS";
+       }
 
        /* simuler le IF EXISTS - version 2 */
-       if ($exist && _sqlite_is_version(2, '', $serveur)){
+       if ($exist && _sqlite_is_version(2, '', $serveur)) {
                $a = spip_sqlite_showtable($view, $serveur);
-               if (!$a) return true;
+               if (!$a) {
+                       return true;
+               }
                $exist = '';
        }
 
@@ -659,44 +808,52 @@ function spip_sqlite_drop_view($view, $exist = '', $serveur = '', $requeter = tr
  * @param string $nom : nom de l'index
  * @param string $table : table sql de l'index
  * @param string $serveur : nom de la connexion sql utilisee
- * @param bool $requeter : true pour executer la requete ou false pour retourner le texte de la requete
+ * @param bool $requeter : true pour executer la requête ou false pour retourner le texte de la requête
  *
  * @return bool ou requete
  */
-function spip_sqlite_drop_index($nom, $table, $serveur = '', $requeter = true){
-       if (!($nom OR $table)){
-               spip_log("Champ manquant pour supprimer un index sqlite ($nom, $table)", 'sqlite.'._LOG_ERREUR);
+function spip_sqlite_drop_index($nom, $table, $serveur = '', $requeter = true) {
+       if (!($nom or $table)) {
+               spip_log("Champ manquant pour supprimer un index sqlite ($nom, $table)", 'sqlite.' . _LOG_ERREUR);
+
                return false;
        }
 
        // SQLite ne differentie pas noms des index en fonction des tables
        // il faut donc creer des noms uniques d'index pour une base sqlite
-       $index = $table.'_'.$nom;
+       $index = $table . '_' . $nom;
        $exist = " IF EXISTS";
 
        /* simuler le IF EXISTS - version 2 */
-       if (_sqlite_is_version(2, '', $serveur)){
+       if (_sqlite_is_version(2, '', $serveur)) {
                $a = spip_sqlite_showtable($table, $serveur);
-               if (!isset($a['key']['KEY '.$nom])) return true;
+               if (!isset($a['key']['KEY ' . $nom])) {
+                       return true;
+               }
                $exist = '';
        }
 
        $query = "DROP INDEX$exist $index";
+
        return spip_sqlite_query($query, $serveur, $requeter);
 }
 
 /**
  * Retourne la dernière erreur generée
  *
- * @param $serveur
- *             nom de la connexion
+ * @uses sql_error_backtrace()
+ *
+ * @param string $query
+ *     Requête qui était exécutée
+ * @param string $serveur
+ *     Nom de la connexion
  * @return string
- *             erreur eventuelle
+ *     Erreur eventuelle
  **/
-function spip_sqlite_error($query = '', $serveur = ''){
+function spip_sqlite_error($query = '', $serveur = '') {
        $link = _sqlite_link($serveur);
 
-       if (_sqlite_is_version(3, $link)){
+       if (_sqlite_is_version(3, $link)) {
                $errs = $link->errorInfo();
                /*
                        $errs[0]
@@ -709,7 +866,7 @@ function spip_sqlite_error($query = '', $serveur = ''){
                                Le texte du message d'erreur
                */
                $s = '';
-               if (ltrim($errs[0],'0')) { // 00000 si pas d'erreur
+               if (ltrim($errs[0], '0')) { // 00000 si pas d'erreur
                        $s = "$errs[2]";
                }
        } elseif ($link) {
@@ -717,7 +874,13 @@ function spip_sqlite_error($query = '', $serveur = ''){
        } else {
                $s = ": aucune ressource sqlite (link)";
        }
-       if ($s) spip_log("$s - $query", 'sqlite.'._LOG_ERREUR);
+       if ($s) {
+               $trace = debug_backtrace();
+               if ($trace[0]['function'] != "spip_mysql_error") {
+                       spip_log("$s - $query - " . sql_error_backtrace(), 'sqlite.' . _LOG_ERREUR);
+               }
+       }
+
        return $s;
 }
 
@@ -726,40 +889,58 @@ function spip_sqlite_error($query = '', $serveur = ''){
  *
  * Le numéro (en sqlite3/pdo) est un retour ODBC tel que (très souvent) HY000
  * http://www.easysoft.com/developer/interfaces/odbc/sqlstate_status_return_codes.html
- * 
+ *
  * @param string $serveur
- *             nom de la connexion
+ *    nom de la connexion
  * @return int|string
- *             0 pas d'erreur
- *             1 ou autre erreur (en sqlite 2)
- *             'HY000/1' : numéro de l'erreur SQLState / numéro d'erreur interne SQLite (en sqlite 3)
+ *    0 pas d'erreur
+ *    1 ou autre erreur (en sqlite 2)
+ *    'HY000/1' : numéro de l'erreur SQLState / numéro d'erreur interne SQLite (en sqlite 3)
  **/
-function spip_sqlite_errno($serveur = ''){
+function spip_sqlite_errno($serveur = '') {
        $link = _sqlite_link($serveur);
 
-       if (_sqlite_is_version(3, $link)){
+       if (_sqlite_is_version(3, $link)) {
                $t = $link->errorInfo();
-               $s = ltrim($t[0],'0'); // 00000 si pas d'erreur
-               if ($s) $s .= ' / ' . $t[1]; // ajoute l'erreur du moteur SQLite
+               $s = ltrim($t[0], '0'); // 00000 si pas d'erreur
+               if ($s) {
+                       $s .= ' / ' . $t[1];
+               } // ajoute l'erreur du moteur SQLite
        } elseif ($link) {
                $s = sqlite_last_error($link);
        } else {
                $s = ": aucune ressource sqlite (link)";
        }
 
-       if ($s) spip_log("Erreur sqlite $s", 'sqlite.'._LOG_ERREUR);
+       if ($s) {
+               spip_log("Erreur sqlite $s", 'sqlite.' . _LOG_ERREUR);
+       }
 
        return $s ? $s : 0;
 }
 
 
-// http://doc.spip.org/@spip_sqlite_explain
-function spip_sqlite_explain($query, $serveur = '', $requeter = true){
-       if (strpos(ltrim($query), 'SELECT')!==0) return array();
+/**
+ * Retourne une explication de requête (Explain) SQLite
+ *
+ * @param string $query Texte de la requête
+ * @param string $serveur Nom de la connexion
+ * @param bool $requeter Exécuter la requête, sinon la retourner
+ * @return array|string|bool
+ *     - array : Tableau de l'explication
+ *     - string si on retourne le texte de la requête
+ *     - false si on a pas pu avoir d'explication
+ */
+function spip_sqlite_explain($query, $serveur = '', $requeter = true) {
+       if (strpos(ltrim($query), 'SELECT') !== 0) {
+               return array();
+       }
 
        $query = spip_sqlite::traduire_requete($query, $serveur);
-       $query = 'EXPLAIN '.$query;
-       if (!$requeter) return $query;
+       $query = 'EXPLAIN ' . $query;
+       if (!$requeter) {
+               return $query;
+       }
        // on ne trace pas ces requetes, sinon on obtient un tracage sans fin...
        $r = spip_sqlite::executer_requete($query, $serveur, false);
 
@@ -767,26 +948,39 @@ function spip_sqlite_explain($query, $serveur = '', $requeter = true){
 }
 
 
-// http://doc.spip.org/@spip_sqlite_fetch
-function spip_sqlite_fetch($r, $t = '', $serveur = '', $requeter = true){
+/**
+ * Rècupère une ligne de résultat
+ *
+ * Récupère la ligne suivante d'une ressource de résultat
+ *
+ * @param Ressource $r Ressource de résultat (issu de sql_select)
+ * @param string $t Structure de résultat attendu (défaut ASSOC)
+ * @param string $serveur Nom de la connexion
+ * @param bool $requeter Inutilisé
+ * @return array           Ligne de résultat
+ */
+function spip_sqlite_fetch($r, $t = '', $serveur = '', $requeter = true) {
 
        $link = _sqlite_link($serveur);
        $is_v3 = _sqlite_is_version(3, $link);
-       if (!$t)
+       if (!$t) {
                $t = ($is_v3 ? SPIP_SQLITE3_ASSOC : SPIP_SQLITE2_ASSOC);
+       }
 
        $retour = false;
-       if ($r)
+       if ($r) {
                $retour = ($is_v3 ? $r->fetch($t) : sqlite_fetch_array($r, $t));
+       }
 
        // les version 2 et 3 parfois renvoie des 'table.titre' au lieu de 'titre' tout court ! pff !
        // suppression de 'table.' pour toutes les cles (c'est un peu violent !)
        // c'est couteux : on ne verifie que la premiere ligne pour voir si on le fait ou non
        if ($retour
-         AND strpos(implode('',array_keys($retour)),'.')!==false){
-               foreach ($retour as $cle => $val){
-                       if (($pos = strpos($cle, '.'))!==false){
-                               $retour[substr($cle, $pos+1)] = &$retour[$cle];
+               and strpos(implode('', array_keys($retour)), '.') !== false
+       ) {
+               foreach ($retour as $cle => $val) {
+                       if (($pos = strpos($cle, '.')) !== false) {
+                               $retour[substr($cle, $pos + 1)] = &$retour[$cle];
                                unset($retour[$cle]);
                        }
                }
@@ -795,55 +989,109 @@ function spip_sqlite_fetch($r, $t = '', $serveur = '', $requeter = true){
        return $retour;
 }
 
-
-function spip_sqlite_seek($r, $row_number, $serveur = '', $requeter = true){
-       if ($r){
+/**
+ * Place le pointeur de résultat sur la position indiquée
+ *
+ * @param Ressource $r Ressource de résultat
+ * @param int $row_number Position. Déplacer le pointeur à cette ligne
+ * @param string $serveur Nom de la connexion
+ * @param bool $requeter Inutilisé
+ * @return bool True si déplacement réussi, false sinon.
+ **/
+function spip_sqlite_seek($r, $row_number, $serveur = '', $requeter = true) {
+       if ($r) {
                $link = _sqlite_link($serveur);
-               if (_sqlite_is_version(3, $link)){
+               if (_sqlite_is_version(3, $link)) {
                        // encore un truc de bien fichu : PDO ne PEUT PAS faire de seek ou de rewind...
                        // je me demande si pour sqlite 3 il ne faudrait pas mieux utiliser
                        // les nouvelles fonctions sqlite3_xx (mais encore moins presentes...)
                        return false;
-               }
-               else {
+               } else {
                        return sqlite_seek($r, $row_number);
                }
        }
 }
 
 
-// http://doc.spip.org/@spip_sqlite_free
-function spip_sqlite_free(&$r, $serveur = '', $requeter = true){
+/**
+ * Libère une ressource de résultat
+ *
+ * Indique à SQLite de libérer de sa mémoire la ressoucre de résultat indiquée
+ * car on n'a plus besoin de l'utiliser.
+ *
+ * @param Ressource|Object $r Ressource de résultat
+ * @param string $serveur Nom de la connexion
+ * @param bool $requeter Inutilisé
+ * @return bool                True si réussi
+ */
+function spip_sqlite_free(&$r, $serveur = '', $requeter = true) {
        unset($r);
+
        return true;
        //return sqlite_free_result($r);
 }
 
 
-// http://doc.spip.org/@spip_sqlite_get_charset
-function spip_sqlite_get_charset($charset = array(), $serveur = '', $requeter = true){
+/**
+ * Teste si le charset indiqué est disponible sur le serveur SQL (aucune action ici)
+ *
+ * Cette fonction n'a aucune action actuellement
+ *
+ * @param array|string $charset Nom du charset à tester.
+ * @param string $serveur Nom de la connexion
+ * @param bool $requeter inutilisé
+ * @return void
+ */
+function spip_sqlite_get_charset($charset = array(), $serveur = '', $requeter = true) {
        //$c = !$charset ? '' : (" LIKE "._q($charset['charset']));
        //return spip_sqlite_fetch(sqlite_query(_sqlite_link($serveur), "SHOW CHARACTER SET$c"), NULL, $serveur);
 }
 
 
-// http://doc.spip.org/@spip_sqlite_hex
-function spip_sqlite_hex($v){
+/**
+ * Prépare une chaîne hexadécimale
+ *
+ * Par exemple : FF ==> 255 en SQLite
+ *
+ * @param string $v
+ *     Chaine hexadecimale
+ * @return string
+ *     Valeur hexadécimale pour SQLite
+ **/
+function spip_sqlite_hex($v) {
        return hexdec($v);
 }
 
 
-// http://doc.spip.org/@spip_sqlite_in
-function spip_sqlite_in($val, $valeurs, $not = '', $serveur = '', $requeter = true){
+/**
+ * Retourne une expression IN pour le gestionnaire de base de données
+ *
+ * IN (...) est limité à 255 éléments, d'où cette fonction assistante
+ *
+ * @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 $requeter
+ *     Inutilisé
+ * @return string
+ *     Expression de requête SQL
+ **/
+function spip_sqlite_in($val, $valeurs, $not = '', $serveur = '', $requeter = true) {
        $n = $i = 0;
        $in_sql = "";
-       while ($n = strpos($valeurs, ',', $n+1)){
-               if ((++$i)>=255){
-                       $in_sql .= "($val $not IN (".
-                                  substr($valeurs, 0, $n).
-                                  "))\n".
-                                  ($not ? "AND\t" : "OR\t");
-                       $valeurs = substr($valeurs, $n+1);
+       while ($n = strpos($valeurs, ',', $n + 1)) {
+               if ((++$i) >= 255) {
+                       $in_sql .= "($val $not IN (" .
+                               substr($valeurs, 0, $n) .
+                               "))\n" .
+                               ($not ? "AND\t" : "OR\t");
+                       $valeurs = substr($valeurs, $n + 1);
                        $i = $n = 0;
                }
        }
@@ -853,31 +1101,78 @@ function spip_sqlite_in($val, $valeurs, $not = '', $serveur = '', $requeter = tr
 }
 
 
-// http://doc.spip.org/@spip_sqlite_insert
-function spip_sqlite_insert($table, $champs, $valeurs, $desc = '', $serveur = '', $requeter = true){
+/**
+ * Insère une ligne dans une table
+ *
+ * @param string $table
+ *     Nom de la table SQL
+ * @param string $champs
+ *     Liste des colonnes impactées,
+ * @param string $valeurs
+ *     Liste des valeurs,
+ * @param array $desc
+ *     Tableau de description des colonnes de la table SQL utilisée
+ *     (il sera calculé si nécessaire s'il n'est pas transmis).
+ * @param string $serveur
+ *     Nom du connecteur
+ * @param bool $requeter
+ *     Exécuter la requête, sinon la retourner
+ * @return bool|string|int|array
+ *     - int|true identifiant de l'élément inséré (si possible), ou true, si réussite
+ *     - Texte de la requête si demandé,
+ *     - False en cas d'erreur,
+ *     - Tableau de description de la requête et du temps d'exécution, si var_profile activé
+ **/
+function spip_sqlite_insert($table, $champs, $valeurs, $desc = array(), $serveur = '', $requeter = true) {
 
-       $query = "INSERT INTO $table ".($champs ? "$champs VALUES $valeurs" : "DEFAULT VALUES");
-       if ($r = spip_sqlite_query($query, $serveur, $requeter)){
-               if (!$requeter) return $r;
+       $query = "INSERT INTO $table " . ($champs ? "$champs VALUES $valeurs" : "DEFAULT VALUES");
+       if ($r = spip_sqlite_query($query, $serveur, $requeter)) {
+               if (!$requeter) {
+                       return $r;
+               }
                $nb = spip_sqlite::last_insert_id($serveur);
+       } else {
+               $nb = false;
        }
-       else
-               $nb = 0;
 
        $err = spip_sqlite_error($query, $serveur);
+
        // cas particulier : ne pas substituer la reponse spip_sqlite_query si on est en profilage
        return isset($_GET['var_profile']) ? $r : $nb;
 
 }
 
 
-// http://doc.spip.org/@spip_sqlite_insertq
-function spip_sqlite_insertq($table, $couples = array(), $desc = array(), $serveur = '', $requeter = true){
-       if (!$desc) $desc = description_table($table, $serveur);
-       if (!$desc) die("$table insertion sans description");
+/**
+ * Insère une ligne dans une table, en protégeant chaque valeur
+ *
+ * @param string $table
+ *     Nom de la table SQL
+ * @param string $couples
+ *    Couples (colonne => valeur)
+ * @param array $desc
+ *     Tableau de description des colonnes de la table SQL utilisée
+ *     (il sera calculé si nécessaire s'il n'est pas transmis).
+ * @param string $serveur
+ *     Nom du connecteur
+ * @param bool $requeter
+ *     Exécuter la requête, sinon la retourner
+ * @return bool|string|int|array
+ *     - int|true identifiant de l'élément inséré (si possible), ou true, si réussite
+ *     - Texte de la requête si demandé,
+ *     - False en cas d'erreur,
+ *     - Tableau de description de la requête et du temps d'exécution, si var_profile activé
+ **/
+function spip_sqlite_insertq($table, $couples = array(), $desc = array(), $serveur = '', $requeter = true) {
+       if (!$desc) {
+               $desc = description_table($table, $serveur);
+       }
+       if (!$desc) {
+               die("$table insertion sans description");
+       }
        $fields = isset($desc['field']) ? $desc['field'] : array();
 
-       foreach ($couples as $champ => $val){
+       foreach ($couples as $champ => $val) {
                $couples[$champ] = _sqlite_calculer_cite($val, $fields[$champ]);
        }
 
@@ -885,21 +1180,44 @@ function spip_sqlite_insertq($table, $couples = array(), $desc = array(), $serve
        $couples = _sqlite_ajouter_champs_timestamp($table, $couples, $desc, $serveur);
 
        $cles = $valeurs = "";
-       if (count($couples)){
-               $cles = "(".join(',', array_keys($couples)).")";
-               $valeurs = "(".join(',', $couples).")";
+       if (count($couples)) {
+               $cles = "(" . join(',', array_keys($couples)) . ")";
+               $valeurs = "(" . join(',', $couples) . ")";
        }
 
        return spip_sqlite_insert($table, $cles, $valeurs, $desc, $serveur, $requeter);
 }
 
 
-// http://doc.spip.org/@spip_sqlite_insertq_multi
-function spip_sqlite_insertq_multi($table, $tab_couples = array(), $desc = array(), $serveur = '', $requeter = true){
-       if (!$desc) $desc = description_table($table, $serveur);
-       if (!$desc) die("$table insertion sans description");
-       if (!isset($desc['field']))
+/**
+ * Insère plusieurs lignes d'un coup dans une table
+ *
+ * @param string $table
+ *     Nom de la table SQL
+ * @param array $tab_couples
+ *     Tableau de tableaux associatifs (colonne => valeur)
+ * @param array $desc
+ *     Tableau de description des colonnes de la table SQL utilisée
+ *     (il sera calculé si nécessaire s'il n'est pas transmis).
+ * @param string $serveur
+ *     Nom du connecteur
+ * @param bool $requeter
+ *     Exécuter la requête, sinon la retourner
+ * @return bool|string
+ *     - True en cas de succès,
+ *     - Texte de la requête si demandé,
+ *     - False en cas d'erreur.
+ **/
+function spip_sqlite_insertq_multi($table, $tab_couples = array(), $desc = array(), $serveur = '', $requeter = true) {
+       if (!$desc) {
+               $desc = description_table($table, $serveur);
+       }
+       if (!$desc) {
+               die("$table insertion sans description");
+       }
+       if (!isset($desc['field'])) {
                $desc['field'] = array();
+       }
 
        // recuperer les champs 'timestamp' pour mise a jour auto de ceux-ci
        $maj = _sqlite_ajouter_champs_timestamp($table, array(), $desc, $serveur);
@@ -907,46 +1225,50 @@ function spip_sqlite_insertq_multi($table, $tab_couples = array(), $desc = array
        // seul le nom de la table est a traduire ici :
        // le faire une seule fois au debut
        $query_start = "INSERT INTO $table ";
-       $query_start = spip_sqlite::traduire_requete($query_start,$serveur);
+       $query_start = spip_sqlite::traduire_requete($query_start, $serveur);
 
        // ouvrir une transaction
-       if ($requeter)
+       if ($requeter) {
                spip_sqlite::demarrer_transaction($serveur);
+       }
 
-       while ($couples = array_shift($tab_couples)){
-               foreach ($couples as $champ => $val){
+       while ($couples = array_shift($tab_couples)) {
+               foreach ($couples as $champ => $val) {
                        $couples[$champ] = _sqlite_calculer_cite($val, $desc['field'][$champ]);
                }
 
                // inserer les champs timestamp par defaut
-               $couples = array_merge($maj,$couples);
+               $couples = array_merge($maj, $couples);
 
                $champs = $valeurs = "";
-               if (count($couples)){
-                       $champs = "(".join(',', array_keys($couples)).")";
-                       $valeurs = "(".join(',', $couples).")";
-                       $query = $query_start."$champs VALUES $valeurs";
+               if (count($couples)) {
+                       $champs = "(" . join(',', array_keys($couples)) . ")";
+                       $valeurs = "(" . join(',', $couples) . ")";
+                       $query = $query_start . "$champs VALUES $valeurs";
+               } else {
+                       $query = $query_start . "DEFAULT VALUES";
+               }
+
+               if ($requeter) {
+                       $retour = spip_sqlite::executer_requete($query, $serveur);
                }
-               else
-                       $query = $query_start."DEFAULT VALUES";
-               
-               if ($requeter)
-                       $retour = spip_sqlite::executer_requete($query,$serveur);
 
                // sur le dernier couple uniquement
-               if (!count($tab_couples)){
+               if (!count($tab_couples)) {
                        $nb = 0;
-                       if ($requeter)
+                       if ($requeter) {
                                $nb = spip_sqlite::last_insert_id($serveur);
-                       else
+                       } else {
                                return $query;
+                       }
                }
 
                $err = spip_sqlite_error($query, $serveur);
        }
 
-       if ($requeter)
+       if ($requeter) {
                spip_sqlite::finir_transaction($serveur);
+       }
 
        // renvoie le dernier id d'autoincrement ajoute
        // cas particulier : ne pas substituer la reponse spip_sqlite_query si on est en profilage
@@ -955,43 +1277,75 @@ function spip_sqlite_insertq_multi($table, $tab_couples = array(), $desc = array
 
 
 /**
- * Retourne si le moteur SQL prefere utiliser des transactions.
+ * Retourne si le moteur SQL préfère utiliser des transactions.
  *
- * @param 
- * @return bool true / false
-**/
+ * @param string $serveur
+ *     Nom du connecteur
+ * @param bool $requeter
+ *     Inutilisé
+ * @return bool
+ *     Toujours true.
+ **/
 function spip_sqlite_preferer_transaction($serveur = '', $requeter = true) {
        return true;
 }
 
 /**
- * Demarre une transaction.
+ * Démarre une transaction
+ *
  * Pratique pour des sql_updateq() dans un foreach,
- * parfois 100* plus rapide s'ils sont nombreux en sqlite ! 
+ * parfois 100* plus rapide s'ils sont nombreux en sqlite !
  *
-**/
+ * @param string $serveur
+ *     Nom du connecteur
+ * @param bool $requeter
+ *     true pour exécuter la requête ou false pour retourner le texte de la requête
+ * @return bool|string
+ *     string si texte de la requête demandé, true sinon
+ **/
 function spip_sqlite_demarrer_transaction($serveur = '', $requeter = true) {
-       if (!$requeter) return "BEGIN TRANSACTION";
+       if (!$requeter) {
+               return "BEGIN TRANSACTION";
+       }
        spip_sqlite::demarrer_transaction($serveur);
+
        return true;
 }
 
 /**
- * Cloture une transaction.
+ * Clôture une transaction
  *
-**/
+ * @param string $serveur
+ *     Nom du connecteur
+ * @param bool $requeter
+ *     true pour exécuter la requête ou false pour retourner le texte de la requête
+ * @return bool|string
+ *     string si texte de la requête demandé, true sinon
+ **/
 function spip_sqlite_terminer_transaction($serveur = '', $requeter = true) {
-       if (!$requeter) return "COMMIT";
+       if (!$requeter) {
+               return "COMMIT";
+       }
        spip_sqlite::finir_transaction($serveur);
+
        return true;
 }
 
 
-// http://doc.spip.org/@spip_sqlite_listdbs
-function spip_sqlite_listdbs($serveur = '', $requeter = true){
+/**
+ * Liste les bases de données disponibles
+ *
+ * @param string $serveur
+ *     Nom du connecteur
+ * @param bool $requeter
+ *     Inutilisé
+ * @return array
+ *     Liste des noms de bases
+ **/
+function spip_sqlite_listdbs($serveur = '', $requeter = true) {
        _sqlite_init();
 
-       if (!is_dir($d = substr(_DIR_DB, 0, -1))){
+       if (!is_dir($d = substr(_DIR_DB, 0, -1))) {
                return array();
        }
 
@@ -999,11 +1353,13 @@ function spip_sqlite_listdbs($serveur = '', $requeter = true){
        $bases = preg_files($d, $pattern = '(.*)\.sqlite$');
        $bds = array();
 
-       foreach ($bases as $b){
+       foreach ($bases as $b) {
                // pas de bases commencant pas sqlite 
                // (on s'en sert pour l'installation pour simuler la presence d'un serveur)
                // les bases sont de la forme _sqliteX_tmp_spip_install.sqlite
-               if (strpos($b, '_sqlite')) continue;
+               if (strpos($b, '_sqlite')) {
+                       continue;
+               }
                $bds[] = preg_replace(";.*/$pattern;iS", '$1', $b);
        }
 
@@ -1011,100 +1367,261 @@ function spip_sqlite_listdbs($serveur = '', $requeter = true){
 }
 
 
-// http://doc.spip.org/@spip_sqlite_multi
-function spip_sqlite_multi($objet, $lang){
+/**
+ * Retourne l'instruction SQL pour obtenir le texte d'un champ contenant
+ * une balise `<multi>` dans la langue indiquée
+ *
+ * Cette sélection est mise dans l'alias `multi` (instruction AS multi).
+ *
+ * @param string $objet Colonne ayant le texte
+ * @param string $lang Langue à extraire
+ * @return string       Texte de sélection pour la requête
+ */
+function spip_sqlite_multi($objet, $lang) {
        $r = "EXTRAIRE_MULTI(" . $objet . ", '" . $lang . "') AS multi";
+
        return $r;
 }
 
 
 /**
  * Optimise une table SQL
- * Note: Sqlite optimise TOUTE un fichier sinon rien.
- * On evite donc 2 traitements sur la meme base dans un hit.
+ *
+ * @note
+ *   Sqlite optimise TOUT un fichier sinon rien.
+ *   On évite donc 2 traitements sur la même base dans un hit.
  *
  * @param $table nom de la table a optimiser
  * @param $serveur nom de la connexion
  * @param $requeter effectuer la requete ? sinon retourner son code
  * @return bool|string true / false / requete
  **/
-// http://doc.spip.org/@spip_sqlite_optimize
-function spip_sqlite_optimize($table, $serveur = '', $requeter = true){
+function spip_sqlite_optimize($table, $serveur = '', $requeter = true) {
        static $do = false;
-       if ($requeter and $do){
+       if ($requeter and $do) {
                return true;
        }
-       if ($requeter){
+       if ($requeter) {
                $do = true;
        }
+
        return spip_sqlite_query("VACUUM", $serveur, $requeter);
 }
 
 
-//
 /**
- * echapper une valeur selon son type ou au mieux
- * comme le fait _q() mais pour sqlite avec ses specificites
+ * Échapper une valeur selon son type
+ * mais pour SQLite avec ses spécificités
  *
  * @param string|array|number $v
+ *     Texte, nombre ou tableau à échapper
  * @param string $type
+ *     Description du type attendu
+ *    (par exemple description SQL de la colonne recevant la donnée)
  * @return string|number
+ *    Donnée prête à être utilisée par le gestionnaire SQL
  */
-function spip_sqlite_quote($v, $type = ''){
-               if (!is_array($v))
-                       return _sqlite_calculer_cite($v,$type);
-               // si c'est un tableau, le parcourir en propageant le type
-               foreach($v as $k=>$r)
-                       $v[$k] = spip_sqlite_quote($r, $type);
-               return join(",", $v);
+function spip_sqlite_quote($v, $type = '') {
+       if (!is_array($v)) {
+               return _sqlite_calculer_cite($v, $type);
+       }
+       // si c'est un tableau, le parcourir en propageant le type
+       foreach ($v as $k => $r) {
+               $v[$k] = spip_sqlite_quote($r, $type);
+       }
+
+       return join(",", $v);
 }
 
 
 /**
  * Tester si une date est proche de la valeur d'un champ
  *
- * @param string $champ le nom du champ a tester
- * @param int $interval valeur de l'interval : -1, 4, ...
- * @param string $unite utite utilisee (DAY, MONTH, YEAR, ...)
- * @return string expression SQL
+ * @param string $champ
+ *     Nom du champ a tester
+ * @param int $interval
+ *     Valeur de l'intervalle : -1, 4, ...
+ * @param string $unite
+ *     Utité utilisée (DAY, MONTH, YEAR, ...)
+ * @return string
+ *     Expression SQL
  **/
-function spip_sqlite_date_proche($champ, $interval, $unite){
+function spip_sqlite_date_proche($champ, $interval, $unite) {
        $op = (($interval <= 0) ? '>' : '<');
-       return "($champ $op datetime('".date("Y-m-d H:i:s")."', '$interval $unite'))";
+
+       return "($champ $op datetime('" . date("Y-m-d H:i:s") . "', '$interval $unite'))";
 }
 
 
-// http://doc.spip.org/@spip_sqlite_replace
-function spip_sqlite_replace($table, $couples, $desc = array(), $serveur = '', $requeter = true){
-       if (!$desc) $desc = description_table($table, $serveur);
-       if (!$desc) die("$table insertion sans description");
+/**
+ * Répare une table SQL
+ *
+ * Il n'y a pas de fonction native repair dans sqlite, mais on profite
+ * pour vérifier que tous les champs (text|char) ont bien une clause DEFAULT
+ *
+ * @param string $table Nom de la table SQL
+ * @param string $serveur Nom de la connexion
+ * @param bool $requeter Exécuter la requête, sinon la retourner
+ * @return string[]
+ *     Tableau avec clé 0 pouvant avoir " OK " ou " ERROR " indiquant
+ *     l'état de la table après la réparation
+ */
+function spip_sqlite_repair($table, $serveur = '', $requeter = true) {
+       if ($desc = spip_sqlite_showtable($table, $serveur)
+               and isset($desc['field'])
+               and is_array($desc['field'])
+       ) {
+               foreach ($desc['field'] as $c => $d) {
+                       if (preg_match(",^(tinytext|mediumtext|text|longtext|varchar|char),i", $d)
+                               and stripos($d, "NOT NULL") !== false
+                               and stripos($d, "DEFAULT") === false
+                               /* pas touche aux cles primaires */
+                               and (!isset($desc['key']['PRIMARY KEY']) or $desc['key']['PRIMARY KEY'] !== $c)
+                       ) {
+                               spip_sqlite_alter($q = "TABLE $table CHANGE $c $c $d DEFAULT ''", $serveur);
+                               spip_log("ALTER $q", "repair" . _LOG_INFO_IMPORTANTE);
+                       }
+                       if (preg_match(",^(INTEGER),i", $d)
+                               and stripos($d, "NOT NULL") !== false
+                               and stripos($d, "DEFAULT") === false
+                               /* pas touche aux cles primaires */
+                               and (!isset($desc['key']['PRIMARY KEY']) or $desc['key']['PRIMARY KEY'] !== $c)
+                       ) {
+                               spip_sqlite_alter($q = "TABLE $table CHANGE $c $c $d DEFAULT '0'", $serveur);
+                               spip_log("ALTER $q", "repair" . _LOG_INFO_IMPORTANTE);
+                       }
+                       if (preg_match(",^(datetime),i", $d)
+                               and stripos($d, "NOT NULL") !== false
+                               and stripos($d, "DEFAULT") === false
+                               /* pas touche aux cles primaires */
+                               and (!isset($desc['key']['PRIMARY KEY']) or $desc['key']['PRIMARY KEY'] !== $c)
+                       ) {
+                               spip_sqlite_alter($q = "TABLE $table CHANGE $c $c $d DEFAULT '0000-00-00 00:00:00'", $serveur);
+                               spip_log("ALTER $q", "repair" . _LOG_INFO_IMPORTANTE);
+                       }
+               }
+
+               return array(" OK ");
+       }
+
+       return array(" ERROR ");
+}
+
+
+/**
+ * Insère où met à jour une entrée d’une table SQL
+ *
+ * La clé ou les cles primaires doivent être présentes dans les données insérés.
+ * La fonction effectue une protection automatique des données.
+ *
+ * Préférer à cette fonction updateq ou insertq.
+ *
+ * @param string $table
+ *     Nom de la table SQL
+ * @param array $couples
+ *     Couples colonne / valeur à modifier,
+ * @param array $desc
+ *     Tableau de description des colonnes de la table SQL utilisée
+ *     (il sera calculé si nécessaire s'il n'est pas transmis).
+ * @param string $serveur
+ *     Nom du connecteur
+ * @param bool $requeter
+ *     Exécuter la requête, sinon la retourner
+ * @return bool|string
+ *     - true si réussite
+ *     - Texte de la requête si demandé,
+ *     - False en cas d'erreur.
+ **/
+function spip_sqlite_replace($table, $couples, $desc = array(), $serveur = '', $requeter = true) {
+       if (!$desc) {
+               $desc = description_table($table, $serveur);
+       }
+       if (!$desc) {
+               die("$table insertion sans description");
+       }
        $fields = isset($desc['field']) ? $desc['field'] : array();
 
-       foreach ($couples as $champ => $val){
+       foreach ($couples as $champ => $val) {
                $couples[$champ] = _sqlite_calculer_cite($val, $fields[$champ]);
        }
 
        // recherche de champs 'timestamp' pour mise a jour auto de ceux-ci
        $couples = _sqlite_ajouter_champs_timestamp($table, $couples, $desc, $serveur);
 
-       return spip_sqlite_query("REPLACE INTO $table (".join(',', array_keys($couples)).') VALUES ('.join(',', $couples).')', $serveur);
+       return spip_sqlite_query("REPLACE INTO $table (" . join(',', array_keys($couples)) . ') VALUES (' . join(',',
+                       $couples) . ')', $serveur);
 }
 
 
-// http://doc.spip.org/@spip_sqlite_replace_multi
-function spip_sqlite_replace_multi($table, $tab_couples, $desc = array(), $serveur = '', $requeter = true){
+/**
+ * Insère où met à jour des entrées d’une table SQL
+ *
+ * La clé ou les cles primaires doivent être présentes dans les données insérés.
+ * La fonction effectue une protection automatique des données.
+ *
+ * Préférez insertq_multi et sql_updateq
+ *
+ * @param string $table
+ *     Nom de la table SQL
+ * @param array $tab_couples
+ *     Tableau de tableau (colonne / valeur à modifier),
+ * @param array $desc
+ *     Tableau de description des colonnes de la table SQL utilisée
+ *     (il sera calculé si nécessaire s'il n'est pas transmis).
+ * @param string $serveur
+ *     Nom du connecteur
+ * @param bool $requeter
+ *     Exécuter la requête, sinon la retourner
+ * @return bool|string
+ *     - true si réussite
+ *     - Texte de la requête si demandé,
+ *     - False en cas d'erreur.
+ **/
+function spip_sqlite_replace_multi($table, $tab_couples, $desc = array(), $serveur = '', $requeter = true) {
 
        // boucler pour trainter chaque requete independemment
-       foreach ($tab_couples as $couples){
+       foreach ($tab_couples as $couples) {
                $retour = spip_sqlite_replace($table, $couples, $desc, $serveur, $requeter);
        }
-       // renvoie le dernier id        
+
+       // renvoie le dernier id
        return $retour;
 }
 
 
-// http://doc.spip.org/@spip_sqlite_select
-function spip_sqlite_select($select, $from, $where = '', $groupby = '', $orderby = '', $limit = '', $having = '', $serveur = '', $requeter = true){
+/**
+ * Exécute une requête de sélection avec SQLite
+ *
+ * Instance de sql_select (voir ses specs).
+ *
+ * @see sql_select()
+ *
+ * @param string|array $select Champs sélectionnés
+ * @param string|array $from Tables sélectionnées
+ * @param string|array $where Contraintes
+ * @param string|array $groupby Regroupements
+ * @param string|array $orderby Tris
+ * @param string $limit Limites de résultats
+ * @param string|array $having Contraintes posts sélections
+ * @param string $serveur Nom de la connexion
+ * @param bool $requeter Exécuter la requête, sinon la retourner
+ * @return array|bool|resource|string
+ *     - string : Texte de la requête si on ne l'exécute pas
+ *     - ressource si requête exécutée, ressource pour fetch()
+ *     - false si la requête exécutée a ratée
+ *     - array  : Tableau décrivant requête et temps d'exécution si var_profile actif pour tracer.
+ */
+function spip_sqlite_select(
+       $select,
+       $from,
+       $where = '',
+       $groupby = '',
+       $orderby = '',
+       $limit = '',
+       $having = '',
+       $serveur = '',
+       $requeter = true
+) {
 
        // version() n'est pas connu de sqlite
        $select = str_replace('version()', 'sqlite_version()', $select);
@@ -1114,47 +1631,52 @@ function spip_sqlite_select($select, $from, $where = '', $groupby = '', $orderby
 
        $query =
                _sqlite_calculer_expression('SELECT', $select, ', ')
-               ._sqlite_calculer_expression('FROM', $from, ', ')
-               ._sqlite_calculer_expression('WHERE', $where)
-               ._sqlite_calculer_expression('GROUP BY', $groupby, ',')
-               ._sqlite_calculer_expression('HAVING', $having)
-               .($orderby ? ("\nORDER BY "._sqlite_calculer_order($orderby)) : '')
-               .($limit ? "\nLIMIT $limit" : '');
+               . _sqlite_calculer_expression('FROM', $from, ', ')
+               . _sqlite_calculer_expression('WHERE', $where)
+               . _sqlite_calculer_expression('GROUP BY', $groupby, ',')
+               . _sqlite_calculer_expression('HAVING', $having)
+               . ($orderby ? ("\nORDER BY " . _sqlite_calculer_order($orderby)) : '')
+               . ($limit ? "\nLIMIT $limit" : '');
 
        // dans un select, on doit renvoyer la requête en cas d'erreur
        $res = spip_sqlite_query($query, $serveur, $requeter);
        // texte de la requete demande ?
-       if (!$requeter) return $res;
+       if (!$requeter) {
+               return $res;
+       }
        // erreur survenue ?
        if ($res === false) {
                return spip_sqlite::traduire_requete($query, $serveur);
        }
+
        return $res;
 }
 
 
 /**
- * Selectionne un fichier de base de donnees
+ * Sélectionne un fichier de base de données
  *
- * @param string $nom
- *             Nom de la base a utiliser
+ * @param string $db
+ *     Nom de la base à utiliser
  * @param string $serveur
- *             Nom du connecteur
+ *     Nom du connecteur
  * @param bool $requeter
- *             Inutilise
- * 
+ *     Inutilisé
+ *
  * @return bool|string
- *             Nom de la base en cas de success.
- *             False en cas d'erreur.
-**/
-function spip_sqlite_selectdb($db, $serveur = '', $requeter = true){
+ *     - Nom de la base en cas de success.
+ *     - False en cas d'erreur.
+ **/
+function spip_sqlite_selectdb($db, $serveur = '', $requeter = true) {
        _sqlite_init();
 
        // interdire la creation d'une nouvelle base, 
        // sauf si on est dans l'installation
-       if (!is_file($f = _DIR_DB.$db.'.sqlite')
-           && (!defined('_ECRIRE_INSTALL') || !_ECRIRE_INSTALL)){
-               spip_log("Il est interdit de creer la base $db", 'sqlite.'._LOG_HS);
+       if (!is_file($f = _DIR_DB . $db . '.sqlite')
+               && (!defined('_ECRIRE_INSTALL') || !_ECRIRE_INSTALL)
+       ) {
+               spip_log("Il est interdit de creer la base $db", 'sqlite.' . _LOG_HS);
+
                return false;
        }
 
@@ -1162,26 +1684,37 @@ function spip_sqlite_selectdb($db, $serveur = '', $requeter = true){
        // avec les identifiants connus
        $index = $serveur ? $serveur : 0;
 
-       if ($link = spip_connect_db('', '', '', '', '@selectdb@'.$db, $serveur, '', '')){
-               if (($db==$link['db']) && $GLOBALS['connexions'][$index] = $link)
+       if ($link = spip_connect_db('', '', '', '', '@selectdb@' . $db, $serveur, '', '')) {
+               if (($db == $link['db']) && $GLOBALS['connexions'][$index] = $link) {
                        return $db;
+               }
        } else {
-               spip_log("Impossible de selectionner la base $db", 'sqlite.'._LOG_HS);
+               spip_log("Impossible de selectionner la base $db", 'sqlite.' . _LOG_HS);
+
                return false;
        }
 
 }
 
 
-// http://doc.spip.org/@spip_sqlite_set_charset
-function spip_sqlite_set_charset($charset, $serveur = '', $requeter = true){
+/**
+ * Définit un charset pour la connexion avec SQLite (aucune action ici)
+ *
+ * Cette fonction n'a aucune action actuellement.
+ *
+ * @param string $charset Charset à appliquer
+ * @param string $serveur Nom de la connexion
+ * @param bool $requeter inutilisé
+ * @return void
+ */
+function spip_sqlite_set_charset($charset, $serveur = '', $requeter = true) {
        # spip_log("Gestion charset sql a ecrire : "."SET NAMES "._q($charset), 'sqlite.'._LOG_ERREUR);
        # return spip_sqlite_query("SET NAMES ". spip_sqlite_quote($charset), $serveur); //<-- Passe pas !
 }
 
 
 /**
- * Retourne une ressource de la liste des tables de la base de données 
+ * Retourne une ressource de la liste des tables de la base de données
  *
  * @param string $match
  *     Filtre sur tables à récupérer
@@ -1192,8 +1725,8 @@ function spip_sqlite_set_charset($charset, $serveur = '', $requeter = true){
  *     false pour retourner le texte de la requête.
  * @return ressource
  *     Ressource à utiliser avec sql_fetch()
-**/
-function spip_sqlite_showbase($match, $serveur = '', $requeter = true){
+ **/
+function spip_sqlite_showbase($match, $serveur = '', $requeter = true) {
        // type est le type d'entrée : table / index / view
        // on ne retourne que les tables (?) et non les vues...
        # ESCAPE non supporte par les versions sqlite <3
@@ -1206,44 +1739,69 @@ function spip_sqlite_showbase($match, $serveur = '', $requeter = true){
        $match = str_replace("[[TIRETBAS]]", "_", $match);
        $match = str_replace("[[POURCENT]]", "%", $match);
        $match = "^$match$";
-       return spip_sqlite_query("SELECT name FROM sqlite_master WHERE type='table' AND tbl_name REGEXP "._q($match), $serveur, $requeter);
+
+       return spip_sqlite_query("SELECT name FROM sqlite_master WHERE type='table' AND tbl_name REGEXP " . _q($match),
+               $serveur, $requeter);
 }
 
 define('_SQLITE_RE_SHOW_TABLE', '/^[^(),]*\(((?:[^()]*\((?:[^()]*\([^()]*\))?[^()]*\)[^()]*)*[^()]*)\)[^()]*$/');
-// http://doc.spip.org/@spip_sqlite_showtable
-function spip_sqlite_showtable($nom_table, $serveur = '', $requeter = true){
+/**
+ * Obtient la description d'une table ou vue SQLite
+ *
+ * Récupère la définition d'une table ou d'une vue avec colonnes, indexes, etc.
+ * au même format que la définition des tables SPIP, c'est à dire
+ * un tableau avec les clés
+ *
+ * - `field` (tableau colonne => description SQL) et
+ * - `key` (tableau type de clé => colonnes)
+ *
+ * @param string $nom_table Nom de la table SQL
+ * @param string $serveur Nom de la connexion
+ * @param bool $requeter Exécuter la requête, sinon la retourner
+ * @return array|string
+ *     - chaîne vide si pas de description obtenue
+ *     - string Texte de la requête si demandé
+ *     - array description de la table sinon
+ */
+function spip_sqlite_showtable($nom_table, $serveur = '', $requeter = true) {
        $query =
                'SELECT sql, type FROM'
-               .' (SELECT * FROM sqlite_master UNION ALL'
-               .' SELECT * FROM sqlite_temp_master)'
-               ." WHERE tbl_name LIKE '$nom_table'"
-               ." AND type!='meta' AND sql NOT NULL AND name NOT LIKE 'sqlite_%'"
-               .' ORDER BY substr(type,2,1), name';
+               . ' (SELECT * FROM sqlite_master UNION ALL'
+               . ' SELECT * FROM sqlite_temp_master)'
+               . " WHERE tbl_name LIKE '$nom_table'"
+               . " AND type!='meta' AND sql NOT NULL AND name NOT LIKE 'sqlite_%'"
+               . ' ORDER BY substr(type,2,1), name';
 
        $a = spip_sqlite_query($query, $serveur, $requeter);
-       if (!$a) return "";
-       if (!$requeter) return $a;
-       if (!($a = spip_sqlite_fetch($a, null, $serveur))) return "";
-       $vue = ($a['type']=='view'); // table | vue
+       if (!$a) {
+               return "";
+       }
+       if (!$requeter) {
+               return $a;
+       }
+       if (!($a = spip_sqlite_fetch($a, null, $serveur))) {
+               return "";
+       }
+       $vue = ($a['type'] == 'view'); // table | vue
 
        // c'est une table
        // il faut parser le create
-       if (!$vue){
-               if (!preg_match(_SQLITE_RE_SHOW_TABLE, array_shift($a), $r)){
+       if (!$vue) {
+               if (!preg_match(_SQLITE_RE_SHOW_TABLE, array_shift($a), $r)) {
                        return "";
                } else {
                        $desc = $r[1];
                        // extraction d'une KEY éventuelle en prenant garde de ne pas
                        // relever un champ dont le nom contient KEY (ex. ID_WHISKEY)
-                       if (preg_match("/^(.*?),([^,]*\sKEY[ (].*)$/s", $desc, $r)){
+                       if (preg_match("/^(.*?),([^,]*\sKEY[ (].*)$/s", $desc, $r)) {
                                $namedkeys = $r[2];
                                $desc = $r[1];
-                       }
-                       else
+                       } else {
                                $namedkeys = "";
+                       }
 
                        $fields = array();
-                       $keys   = array();
+                       $keys = array();
 
                        // enlever les contenus des valeurs DEFAULT 'xxx' qui pourraient perturber
                        // par exemple s'il contiennent une virgule.
@@ -1253,7 +1811,7 @@ function spip_sqlite_showtable($nom_table, $serveur = '', $requeter = true){
                        // separer toutes les descriptions de champs, separes par des virgules
                        # /!\ explode peut exploser aussi DECIMAL(10,2) !
                        $k_precedent = null;
-                       foreach (explode(",", $desc) as $v){
+                       foreach (explode(",", $desc) as $v) {
 
                                preg_match("/^\s*([^\s]+)\s+(.*)/", $v, $r);
                                // Les cles de champs peuvent etre entourees
@@ -1262,7 +1820,9 @@ function spip_sqlite_showtable($nom_table, $serveur = '', $requeter = true){
                                $k = strtolower(query_reinjecte_textes($r[1], $echaps)); // champ, "champ", [champ]...
                                if ($char = strpbrk($k[0], '\'"[`')) {
                                        $k = trim($k, $char);
-                                       if ($char == '[') $k = rtrim($k, ']');
+                                       if ($char == '[') {
+                                               $k = rtrim($k, ']');
+                                       }
                                }
                                $def = query_reinjecte_textes($r[2], $echaps); // valeur du champ
 
@@ -1271,10 +1831,10 @@ function spip_sqlite_showtable($nom_table, $serveur = '', $requeter = true){
                                        $fields[$k_precedent] .= ',' . $k . ' ' . $def;
                                        continue;
                                }
-                               
+
                                $fields[$k] = $def;
                                $k_precedent = $k;
-                               
+
                                // la primary key peut etre dans une des descriptions de champs
                                // et non en fin de table, cas encore decouvert avec Sqlite Manager
                                if (stripos($r[2], 'PRIMARY KEY') !== false) {
@@ -1282,80 +1842,143 @@ function spip_sqlite_showtable($nom_table, $serveur = '', $requeter = true){
                                }
                        }
                        // key inclues dans la requete
-                       foreach(preg_split('/\)\s*(,|$)/',$namedkeys) as $v) {
-                               if (preg_match("/^\s*([^(]*)\(([^(]*(\(\d+\))?)$/",$v,$r)) {
+                       foreach (preg_split('/\)\s*(,|$)/', $namedkeys) as $v) {
+                               if (preg_match("/^\s*([^(]*)\(([^(]*(\(\d+\))?)$/", $v, $r)) {
                                        $k = str_replace("`", '', trim($r[1]));
                                        $t = trim(strtolower(str_replace("`", '', $r[2])), '"');
-                                       if ($k && !isset($keys[$k])) $keys[$k] = $t; else $keys[] = $t;
+                                       if ($k && !isset($keys[$k])) {
+                                               $keys[$k] = $t;
+                                       } else {
+                                               $keys[] = $t;
+                                       }
                                }
                        }
                        // sinon ajouter les key index
                        $query =
                                'SELECT name,sql FROM'
-                               .' (SELECT * FROM sqlite_master UNION ALL'
-                               .' SELECT * FROM sqlite_temp_master)'
-                               ." WHERE tbl_name LIKE '$nom_table'"
-                               ." AND type='index' AND name NOT LIKE 'sqlite_%'"
-                               .'ORDER BY substr(type,2,1), name';
+                               . ' (SELECT * FROM sqlite_master UNION ALL'
+                               . ' SELECT * FROM sqlite_temp_master)'
+                               . " WHERE tbl_name LIKE '$nom_table'"
+                               . " AND type='index' AND name NOT LIKE 'sqlite_%'"
+                               . 'ORDER BY substr(type,2,1), name';
                        $a = spip_sqlite_query($query, $serveur, $requeter);
-                       while ($r = spip_sqlite_fetch($a, null, $serveur)){
-                               $key = str_replace($nom_table.'_', '', $r['name']); // enlever le nom de la table ajoute a l'index
+                       while ($r = spip_sqlite_fetch($a, null, $serveur)) {
+                               $key = str_replace($nom_table . '_', '', $r['name']); // enlever le nom de la table ajoute a l'index
+                               $keytype = "KEY";
+                               if (strpos($r['sql'], "UNIQUE INDEX") !== false) {
+                                       $keytype = "UNIQUE KEY";
+                               }
                                $colonnes = preg_replace(',.*\((.*)\).*,', '$1', $r['sql']);
-                               $keys['KEY '.$key] = $colonnes;
+                               $keys[$keytype . ' ' . $key] = $colonnes;
                        }
                }
-       }
-       // c'est une vue, on liste les champs disponibles simplement
+
+       // c'est une vue, on liste les champs disponibles simplement
        else {
-               if ($res = sql_fetsel('*', $nom_table, '', '', '', '1', '', $serveur)){ // limit 1
+               if ($res = sql_fetsel('*', $nom_table, '', '', '', '1', '', $serveur)) { // limit 1
                        $fields = array();
-                       foreach ($res as $c => $v) $fields[$c] = '';
+                       foreach ($res as $c => $v) {
+                               $fields[$c] = '';
+                       }
                        $keys = array();
                } else {
                        return "";
                }
        }
+
        return array('field' => $fields, 'key' => $keys);
 
 }
 
 
-// http://doc.spip.org/@spip_sqlite_update
-function spip_sqlite_update($table, $champs, $where = '', $desc = '', $serveur = '', $requeter = true){
+/**
+ * Met à jour des enregistrements d'une table SQL
+ *
+ * @param string $table
+ *     Nom de la table
+ * @param array $champs
+ *     Couples (colonne => valeur)
+ * @param string|array $where
+ *     Conditions a remplir (Where)
+ * @param array $desc
+ *     Tableau de description des colonnes de la table SQL utilisée
+ *     (il sera calculé si nécessaire s'il n'est pas transmis).
+ * @param string $serveur
+ *     Nom de la connexion
+ * @param bool $requeter
+ *     Exécuter la requête, sinon la retourner
+ * @return array|bool|string
+ *     - string : texte de la requête si demandé
+ *     - true si la requête a réussie, false sinon
+ *     - array Tableau décrivant la requête et son temps d'exécution si var_profile est actif
+ */
+function spip_sqlite_update($table, $champs, $where = '', $desc = '', $serveur = '', $requeter = true) {
        // recherche de champs 'timestamp' pour mise a jour auto de ceux-ci
        $champs = _sqlite_ajouter_champs_timestamp($table, $champs, $desc, $serveur);
 
        $set = array();
-       foreach ($champs as $champ => $val)
-               $set[] = $champ."=$val";
-       if (!empty($set))
+       foreach ($champs as $champ => $val) {
+               $set[] = $champ . "=$val";
+       }
+       if (!empty($set)) {
                return spip_sqlite_query(
                        _sqlite_calculer_expression('UPDATE', $table, ',')
-                       ._sqlite_calculer_expression('SET', $set, ',')
-                       ._sqlite_calculer_expression('WHERE', $where),
+                       . _sqlite_calculer_expression('SET', $set, ',')
+                       . _sqlite_calculer_expression('WHERE', $where),
                        $serveur, $requeter);
+       }
 }
 
 
-// http://doc.spip.org/@spip_sqlite_updateq
-function spip_sqlite_updateq($table, $champs, $where = '', $desc = array(), $serveur = '', $requeter = true){
+/**
+ * Met à jour des enregistrements d'une table SQL et protège chaque valeur
+ *
+ * Protège chaque valeur transmise avec sql_quote(), adapté au type
+ * de champ attendu par la table SQL
+ *
+ * @param string $table
+ *     Nom de la table
+ * @param array $champs
+ *     Couples (colonne => valeur)
+ * @param string|array $where
+ *     Conditions a remplir (Where)
+ * @param array $desc
+ *     Tableau de description des colonnes de la table SQL utilisée
+ *     (il sera calculé si nécessaire s'il n'est pas transmis).
+ * @param string $serveur
+ *     Nom de la connexion
+ * @param bool $requeter
+ *     Exécuter la requête, sinon la retourner
+ * @return array|bool|string
+ *     - string : texte de la requête si demandé
+ *     - true si la requête a réussie, false sinon
+ *     - array Tableau décrivant la requête et son temps d'exécution si var_profile est actif
+ */
+function spip_sqlite_updateq($table, $champs, $where = '', $desc = array(), $serveur = '', $requeter = true) {
 
-       if (!$champs) return;
-       if (!$desc) $desc = description_table($table, $serveur);
-       if (!$desc) die("$table insertion sans description");
+       if (!$champs) {
+               return;
+       }
+       if (!$desc) {
+               $desc = description_table($table, $serveur);
+       }
+       if (!$desc) {
+               die("$table insertion sans description");
+       }
        $fields = $desc['field'];
 
        // recherche de champs 'timestamp' pour mise a jour auto de ceux-ci
        $champs = _sqlite_ajouter_champs_timestamp($table, $champs, $desc, $serveur);
 
        $set = array();
-       foreach ($champs as $champ => $val){
-               $set[] = $champ.'='._sqlite_calculer_cite($val, $fields[$champ]);
+       foreach ($champs as $champ => $val) {
+               $set[] = $champ . '=' . _sqlite_calculer_cite($val, isset($fields[$champ]) ? $fields[$champ] : '');
        }
+
        return spip_sqlite_query(
                _sqlite_calculer_expression('UPDATE', $table, ',')
-               ._sqlite_calculer_expression('SET', $set, ',')
-               ._sqlite_calculer_expression('WHERE', $where),
+               . _sqlite_calculer_expression('SET', $set, ',')
+               . _sqlite_calculer_expression('WHERE', $where),
                $serveur, $requeter);
 }
 
@@ -1369,16 +1992,19 @@ function spip_sqlite_updateq($table, $champs, $where = '', $desc = array(), $ser
 
 
 /**
- * fonction pour la premiere connexion a un serveur SQLite
- * http://doc.spip.org/@_sqlite_init
+ * Initialise la première connexion à un serveur SQLite
  *
  * @return void
  */
-function _sqlite_init(){
-       if (!defined('_DIR_DB')) define('_DIR_DB', _DIR_ETC.'bases/');
-       if (!defined('_SQLITE_CHMOD')) define('_SQLITE_CHMOD', _SPIP_CHMOD);
+function _sqlite_init() {
+       if (!defined('_DIR_DB')) {
+               define('_DIR_DB', _DIR_ETC . 'bases/');
+       }
+       if (!defined('_SQLITE_CHMOD')) {
+               define('_SQLITE_CHMOD', _SPIP_CHMOD);
+       }
 
-       if (!is_dir($d = _DIR_DB)){
+       if (!is_dir($d = _DIR_DB)) {
                include_spip('inc/flock');
                sous_repertoire($d);
        }
@@ -1386,8 +2012,7 @@ function _sqlite_init(){
 
 
 /**
- * teste la version sqlite du link en cours
- * http://doc.spip.org/@_sqlite_is_version
+ * Teste la version sqlite du link en cours
  *
  * @param string $version
  * @param string $link
@@ -1395,29 +2020,36 @@ function _sqlite_init(){
  * @param bool $requeter
  * @return bool|int
  */
-function _sqlite_is_version($version = '', $link = '', $serveur = '', $requeter = true){
-       if ($link==='') $link = _sqlite_link($serveur);
-       if (!$link) return false;
-       if ($link instanceof PDO){
+function _sqlite_is_version($version = '', $link = '', $serveur = '', $requeter = true) {
+       if ($link === '') {
+               $link = _sqlite_link($serveur);
+       }
+       if (!$link) {
+               return false;
+       }
+       if ($link instanceof PDO) {
                $v = 3;
        } else {
                $v = 2;
        }
 
-       if (!$version) return $v;
-       return ($version==$v);
+       if (!$version) {
+               return $v;
+       }
+
+       return ($version == $v);
 }
 
 
 /**
- * retrouver un link
- * http://doc.spip.org/@_sqlite_link
+ * Retrouver un link d'une connexion SQLite
  *
- * @param string $serveur
- * @return
+ * @param string $serveur Nom du serveur
+ * @return Object Information de connexion pour SQLite
  */
-function _sqlite_link($serveur = ''){
+function _sqlite_link($serveur = '') {
        $link = &$GLOBALS['connexions'][$serveur ? $serveur : 0]['link'];
+
        return $link;
 }
 
@@ -1426,227 +2058,277 @@ function _sqlite_link($serveur = ''){
 
 
 /**
- * renvoie les bons echappements (pas sur les fonctions now())
- * http://doc.spip.org/@_sqlite_calculer_cite
+ * Renvoie les bons echappements (mais pas sur les fonctions comme NOW())
  *
- * @param string|array|number $v
- * @param string $type
- * @return string|array|number
+ * @param string|number $v Texte ou nombre à échapper
+ * @param string $type Type de donnée attendue, description SQL de la colonne de destination
+ * @return string|number     Texte ou nombre échappé
  */
-function _sqlite_calculer_cite($v, $type){
-       if ($type){
-               if(is_null($v)
-                       AND stripos($type,"NOT NULL")===false) return 'NULL'; // null php se traduit en NULL SQL
-
-               if (sql_test_date($type) AND preg_match('/^\w+\(/', $v))
+function _sqlite_calculer_cite($v, $type) {
+       if ($type) {
+               if (is_null($v)
+                       and stripos($type, "NOT NULL") === false
+               ) {
+                       return 'NULL';
+               } // null php se traduit en NULL SQL
+
+               if (sql_test_date($type) and preg_match('/^\w+\(/', $v)) {
                        return $v;
-               if (sql_test_int($type)){
-                       if (is_numeric($v))
+               }
+               if (sql_test_int($type)) {
+                       if (is_numeric($v)) {
                                return $v;
-                       elseif (ctype_xdigit(substr($v, 2)) AND strncmp($v, '0x', 2)==0)
+                       } elseif (ctype_xdigit(substr($v, 2)) and strncmp($v, '0x', 2) == 0) {
                                return hexdec(substr($v, 2));
-                       else
+                       } else {
                                return intval($v);
+                       }
                }
-       }
-       else {
+       } else {
                // si on ne connait pas le type on le deduit de $v autant que possible
-               if (is_numeric($v))
+               if (is_numeric($v)) {
                        return strval($v);
+               }
        }
 
-       if (function_exists('sqlite_escape_string')){
-               return "'".sqlite_escape_string($v)."'";
+       if (function_exists('sqlite_escape_string')) {
+               return "'" . sqlite_escape_string($v) . "'";
        }
 
        // trouver un link sqlite3 pour faire l'echappement
-       foreach ($GLOBALS['connexions'] as $s){
-               if (_sqlite_is_version(3, $l = $s['link'])){
+       foreach ($GLOBALS['connexions'] as $s) {
+               if (_sqlite_is_version(3, $l = $s['link'])) {
                        return $l->quote($v);
                }
        }
 
        // echapper les ' en ''
-       spip_log("Pas de methode sqlite_escape_string ni ->quote pour echapper","sqlite."._LOG_INFO_IMPORTANTE);
-       return  ("'" . str_replace("'","''",$v) . "'");
+       spip_log("Pas de methode sqlite_escape_string ni ->quote pour echapper", "sqlite." . _LOG_INFO_IMPORTANTE);
+
+       return ("'" . str_replace("'", "''", $v) . "'");
 }
 
 
 /**
- * renvoie grosso modo "$expression join($join, $v)"
- * http://doc.spip.org/@_sqlite_calculer_expression
+ * Calcule un expression pour une requête, en cumulant chaque élément
+ * avec l'opérateur de liaison ($join) indiqué
  *
- * @param  $expression
- * @param  $v
- * @param string $join
- * @return string
+ * Renvoie grosso modo "$expression join($join, $v)"
+ *
+ * @param string $expression Mot clé de l'expression, tel que "WHERE" ou "ORDER BY"
+ * @param array|string $v Données de l'expression
+ * @param string $join Si les données sont un tableau, elles seront groupées par cette jointure
+ * @return string            Texte de l'expression, une partie donc, du texte la requête.
  */
-function _sqlite_calculer_expression($expression, $v, $join = 'AND'){
-       if (empty($v))
+function _sqlite_calculer_expression($expression, $v, $join = 'AND') {
+       if (empty($v)) {
                return '';
+       }
 
        $exp = "\n$expression ";
 
-       if (!is_array($v)){
-               return $exp.$v;
+       if (!is_array($v)) {
+               return $exp . $v;
        } else {
-               if (strtoupper($join)==='AND')
-                       return $exp.join("\n\t$join ", array_map('_sqlite_calculer_where', $v));
-               else
-                       return $exp.join($join, $v);
+               if (strtoupper($join) === 'AND') {
+                       return $exp . join("\n\t$join ", array_map('_sqlite_calculer_where', $v));
+               } else {
+                       return $exp . join($join, $v);
+               }
        }
 }
 
 
 /**
- * pour conversion 0+x ? (pas la peine en sqlite)
- * http://doc.spip.org/@_sqlite_calculer_order
+ * Prépare une clause order by
  *
- * @param  $orderby
- * @return string
+ * Regroupe en texte les éléments si un tableau est donné
+ *
+ * @note
+ *   Pas besoin de conversion pour 0+x comme il faudrait pour mysql.
+ *
+ * @param string|array $orderby Texte du orderby à préparer
+ * @return string Texte du orderby préparé
  */
-function _sqlite_calculer_order($orderby){
+function _sqlite_calculer_order($orderby) {
        return (is_array($orderby)) ? join(", ", $orderby) : $orderby;
 }
 
 
-// renvoie des 'nom AS alias' 
-// http://doc.spip.org/@_sqlite_calculer_select_as
-function _sqlite_calculer_select_as($args){
+/**
+ * Renvoie des `nom AS alias`
+ *
+ * @param array $args
+ * @return string Sélection de colonnes pour une clause SELECT
+ */
+function _sqlite_calculer_select_as($args) {
        $res = '';
-       foreach ($args as $k => $v){
-               if (substr($k, -1)=='@'){
+       foreach ($args as $k => $v) {
+               if (substr($k, -1) == '@') {
                        // c'est une jointure qui se refere au from precedent
                        // pas de virgule
-                       $res .= '  '.$v;
-               }
-               else {
-                       if (!is_numeric($k)){
+                       $res .= '  ' . $v;
+               } else {
+                       if (!is_numeric($k)) {
                                $p = strpos($v, " ");
-                               if ($p)
-                                       $v = substr($v, 0, $p)." AS '$k'".substr($v, $p);
-                               else $v .= " AS '$k'";
+                               if ($p) {
+                                       $v = substr($v, 0, $p) . " AS '$k'" . substr($v, $p);
+                               } else {
+                                       $v .= " AS '$k'";
+                               }
                        }
-                       $res .= ', '.$v;
+                       $res .= ', ' . $v;
                }
        }
+
        return substr($res, 2);
 }
 
 
 /**
- * renvoie les bonnes parentheses pour des where imbriquees
- * http://doc.spip.org/@_sqlite_calculer_where
+ * Prépare une clause WHERE pour SQLite
+ *
+ * Retourne une chaîne avec les bonnes parenthèses pour la
+ * contrainte indiquée, au format donnée par le compilateur
  *
- * @param  $v
- * @return array|mixed|string
+ * @param array|string $v
+ *     Description des contraintes
+ *     - string : Texte du where
+ *     - sinon tableau : A et B peuvent être de type string ou array,
+ *       OP et C sont de type string :
+ *       - array(A) : A est le texte du where
+ *       - array(OP, A) : contrainte OP( A )
+ *       - array(OP, A, B) : contrainte (A OP B)
+ *       - array(OP, A, B, C) : contrainte (A OP (B) : C)
+ * @return string
+ *     Contrainte pour clause WHERE
  */
-function _sqlite_calculer_where($v){
-       if (!is_array($v))
+function _sqlite_calculer_where($v) {
+       if (!is_array($v)) {
                return $v;
+       }
 
        $op = array_shift($v);
-       if (!($n = count($v)))
+       if (!($n = count($v))) {
                return $op;
-       else {
+       else {
                $arg = _sqlite_calculer_where(array_shift($v));
-               if ($n==1){
+               if ($n == 1) {
                        return "$op($arg)";
                } else {
                        $arg2 = _sqlite_calculer_where(array_shift($v));
-                       if ($n==2){
+                       if ($n == 2) {
                                return "($arg $op $arg2)";
-                       } else return "($arg $op ($arg2) : $v[0])";
+                       } else {
+                               return "($arg $op ($arg2) : $v[0])";
+                       }
                }
        }
 }
 
 
 /**
- * Charger les modules sqlite (si possible) (juste la version demandee),
- * ou, si aucune version, renvoie les versions sqlite dispo
- * sur ce serveur dans un array
+ * Charger les modules SQLite
  *
- * http://doc.spip.org/@_sqlite_charger_version
+ * Si possible et juste la version demandée,
+ * ou, si aucune version, on renvoie les versions sqlite disponibles
+ * sur ce serveur dans un tableau
  *
  * @param string $version
  * @return array|bool
  */
-function _sqlite_charger_version($version = ''){
+function _sqlite_charger_version($version = '') {
        $versions = array();
 
        // version 2
-       if (!$version || $version==2){
-               if (charger_php_extension('sqlite')){
+       if (!$version || $version == 2) {
+               if (charger_php_extension('sqlite')) {
                        $versions[] = 2;
                }
        }
 
        // version 3
-       if (!$version || $version==3){
-               if (charger_php_extension('pdo') && charger_php_extension('pdo_sqlite')){
+       if (!$version || $version == 3) {
+               if (charger_php_extension('pdo') && charger_php_extension('pdo_sqlite')) {
                        $versions[] = 3;
                }
        }
-       if ($version) return in_array($version, $versions);
+       if ($version) {
+               return in_array($version, $versions);
+       }
+
        return $versions;
 }
 
 
 /**
- * Gestion des requetes ALTER non reconnues de SQLite :
- * ALTER TABLE table DROP column
- * ALTER TABLE table CHANGE [COLUMN] columnA columnB definition
- * ALTER TABLE table MODIFY column definition
- * ALTER TABLE table ADD|DROP PRIMARY KEY
+ * Gestion des requêtes ALTER non reconnues de SQLite
  *
- * (MODIFY transforme en CHANGE columnA columnA) par spip_sqlite_alter()
+ * Requêtes non reconnues :
  *
- * 1) creer une table B avec le nouveau format souhaite
- * 2) copier la table d'origine A vers B
- * 3) supprimer la table A
- * 4) renommer la table B en A
- * 5) remettre les index (qui sont supprimes avec la table A)
+ *     ALTER TABLE table DROP column
+ *     ALTER TABLE table CHANGE [COLUMN] columnA columnB definition
+ *     ALTER TABLE table MODIFY column definition
+ *     ALTER TABLE table ADD|DROP PRIMARY KEY
  *
- * http://doc.spip.org/@_sqlite_modifier_table
+ * `MODIFY` est transformé en `CHANGE columnA columnA` par spip_sqlite_alter()
  *
- * @param string/array $table : nom_table, array(nom_table=>nom_futur)
- * @param string/array $col : nom_colonne, array(nom_colonne=>nom_futur)
- * @param array $opt : options comme les tables spip, qui sera merge a la table creee : array('field'=>array('nom'=>'syntaxe', ...), 'key'=>array('KEY nom'=>'colonne', ...))
- * @param string $serveur : nom de la connexion sql en cours
+ * 1) Créer une table B avec le nouveau format souhaité
+ * 2) Copier la table d'origine A vers B
+ * 3) Supprimer la table A
+ * 4) Renommer la table B en A
+ * 5) Remettre les index (qui sont supprimés avec la table A)
  *
+ * @param string|array $table
+ *     - string : Nom de la table table,
+ *     - array : couple (nom de la table => nom futur)
+ * @param string|array $colonne
+ *     - string : nom de la colonne,
+ *     - array : couple (nom de la colonne => nom futur)
+ * @param array $opt
+ *     options comme les tables SPIP, qui sera mergé à la table créee :
+ *     `array('field'=>array('nom'=>'syntaxe', ...), 'key'=>array('KEY nom'=>'colonne', ...))`
+ * @param string $serveur
+ *     Nom de la connexion SQL en cours
+ * @return bool
+ *     true si OK, false sinon.
  */
-function _sqlite_modifier_table($table, $colonne, $opt = array(), $serveur = ''){
+function _sqlite_modifier_table($table, $colonne, $opt = array(), $serveur = '') {
 
-       if (is_array($table)){
+       if (is_array($table)) {
                reset($table);
-               list($table_origine,$table_destination) = each($table);
+               list($table_origine, $table_destination) = each($table);
        } else {
                $table_origine = $table_destination = $table;
        }
        // ne prend actuellement qu'un changement
        // mais pourra etre adapte pour changer plus qu'une colonne a la fois
-       if (is_array($colonne)){
+       if (is_array($colonne)) {
                reset($colonne);
-               list($colonne_origine,$colonne_destination) = each($colonne);
+               list($colonne_origine, $colonne_destination) = each($colonne);
        } else {
                $colonne_origine = $colonne_destination = $colonne;
        }
-       if (!isset($opt['field'])) $opt['field'] = array();
-       if (!isset($opt['key'])) $opt['key'] = array();
+       if (!isset($opt['field'])) {
+               $opt['field'] = array();
+       }
+       if (!isset($opt['key'])) {
+               $opt['key'] = array();
+       }
 
        // si les noms de tables sont differents, pas besoin de table temporaire
        // on prendra directement le nom de la future table
-       $meme_table = ($table_origine==$table_destination);
+       $meme_table = ($table_origine == $table_destination);
 
        $def_origine = sql_showtable($table_origine, false, $serveur);
-       if (!$def_origine OR !isset($def_origine['field'])){
-               spip_log("Alter table impossible sur $table_origine : table non trouvee",'sqlite'._LOG_ERREUR);
+       if (!$def_origine or !isset($def_origine['field'])) {
+               spip_log("Alter table impossible sur $table_origine : table non trouvee", 'sqlite' . _LOG_ERREUR);
+
                return false;
        }
 
 
-       $table_tmp = $table_origine.'_tmp';
+       $table_tmp = $table_origine . '_tmp';
 
        // 1) creer une table temporaire avec les modifications 
        // - DROP : suppression de la colonne
@@ -1658,11 +2340,11 @@ function _sqlite_modifier_table($table, $colonne, $opt = array(), $serveur = '')
        // pour le INSERT INTO plus loin
        // stocker la correspondance nouvelles->anciennes colonnes
        $fields_correspondances = array();
-       foreach ($def_origine['field'] as $c => $d){
+       foreach ($def_origine['field'] as $c => $d) {
 
-               if ($colonne_origine && ($c==$colonne_origine)){
+               if ($colonne_origine && ($c == $colonne_origine)) {
                        // si pas DROP
-                       if ($colonne_destination){
+                       if ($colonne_destination) {
                                $fields[$colonne_destination] = $opt['field'][$colonne_destination];
                                $fields_correspondances[$colonne_destination] = $c;
                        }
@@ -1672,18 +2354,19 @@ function _sqlite_modifier_table($table, $colonne, $opt = array(), $serveur = '')
                }
        }
        // cas de ADD sqlite2 (ajout du champ en fin de table):
-       if (!$colonne_origine && $colonne_destination){
+       if (!$colonne_origine && $colonne_destination) {
                $fields[$colonne_destination] = $opt['field'][$colonne_destination];
        }
 
        // key...
        $keys = array();
-       foreach ($def_origine['key'] as $c => $d){
+       foreach ($def_origine['key'] as $c => $d) {
                $c = str_replace($colonne_origine, $colonne_destination, $c);
                $d = str_replace($colonne_origine, $colonne_destination, $d);
                // seulement si on ne supprime pas la colonne !
-               if ($d)
+               if ($d) {
                        $keys[$c] = $d;
+               }
        }
 
        // autres keys, on merge
@@ -1693,8 +2376,9 @@ function _sqlite_modifier_table($table, $colonne, $opt = array(), $serveur = '')
        // copier dans destination (si differente de origine), sinon tmp
        $table_copie = ($meme_table) ? $table_tmp : $table_destination;
        $autoinc = (isset($keys['PRIMARY KEY'])
-                                       AND stripos($keys['PRIMARY KEY'],',')===false
-                                       AND stripos($fields[$keys['PRIMARY KEY']],'default')===false);
+               and $keys['PRIMARY KEY']
+               and stripos($keys['PRIMARY KEY'], ',') === false
+               and stripos($fields[$keys['PRIMARY KEY']], 'default') === false);
 
        if ($q = _sqlite_requete_create(
                $table_copie,
@@ -1703,7 +2387,8 @@ function _sqlite_modifier_table($table, $colonne, $opt = array(), $serveur = '')
                $autoinc,
                $temporary = false,
                $ifnotexists = true,
-               $serveur)){
+               $serveur)
+       ) {
                $queries[] = $q;
        }
 
@@ -1719,8 +2404,8 @@ function _sqlite_modifier_table($table, $colonne, $opt = array(), $serveur = '')
        // 4) renommer la table temporaire 
        // avec le nom de la table destination
        // si necessaire
-       if ($meme_table){
-               if (_sqlite_is_version(3, '', $serveur)){
+       if ($meme_table) {
+               if (_sqlite_is_version(3, '', $serveur)) {
                        $queries[] = "ALTER TABLE $table_copie RENAME TO $table_destination";
                } else {
                        $queries[] = _sqlite_requete_create(
@@ -1737,25 +2422,25 @@ function _sqlite_modifier_table($table, $colonne, $opt = array(), $serveur = '')
        }
 
        // 5) remettre les index !
-       foreach ($keys as $k => $v){
-               if ($k=='PRIMARY KEY'){
-               }
-               else {
+       foreach ($keys as $k => $v) {
+               if ($k == 'PRIMARY KEY') {
+               } else {
                        // enlever KEY
                        $k = substr($k, 4);
-                       $queries[] = "CREATE INDEX $table_destination"."_$k ON $table_destination ($v)";
+                       $queries[] = "CREATE INDEX $table_destination" . "_$k ON $table_destination ($v)";
                }
        }
 
 
-       if (count($queries)){
+       if (count($queries)) {
                spip_sqlite::demarrer_transaction($serveur);
                // il faut les faire une par une car $query = join('; ', $queries).";"; ne fonctionne pas
-               foreach ($queries as $q){
-                       if (!spip_sqlite::executer_requete($q, $serveur)){
+               foreach ($queries as $q) {
+                       if (!spip_sqlite::executer_requete($q, $serveur)) {
                                spip_log(_LOG_GRAVITE_ERREUR, "SQLite : ALTER TABLE table :"
-                                                                                                                                                       ." Erreur a l'execution de la requete : $q", 'sqlite');
+                                       " Erreur a l'execution de la requete : $q", 'sqlite');
                                spip_sqlite::annuler_transaction($serveur);
+
                                return false;
                        }
                }
@@ -1768,11 +2453,10 @@ function _sqlite_modifier_table($table, $colonne, $opt = array(), $serveur = '')
 
 /**
  * Nom des fonctions
- * http://doc.spip.org/@_sqlite_ref_fonctions
  *
  * @return array
  */
-function _sqlite_ref_fonctions(){
+function _sqlite_ref_fonctions() {
        $fonctions = array(
                'alter' => 'spip_sqlite_alter',
                'count' => 'spip_sqlite_count',
@@ -1800,6 +2484,7 @@ function _sqlite_ref_fonctions(){
                'optimize' => 'spip_sqlite_optimize',
                'query' => 'spip_sqlite_query',
                'quote' => 'spip_sqlite_quote',
+               'repair' => 'spip_sqlite_repair',
                'replace' => 'spip_sqlite_replace',
                'replace_multi' => 'spip_sqlite_replace_multi',
                'select' => 'spip_sqlite_select',
@@ -1831,77 +2516,80 @@ function _sqlite_ref_fonctions(){
 
 /**
  * $query est une requete ou une liste de champs
- * http://doc.spip.org/@_sqlite_remplacements_definitions_table
  *
  * @param  $query
  * @param bool $autoinc
  * @return mixed
  */
-function _sqlite_remplacements_definitions_table($query, $autoinc = false){
+function _sqlite_remplacements_definitions_table($query, $autoinc = false) {
        // quelques remplacements
        $num = "(\s*\([0-9]*\))?";
        $enum = "(\s*\([^\)]*\))?";
 
        $remplace = array(
-               '/enum'.$enum.'/is' => 'VARCHAR(255)',
+               '/enum' . $enum . '/is' => 'VARCHAR(255)',
                '/COLLATE \w+_bin/is' => 'COLLATE BINARY',
                '/COLLATE \w+_ci/is' => 'COLLATE NOCASE',
                '/auto_increment/is' => '',
                '/(timestamp .* )ON .*$/is' => '\\1',
                '/character set \w+/is' => '',
-               '/((big|small|medium|tiny)?int(eger)?)'.$num.'\s*unsigned/is' => '\\1 UNSIGNED',
+               '/((big|small|medium|tiny)?int(eger)?)' . $num . '\s*unsigned/is' => '\\1 UNSIGNED',
                '/(text\s+not\s+null(\s+collate\s+\w+)?)\s*$/is' => "\\1 DEFAULT ''",
-               '/((char|varchar)'.$num.'\s+not\s+null(\s+collate\s+\w+)?)\s*$/is' => "\\1 DEFAULT ''",
+               '/((char|varchar)' . $num . '\s+not\s+null(\s+collate\s+\w+)?)\s*$/is' => "\\1 DEFAULT ''",
                '/(datetime\s+not\s+null)\s*$/is' => "\\1 DEFAULT '0000-00-00 00:00:00'",
                '/(date\s+not\s+null)\s*$/is' => "\\1 DEFAULT '0000-00-00'",
        );
 
        // pour l'autoincrement, il faut des INTEGER NOT NULL PRIMARY KEY
        $remplace_autocinc = array(
-               '/(big|small|medium|tiny)?int(eger)?'.$num.'/is' => 'INTEGER'
+               '/(big|small|medium|tiny)?int(eger)?' . $num . '/is' => 'INTEGER'
        );
        // pour les int non autoincrement, il faut un DEFAULT
        $remplace_nonautocinc = array(
-               '/((big|small|medium|tiny)?int(eger)?'.$num.'\s+not\s+null)\s*$/is' => "\\1 DEFAULT 0",
+               '/((big|small|medium|tiny)?int(eger)?' . $num . '\s+not\s+null)\s*$/is' => "\\1 DEFAULT 0",
        );
 
-       if (is_string($query)){
+       if (is_string($query)) {
                $query = preg_replace(array_keys($remplace), $remplace, $query);
-               if ($autoinc OR preg_match(',AUTO_INCREMENT,is',$query))
+               if ($autoinc or preg_match(',AUTO_INCREMENT,is', $query)) {
                        $query = preg_replace(array_keys($remplace_autocinc), $remplace_autocinc, $query);
-               else{
+               } else {
                        $query = preg_replace(array_keys($remplace_nonautocinc), $remplace_nonautocinc, $query);
                        $query = _sqlite_collate_ci($query);
                }
-       }
-       elseif(is_array($query)){
-               foreach($query as $k=>$q) {
-                       $ai = ($autoinc?$k==$autoinc:preg_match(',AUTO_INCREMENT,is',$q));
+       } elseif (is_array($query)) {
+               foreach ($query as $k => $q) {
+                       $ai = ($autoinc ? $k == $autoinc : preg_match(',AUTO_INCREMENT,is', $q));
                        $query[$k] = preg_replace(array_keys($remplace), $remplace, $query[$k]);
-                       if ($ai)
+                       if ($ai) {
                                $query[$k] = preg_replace(array_keys($remplace_autocinc), $remplace_autocinc, $query[$k]);
-                       else{
+                       } else {
                                $query[$k] = preg_replace(array_keys($remplace_nonautocinc), $remplace_nonautocinc, $query[$k]);
                                $query[$k] = _sqlite_collate_ci($query[$k]);
                        }
                }
        }
+
        return $query;
 }
 
 /**
  * Definir la collation d'un champ en fonction de si une collation est deja explicite
  * et du par defaut que l'on veut NOCASE
+ *
  * @param string $champ
  * @return string
  */
-function _sqlite_collate_ci($champ){
-       if (stripos($champ,"COLLATE")!==false)
+function _sqlite_collate_ci($champ) {
+       if (stripos($champ, "COLLATE") !== false) {
                return $champ;
-       if (stripos($champ,"BINARY")!==false)
-               return str_ireplace("BINARY","COLLATE BINARY",$champ);
-       if (preg_match(",^(char|varchar|(long|small|medium|tiny)?text),i",$champ))
+       }
+       if (stripos($champ, "BINARY") !== false) {
+               return str_ireplace("BINARY", "COLLATE BINARY", $champ);
+       }
+       if (preg_match(",^(char|varchar|(long|small|medium|tiny)?text),i", $champ)) {
                return $champ . " COLLATE NOCASE";
+       }
 
        return $champ;
 }
@@ -1911,8 +2599,6 @@ function _sqlite_collate_ci($champ){
  * Creer la requete pour la creation d'une table
  * retourne la requete pour utilisation par sql_create() et sql_alter()
  *
- * http://doc.spip.org/@_sqlite_requete_create
- *
  * @param  $nom
  * @param  $champs
  * @param  $cles
@@ -1923,22 +2609,32 @@ function _sqlite_collate_ci($champ){
  * @param bool $requeter
  * @return bool|string
  */
-function _sqlite_requete_create($nom, $champs, $cles, $autoinc = false, $temporary = false, $_ifnotexists = true, $serveur = '', $requeter = true){
+function _sqlite_requete_create(
+       $nom,
+       $champs,
+       $cles,
+       $autoinc = false,
+       $temporary = false,
+       $_ifnotexists = true,
+       $serveur = '',
+       $requeter = true
+) {
        $query = $keys = $s = $p = '';
 
        // certains plugins declarent les tables  (permet leur inclusion dans le dump)
        // sans les renseigner (laisse le compilo recuperer la description)
-       if (!is_array($champs) || !is_array($cles))
+       if (!is_array($champs) || !is_array($cles)) {
                return;
+       }
 
        // sqlite ne gere pas KEY tout court dans une requete CREATE TABLE
        // il faut passer par des create index
        // Il gere par contre primary key !
        // Soit la PK est definie dans les cles, soit dans un champs
        $c = ""; // le champ de cle primaire
-       if (!isset($cles[$pk = "PRIMARY KEY"]) OR !$c = $cles[$pk]){
-               foreach ($champs as $k => $v){
-                       if (false!==stripos($v, $pk)){
+       if (!isset($cles[$pk = "PRIMARY KEY"]) or !$c = $cles[$pk]) {
+               foreach ($champs as $k => $v) {
+                       if (false !== stripos($v, $pk)) {
                                $c = $k;
                                // on n'en a plus besoin dans field, vu que defini dans key
                                $champs[$k] = preg_replace("/$pk/is", '', $champs[$k]);
@@ -1946,37 +2642,45 @@ function _sqlite_requete_create($nom, $champs, $cles, $autoinc = false, $tempora
                        }
                }
        }
-       if ($c) $keys = "\n\t\t$pk ($c)";
+       if ($c) {
+               $keys = "\n\t\t$pk ($c)";
+       }
        // Pas de DEFAULT 0 sur les cles primaires en auto-increment
        if (isset($champs[$c])
-               AND stripos($champs[$c],"default 0")!==false){
-               $champs[$c] = trim(str_ireplace("default 0","",$champs[$c]));
+               and stripos($champs[$c], "default 0") !== false
+       ) {
+               $champs[$c] = trim(str_ireplace("default 0", "", $champs[$c]));
        }
 
-       $champs = _sqlite_remplacements_definitions_table($champs, $autoinc?$c:false);
-       foreach ($champs as $k => $v){
+       $champs = _sqlite_remplacements_definitions_table($champs, $autoinc ? $c : false);
+       foreach ($champs as $k => $v) {
                $query .= "$s\n\t\t$k $v";
                $s = ",";
        }
 
        $ifnotexists = "";
-       if ($_ifnotexists){
+       if ($_ifnotexists) {
 
-               $version = spip_sqlite_fetch(spip_sqlite_query("select sqlite_version() AS sqlite_version",$serveur),'',$serveur);
-               if (!function_exists('spip_version_compare')) include_spip('plugins/installer');
+               $version = spip_sqlite_fetch(spip_sqlite_query("select sqlite_version() AS sqlite_version", $serveur), '',
+                       $serveur);
+               if (!function_exists('spip_version_compare')) {
+                       include_spip('plugins/installer');
+               }
 
-               if ($version AND spip_version_compare($version['sqlite_version'],'3.3.0','>=')) {
+               if ($version and spip_version_compare($version['sqlite_version'], '3.3.0', '>=')) {
                        $ifnotexists = ' IF NOT EXISTS';
                } else {
                        /* simuler le IF EXISTS - version 2 et sqlite < 3.3a */
                        $a = spip_sqlite_showtable($table, $serveur);
-                       if (isset($a['key']['KEY '.$nom])) return true;
+                       if (isset($a['key']['KEY ' . $nom])) {
+                               return true;
+                       }
                }
 
        }
 
        $temporary = $temporary ? ' TEMPORARY' : '';
-       $q = "CREATE$temporary TABLE$ifnotexists $nom ($query".($keys ? ",$keys" : '').")\n";
+       $q = "CREATE$temporary TABLE$ifnotexists $nom ($query" . ($keys ? ",$keys" : '') . ")\n";
 
        return $q;
 }
@@ -1990,24 +2694,24 @@ function _sqlite_requete_create($nom, $champs, $cles, $autoinc = false, $tempora
  * stocke le resultat pour ne pas faire
  * de requetes showtable intempestives
  *
- * http://doc.spip.org/@_sqlite_ajouter_champs_timestamp
- *
  * @param  $table
  * @param  $couples
  * @param string $desc
  * @param string $serveur
  * @return
  */
-function _sqlite_ajouter_champs_timestamp($table, $couples, $desc = '', $serveur = ''){
+function _sqlite_ajouter_champs_timestamp($table, $couples, $desc = '', $serveur = '') {
        static $tables = array();
 
-       if (!isset($tables[$table])){
+       if (!isset($tables[$table])) {
 
-               if (!$desc){
+               if (!$desc) {
                        $trouver_table = charger_fonction('trouver_table', 'base');
                        $desc = $trouver_table($table, $serveur);
                        // si pas de description, on ne fait rien, ou on die() ?
-                       if (!$desc) return $couples;
+                       if (!$desc) {
+                               return $couples;
+                       }
                }
 
                // recherche des champs avec simplement 'TIMESTAMP'
@@ -2016,34 +2720,38 @@ function _sqlite_ajouter_champs_timestamp($table, $couples, $desc = '', $serveur
                // mais ceux-ci ne sont pas utilises dans le core
                $tables[$table] = array();
 
-               foreach ($desc['field'] as $k => $v){
-                       if (strpos(strtolower(ltrim($v)), 'timestamp')===0)
+               foreach ($desc['field'] as $k => $v) {
+                       if (strpos(strtolower(ltrim($v)), 'timestamp') === 0) {
                                $tables[$table][$k] = "datetime('now')";
+                       }
                }
        }
 
        // ajout des champs type 'timestamp' absents
-       return array_merge($tables[$table],$couples);
+       return array_merge($tables[$table], $couples);
 }
 
 
 /**
- * renvoyer la liste des versions sqlite disponibles
+ * Renvoyer la liste des versions sqlite disponibles
  * sur le serveur
- * http://doc.spip.org/@spip_versions_sqlite
  *
  * @return array|bool
  */
-function spip_versions_sqlite(){
+function spip_versions_sqlite() {
        return _sqlite_charger_version();
 }
 
-
+/**
+ * Gère l'envoi et la réception de requêtes à SQLite, qui peuvent être
+ * encadrées de transactions.
+ **/
 class spip_sqlite {
-       static $requeteurs = array();
-       static $transaction_en_cours = array();
+       /** @var sqlite_requeteur[] Liste des instances de requêteurs créés */
+       public static $requeteurs = array();
+       /** @var bool[] Pour chaque connexion, flag pour savoir si une transaction est en cours */
+       public static $transaction_en_cours = array();
 
-       function spip_sqlite(){}
 
        /**
         * Retourne une unique instance du requêteur
@@ -2052,85 +2760,141 @@ class spip_sqlite {
         * donnée
         *
         * @param string $serveur
-        *              Nom du connecteur
+        *    Nom du connecteur
         * @return sqlite_requeteur
-        *              Instance unique du requêteur
-       **/
-       static function requeteur($serveur){
-               if (!isset(spip_sqlite::$requeteurs[$serveur]))
+        *    Instance unique du requêteur
+        **/
+       public static function requeteur($serveur) {
+               if (!isset(spip_sqlite::$requeteurs[$serveur])) {
                        spip_sqlite::$requeteurs[$serveur] = new sqlite_requeteur($serveur);
+               }
+
                return spip_sqlite::$requeteurs[$serveur];
        }
 
-       static function traduire_requete($query, $serveur){
+       /**
+        * Prépare le texte d'une requête avant son exécution
+        *
+        * Adapte la requête au format plus ou moins MySQL par un format
+        * compris de SQLite.
+        *
+        * Change les préfixes de tables SPIP par ceux véritables
+        *
+        * @param string $query Requête à préparer
+        * @param string $serveur Nom de la connexion
+        * @return string           Requête préparée
+        */
+       public static function traduire_requete($query, $serveur) {
                $requeteur = spip_sqlite::requeteur($serveur);
-               $traducteur = new sqlite_traducteur($query, $requeteur->prefixe,$requeteur->sqlite_version);
+               $traducteur = new sqlite_traducteur($query, $requeteur->prefixe, $requeteur->sqlite_version);
+
                return $traducteur->traduire_requete();
        }
 
-       static function demarrer_transaction($serveur){
-               spip_sqlite::executer_requete("BEGIN TRANSACTION",$serveur);
+       /**
+        * Démarre une transaction
+        *
+        * @param string $serveur Nom de la connexion
+        **/
+       public static function demarrer_transaction($serveur) {
+               spip_sqlite::executer_requete("BEGIN TRANSACTION", $serveur);
                spip_sqlite::$transaction_en_cours[$serveur] = true;
        }
 
-       static function executer_requete($query, $serveur, $tracer=null){
+       /**
+        * Exécute la requête donnée
+        *
+        * @param string $query Requête
+        * @param string $serveur Nom de la connexion
+        * @param null|bool $tracer Demander des statistiques (temps) ?
+        **/
+       public static function executer_requete($query, $serveur, $tracer = null) {
                $requeteur = spip_sqlite::requeteur($serveur);
+
                return $requeteur->executer_requete($query, $tracer);
        }
 
-       static function last_insert_id($serveur){
+       /**
+        * Obtient l'identifiant de la dernière ligne insérée ou modifiée
+        *
+        * @param string $serveur Nom de la connexion
+        * return int                Identifiant
+        **/
+       public static function last_insert_id($serveur) {
                $requeteur = spip_sqlite::requeteur($serveur);
+
                return $requeteur->last_insert_id($serveur);
        }
 
-       static function annuler_transaction($serveur){
-               spip_sqlite::executer_requete("ROLLBACK",$serveur);
+       /**
+        * Annule une transaction
+        *
+        * @param string $serveur Nom de la connexion
+        **/
+       public static function annuler_transaction($serveur) {
+               spip_sqlite::executer_requete("ROLLBACK", $serveur);
                spip_sqlite::$transaction_en_cours[$serveur] = false;
        }
 
-       static function finir_transaction($serveur){
+       /**
+        * Termine une transaction
+        *
+        * @param string $serveur Nom de la connexion
+        **/
+       public static function finir_transaction($serveur) {
                // si pas de transaction en cours, ne rien faire et le dire
-               if (!isset (spip_sqlite::$transaction_en_cours[$serveur])
-                 OR spip_sqlite::$transaction_en_cours[$serveur]==false)
+               if (!isset(spip_sqlite::$transaction_en_cours[$serveur])
+                       or spip_sqlite::$transaction_en_cours[$serveur] == false
+               ) {
                        return false;
+               }
                // sinon fermer la transaction et retourner true
-               spip_sqlite::executer_requete("COMMIT",$serveur);
+               spip_sqlite::executer_requete("COMMIT", $serveur);
                spip_sqlite::$transaction_en_cours[$serveur] = false;
+
                return true;
        }
 }
 
 /*
- * Classe pour partager les lancements de requete
- * instanciee une fois par $serveur
- * - peut corriger la syntaxe des requetes pour la conformite a sqlite
- * - peut tracer les requetes
+ * Classe pour partager les lancements de requête
+ * 
+ * Instanciée une fois par `$serveur` :
  * 
+ * - peut corriger la syntaxe des requêtes pour la conformité à SQLite
+ * - peut tracer les requêtes
  */
-class sqlite_requeteur {
-       var $query = ''; // la requete
-       var $serveur = ''; // le serveur
-       var $link = ''; // le link (ressource) sqlite
-       var $prefixe = ''; // le prefixe des tables
-       var $db = ''; // le nom de la base 
-       var $tracer = false; // doit-on tracer les requetes (var_profile)
 
-       var $sqlite_version = ''; // Version de sqlite (2 ou 3)
+class sqlite_requeteur {
+       /** @var string Texte de la requête */
+       public $query = ''; // la requete
+       /** @var string Nom de la connexion */
+       public $serveur = '';
+       /** @var Ressource Identifiant de la connexion SQLite */
+       public $link = '';
+       /** @var string Prefixe des tables SPIP */
+       public $prefixe = '';
+       /** @var string Nom de la base de donnée */
+       public $db = '';
+       /** @var bool Doit-on tracer les requetes (var_profile) ? */
+       public $tracer = false; // doit-on tracer les requetes (var_profile)
+
+       /** @var string Version de SQLite (2 ou 3) */
+       public $sqlite_version = '';
 
        /**
-        * constructeur
-        * http://doc.spip.org/@sqlite_traiter_requete
+        * Constructeur
         *
-        * @param  $query
         * @param string $serveur
         * @return bool
         */
-       function sqlite_requeteur($serveur = ''){
+       public function __construct($serveur = '') {
                _sqlite_init();
                $this->serveur = strtolower($serveur);
 
-               if (!($this->link = _sqlite_link($this->serveur)) && (!defined('_ECRIRE_INSTALL') || !_ECRIRE_INSTALL)){
-                       spip_log("Aucune connexion sqlite (link)", 'sqlite.'._LOG_ERREUR);
+               if (!($this->link = _sqlite_link($this->serveur)) && (!defined('_ECRIRE_INSTALL') || !_ECRIRE_INSTALL)) {
+                       spip_log("Aucune connexion sqlite (link)", 'sqlite.' . _LOG_ERREUR);
+
                        return false;
                }
 
@@ -2144,30 +2908,34 @@ class sqlite_requeteur {
        }
 
        /**
-        * lancer la requete $query,
-        * faire le tracage si demande
-        * http://doc.spip.org/@executer_requete
+        * Lancer la requête transmise et faire le tracage si demandé
         *
+        * @param string $query
+        *     Requête à exécuter
+        * @param bool|null $tracer
+        *     true pour tracer la requête
         * @return bool|SQLiteResult
         */
-       function executer_requete($query, $tracer=null){
-               if (is_null($tracer))
+       public function executer_requete($query, $tracer = null) {
+               if (is_null($tracer)) {
                        $tracer = $this->tracer;
+               }
                $err = "";
                $t = 0;
-               if ($tracer){
+               if ($tracer) {
                        include_spip('public/tracer');
                        $t = trace_query_start();
                }
-               
+
                # spip_log("requete: $this->serveur >> $query",'sqlite.'._LOG_DEBUG); // boum ? pourquoi ?
-               if ($this->link){
+               if ($this->link) {
                        // memoriser la derniere erreur PHP vue
-                       $e = (function_exists('error_get_last')?error_get_last():"");
+                       $e = (function_exists('error_get_last') ? error_get_last() : "");
                        // sauver la derniere requete
                        $GLOBALS['connexions'][$this->serveur ? $this->serveur : 0]['last'] = $query;
+                       $GLOBALS['connexions'][$this->serveur ? $this->serveur : 0]['total_requetes']++;
 
-                       if ($this->sqlite_version==3){
+                       if ($this->sqlite_version == 3) {
                                $r = $this->link->query($query);
                                // sauvegarde de la requete (elle y est deja dans $r->queryString)
                                # $r->spipQueryString = $query;
@@ -2176,42 +2944,48 @@ class sqlite_requeteur {
                                // par une requete SELECT
                                // aucune autre solution ne donne le nombre attendu :( !
                                // particulierement s'il y a des LIMIT dans la requete.
-                               if (strtoupper(substr(ltrim($query), 0, 6))=='SELECT'){
-                                       if ($r){
+                               if (strtoupper(substr(ltrim($query), 0, 6)) == 'SELECT') {
+                                       if ($r) {
                                                // noter le link et la query pour faire le comptage *si* on en a besoin
-                                               $r->spipSqliteRowCount = array($this->link,$query);
-                                       }
-                                       elseif ($r instanceof PDOStatement) {
+                                               $r->spipSqliteRowCount = array($this->link, $query);
+                                       } elseif ($r instanceof PDOStatement) {
                                                $r->spipSqliteRowCount = 0;
                                        }
                                }
-                       }
-                       else {
+                       } else {
                                $r = sqlite_query($this->link, $query);
                        }
 
                        // loger les warnings/erreurs eventuels de sqlite remontant dans PHP
-                       if ($err = (function_exists('error_get_last')?error_get_last():"") AND $err!=$e){
-                               $err = strip_tags($err['message'])." in ".$err['file']." line ".$err['line'];
-                               spip_log("$err - ".$query, 'sqlite.'._LOG_ERREUR);
+                       if ($err = (function_exists('error_get_last') ? error_get_last() : "") and $err != $e) {
+                               $err = strip_tags($err['message']) . " in " . $err['file'] . " line " . $err['line'];
+                               spip_log("$err - " . $query, 'sqlite.' . _LOG_ERREUR);
+                       } else {
+                               $err = "";
                        }
-                       else $err = "";
 
-               }
-               else {
+               } else {
                        $r = false;
                }
 
-               if (spip_sqlite_errno($this->serveur))
+               if (spip_sqlite_errno($this->serveur)) {
                        $err .= spip_sqlite_error($query, $this->serveur);
+               }
+
                return $t ? trace_query_end($query, $t, $r, $err, $this->serveur) : $r;
        }
 
-       function last_insert_id(){
-               if ($this->sqlite_version==3)
+       /**
+        * Obtient l'identifiant de la dernière ligne insérée ou modifiée
+        *
+        * @return int
+        **/
+       public function last_insert_id() {
+               if ($this->sqlite_version == 3) {
                        return $this->link->lastInsertId();
-               else
+               } else {
                        return sqlite_last_insert_rowid($this->link);
+               }
        }
 }
 
@@ -2222,29 +2996,40 @@ class sqlite_requeteur {
  * (fonction pour proteger les textes)
  */
 class sqlite_traducteur {
-       var $query = '';
-       var $prefixe = ''; // le prefixe des tables
-       var $sqlite_version = ''; // Version de sqlite (2 ou 3)
-       
-       // Pour les corrections a effectuer sur les requetes :
-       var $textes = array(); // array(code=>'texte') trouvé
-
-       function sqlite_traducteur($query, $prefixe, $sqlite_version){
+       /** @var string $query Texte de la requête */
+       public $query = '';
+       /** @var string $prefixe Préfixe des tables */
+       public $prefixe = '';
+       /** @var string $sqlite_version Version de sqlite (2 ou 3) */
+       public $sqlite_version = '';
+
+       /** Pour les corrections à effectuer sur les requêtes : array(code=>'texte') trouvé
+        *
+        * @var array
+        */
+       public $textes = array();
+
+       /**
+        * Constructeur
+        *
+        * @param string $query Requête à préparer
+        * @param string $prefixe Prefixe des tables à utiliser
+        * @param string $sqlite_version Version SQLite (2 ou 3)
+        */
+       public function __construct($query, $prefixe, $sqlite_version) {
                $this->query = $query;
                $this->prefixe = $prefixe;
                $this->sqlite_version = $sqlite_version;
        }
 
        /**
-        * transformer la requete pour sqlite
-        * enleve les textes, transforme la requete pour quelle soit
-        * bien interpretee par sqlite, puis remet les textes
-        * la fonction affecte $this->query
-        * http://doc.spip.org/@traduire_requete
+        * Transformer la requete pour SQLite
         *
-        * @return void
+        * Enlève les textes, transforme la requête pour quelle soit
+        * bien interprétée par SQLite, puis remet les textes
+        * la fonction affecte `$this->query`
         */
-       function traduire_requete(){
+       public function traduire_requete() {
                //
                // 1) Protection des textes en les remplacant par des codes
                //
@@ -2256,61 +3041,62 @@ class sqlite_traducteur {
                //
                // Correction Create Database
                // Create Database -> requete ignoree
-               if (strpos($this->query, 'CREATE DATABASE')===0){
-                       spip_log("Sqlite : requete non executee -> $this->query", 'sqlite.'._LOG_AVERTISSEMENT);
+               if (strpos($this->query, 'CREATE DATABASE') === 0) {
+                       spip_log("Sqlite : requete non executee -> $this->query", 'sqlite.' . _LOG_AVERTISSEMENT);
                        $this->query = "SELECT 1";
                }
 
                // Correction Insert Ignore
                // INSERT IGNORE -> insert (tout court et pas 'insert or replace')
-               if (strpos($this->query, 'INSERT IGNORE')===0){
-                       spip_log("Sqlite : requete transformee -> $this->query", 'sqlite.'._LOG_DEBUG);
-                       $this->query = 'INSERT '.substr($this->query, '13');
+               if (strpos($this->query, 'INSERT IGNORE') === 0) {
+                       spip_log("Sqlite : requete transformee -> $this->query", 'sqlite.' . _LOG_DEBUG);
+                       $this->query = 'INSERT ' . substr($this->query, '13');
                }
 
                // Correction des dates avec INTERVAL
                // utiliser sql_date_proche() de preference
-               if (strpos($this->query, 'INTERVAL')!==false){
+               if (strpos($this->query, 'INTERVAL') !== false) {
                        $this->query = preg_replace_callback("/DATE_(ADD|SUB)(.*)INTERVAL\s+(\d+)\s+([a-zA-Z]+)\)/U",
-                                                            array(&$this, '_remplacerDateParTime'),
-                                                            $this->query);
+                               array(&$this, '_remplacerDateParTime'),
+                               $this->query);
                }
 
-               if (strpos($this->query, 'LEFT(')!==false){
-                       $this->query = str_replace('LEFT(','_LEFT(',$this->query);
+               if (strpos($this->query, 'LEFT(') !== false) {
+                       $this->query = str_replace('LEFT(', '_LEFT(', $this->query);
                }
 
-               if (strpos($this->query, 'TIMESTAMPDIFF(')!==false){
-                       $this->query = preg_replace('/TIMESTAMPDIFF\(\s*([^,]*)\s*,/Uims',"TIMESTAMPDIFF('\\1',",$this->query);
+               if (strpos($this->query, 'TIMESTAMPDIFF(') !== false) {
+                       $this->query = preg_replace('/TIMESTAMPDIFF\(\s*([^,]*)\s*,/Uims', "TIMESTAMPDIFF('\\1',", $this->query);
                }
 
 
                // Correction Using
                // USING (non reconnu en sqlite2)
                // problematique car la jointure ne se fait pas du coup.
-               if (($this->sqlite_version==2) && (strpos($this->query, "USING")!==false)){
-                       spip_log("'USING (champ)' n'est pas reconnu en SQLite 2. Utilisez 'ON table1.champ = table2.champ'", 'sqlite.'._LOG_ERREUR);
+               if (($this->sqlite_version == 2) && (strpos($this->query, "USING") !== false)) {
+                       spip_log("'USING (champ)' n'est pas reconnu en SQLite 2. Utilisez 'ON table1.champ = table2.champ'",
+                               'sqlite.' . _LOG_ERREUR);
                        $this->query = preg_replace('/USING\s*\([^\)]*\)/', '', $this->query);
                }
 
                // Correction Field
                // remplace FIELD(table,i,j,k...) par CASE WHEN table=i THEN n ... ELSE 0 END
-               if (strpos($this->query, 'FIELD')!==false){
+               if (strpos($this->query, 'FIELD') !== false) {
                        $this->query = preg_replace_callback('/FIELD\s*\(([^\)]*)\)/',
-                                                            array(&$this, '_remplacerFieldParCase'),
-                                                            $this->query);
+                               array(&$this, '_remplacerFieldParCase'),
+                               $this->query);
                }
 
                // Correction des noms de tables FROM
                // mettre les bons noms de table dans from, update, insert, replace...
-               if (preg_match('/\s(SET|VALUES|WHERE|DATABASE)\s/iS', $this->query, $regs)){
+               if (preg_match('/\s(SET|VALUES|WHERE|DATABASE)\s/iS', $this->query, $regs)) {
                        $suite = strstr($this->query, $regs[0]);
                        $this->query = substr($this->query, 0, -strlen($suite));
-               }
-               else
+               } else {
                        $suite = '';
-               $pref = ($this->prefixe) ? $this->prefixe."_" : "";
-               $this->query = preg_replace('/([,\s])spip_/S', '\1'.$pref, $this->query).$suite;
+               }
+               $pref = ($this->prefixe) ? $this->prefixe . "_" : "";
+               $this->query = preg_replace('/([,\s])spip_/S', '\1' . $pref, $this->query) . $suite;
 
                // Correction zero AS x
                // pg n'aime pas 0+x AS alias, sqlite, dans le meme style, 
@@ -2319,16 +3105,16 @@ class sqlite_traducteur {
                // on remplace du coup x par vide() dans ce cas uniquement
                //
                // rien que pour public/vertebrer.php ?
-               if ((strpos($this->query, "0 AS")!==false)){
+               if ((strpos($this->query, "0 AS") !== false)) {
                        // on ne remplace que dans ORDER BY ou GROUP BY
-                       if (preg_match('/\s(ORDER|GROUP) BY\s/i', $this->query, $regs)){
+                       if (preg_match('/\s(ORDER|GROUP) BY\s/i', $this->query, $regs)) {
                                $suite = strstr($this->query, $regs[0]);
                                $this->query = substr($this->query, 0, -strlen($suite));
 
                                // on cherche les noms des x dans 0 AS x
                                // on remplace dans $suite le nom par vide()
                                preg_match_all('/\b0 AS\s*([^\s,]+)/', $this->query, $matches, PREG_PATTERN_ORDER);
-                               foreach ($matches[1] as $m){
+                               foreach ($matches[1] as $m) {
                                        $suite = str_replace($m, 'VIDE()', $suite);
                                }
                                $this->query .= $suite;
@@ -2350,7 +3136,7 @@ class sqlite_traducteur {
 
 
                // Correction critere REGEXP, non reconnu en sqlite2
-               if (($this->sqlite_version==2) && (strpos($this->query, 'REGEXP')!==false)){
+               if (($this->sqlite_version == 2) && (strpos($this->query, 'REGEXP') !== false)) {
                        $this->query = preg_replace('/([^\s\(]*)(\s*)REGEXP(\s*)([^\s\)]*)/', 'REGEXP($4, $1)', $this->query);
                }
 
@@ -2359,8 +3145,9 @@ class sqlite_traducteur {
                //
                // Correction Antiquotes et echappements
                // ` => rien
-               if (strpos($this->query,'`')!==false)
-                       $this->query = str_replace('`','', $this->query);
+               if (strpos($this->query, '`') !== false) {
+                       $this->query = str_replace('`', '', $this->query);
+               }
 
                $this->query = query_reinjecte_textes($this->query, $textes);
 
@@ -2369,39 +3156,38 @@ class sqlite_traducteur {
 
 
        /**
-        * les callbacks
-        * remplacer DATE_ / INTERVAL par DATE...strtotime
-        * http://doc.spip.org/@_remplacerDateParTime
+        * Callback pour remplacer `DATE_` / `INTERVAL`
+        * par `DATE ... strtotime`
         *
-        * @param  $matches
-        * @return string
+        * @param array $matches Captures
+        * @return string Texte de date compris par SQLite
         */
-       function _remplacerDateParTime($matches){
-               $op = strtoupper($matches[1]=='ADD') ? '+' : '-';
+       public function _remplacerDateParTime($matches) {
+               $op = strtoupper($matches[1] == 'ADD') ? '+' : '-';
+
                return "datetime$matches[2] '$op$matches[3] $matches[4]')";
        }
 
        /**
-        * callback ou l'on remplace FIELD(table,i,j,k...) par CASE WHEN table=i THEN n ... ELSE 0 END
-        * http://doc.spip.org/@_remplacerFieldParCase
+        * Callback pour remplacer `FIELD(table,i,j,k...)`
+        * par `CASE WHEN table=i THEN n ... ELSE 0 END`
         *
-        * @param  $matches
-        * @return string
+        * @param array $matches Captures
+        * @return string Texte de liste ordonnée compris par SQLite
         */
-       function _remplacerFieldParCase($matches){
+       public function _remplacerFieldParCase($matches) {
                $fields = substr($matches[0], 6, -1); // ne recuperer que l'interieur X de field(X)
                $t = explode(',', $fields);
                $index = array_shift($t);
 
                $res = '';
                $n = 0;
-               foreach ($t as $v){
+               foreach ($t as $v) {
                        $n++;
                        $res .= "\nWHEN $index=$v THEN $n";
                }
+
                return "CASE $res ELSE 0 END ";
        }
 
 }
-
-?>