Completed
Push — spip-2.1 ( b6b097 )
by cam
42:28 queued 30:44
created

sqlite_generique.php ➔ _sqlite_modifier_table()   F

Complexity

Conditions 21
Paths > 20000

Size

Total Lines 137
Code Lines 78

Duplication

Lines 6
Ratio 4.38 %

Importance

Changes 0
Metric Value
cc 21
eloc 78
nc 41472
nop 4
dl 6
loc 137
rs 2
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/***************************************************************************\
4
 *  SPIP, Systeme de publication pour l'internet                           *
5
 *                                                                         *
6
 *  Copyright (c) 2001-2016                                                *
7
 *  Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James  *
8
 *                                                                         *
9
 *  Ce programme est un logiciel libre distribue sous licence GNU/GPL.     *
10
 *  Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne.   *
11
\***************************************************************************/
12
13
if (!defined('_ECRIRE_INC_VERSION')) return;
14
15
// infos :
16
// il ne faut pas avoir de PDO::CONSTANTE dans ce fichier sinon php4 se tue !
17
// idem, il ne faut pas de $obj->toto()->toto sinon php4 se tue !
18
19
# todo : get/set_caracteres ?
20
21
22
/*
23
 * 
24
 * regroupe le maximum de fonctions qui peuvent cohabiter
25
 * D'abord les fonctions d'abstractions de SPIP
26
 * 
27
 */
28
// http://doc.spip.org/@req_sqlite_dist
29
function req_sqlite_dist($addr, $port, $login, $pass, $db='', $prefixe='', $sqlite_version=''){
30
	static $last_connect = array();
31
32
	// si provient de selectdb
33
	// un code pour etre sur que l'on vient de select_db()
34
	if (strpos($db, $code = '@selectdb@')!==false) {
35 View Code Duplication
		foreach (array('addr','port','login','pass','prefixe') as $a){
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
36
			$$a = $last_connect[$a];
37
		}
38
		$db = str_replace($code, '', $db);
39
	}
40
41
	/*
42
	 * En sqlite, seule l'adresse du fichier est importante.
43
	 * Ce sera $db le nom, et le path _DIR_DB
44
	 */
45
	_sqlite_init();
46
47
	// un nom de base demande et impossible d'obtenir la base, on s'en va
48
	if ($db && !is_file($f = _DIR_DB . $db . '.sqlite') && !is_writable(_DIR_DB))
49
			return false;
50
51
	
52
	// charger les modules sqlite au besoin
53
	if (!_sqlite_charger_version($sqlite_version)) {
54
		spip_log("Impossible de trouver/charger le module SQLite ($sqlite_version)!");
55
		return false;
56
	}
57
58
	// chargement des constantes
59
	// il ne faut pas definir les constantes avant d'avoir charge les modules sqlite
60
	$define = "spip_sqlite".$sqlite_version."_constantes";
61
	$define();
62
	
63
	$ok = false;
0 ignored issues
show
Unused Code introduced by
$ok is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
64
	if (!$db){
65
		// si installation -> base temporaire tant qu'on ne connait pas son vrai nom
66
		if (defined('_ECRIRE_INSTALL') && _ECRIRE_INSTALL){
67
			// creation d'une base temporaire pour le debut d'install
68
			$db = "_sqlite".$sqlite_version."_install";	
69
			$tmp = _DIR_DB . $db . ".sqlite";
70 View Code Duplication
			if ($sqlite_version == 3) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
71
				$ok = $link = new PDO("sqlite:$tmp");
72
			} else {
73
				$ok = $link = sqlite_open($tmp, _SQLITE_CHMOD, $err);
74
			}
75
		// sinon, on arrete finalement
76
		} else {
77
			return false;
78
		}
79 View Code Duplication
	} else {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
80
		// Ouvrir (eventuellement creer la base)
81
		// si pas de version fourni, on essaie la 3, sinon la 2
82
		if ($sqlite_version == 3) {
83
			$ok = $link = new PDO("sqlite:$f");
0 ignored issues
show
Bug introduced by
The variable $f does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
84
		} else {
85
			$ok = $link = sqlite_open($f, _SQLITE_CHMOD, $err);
86
		}
87
	}
88
89
	if (!$ok){
90
		spip_log("Impossible d'ouvrir la base de donnee SQLite ($sqlite_version) : $f ");
91
		return false;
92
	}
93
	
94 View Code Duplication
	if ($link) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
95
		$last_connect = array (
96
			'addr' => $addr,
97
			'port' => $port,
98
			'login' => $login,
99
			'pass' => $pass,
100
			'db' => $db,
101
			'prefixe' => $prefixe,
102
		);
103
	}
104
105
	return array(
106
		'db' => $db,
107
		'prefixe' => $prefixe ? $prefixe : $db,
108
		'link' => $link,
109
		);	
110
}
111
112
113
114
// Fonction de requete generale, munie d'une trace a la demande
115
// http://doc.spip.org/@spip_sqlite_query
116
function spip_sqlite_query($query, $serveur='',$requeter=true) {
117
#spip_log("spip_sqlite_query() > $query");
118
	_sqlite_init();
119
	
120
	$requete = new sqlite_traiter_requete($query, $serveur);
121
	$requete->traduire_requete(); // mysql -> sqlite
122
	if (!$requeter) return $requete->query;
123
	return $requete->executer_requete();
124
}
125
126
127
/* ordre alphabetique pour les autres */
128
129
// http://doc.spip.org/@spip_sqlite_alter
130
function spip_sqlite_alter($query, $serveur='',$requeter=true){
0 ignored issues
show
Unused Code introduced by
The parameter $requeter is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
131
132
	$query = spip_sqlite_query("ALTER $query",$serveur,false);
133
	
134
	/* 
135
	 * la il faut faire les transformations
136
	 * si ALTER TABLE x (DROP|CHANGE) y
137
	 * 
138
	 * 1) recuperer "ALTER TABLE table "
139
	 * 2) spliter les sous requetes (,)
140
	 * 3) faire chaque requete independemment
141
	 */
142
	
143
	// 1
144
	if (preg_match("/\s*(ALTER(\s*IGNORE)?\s*TABLE\s*([^\s]*))\s*(.*)?/is", $query, $regs)){
145
		$debut = $regs[1];
146
		$table = $regs[3];
147
		$suite = $regs[4];
148
	} else {
149
		spip_log("SQLite : Probleme de ALTER TABLE mal forme dans $query", 'sqlite');
150
		return false;
151
	}
152
153
	// 2
154
	// il faudrait une regexp pour eviter de spliter ADD PRIMARY KEY (colA, colB)
155
	// tout en cassant "ADD PRIMARY KEY (colA, colB), ADD INDEX (chose)"... en deux
156
	// ou revoir l'api de sql_alter en creant un 
157
	// sql_alter_table($table,array($actions));
158
	$todo = explode(',', $suite);
159
160
	// on remet les morceaux dechires ensembles... que c'est laid !
161
	$todo2 = array(); $i=0;
162
	$ouverte = false;
163 View Code Duplication
	while ($do = array_shift($todo)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
164
		$todo2[$i] = isset($todo2[$i]) ? $todo2[$i] . "," . $do : $do;
165
		$o=(false!==strpos($do,"("));
166
		$f=(false!==strpos($do,")"));
167
		if ($o AND !$f) $ouverte=true;
168
		elseif ($f) $ouverte=false;
169
		if (!$ouverte) $i++;
170
	}
171
	
172
	// 3	
173
	$resultats = array();
0 ignored issues
show
Unused Code introduced by
$resultats is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
174
	foreach ($todo2 as $do){
175
		$do = trim($do);
176
		if (!preg_match('/(DROP PRIMARY KEY|DROP INDEX|DROP COLUMN|DROP'
177
				.'|CHANGE COLUMN|CHANGE|MODIFY|RENAME TO|RENAME'
178
				.'|ADD PRIMARY KEY|ADD INDEX|ADD COLUMN|ADD'
179
				.')\s*([^\s]*)\s*(.*)?/', $do, $matches)){
180
			spip_log("SQLite : Probleme de ALTER TABLE, utilisation non reconnue dans : $do \n(requete d'origine : $query)", 'sqlite');
181
			return false;
182
		}
183
184
		$cle = strtoupper($matches[1]);
185
		$colonne_origine = $matches[2];
186
		$colonne_destination = '';
0 ignored issues
show
Unused Code introduced by
$colonne_destination is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
187
188
		$def = $matches[3];
189
190
		// eluder une eventuelle clause before|after|first inutilisable
191
		$defr = rtrim(preg_replace('/(BEFORE|AFTER|FIRST)(.*)$/is','', $def));
192
		// remplacer les definitions venant de mysql
193
		$defr = _sqlite_remplacements_definitions_table($defr);
194
195
		// reinjecter dans le do
196
		$do = str_replace($def,$defr,$do);
197
		$def = $defr;
198
		
199
		switch($cle){
200
			// suppression d'un index
201
			case 'DROP INDEX':
202
				$nom_index = $colonne_origine;
203
				spip_sqlite_drop_index($nom_index, $table, $serveur);
204
				break;
205
			
206
			// suppression d'une pk
207 View Code Duplication
			case 'DROP PRIMARY KEY':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
208
				if (!_sqlite_modifier_table(
209
					$table, 
210
					$colonne_origine, 
211
					array('key'=>array('PRIMARY KEY'=>'')), 
212
					$serveur)){
213
						return false;
214
				}
215
				break;
216
			// suppression d'une colonne
217
			case 'DROP COLUMN':
218 View Code Duplication
			case 'DROP':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
219
				if (!_sqlite_modifier_table(
220
					$table, 
221
					array($colonne_origine=>""), 
222
					'', 
223
					$serveur)){
224
						return false;
225
				}
226
				break;
227
			
228
			case 'CHANGE COLUMN':
229
			case 'CHANGE':
230
				// recuperer le nom de la future colonne 
231
				$def = trim($def);
232
				$colonne_destination = substr($def, 0, strpos($def,' '));
233
				$def = substr($def, strlen($colonne_destination)+1);
234
				
235
				if (!_sqlite_modifier_table(
236
					$table, 
237
					array($colonne_origine=>$colonne_destination), 
238
					array('field'=>array($colonne_destination=>$def)), 
239
					$serveur)){
240
						return false;
241
				}
242
				break;
243
				
244 View Code Duplication
			case 'MODIFY':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
245
				if (!_sqlite_modifier_table(
246
					$table, 
247
					$colonne_origine, 
248
					array('field'=>array($colonne_origine=>$def)), 
249
					$serveur)){
250
						return false;
251
				}
252
				break;
253
			
254
			// pas geres en sqlite2
255
			case 'RENAME':
256
					$do = "RENAME TO" . substr($do,6);
257
			case 'RENAME TO':
258
				if (_sqlite_is_version(3, '', $serveur)){
259
					$requete = new sqlite_traiter_requete("$debut $do", $serveur);
260
					if (!$requete->executer_requete()){
261
						spip_log("SQLite : Erreur ALTER TABLE / RENAME : $query", 'sqlite');
262
						return false;
263
					}
264
				// artillerie lourde pour sqlite2 !
265
				} else {
266
					$table_dest = trim(substr($do, 9));
267
					if (!_sqlite_modifier_table(array($table=>$table_dest), '', '', $serveur)){
268
						spip_log("SQLite : Erreur ALTER TABLE / RENAME : $query", 'sqlite');
269
						return false;
270
					}
271
				}
272
				break;
273
274
			// ajout d'une pk
275
			case 'ADD PRIMARY KEY':
276
				$pk = trim(substr($do,16));
277
				$pk = ($pk[0]=='(') ? substr($pk,1,-1) : $pk;
278
				if (!_sqlite_modifier_table(
279
					$table, 
280
					$colonne_origine, 
281
					array('key'=>array('PRIMARY KEY'=>$pk)), 
282
					$serveur)){
283
						return false;
284
				}
285
				break;			
286
			// ajout d'un index
287
			case 'ADD INDEX':
288
				// peut etre "(colonne)" ou "nom_index (colonnes)"
289
				// bug potentiel si qqn met "(colonne, colonne)"
290
				//
291
				// nom_index (colonnes)
292
				if ($def) {
293
					$colonnes = substr($def,1,-1);
294
					$nom_index = $colonne_origine;
295
				}
296
				else {
297
					// (colonne)
298
					if ($colonne_origine[0] == "(") {
299
						$colonnes = substr($colonne_origine,1,-1);
300 View Code Duplication
						if (false!==strpos(",",$colonnes)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
301
							spip_log("SQLite : Erreur, impossible de creer un index sur plusieurs colonnes"
302
							 	." sans qu'il ait de nom ($table, ($colonnes))", 'sqlite');	
303
							break;
304
						} else {
305
							$nom_index = $colonnes;
306
						}
307
					}
308
					// nom_index
309
					else {
310
						$nom_index = $colonnes = $colonne_origine ;
311
					}
312
				}
313
				spip_sqlite_create_index($nom_index, $table, $colonnes, $serveur);
314
				break;
315
				
316
			// pas geres en sqlite2
317
			case 'ADD COLUMN':
318
					$do = "ADD".substr($do, 10);
319
			case 'ADD':
320
			default:
321
				if (_sqlite_is_version(3, '', $serveur)){
322
					$requete = new sqlite_traiter_requete("$debut $do", $serveur);
323
					if (!$requete->executer_requete()){
324
						spip_log("SQLite : Erreur ALTER TABLE / ADD : $query", 'sqlite');
325
						return false;
326
					}
327
					break;
328
				// artillerie lourde pour sqlite2 !
329
				} else {
330
					$def = trim(substr($do, 3));
331
					$colonne_ajoutee = substr($def, 0, strpos($def,' '));
332
					$def = substr($def, strlen($colonne_ajoutee)+1);
333
					if (!_sqlite_modifier_table($table, array($colonne_ajoutee), array('field'=>array($colonne_ajoutee=>$def)), $serveur)){
334
						spip_log("SQLite : Erreur ALTER TABLE / ADD : $query", 'sqlite');
335
						return false;
336
					}
337
				}
338
				break;
339
		}
340
		// tout est bon, ouf !
341
		spip_log("SQLite ($serveur) : Changements OK : $debut $do");
342
	}
343
344
	spip_log("SQLite ($serveur) : fin ALTER TABLE OK !");
345
	return true;
346
}
347
348
349
// Fonction de creation d'une table SQL nommee $nom
350
// http://doc.spip.org/@spip_sqlite_create
351
function spip_sqlite_create($nom, $champs, $cles, $autoinc=false, $temporary=false, $serveur='',$requeter=true) {
352
	$query = _sqlite_requete_create($nom, $champs, $cles, $autoinc, $temporary, $ifnotexists=true, $serveur, $requeter);
353
	if (!$query) return false;
354
	$res = spip_sqlite_query($query, $serveur, $requeter);
355
	
356
	// SQLite ne cree pas les KEY sur les requetes CREATE TABLE
357
	// il faut donc les faire creer ensuite
358
	if (!$requeter) return $res;
359
360
	$ok = $res ? true : false;
361
	if ($ok) {
362
		foreach($cles as $k=>$v) {
363
			if (strpos($k, "KEY ") === 0) {
364
				$index = preg_replace("/KEY +/", '',$k);
365
				$ok &= $res = spip_sqlite_create_index($index, $nom, $v, $serveur);
0 ignored issues
show
Unused Code introduced by
$res is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
366
			}
367
		}
368
	}
369
	return $ok ? true : false;
370
}
371
372
/**
373
 * Fonction pour creer une base de donnees SQLite
374
 *
375
 * @param string $nom le nom de la base (sans l'extension de fichier)
376
 * @param string $serveur le nom de la connexion
377
 * @param string $option options
0 ignored issues
show
Documentation introduced by
Should the type for parameter $option not be boolean|string?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
378
 * 
379
 * @return bool true si la base est creee.
380
**/
381
function spip_sqlite_create_base($nom, $serveur='', $option=true) {
0 ignored issues
show
Unused Code introduced by
The parameter $option is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
382
	$f = _DIR_DB . $nom . '.sqlite';
383
	if (_sqlite_is_version(2, '', $serveur)) {
384
		$ok = sqlite_open($f, _SQLITE_CHMOD, $err);
385
	} else {
386
		$ok = new PDO("sqlite:$f");
387
	}
388
	if ($ok) {
389
		unset($ok);
390
		return true;
391
	}
392
	unset($ok);
393
	return false;
394
}
395
396
397
// Fonction de creation d'une vue SQL nommee $nom
398
// http://doc.spip.org/@spip_sqlite_create_view
399 View Code Duplication
function spip_sqlite_create_view($nom, $query_select, $serveur='',$requeter=true) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
400
	if (!$query_select) return false;
401
	// vue deja presente
402
	if (sql_showtable($nom, false, $serveur)) {
403
		spip_log("Echec creation d'une vue sql ($nom) car celle-ci existe deja (serveur:$serveur)");
404
		return false;
405
	}
406
	
407
	$query = "CREATE VIEW $nom AS ". $query_select;
408
	return spip_sqlite_query($query, $serveur, $requeter);
409
}
410
411
/**
412
 * Fonction de creation d'un INDEX
413
 * 
414
 * @param string $nom : nom de l'index
415
 * @param string $table : table sql de l'index
416
 * @param string/array $champs : liste de champs sur lesquels s'applique l'index
0 ignored issues
show
Documentation introduced by
The doc-type string/array could not be parsed: Unknown type name "string/array" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
417
 * @param string $serveur : nom de la connexion sql utilisee
418
 * @param bool $requeter : true pour executer la requete ou false pour retourner le texte de la requete
419
 * 
420
 * @return bool ou requete
421
 */
422
function spip_sqlite_create_index($nom, $table, $champs, $serveur='', $requeter=true) {
423 View Code Duplication
	if (!($nom OR $table OR $champs)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
424
		spip_log("Champ manquant pour creer un index sqlite ($nom, $table, (".join(',',$champs)."))");
425
		return false;
426
	}
427
	
428
	// SQLite ne differentie pas noms des index en fonction des tables
429
	// il faut donc creer des noms uniques d'index pour une base sqlite
430
	$nom = $table.'_'.$nom;
431
	// enlever d'eventuelles parentheses deja presentes sur champs
432 View Code Duplication
	if (!is_array($champs)){
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
433
		 if ($champs[0]=="(") $champs = substr($champs,1,-1);
434
		 $champs = array($champs);
435
	}
436
	$query = "CREATE INDEX $nom ON $table (" . join(',',$champs) . ")";
437
	$res = spip_sqlite_query($query, $serveur, $requeter);
438
	if (!$requeter) return $res;
439
	if ($res)
0 ignored issues
show
Coding Style introduced by
The if-else statement can be simplified to return (bool) $res;.
Loading history...
440
		return true;
441
	else
442
		return false;
443
}
444
445
// en PDO/sqlite3, il faut calculer le count par une requete count(*)
446
// pour les resultats de SELECT
447
// cela est fait sans spip_sqlite_query()
448
// http://doc.spip.org/@spip_sqlite_count
449
function spip_sqlite_count($r, $serveur='',$requeter=true) {
0 ignored issues
show
Unused Code introduced by
The parameter $requeter is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
450
	if (!$r) return 0;
451
		
452
	if (_sqlite_is_version(3, '', $serveur)){
453
		// select ou autre (insert, update,...) ?
454
		if (isset($r->spipSqliteRowCount)) {
455
			// Ce compte est faux s'il y a des limit dans la requete :(
456
			// il retourne le nombre d'enregistrements sans le limit
457
			return $r->spipSqliteRowCount;
458
		} else {
459
			return $r->rowCount();
460
		}
461
	} else {
462
		return sqlite_num_rows($r);
463
	}
464
}
465
466
467
// http://doc.spip.org/@spip_sqlite_countsel
468
function spip_sqlite_countsel($from = array(), $where = array(), $groupby = '', $having = array(), $serveur='',$requeter=true) {
469
	$c = !$groupby ? '*' : ('DISTINCT ' . (is_string($groupby) ? $groupby : join(',', $groupby)));
470
	$r = spip_sqlite_select("COUNT($c)", $from, $where,'', '', '',$having, $serveur, $requeter);
471
	if ((is_resource($r) or is_object($r)) && $requeter) { // ressource : sqlite2, object : sqlite3
472
		if (_sqlite_is_version(3,'',$serveur)){
473
			list($n) = spip_sqlite_fetch($r, SPIP_SQLITE3_NUM, $serveur);
474
		} else {
475
			list($n) = spip_sqlite_fetch($r, SPIP_SQLITE2_NUM, $serveur);
476
		}
477
		spip_sqlite_free($r,$serveur);
478
	}
479
	return $n;
0 ignored issues
show
Bug introduced by
The variable $n does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
480
}
481
482
483
484
// http://doc.spip.org/@spip_sqlite_delete
485
function spip_sqlite_delete($table, $where='', $serveur='',$requeter=true) {
486
	$res = spip_sqlite_query(
487
			  _sqlite_calculer_expression('DELETE FROM', $table, ',')
488
			. _sqlite_calculer_expression('WHERE', $where),
489
			$serveur, $requeter);
490
491
	// renvoyer la requete inerte si demandee
492
	if (!$requeter) return $res;
493
	
494
  if ($res){
495
	  $link  = _sqlite_link($serveur);
496
	  if (_sqlite_is_version(3, $link)) {
497
		  return $res->rowCount();
498
	  } else {
499
		  return sqlite_changes($link);
500
	  }
501
  }
502
  else
503
	  return false;
504
}
505
506
507
// http://doc.spip.org/@spip_sqlite_drop_table
508
function spip_sqlite_drop_table($table, $exist='', $serveur='',$requeter=true) {
509
	if ($exist) $exist =" IF EXISTS";
510
	
511
	/* simuler le IF EXISTS - version 2 */
512 View Code Duplication
	if ($exist && _sqlite_is_version(2, '', $serveur)){
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
513
		$a = spip_sqlite_showtable($table, $serveur); 
514
		if (!$a) return true;
515
		$exist = '';
516
	}
517
	if (spip_sqlite_query("DROP TABLE$exist $table", $serveur, $requeter))
0 ignored issues
show
Coding Style introduced by
The if-else statement can be simplified to return (bool) spip_sqlit..., $serveur, $requeter);.
Loading history...
518
		return true;
519
	else 
520
		return false;
521
}
522
523
// supprime une vue 
524
// http://doc.spip.org/@spip_sqlite_drop_view
525
function spip_sqlite_drop_view($view, $exist='', $serveur='',$requeter=true) {
526
	if ($exist) $exist =" IF EXISTS";
527
	
528
	/* simuler le IF EXISTS - version 2 */
529 View Code Duplication
	if ($exist && _sqlite_is_version(2, '', $serveur)){
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
530
		$a = spip_sqlite_showtable($view, $serveur); 
531
		if (!$a) return true;
532
		$exist = '';
533
	}
534
	
535
	return spip_sqlite_query("DROP VIEW$exist $view", $serveur, $requeter);
536
}
537
538
/**
539
 * Fonction de suppression d'un INDEX
540
 * 
541
 * @param string $nom : nom de l'index
542
 * @param string $table : table sql de l'index
543
 * @param string $serveur : nom de la connexion sql utilisee
544
 * @param bool $requeter : true pour executer la requete ou false pour retourner le texte de la requete
545
 * 
546
 * @return bool ou requete
547
 */
548
function spip_sqlite_drop_index($nom, $table, $serveur='', $requeter=true) {
549
	if (!($nom OR $table)) {
550
		spip_log("Champ manquant pour supprimer un index sqlite ($nom, $table)");
551
		return false;
552
	}
553
	
554
	// SQLite ne differentie pas noms des index en fonction des tables
555
	// il faut donc creer des noms uniques d'index pour une base sqlite
556
	$index = $table.'_'.$nom;
557
	$exist =" IF EXISTS";
558
	
559
	/* simuler le IF EXISTS - version 2 */
560
	if (_sqlite_is_version(2, '', $serveur)){
561
		$a = spip_sqlite_showtable($table, $serveur); 
562
		if (!isset($a['key']['KEY '.$nom])) return true;
563
		$exist = '';
564
	}
565
	
566
	$query = "DROP INDEX$exist $index";
567
	return spip_sqlite_query($query, $serveur, $requeter);
568
}
569
570
/**
571
 * Retourne la derniere erreur generee
572
 *
573
 * @param $serveur nom de la connexion
574
 * @return string erreur eventuelle
575
**/
576
// http://doc.spip.org/@spip_sqlite_error
577
function spip_sqlite_error($query='', $serveur='') {
578
	$link  = _sqlite_link($serveur);
579
	
580
	if (_sqlite_is_version(3, $link)) {
581
		$errs = $link->errorInfo();
582
		$s = '';
583
		foreach($errs as $n=>$e){
584
			$s .= "\n$n : $e";
585
		}
586
	} elseif ($link) {
587
		$s = sqlite_error_string(sqlite_last_error($link));
588
	} else {
589
		$s = ": aucune ressource sqlite (link)";
590
	}
591
	if ($s) spip_log("$s - $query", 'sqlite');
592
	return $s;
593
}
594
595
/**
596
 * Retourne le numero de la derniere erreur SQL
597
 * (sauf que SQLite semble ne connaitre que 0 ou 1)
598
 *
599
 * @param $serveur nom de la connexion
600
 * @return int 0 pas d'erreur / 1 une erreur
601
**/
602
// http://doc.spip.org/@spip_sqlite_errno
603
function spip_sqlite_errno($serveur='') {
604
	$link  = _sqlite_link($serveur);
605
	
606
	if (_sqlite_is_version(3, $link)){
607
		$t = $link->errorInfo();
608
		$s = $t[1];
609
	} elseif ($link) {
610
		$s = sqlite_last_error($link);
611
	} else {
612
		$s = ": aucune ressource sqlite (link)";	
613
	}
614
		
615
	if ($s) spip_log("Erreur sqlite $s");
616
617
	return $s ? 1 : 0;
618
}
619
620
621
// http://doc.spip.org/@spip_sqlite_explain
622
function spip_sqlite_explain($query, $serveur='',$requeter=true){
623
	if (strpos(ltrim($query), 'SELECT') !== 0) return array();
624
625
	$requete = new sqlite_traiter_requete("$query", $serveur);
626
	$requete->traduire_requete(); // mysql -> sqlite
627
	$requete->query = 'EXPLAIN ' . $requete->query;
628
	if (!$requeter) return $requete;
629
	// on ne trace pas ces requetes, sinon on obtient un tracage sans fin...
630
	$requete->tracer = false; 
631
	$r = $requete->executer_requete();
632
633
	return $r ? spip_sqlite_fetch($r, null, $serveur) : false; // hum ? etrange ca... a verifier
634
}
635
636
637
// http://doc.spip.org/@spip_sqlite_fetch
638
function spip_sqlite_fetch($r, $t='', $serveur='',$requeter=true) {
0 ignored issues
show
Unused Code introduced by
The parameter $requeter is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
639
640
	$link = _sqlite_link($serveur);
641
	if (!$t) {
642
		if (_sqlite_is_version(3, $link)) {
643
			$t = SPIP_SQLITE3_ASSOC;
644
		} else {
645
			$t = SPIP_SQLITE2_ASSOC;
646
		}
647
	}
648
649
650
	if (_sqlite_is_version(3, $link)){
651
		if ($r) $retour = $r->fetch($t);
652
	} elseif ($r) {
653
		$retour = sqlite_fetch_array($r, $t);
654
	}
655
	
656
	// les version 2 et 3 parfois renvoie des 'table.titre' au lieu de 'titre' tout court ! pff !
657
	// suppression de 'table.' pour toutes les cles (c'est un peu violent !)
658
	if ($retour){
659
		$new = array();
660
		foreach ($retour as $cle=>$val){
0 ignored issues
show
Bug introduced by
The variable $retour does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
661
			if (($pos = strpos($cle, '.'))!==false){
662
				$cle = substr($cle,++$pos);
663
			}
664
			$new[$cle] = $val;
665
		}
666
		$retour = &$new;
667
	}
668
669
	return $retour;
670
}
671
672
673
function spip_sqlite_seek($r, $row_number, $serveur='',$requeter=true) {
0 ignored issues
show
Unused Code introduced by
The parameter $requeter is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
674
	if ($r){
675
		$link = _sqlite_link($serveur);
676
		if (_sqlite_is_version(3, $link)){
677
			// encore un truc de bien fichu : PDO ne PEUT PAS faire de seek ou de rewind...
678
			// je me demande si pour sqlite 3 il ne faudrait pas mieux utiliser
679
			// les nouvelles fonctions sqlite3_xx (mais encore moins presentes...)
680
			return false;
681
		}
682
		else {
683
			return sqlite_seek($r, $row_number);
684
		}
685
	}
686
}
687
688
689
// http://doc.spip.org/@spip_sqlite_free
690
function spip_sqlite_free(&$r, $serveur='',$requeter=true) {
0 ignored issues
show
Unused Code introduced by
The parameter $serveur is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $requeter is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
691
	unset($r);
692
	return true;
693
	//return sqlite_free_result($r);
694
}
695
696
697
// http://doc.spip.org/@spip_sqlite_get_charset
698
function spip_sqlite_get_charset($charset=array(), $serveur='',$requeter=true){
0 ignored issues
show
Unused Code introduced by
The parameter $charset is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $serveur is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $requeter is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
699
	//$c = !$charset ? '' : (" LIKE "._q($charset['charset']));
700
	//return spip_sqlite_fetch(sqlite_query(_sqlite_link($serveur), "SHOW CHARACTER SET$c"), NULL, $serveur);
701
}
702
703
704
// http://doc.spip.org/@spip_sqlite_hex
705
function spip_sqlite_hex($v){
706
	return hexdec($v);
707
}
708
709
710
// http://doc.spip.org/@spip_sqlite_in
711 View Code Duplication
function spip_sqlite_in($val, $valeurs, $not='', $serveur='',$requeter=true) {
0 ignored issues
show
Unused Code introduced by
The parameter $serveur is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $requeter is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
712
	$n = $i = 0;
713
	$in_sql ="";
714
	while ($n = strpos($valeurs, ',', $n+1)) {
715
	  if ((++$i) >= 255) {
716
			$in_sql .= "($val $not IN (" .
717
			  substr($valeurs, 0, $n) .
718
			  "))\n" .
719
			  ($not ? "AND\t" : "OR\t");
720
			$valeurs = substr($valeurs, $n+1);
721
			$i = $n = 0;
722
		}
723
	}
724
	$in_sql .= "($val $not IN ($valeurs))";
725
726
	return "($in_sql)";
727
}
728
729
730
// http://doc.spip.org/@spip_sqlite_insert
731
function spip_sqlite_insert($table, $champs, $valeurs, $desc='', $serveur='',$requeter=true) {
0 ignored issues
show
Unused Code introduced by
The parameter $desc is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
732
733
	$connexion = $GLOBALS['connexions'][$serveur ? $serveur : 0];
734
	$prefixe = $connexion['prefixe'];
735
	$sqlite = $connexion['link'];
736
	$db = $connexion['db'];
0 ignored issues
show
Unused Code introduced by
$db is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
737
738
	if ($prefixe) $table = preg_replace('/^spip/', $prefixe, $table);
739
740
741 View Code Duplication
	if (isset($_GET['var_profile'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
742
		include_spip('public/tracer');
743
		$t = trace_query_start();
744
	} else $t = 0 ;
745
 
746
	$query="INSERT INTO $table ".($champs?"$champs VALUES $valeurs":"DEFAULT VALUES");
747
	
748
	
749
	if ($r = spip_sqlite_query($query, $serveur, $requeter)) {
750
		if (!$requeter) return $r;
751
		
752
		if (_sqlite_is_version(3, $sqlite)) $nb = $sqlite->lastInsertId();
753
		else $nb = sqlite_last_insert_rowid($sqlite);
754
	} else $nb = 0;
755
756
	$err = spip_sqlite_error($query, $serveur);
757
	return $t ? trace_query_end($query, $t, $nb, $err, $serveur) : $nb;
758
759
}
760
761
762
// http://doc.spip.org/@spip_sqlite_insertq
763
function spip_sqlite_insertq($table, $couples=array(), $desc=array(), $serveur='',$requeter=true) {
764
	if (!$desc) $desc = description_table($table);
0 ignored issues
show
Bug Best Practice introduced by
The expression $desc of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
765
	if (!$desc) die("$table insertion sans description");
0 ignored issues
show
Coding Style Compatibility introduced by
The function spip_sqlite_insertq() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
766
	$fields =  isset($desc['field'])?$desc['field']:array();
767
768
	foreach ($couples as $champ => $val) {
769
		$couples[$champ]= _sqlite_calculer_cite($val, $fields[$champ]);
770
	}
771
772
	// recherche de champs 'timestamp' pour mise a jour auto de ceux-ci
773
	$couples = _sqlite_ajouter_champs_timestamp($table, $couples, $desc, $serveur);
774
775
	// si aucun champ donne pour l'insertion, on en cherche un avec un DEFAULT
776
	// sinon sqlite3 ne veut pas inserer
777
	$cles = $valeurs = "";
778
	if (count($couples)) {
779
		$cles = "(".join(',',array_keys($couples)).")";
780
		$valeurs = "(".join(',', $couples).")";
781
	}
782
	
783
	return spip_sqlite_insert($table, $cles , $valeurs , $desc, $serveur, $requeter);
784
}
785
786
787
788
// http://doc.spip.org/@spip_sqlite_insertq_multi
789
function spip_sqlite_insertq_multi($table, $tab_couples=array(), $desc=array(), $serveur='',$requeter=true) {
790
	foreach ($tab_couples as $couples) {
791
		$retour = spip_sqlite_insertq($table, $couples, $desc, $serveur, $requeter);
792
	}
793
	// renvoie le dernier id d'autoincrement ajoute
794
	return $retour;
0 ignored issues
show
Bug introduced by
The variable $retour does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
795
}
796
797
798
799
// http://doc.spip.org/@spip_sqlite_listdbs
800
function spip_sqlite_listdbs($serveur='',$requeter=true) {
0 ignored issues
show
Unused Code introduced by
The parameter $serveur is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $requeter is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
801
	_sqlite_init();
802
	
803
	if (!is_dir($d = substr(_DIR_DB,0,-1))){
804
		return array();
805
	}
806
	
807
	include_spip('inc/flock');
808
	$bases = preg_files($d, $pattern = '(.*)\.sqlite$');
809
	$bds = array();
810
811
	foreach($bases as $b){
812
		// pas de bases commencant pas sqlite 
813
		// (on s'en sert pour l'installation pour simuler la presence d'un serveur)
814
		// les bases sont de la forme _sqliteX_tmp_spip_install.sqlite
815
		if (strpos($b, '_sqlite')) continue;
816
		$bds[] = preg_replace(";.*/$pattern;iS",'$1', $b);
817
	}
818
819
	return $bds;
820
}
821
822
823
// http://doc.spip.org/@spip_sqlite_multi
824
function spip_sqlite_multi ($objet, $lang) {
825
	$r = "PREG_REPLACE("
826
	  . $objet
827
	  . ",'<multi>.*[\[]"
828
	  . $lang
829
	  . "[\]]([^\[]*).*</multi>', '$1') AS multi";
830
	return $r;
831
}
832
833
834
/**
835
 * Optimise une table SQL
836
 * Note: Sqlite optimise TOUTE un fichier sinon rien.
837
 * On evite donc 2 traitements sur la meme base dans un hit.
838
 * 
839
 * @param $table nom de la table a optimiser
840
 * @param $serveur nom de la connexion
841
 * @param $requeter effectuer la requete ? sinon retourner son code
842
 * @return bool|string true / false / requete
843
**/
844
// http://doc.spip.org/@spip_sqlite_optimize
845
function spip_sqlite_optimize($table, $serveur='', $requeter=true) {
0 ignored issues
show
Unused Code introduced by
The parameter $table is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
846
	static $do = false;
847
	if ($requeter and $do) {return true;}
848
	if ($requeter) { $do = true; }
849
	return spip_sqlite_query("VACUUM", $serveur, $requeter);
850
}
851
852
853
// avoir le meme comportement que _q()
854
function spip_sqlite_quote($v, $type=''){
855
	if (is_array($v)) return join(",", array_map('spip_sqlite_quote', $v));
856
	if (is_int($v)) return strval($v);
857 View Code Duplication
	if (strncmp($v,'0x',2)==0 AND ctype_xdigit(substr($v,2))) return hexdec(substr($v,2));
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
858
	if ($type === 'int' AND !$v) return '0';
859
860
	if (function_exists('sqlite_escape_string')) {
861
		return "'" . sqlite_escape_string($v) . "'";
862
	}
863
	
864
	// trouver un link sqlite3 pour faire l'echappement
865
	foreach ($GLOBALS['connexions'] as $s) {
866
		if (_sqlite_is_version(3, $l = $s['link'])){
867
			return	$l->quote($v);
868
		}	
869
	}
870
}
871
872
873
/**
874
 * Tester si une date est proche de la valeur d'un champ
875
 *
876
 * @param string $champ le nom du champ a tester
877
 * @param int $interval valeur de l'interval : -1, 4, ...
878
 * @param string $unite utite utilisee (DAY, MONTH, YEAR, ...)
879
 * @return string expression SQL
880
**/
881
function spip_sqlite_date_proche($champ, $interval, $unite)
882
{
883
	$op = $interval > 0 ? '>' : '<';
884
	return "($champ $op datetime('" . date("Y-m-d H:i:s") . "', '$interval $unite'))";
885
}
886
887
888
// http://doc.spip.org/@spip_sqlite_replace
889
function spip_sqlite_replace($table, $couples, $desc=array(), $serveur='',$requeter=true) {
0 ignored issues
show
Unused Code introduced by
The parameter $requeter is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
890
	if (!$desc) $desc = description_table($table);
0 ignored issues
show
Bug Best Practice introduced by
The expression $desc of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
891
	if (!$desc) die("$table insertion sans description");
0 ignored issues
show
Coding Style Compatibility introduced by
The function spip_sqlite_replace() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
892
	$fields =  isset($desc['field'])?$desc['field']:array();
893
894
	foreach ($couples as $champ => $val) {
895
		$couples[$champ]= _sqlite_calculer_cite($val, $fields[$champ]);
896
	}
897
	
898
	// recherche de champs 'timestamp' pour mise a jour auto de ceux-ci
899
	$couples = _sqlite_ajouter_champs_timestamp($table, $couples, $desc, $serveur);
900
	
901
	return spip_sqlite_query("REPLACE INTO $table (" . join(',',array_keys($couples)) . ') VALUES (' .join(',',$couples) . ')', $serveur);
902
}
903
904
905
906
// http://doc.spip.org/@spip_sqlite_replace_multi
907
function spip_sqlite_replace_multi($table, $tab_couples, $desc=array(), $serveur='',$requeter=true) {
908
	
909
	// boucler pour trainter chaque requete independemment
910
	foreach ($tab_couples as $couples){
911
		$retour = spip_sqlite_replace($table, $couples, $desc, $serveur,$requeter);
912
	}
913
	// renvoie le dernier id	
914
	return $retour; 
0 ignored issues
show
Bug introduced by
The variable $retour does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
915
}
916
917
918
// http://doc.spip.org/@spip_sqlite_select
919
function spip_sqlite_select($select, $from, $where='', $groupby='', $orderby='', $limit='', $having='', $serveur='',$requeter=true) {	
920
921
	// version() n'est pas connu de sqlite
922
	$select = str_replace('version()', 'sqlite_version()',$select);
923
924
	// recomposer from
925
	$from = (!is_array($from) ? $from : _sqlite_calculer_select_as($from));
926
927
	$query = 
928
		  _sqlite_calculer_expression('SELECT', $select, ', ')
929
		. _sqlite_calculer_expression('FROM', $from, ', ')
930
		. _sqlite_calculer_expression('WHERE', $where)
931
		. _sqlite_calculer_expression('GROUP BY', $groupby, ',')
932
		. _sqlite_calculer_expression('HAVING', $having)
933
		. ($orderby ? ("\nORDER BY " . _sqlite_calculer_order($orderby)) :'')
934
		. ($limit ? "\nLIMIT $limit" : '');
935
936
	return spip_sqlite_query($query, $serveur, $requeter);
937
}
938
939
940
// http://doc.spip.org/@spip_sqlite_selectdb
941
function spip_sqlite_selectdb($db, $serveur='',$requeter=true) {
0 ignored issues
show
Unused Code introduced by
The parameter $requeter is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
942
	_sqlite_init();
943
944
	// interdire la creation d'une nouvelle base, 
945
	// sauf si on est dans l'installation
946
	if (!is_file($f = _DIR_DB . $db . '.sqlite')
947
		&& (!defined('_ECRIRE_INSTALL') || !_ECRIRE_INSTALL))
948
		return false;
949
950
	// se connecter a la base indiquee
951
	// avec les identifiants connus
952
	$index = $serveur ? $serveur : 0;
953
954
	if ($link = spip_connect_db('', '', '', '', '@selectdb@' . $db , $serveur, '', '')){
955 View Code Duplication
		if (($db==$link['db']) && $GLOBALS['connexions'][$index] = $link)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
956
			return $db;					
957
	} else {
958
		spip_log("Impossible de selectionner la base $db", 'sqlite');
959
		return false;
960
	}
961
962
}
963
964
965
// http://doc.spip.org/@spip_sqlite_set_charset
966
function spip_sqlite_set_charset($charset, $serveur='',$requeter=true){
0 ignored issues
show
Unused Code introduced by
The parameter $charset is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $serveur is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $requeter is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
967
	#spip_log("changement de charset sql : "."SET NAMES "._q($charset));
968
	# return spip_sqlite_query("SET NAMES ". spip_sqlite_quote($charset), $serveur); //<-- Passe pas !
969
}
970
971
972
// http://doc.spip.org/@spip_sqlite_showbase
973
function spip_sqlite_showbase($match, $serveur='',$requeter=true){
974
	// type est le type d'entrée : table / index / view
975
	// on ne retourne que les tables (?) et non les vues...
976
	# ESCAPE non supporte par les versions sqlite <3
977
	#	return spip_sqlite_query("SELECT name FROM sqlite_master WHERE type='table' AND tbl_name LIKE "._q($match)." ESCAPE '\'", $serveur, $requeter);
978
	$match = preg_quote($match);
979
	$match = str_replace("\\\_","[[TIRETBAS]]",$match);
980
	$match = str_replace("\\\%","[[POURCENT]]",$match);
981
	$match = str_replace("_",".",$match);
982
	$match = str_replace("%",".*",$match);
983
	$match = str_replace("[[TIRETBAS]]","_",$match);
984
	$match = str_replace("[[POURCENT]]","%",$match);
985
	$match = "^$match$";
986
	return spip_sqlite_query("SELECT name FROM sqlite_master WHERE type='table' AND tbl_name REGEXP "._q($match), $serveur, $requeter);
987
}
988
989
990
// http://doc.spip.org/@spip_sqlite_showtable
991
function spip_sqlite_showtable($nom_table, $serveur='',$requeter=true){
992
	
993
	$query = 
994
			'SELECT sql, type FROM'
995
   			. ' (SELECT * FROM sqlite_master UNION ALL'
996
   			. ' SELECT * FROM sqlite_temp_master)'
997
			. " WHERE tbl_name LIKE '$nom_table'"
998
			. " AND type!='meta' AND sql NOT NULL AND name NOT LIKE 'sqlite_%'"
999
			. ' ORDER BY substr(type,2,1), name';
1000
	
1001
	$a = spip_sqlite_query($query, $serveur, $requeter);
1002
	if (!$a) return "";
1003
	if (!$requeter) return $a;
1004
	if (!($a = spip_sqlite_fetch($a, null, $serveur))) return "";
1005
	$vue = ($a['type'] == 'view'); // table | vue
1006
1007
	// c'est une table
1008
	// il faut parser le create
1009
	if (!$vue) {
1010
		if (!preg_match("/^[^(),]*\((([^()]*(\([^()]*\))?[^()]*)*)\)[^()]*$/", array_shift($a), $r))
1011
			return "";
1012
		else {
1013
			$dec = $r[1];
1014 View Code Duplication
			if (preg_match("/^(.*?),([^,]*KEY.*)$/s", $dec, $r)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1015
				$namedkeys = $r[2];
1016
				$dec = $r[1];
1017
			}
1018
			else 
1019
				$namedkeys = "";
1020
1021
			$fields = array();
1022 View Code Duplication
			foreach (explode(",",$dec) as $v) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1023
				preg_match("/^\s*([^\s]+)\s+(.*)/",$v,$r);
1024
				// trim car 'Sqlite Manager' (plugin Firefox) utilise des guillemets
1025
				// lorsqu'on modifie une table avec cet outil.
1026
				// possible que d'autres fassent de meme.
1027
				$fields[ trim(strtolower($r[1]),'"') ] = $r[2];
1028
			}
1029
			// key inclues dans la requete
1030
			$keys = array();
1031 View Code Duplication
			foreach(preg_split('/\)\s*,?/',$namedkeys) as $v) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1032
				if (preg_match("/^\s*([^(]*)\((.*)$/",$v,$r)) {
1033
					$k = str_replace("`", '', trim($r[1]));
1034
					$t = trim(strtolower(str_replace("`", '', $r[2])), '"');
1035
					if ($k && !isset($keys[$k])) $keys[$k] = $t; else $keys[] = $t;
1036
				}
1037
			}
1038
			// sinon ajouter les key index
1039
			$query = 
1040
				'SELECT name,sql FROM'
1041
				. ' (SELECT * FROM sqlite_master UNION ALL'
1042
				. ' SELECT * FROM sqlite_temp_master)'
1043
				. " WHERE tbl_name LIKE '$nom_table'"
1044
				. " AND type='index' AND name NOT LIKE 'sqlite_%'"
1045
				. 'ORDER BY substr(type,2,1), name';
1046
			$a = spip_sqlite_query($query, $serveur, $requeter);
1047
			while ($r = spip_sqlite_fetch($a, null, $serveur)) {
1048
				$key = str_replace($nom_table.'_','',$r['name']); // enlever le nom de la table ajoute a l'index
1049
				$colonnes = preg_replace(',.*\((.*)\).*,','$1',$r['sql']);
1050
				$keys['KEY '.$key] = $colonnes;
1051
			}			
1052
		}
1053
	// c'est une vue, on liste les champs disponibles simplement
1054
	} else {
1055
		if ($res = sql_fetsel('*',$nom_table,'','','','1','',$serveur)){ // limit 1
1056
			$fields = array();
1057
			foreach($res as $c=>$v) $fields[$c]='';
1058
			$keys = array();		
1059
		} else {	
1060
			return "";	
1061
		}
1062
	}
1063
	return array('field' => $fields, 'key' => $keys);
1064
	
1065
}
1066
1067
1068
// http://doc.spip.org/@spip_sqlite_update
1069
function spip_sqlite_update($table, $champs, $where='', $desc='', $serveur='',$requeter=true) {
1070
	// recherche de champs 'timestamp' pour mise a jour auto de ceux-ci
1071
	$champs = _sqlite_ajouter_champs_timestamp($table, $champs, $desc, $serveur);
1072
	
1073
	$set = array();
1074
	foreach ($champs as $champ => $val)
1075
		$set[] = $champ . "=$val";
1076 View Code Duplication
	if (!empty($set))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1077
		return spip_sqlite_query(
1078
			  _sqlite_calculer_expression('UPDATE', $table, ',')
1079
			. _sqlite_calculer_expression('SET', $set, ',')
1080
			. _sqlite_calculer_expression('WHERE', $where), 
1081
			$serveur, $requeter);
1082
}
1083
1084
1085
// http://doc.spip.org/@spip_sqlite_updateq
1086
function spip_sqlite_updateq($table, $champs, $where='', $desc=array(), $serveur='',$requeter=true) {
1087
1088
	if (!$champs) return;
1089
	if (!$desc) $desc = description_table($table);
0 ignored issues
show
Bug Best Practice introduced by
The expression $desc of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
1090
	if (!$desc) die("$table insertion sans description");
0 ignored issues
show
Coding Style Compatibility introduced by
The function spip_sqlite_updateq() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
1091
	$fields =  $desc['field'];
1092
	
1093
	// recherche de champs 'timestamp' pour mise a jour auto de ceux-ci
1094
	$champs = _sqlite_ajouter_champs_timestamp($table, $champs, $desc, $serveur);
1095
	
1096
	$set = array();
1097
	foreach ($champs as $champ => $val) {
1098
		$set[] = $champ . '=' . _sqlite_calculer_cite($val, $fields[$champ]);
1099
	}
1100
	return spip_sqlite_query(
1101
			  _sqlite_calculer_expression('UPDATE', $table, ',')
1102
			. _sqlite_calculer_expression('SET', $set, ',')
1103
			. _sqlite_calculer_expression('WHERE', $where),
1104
			$serveur, $requeter);
1105
}
1106
1107
1108
1109
/*
1110
 * 
1111
 * Ensuite les fonctions non abstraites
1112
 * crees pour l'occasion de sqlite
1113
 * 
1114
 */
1115
1116
1117
// fonction pour la premiere connexion a un serveur SQLite
1118
// http://doc.spip.org/@_sqlite_init
1119
function _sqlite_init(){
1120
	if (!defined('_DIR_DB')) define('_DIR_DB', _DIR_ETC . 'bases/');
1121
	if (!defined('_SQLITE_CHMOD')) define('_SQLITE_CHMOD', _SPIP_CHMOD);
1122
	
1123
	if (!is_dir($d = _DIR_DB)){
1124
		include_spip('inc/flock');
1125
		sous_repertoire($d);
1126
	}
1127
}
1128
1129
1130
// teste la version sqlite du link en cours
1131
// http://doc.spip.org/@_sqlite_is_version
1132
function _sqlite_is_version($version='', $link='', $serveur='',$requeter=true){
0 ignored issues
show
Unused Code introduced by
The parameter $requeter is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1133
	if ($link==='') $link = _sqlite_link($serveur);
1134
	if (!$link) return false;
1135
	if (is_a($link, 'PDO')){
1136
		$v = 3;	
1137
	} else {
1138
		$v = 2;	
1139
	}
1140
	
1141
	if (!$version) return $v;
1142
	return ($version == $v);
1143
}
1144
1145
1146
// retrouver un link (et definir les fonctions externes sqlite->php)
1147
// $recharger devient inutile (a supprimer ?)
1148
// http://doc.spip.org/@_sqlite_link
1149
function _sqlite_link($serveur = '', $recharger = false){
1150
	static $charge = array();
1151
	if ($recharger) $charge[$serveur] = false;
1152
	
1153
	$link = &$GLOBALS['connexions'][$serveur ? $serveur : 0]['link'];
1154
1155
	if ($link && !$charge[$serveur]){
1156
		include_spip('req/sqlite_fonctions');
1157
		_sqlite_init_functions($link);
1158
		$charge[$serveur] = true;
1159
	}
1160
	return $link;
1161
}
1162
1163
1164
/* ordre alphabetique pour les autres */
1165
1166
1167
// renvoie les bons echappements (pas sur les fonctions now())
1168
// http://doc.spip.org/@_sqlite_calculer_cite
1169
function _sqlite_calculer_cite($v, $type) {
1170
	if (sql_test_date($type) AND preg_match('/^\w+\(/', $v))
1171
		return $v;
1172
	if (sql_test_int($type)) {
1173
		if (is_numeric($v))
1174
			return $v;
1175 View Code Duplication
		if (ctype_xdigit(substr($v,2)) AND strncmp($v,'0x',2)==0)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1176
			return hexdec(substr($v,2));
1177
	}
1178
	//else return  ("'" . spip_sqlite_quote($v) . "'");
1179
	return  (spip_sqlite_quote($v));
1180
}
1181
1182
1183
// renvoie grosso modo "$expression join($join, $v)"
1184
// http://doc.spip.org/@_sqlite_calculer_expression
1185 View Code Duplication
function _sqlite_calculer_expression($expression, $v, $join = 'AND'){
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1186
	if (empty($v))
1187
		return '';
1188
	
1189
	$exp = "\n$expression ";
1190
	
1191
	if (!is_array($v)) {
1192
		return $exp . $v;
1193
	} else {
1194
		if (strtoupper($join) === 'AND')
1195
			return $exp . join("\n\t$join ", array_map('_sqlite_calculer_where', $v));
1196
		else
1197
			return $exp . join($join, $v);
1198
	}
1199
}
1200
1201
1202
1203
1204
// pour conversion 0+x ? (pas la peine en sqlite)
1205
// http://doc.spip.org/@_sqlite_calculer_order
1206
function _sqlite_calculer_order($orderby) {
1207
	return (is_array($orderby)) ? join(", ", $orderby) :  $orderby;
1208
}
1209
1210
1211
// renvoie des 'nom AS alias' 
1212
// http://doc.spip.org/@_sqlite_calculer_select_as
1213 View Code Duplication
function _sqlite_calculer_select_as($args){
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1214
	$res = '';
1215
	foreach($args as $k => $v) {
1216
		if (substr($k,-1)=='@') {
1217
			// c'est une jointure qui se refere au from precedent
1218
			// pas de virgule
1219
		  $res .= '  ' . $v ;
1220
		}
1221
		else {
1222
			if (!is_numeric($k)) {
1223
				$p = strpos($v, " ");
1224
				if ($p)
1225
		  		$v = substr($v,0,$p) . " AS '$k'" . substr($v,$p);
1226
				else $v .= " AS '$k'";
1227
	  	}
1228
	  	$res .= ', ' . $v ;
1229
		}
1230
	}
1231
	return substr($res,2) . $join;
0 ignored issues
show
Bug introduced by
The variable $join does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
1232
}
1233
1234
1235
// renvoie les bonnes parentheses pour des where imbriquees
1236
// http://doc.spip.org/@_sqlite_calculer_where
1237 View Code Duplication
function _sqlite_calculer_where($v){
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1238
	if (!is_array($v))
1239
	  return $v ;
1240
1241
	$op = array_shift($v);
1242
	if (!($n=count($v)))
1243
		return $op;
1244
	else {
1245
		$arg = _sqlite_calculer_where(array_shift($v));
1246
		if ($n==1) {
1247
			  return "$op($arg)";
1248
		} else {
1249
			$arg2 = _sqlite_calculer_where(array_shift($v));
1250
			if ($n==2) {
1251
				return "($arg $op $arg2)";
1252
			} else return "($arg $op ($arg2) : $v[0])";
1253
		}
1254
	}
1255
}
1256
1257
1258
1259
/*
1260
 * Charger les modules sqlite (si possible) (juste la version demandee),
1261
 * ou, si aucune version, renvoie les versions sqlite dispo 
1262
 * sur ce serveur dans un array
1263
 */
1264
// http://doc.spip.org/@_sqlite_charger_version
1265
function _sqlite_charger_version($version=''){
1266
	$versions = array();
1267
	
1268
	// version 2
1269
	if (!$version || $version == 2){
1270
		if (charger_php_extension('sqlite')) {
1271
			$versions[]=2;
1272
		}
1273
	}
1274
	
1275
	// version 3
1276
	if (!$version || $version == 3){
1277
		if (charger_php_extension('pdo') && charger_php_extension('pdo_sqlite')) {
1278
			$versions[]=3;
1279
		}
1280
	}
1281
	if ($version) return in_array($version, $versions);
1282
	return $versions;
1283
}
1284
1285
1286
1287
/**
1288
 * Gestion des requetes ALTER non reconnues de SQLite :
1289
 * ALTER TABLE table DROP column
1290
 * ALTER TABLE table CHANGE [COLUMN] columnA columnB definition
1291
 * ALTER TABLE table MODIFY column definition
1292
 * ALTER TABLE table ADD|DROP PRIMARY KEY
1293
 * 
1294
 * (MODIFY transforme en CHANGE columnA columnA) par spip_sqlite_alter()
1295
 * 
1296
 * 1) creer une table B avec le nouveau format souhaite
1297
 * 2) copier la table d'origine A vers B
1298
 * 3) supprimer la table A
1299
 * 4) renommer la table B en A
1300
 * 5) remettre les index (qui sont supprimes avec la table A)
1301
 * 
1302
 * @param string/array $table : nom_table, array(nom_table=>nom_futur)
1303
 * @param string/array $col : nom_colonne, array(nom_colonne=>nom_futur)
1304
 * @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', ...))
1305
 * @param string $serveur : nom de la connexion sql en cours
1306
 * 
1307
 */
1308
// http://doc.spip.org/@_sqlite_modifier_table
1309
function _sqlite_modifier_table($table, $colonne, $opt=array(), $serveur=''){
1310
1311
	if (is_array($table)) {
1312
		reset($table);
1313
		list($table_origine,$table_destination) = each($table);
1314
	} else {
1315
		$table_origine = $table_destination = $table;
1316
	}
1317
	// ne prend actuellement qu'un changement
1318
	// mais pourra etre adapte pour changer plus qu'une colonne a la fois
1319
	if (is_array($colonne)) {
1320
		reset($colonne);
1321
		list($colonne_origine,$colonne_destination) = each($colonne);
1322
	} else {
1323
		$colonne_origine = $colonne_destination = $colonne;
1324
	}	
1325
	if (!isset($opt['field'])) $opt['field'] = array();
1326
	if (!isset($opt['key'])) $opt['key'] = array();
1327
	
1328
	// si les noms de tables sont differents, pas besoin de table temporaire
1329
	// on prendra directement le nom de la future table
1330
	$meme_table = ($table_origine == $table_destination);
1331
	
1332
	$def_origine = sql_showtable($table_origine, false, $serveur);
1333
	$table_tmp = $table_origine . '_tmp';
1334
1335
	// 1) creer une table temporaire avec les modifications	
1336
	// - DROP : suppression de la colonne
1337
	// - CHANGE : modification de la colonne
1338
	// (foreach pour conserver l'ordre des champs)
1339
	
1340
	// field 
1341
	$fields = array();
1342
	// pour le INSERT INTO plus loin
1343
	// stocker la correspondance nouvelles->anciennes colonnes
1344
	$fields_correspondances = array(); 
1345
	foreach ($def_origine['field'] as $c=>$d){
1346
1347
		if ($colonne_origine && ($c == $colonne_origine)) {
1348
			// si pas DROP
1349
			if ($colonne_destination){
1350
				$fields[$colonne_destination] = $opt['field'][$colonne_destination];
1351
				$fields_correspondances[$colonne_destination] = $c;
1352
			}	
1353
		} else {
1354
			$fields[$c] = $d;
1355
			$fields_correspondances[$c] = $c;
1356
		}
1357
	}
1358
	// cas de ADD sqlite2 (ajout du champ en fin de table):
1359
	if (!$colonne_origine && $colonne_destination){
1360
			$fields[$colonne_destination] = $opt['field'][$colonne_destination];
1361
	}
1362
	
1363
	// key...
1364
	$keys = array();
1365
	foreach ($def_origine['key'] as $c=>$d){
1366
		$c = str_replace($colonne_origine,$colonne_destination,$c);
1367
		$d = str_replace($colonne_origine,$colonne_destination,$d);
1368
		// seulement si on ne supprime pas la colonne !
1369
		if ($d)
1370
			$keys[$c] = $d;
1371
	}
1372
1373
	// autres keys, on merge
1374
	$keys = array_merge($keys,$opt['key']);
1375
	$queries = array();
1376
	$queries[] = 'BEGIN TRANSACTION';
1377
	
1378
	// copier dans destination (si differente de origine), sinon tmp
1379
	$table_copie = ($meme_table) ? $table_tmp : $table_destination;
1380
	
1381
	if ($q = _sqlite_requete_create(
1382
			$table_copie, 
1383
			$fields, 
1384
			$keys, 
1385
			$autoinc=false,
1386
			$temporary=false, 
1387
			$ifnotexists=true,
1388
			$serveur)){
1389
		$queries[] = $q;			
1390
	}
1391
1392
	
1393
	// 2) y copier les champs qui vont bien
1394
	$champs_dest = join(', ', array_keys($fields_correspondances));
1395
	$champs_ori = join(', ', $fields_correspondances);
1396
	$queries[] = "INSERT INTO $table_copie ($champs_dest) SELECT $champs_ori FROM $table_origine";
1397
		
1398
	// 3) supprimer la table d'origine
1399
	$queries[] = "DROP TABLE $table_origine";
1400
	
1401
	// 4) renommer la table temporaire 
1402
	// avec le nom de la table destination
1403
	// si necessaire
1404
	if ($meme_table){
1405
		if (_sqlite_is_version(3, '', $serveur)){
1406
			$queries[] = "ALTER TABLE $table_copie RENAME TO $table_destination";
1407
		} else {
1408
			$queries[] = _sqlite_requete_create(
1409
					$table_destination, 
1410
					$fields, 
1411
					$keys, 
1412
					$autoinc=false,
1413
					$temporary=false, 
1414
					$ifnotexists=false, // la table existe puisqu'on est dans une transaction
1415
					$serveur);	
1416
			$queries[] = "INSERT INTO $table_destination SELECT * FROM $table_copie";		
1417
			$queries[] = "DROP TABLE $table_copie";
1418
		}
1419
	}
1420
	
1421
	// 5) remettre les index !
1422
	foreach ($keys as $k=>$v) {
1423 View Code Duplication
		if ($k=='PRIMARY KEY'){}
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1424
		else {
1425
			// enlever KEY
1426
			$k = substr($k,4);
1427
			$queries[] = "CREATE INDEX $table_destination"."_$k ON $table_destination ($v)";
1428
		}
1429
	}
1430
	
1431
	$queries[] = "COMMIT";
1432
	
1433
1434
	// il faut les faire une par une car $query = join('; ', $queries).";"; ne fonctionne pas
1435
	foreach ($queries as $q){
1436
		$req = new sqlite_traiter_requete($q, $serveur);
1437
		if (!$req->executer_requete()){	
1438
			spip_log("SQLite : ALTER TABLE table :" 
1439
			." Erreur a l'execution de la requete : $q",'sqlite'); 
1440
			return false;
1441
		}
1442
	}
1443
1444
	return true;					
1445
}
1446
1447
1448
1449
1450
/*
1451
 * Nom des fonctions
1452
 */
1453
// http://doc.spip.org/@_sqlite_ref_fonctions
1454
function _sqlite_ref_fonctions(){
1455
	$fonctions = array(
1456
		'alter' => 'spip_sqlite_alter',
1457
		'count' => 'spip_sqlite_count',
1458
		'countsel' => 'spip_sqlite_countsel',
1459
		'create' => 'spip_sqlite_create',
1460
		'create_base' => 'spip_sqlite_create_base',
1461
		'create_view' => 'spip_sqlite_create_view',
1462
		'date_proche' => 'spip_sqlite_date_proche',
1463
		'delete' => 'spip_sqlite_delete',
1464
		'drop_table' => 'spip_sqlite_drop_table',
1465
		'drop_view' => 'spip_sqlite_drop_view',
1466
		'errno' => 'spip_sqlite_errno',
1467
		'error' => 'spip_sqlite_error',
1468
		'explain' => 'spip_sqlite_explain',
1469
		'fetch' => 'spip_sqlite_fetch',
1470
		'seek' => 'spip_sqlite_seek',
1471
		'free' => 'spip_sqlite_free',
1472
		'hex' => 'spip_sqlite_hex',
1473
		'in' => 'spip_sqlite_in', 
1474
		'insert' => 'spip_sqlite_insert',
1475
		'insertq' => 'spip_sqlite_insertq',
1476
		'insertq_multi' => 'spip_sqlite_insertq_multi',
1477
		'listdbs' => 'spip_sqlite_listdbs',
1478
		'multi' => 'spip_sqlite_multi',
1479
		'optimize' => 'spip_sqlite_optimize',
1480
		'query' => 'spip_sqlite_query',
1481
		'quote' => 'spip_sqlite_quote',
1482
		'replace' => 'spip_sqlite_replace',
1483
		'replace_multi' => 'spip_sqlite_replace_multi',
1484
		'select' => 'spip_sqlite_select',
1485
		'selectdb' => 'spip_sqlite_selectdb',
1486
		'set_charset' => 'spip_sqlite_set_charset',
1487
		'get_charset' => 'spip_sqlite_get_charset',
1488
		'showbase' => 'spip_sqlite_showbase',
1489
		'showtable' => 'spip_sqlite_showtable',
1490
		'update' => 'spip_sqlite_update',
1491
		'updateq' => 'spip_sqlite_updateq',
1492
	);
1493
	
1494
	// association de chaque nom http d'un charset aux couples sqlite 
1495
	// SQLite supporte utf-8 et utf-16 uniquement.
1496
	$charsets = array(
1497
		'utf-8'=>array('charset'=>'utf8','collation'=>'utf8_general_ci'), 
1498
		//'utf-16be'=>array('charset'=>'utf16be','collation'=>'UTF-16BE'),// aucune idee de quoi il faut remplir dans es champs la
1499
		//'utf-16le'=>array('charset'=>'utf16le','collation'=>'UTF-16LE')
1500
	);
1501
	
1502
	$fonctions['charsets'] = $charsets;
1503
	
1504
	return $fonctions;
1505
}
1506
1507
1508
1509
// $query est une requete ou une liste de champs
1510
// http://doc.spip.org/@_sqlite_remplacements_definitions_table
1511
function _sqlite_remplacements_definitions_table($query,$autoinc=false){
1512
	// quelques remplacements
1513
	$num = "(\s*\([0-9]*\))?";
1514
	$enum = "(\s*\([^\)]*\))?";
1515
	
1516
	$remplace = array(
1517
		'/enum'.$enum.'/is' => 'VARCHAR',
1518
		'/binary/is' => '',
1519
		'/COLLATE \w+_bin/is' => '',
1520
		'/auto_increment/is' => '',
1521
		'/(timestamp .* )ON .*$/is' => '\\1',
1522
		'/character set \w+/is' => '',
1523
		'/((big|small|medium|tiny)?int(eger)?)'.$num.'\s*unsigned/is' => '\\1 UNSIGNED',
1524
		'/(text\s+not\s+null)\s*$/is' => "\\1 DEFAULT ''",
1525
	);
1526
1527
	// pour l'autoincrement, il faut des INTEGER NOT NULL PRIMARY KEY
1528
	if ($autoinc)
1529
		$remplace['/(big|small|medium|tiny)?int(eger)?'.$num.'/is'] = 'INTEGER';
1530
1531
	return preg_replace(array_keys($remplace), $remplace, $query);
1532
}
1533
1534
1535
/*
1536
 * Creer la requete pour la creation d'une table
1537
 * retourne la requete pour utilisation par sql_create() et sql_alter()
1538
 */
1539
// http://doc.spip.org/@_sqlite_requete_create
1540
function _sqlite_requete_create($nom, $champs, $cles, $autoinc=false, $temporary=false, $_ifnotexists=true, $serveur='',$requeter=true) {
0 ignored issues
show
Unused Code introduced by
The parameter $requeter is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1541
	$query = $keys = $s = $p = '';
0 ignored issues
show
Unused Code introduced by
$p is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1542
1543
	// certains plugins declarent les tables  (permet leur inclusion dans le dump)
1544
	// sans les renseigner (laisse le compilo recuperer la description)
1545
	if (!is_array($champs) || !is_array($cles)) 
1546
		return;
1547
1548
	// sqlite ne gere pas KEY tout court dans une requete CREATE TABLE
1549
	// il faut passer par des create index
1550
	// Il gere par contre primary key !
1551
	// Soit la PK est definie dans les cles, soit dans un champs
1552
	if (!$c = $cles[$pk = "PRIMARY KEY"]) {
1553
		foreach($champs as $k => $v) {
1554
			if (false !== stripos($v,$pk)) {
1555
				$c = $k;
1556
				// on n'en a plus besoin dans field, vu que defini dans key
1557
				$champs[$k] = preg_replace("/$pk/is", '', $champs[$k]); 
1558
				break;	
1559
			}
1560
		}
1561
	}
1562
	if ($c) $keys = "\n\t\t$pk ($c)";
1563
	
1564
	$champs = _sqlite_remplacements_definitions_table($champs, $autoinc);
1565
	foreach($champs as $k => $v) {
1566
		$query .= "$s\n\t\t$k $v";
1567
		$s = ",";
1568
	}
1569
1570
	$ifnotexists = "";
1571 View Code Duplication
	if ($_ifnotexists) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1572
		// simuler le IF NOT EXISTS - version 2 
1573
		if (_sqlite_is_version(2, '', $serveur)){
1574
			$a = spip_sqlite_showtable($nom, $serveur);
1575
			if ($a) return false;
1576
		} 
1577
		// sinon l'ajouter en version 3
1578
		else {
1579
			$ifnotexists = ' IF NOT EXISTS';
1580
		}
1581
	}
1582
1583
	$temporary = $temporary ? ' TEMPORARY':'';
1584
	$q = "CREATE$temporary TABLE$ifnotexists $nom ($query" . ($keys ? ",$keys" : '') . ")\n";
1585
1586
	return $q;
1587
}
1588
	
1589
1590
1591
/*
1592
 * Retrouver les champs 'timestamp'
1593
 * pour les ajouter aux 'insert' ou 'replace'
1594
 * afin de simuler le fonctionnement de mysql 
1595
 * 
1596
 * stocke le resultat pour ne pas faire 
1597
 * de requetes showtable intempestives
1598
 */
1599
// http://doc.spip.org/@_sqlite_ajouter_champs_timestamp
1600 View Code Duplication
function _sqlite_ajouter_champs_timestamp($table, $couples, $desc='', $serveur=''){
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1601
	static $tables = array();
1602
	
1603
	if (!isset($tables[$table])){
1604
		
1605
		if (!$desc){
1606
			$f = charger_fonction('trouver_table', 'base');
1607
			$desc = $f($table, $serveur);
1608
			// si pas de description, on ne fait rien, ou on die() ?
1609
			if (!$desc OR !$desc['field']) return $couples;
1610
		}
1611
		
1612
		// recherche des champs avec simplement 'TIMESTAMP'
1613
		// cependant, il faudra peut etre etendre
1614
		// avec la gestion de DEFAULT et ON UPDATE
1615
		// mais ceux-ci ne sont pas utilises dans le core
1616
		$tables[$table] = array();
1617
1618
		foreach ($desc['field'] as $k=>$v){
1619
			if (strpos(strtolower(ltrim($v)), 'timestamp')===0)
1620
			$tables[$table][] = $k;
1621
		}
1622
	}
1623
	
1624
	// ajout des champs type 'timestamp' absents
1625
	foreach ($tables[$table] as $maj){
1626
		if (!array_key_exists($maj, $couples))
1627
			$couples[$maj] = "datetime('now')";	
1628
	}
1629
	return $couples;
1630
}
1631
 	
1632
 	
1633
1634
/*
1635
 * renvoyer la liste des versions sqlite disponibles
1636
 * sur le serveur 
1637
 */
1638
// http://doc.spip.org/@spip_versions_sqlite
1639
function spip_versions_sqlite(){
1640
	return 	_sqlite_charger_version();
1641
}
1642
1643
1644
1645
1646
/*
1647
 * Classe pour partager les lancements de requete
1648
 * - peut corriger la syntaxe des requetes pour la conformite a sqlite
1649
 * - peut tracer les requetes
1650
 * 
1651
 * Cette classe est presente essentiellement pour un preg_replace_callback 
1652
 * avec des parametres dans la fonction appelee que l'on souhaite incrementer 
1653
 * (fonction pour proteger les textes)
1654
 * 
1655
 */
1656
class sqlite_traiter_requete{
1657
	var $query = ''; // la requete
1658
	var $queryCount = ''; // la requete pour compter
1659
	var $serveur = ''; // le serveur
1660
	var $link = ''; // le link (ressource) sqlite
1661
	var $prefixe = ''; // le prefixe des tables
1662
	var $db = ''; // le nom de la base 
1663
	var $tracer = false; // doit-on tracer les requetes (var_profile)
1664
	
1665
	var $sqlite_version = ''; // Version de sqlite (2 ou 3)
1666
	
1667
	// Pour les corrections a effectuer sur les requetes :
1668
	var $textes = array(); 	// array(code=>'texte') trouvé
1669
	
1670
	
1671
	// constructeur
1672
// http://doc.spip.org/@sqlite_traiter_requete
1673
	function sqlite_traiter_requete($query, $serveur = ''){
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1674
		$this->query = $query;
1675
		$this->serveur = strtolower($serveur);
1676
		
1677
		if (!($this->link = _sqlite_link($this->serveur)) && (!defined('_ECRIRE_INSTALL') || !_ECRIRE_INSTALL)){
1678
			spip_log("Aucune connexion sqlite (link)");
1679
			return false;	
1680
		}
1681
1682
		$this->sqlite_version =_sqlite_is_version('', $this->link);
0 ignored issues
show
Documentation Bug introduced by
It seems like _sqlite_is_version('', $this->link) of type integer or boolean is incompatible with the declared type string of property $sqlite_version.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
1683
		
1684
		$this->prefixe 	= $GLOBALS['connexions'][$this->serveur ? $this->serveur : 0]['prefixe'];
1685
		$this->db 		= $GLOBALS['connexions'][$this->serveur ? $this->serveur : 0]['db'];
1686
		
1687
		// tracage des requetes ?
1688
		$this->tracer = (isset($_GET['var_profile']) && $_GET['var_profile']);
1689
	}
1690
	
1691
	
1692
	// lancer la requete $this->query,
1693
	// faire le tracage si demande 
1694
// http://doc.spip.org/@executer_requete
1695
	function executer_requete(){
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1696
		$err = "";
1697
		if ($this->tracer) {
1698
			include_spip('public/tracer');
1699
			$t = trace_query_start();
1700
		} else $t = 0 ;
1701
 
1702
# spip_log("requete: $this->serveur >> $this->query",'query'); // boum ? pourquoi ?
1703
		if ($this->link){
1704
			// memoriser la derniere erreur PHP vue
1705
			$e = error_get_last();
1706
			// sauver la derniere requete
1707
			$GLOBALS['connexions'][$this->serveur ? $this->serveur : 0]['last'] = $this->query;
1708
			
1709
			if ($this->sqlite_version == 3) {
1710
				$r = $this->link->query($this->query);
0 ignored issues
show
Bug introduced by
The method query cannot be called on $this->link (of type string).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
1711
				// sauvegarde de la requete (elle y est deja dans $r->queryString)
1712
				# $r->spipQueryString = $this->query;
1713
1714
				// comptage : oblige de compter le nombre d'entrees retournees 
1715
				// par une requete SELECT
1716
				// aucune autre solution ne donne le nombre attendu :( !
1717
				// particulierement s'il y a des LIMIT dans la requete.
1718
				if (strtoupper(substr(ltrim($this->query),0,6)) == 'SELECT'){
1719
					if ($r) {
1720
						$l = $this->link->query($this->query);
0 ignored issues
show
Bug introduced by
The method query cannot be called on $this->link (of type string).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
1721
						$r->spipSqliteRowCount =  count($l->fetchAll());
1722
						unset($l);
1723
					} elseif (is_a($r, 'PDOStatement')) {
1724
						$r->spipSqliteRowCount = 0;
1725
					}
1726
				}
1727
			} else {
1728
				$r = sqlite_query($this->link, $this->query);
1729
			}
1730
1731
			// loger les warnings/erreurs eventuels de sqlite remontant dans PHP
1732
			if ($err = error_get_last() AND $err!=$e) {
1733
				$err = strip_tags($err['message'])." in ".$err['file']." line ".$err['line'];
1734
				spip_log("$err - ".$this->query, 'sqlite');
1735
			}
1736
		  else $err="";
1737
1738
		} else {
1739
			$r = false;	
1740
		}
1741
1742
		if (spip_sqlite_errno($serveur))
1743
			$err .= spip_sqlite_error($this->query, $serveur);
0 ignored issues
show
Bug introduced by
The variable $serveur does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
1744
		return $t ? trace_query_end($this->query, $t, $r, $err, $serveur) : $r;
1745
	}
1746
		
1747
	// transformer la requete pour sqlite 
1748
	// enleve les textes, transforme la requete pour quelle soit
1749
	// bien interpretee par sqlite, puis remet les textes
1750
	// la fonction affecte $this->query
1751
	// http://doc.spip.org/@traduire_requete
1752
	function traduire_requete(){
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1753
		//
1754
		// 1) Protection des textes en les remplacant par des codes
1755
		//
1756
		// enlever les 'textes' et initialiser avec
1757
		list($this->query, $textes) = query_echappe_textes($this->query);
1758
		
1759
		//
1760
		// 2) Corrections de la requete
1761
		//
1762
		// Correction Create Database
1763
		// Create Database -> requete ignoree
1764
		if (strpos($this->query, 'CREATE DATABASE')===0){
1765
			spip_log("Sqlite : requete non executee -> $this->query","sqlite");
1766
			$this->query = "SELECT 1";	
1767
		}
1768
		
1769
		// Correction Insert Ignore
1770
		// INSERT IGNORE -> insert (tout court et pas 'insert or replace')
1771
		if (strpos($this->query, 'INSERT IGNORE')===0){
1772
			#spip_log("Sqlite : requete transformee -> $this->query","sqlite");
1773
			$this->query = 'INSERT ' . substr($this->query,'13');	
1774
		}
1775
		
1776
		// Correction des dates avec INTERVAL
1777
		// utiliser sql_date_proche() de preference
1778 View Code Duplication
		if (strpos($this->query, 'INTERVAL')!==false){
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1779
			$this->query = preg_replace_callback("/DATE_(ADD|SUB).*INTERVAL\s+(\d+)\s+([a-zA-Z]+)\)/U", 
1780
							array(&$this, '_remplacerDateParTime'), 
1781
							$this->query);
1782
		}
1783
		
1784
		// Correction Using
1785
		// USING (non reconnu en sqlite2)
1786
		// problematique car la jointure ne se fait pas du coup.
1787 View Code Duplication
		if (($this->sqlite_version == 2) && (strpos($this->query, "USING")!==false)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1788
			spip_log("'USING (champ)' n'est pas reconnu en SQLite 2. Utilisez 'ON table1.champ = table2.champ', 'sqlite'");
1789
			$this->query = preg_replace('/USING\s*\([^\)]*\)/', '', $this->query);
1790
		}
1791
		
1792
		// Correction Field
1793
		// remplace FIELD(table,i,j,k...) par CASE WHEN table=i THEN n ... ELSE 0 END
1794 View Code Duplication
		if (strpos($this->query, 'FIELD')!==false){
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1795
			$this->query = preg_replace_callback('/FIELD\s*\(([^\)]*)\)/', 
1796
							array(&$this, '_remplacerFieldParCase'), 
1797
							$this->query); 
1798
		}
1799
		
1800
		// Correction des noms de tables FROM
1801
		// mettre les bons noms de table dans from, update, insert, replace...
1802
		if (preg_match('/\s(SET|VALUES|WHERE|DATABASE)\s/i', $this->query, $regs)) {
1803
			$suite = strstr($this->query, $regs[0]);
1804
			$this->query = substr($this->query, 0, -strlen($suite));
1805
		} else $suite ='';
1806
		$pref = ($this->prefixe) ? $this->prefixe . "_": "";
1807
		$this->query = preg_replace('/([,\s])spip_/', '\1'.$pref, $this->query) . $suite;
1808
1809
		// Correction zero AS x
1810
		// pg n'aime pas 0+x AS alias, sqlite, dans le meme style, 
1811
		// n'apprecie pas du tout SELECT 0 as x ... ORDER BY x
1812
		// il dit que x ne doit pas être un integer dans le order by !
1813
		// on remplace du coup x par vide() dans ce cas uniquement
1814
		//
1815
		// rien que pour public/vertebrer.php ?
1816
		if ((strpos($this->query, "0 AS")!==false)){
1817
			// on ne remplace que dans ORDER BY ou GROUP BY
1818
			if (preg_match('/\s(ORDER|GROUP) BY\s/i', $this->query, $regs)) {
1819
				$suite = strstr($this->query, $regs[0]);
1820
				$this->query = substr($this->query, 0, -strlen($suite));
1821
			
1822
				// on cherche les noms des x dans 0 AS x
1823
				// on remplace dans $suite le nom par vide()
1824
				preg_match_all('/\b0 AS\s*([^\s,]+)/', $this->query, $matches, PREG_PATTERN_ORDER);
1825
				foreach ($matches[1] as $m){
1826
					$suite = str_replace($m, 'VIDE()', $suite);
1827
				}
1828
				$this->query .= $suite;
1829
			}
1830
		}
1831
1832
		// Correction possible des divisions entieres
1833
		// Le standard SQL (lequel? ou?) semble indiquer que
1834
		// a/b=c doit donner c entier si a et b sont entiers 4/3=1.
1835
		// C'est ce que retournent effectivement SQL Server et SQLite
1836
		// Ce n'est pas ce qu'applique MySQL qui retourne un reel : 4/3=1.333...
1837
		// 
1838
		// On peut forcer la conversion en multipliant par 1.0 avant la division
1839
		// /!\ SQLite 3.5.9 Debian/Ubuntu est victime d'un bug en plus ! 
1840
		// cf. https://bugs.launchpad.net/ubuntu/+source/sqlite3/+bug/254228
1841
		//     http://www.sqlite.org/cvstrac/tktview?tn=3202
1842
		// (4*1.0/3) n'est pas rendu dans ce cas !
1843
		# $this->query = str_replace('/','* 1.00 / ',$this->query);
1844
			
1845
		// Correction Antiquotes
1846
		// ` => rien
1847
		$this->query = str_replace('`','',$this->query);
1848
		
1849
		// Correction critere REGEXP, non reconnu en sqlite2
1850 View Code Duplication
		if (($this->sqlite_version == 2) && (strpos($this->query, 'REGEXP')!==false)){
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1851
			$this->query = preg_replace('/([^\s\(]*)(\s*)REGEXP(\s*)([^\s\)]*)/', 'REGEXP($4, $1)', $this->query);
1852
		}
1853
		
1854
		
1855
		//
1856
		// 3) Remise en place des textes d'origine
1857
		//
1858
		// Correction Antiquotes et echappements
1859
		// ` => rien
1860
		if (strpos($this->query,'`')!==false)
1861
			$this->query = str_replace('`','', $this->query);
1862
1863
		$this->query = query_reinjecte_textes($this->query, $textes);
0 ignored issues
show
Security Bug introduced by
It seems like $textes can also be of type false; however, query_reinjecte_textes() does only seem to accept array, did you maybe forget to handle an error condition?
Loading history...
1864
	}
1865
	
1866
1867
1868
	// les callbacks	
1869
	// remplacer DATE_ / INTERVAL par DATE...strtotime
1870
// http://doc.spip.org/@_remplacerDateParTime
1871
	function _remplacerDateParTime($matches){
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1872
		$op = strtoupper($matches[1] == 'ADD')?'+':'-';	
1873
		return "datetime('" . date("Y-m-d H:i:s") . "', '$op$matches[2] $matches[3]')";
1874
	}
1875
1876
	// callback ou l'on remplace FIELD(table,i,j,k...) par CASE WHEN table=i THEN n ... ELSE 0 END
1877
// http://doc.spip.org/@_remplacerFieldParCase
1878
	function _remplacerFieldParCase($matches){
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1879
		$fields = substr($matches[0],6,-1); // ne recuperer que l'interieur X de field(X)
1880
		$t = explode(',', $fields);
1881
		$index = array_shift($t);
1882
1883
		$res = '';
1884
		$n=0;
1885
		foreach($t as $v) {
1886
			$n++;
1887
			$res .= "\nWHEN $index=$v THEN $n";
1888
		}
1889
		return "CASE $res ELSE 0 END ";			
1890
	}
1891
1892
	// callback ou l'on sauve le texte qui est cache dans un tableau $this->textes
1893
// http://doc.spip.org/@_remplacerTexteParCode
1894
	function _remplacerTexteParCode($matches){
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1895
		$this->textes[$code = "%@##".count($this->textes)."##@%"] = $matches[1];
1896
		return $code;	
1897
	}
1898
1899
}
1900
1901
?>
0 ignored issues
show
Best Practice introduced by
It is not recommended to use PHP's closing tag ?> in files other than templates.

Using a closing tag in PHP files that only contain PHP code is not recommended as you might accidentally add whitespace after the closing tag which would then be output by PHP. This can cause severe problems, for example headers cannot be sent anymore.

A simple precaution is to leave off the closing tag as it is not required, and it also has no negative effects whatsoever.

Loading history...
1902