Completed
Push — spip-2-stable ( d79e3d )
by cam
30:47 queued 16:59
created

connect_sql.php ➔ spip_connect()   F

Complexity

Conditions 27
Paths > 20000

Size

Total Lines 87
Code Lines 54

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 27
eloc 54
nc 23672
nop 2
dl 0
loc 87
rs 2.1034
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
//
16
// Utilitaires indispensables autour des serveurs SQL
17
//
18
19
// API d'appel aux bases de donnees:
20
// on charge le fichier config/$serveur ($serveur='connect' pour le principal)
21
// qui est cense initaliser la connexion en appelant spip_connect_db
22
// laquelle met dans la globale db_ok la description de la connexion
23
// On la memorise dans un tableau pour permettre plusieurs serveurs.
24
// A l'installation, il faut simuler l'existence de ce fichier
25
26
// http://doc.spip.org/@spip_connect
27
function spip_connect($serveur='', $version='') {
28
	global $connexions, $spip_sql_version;
29
30
	$serveur = !is_string($serveur) ? '' : strtolower($serveur);
31
	$index = $serveur ? $serveur : 0;
32
	if (!$version) $version = $spip_sql_version;
33
	if (isset($connexions[$index][$version])) return $connexions[$index];
34
35
	include_spip('base/abstract_sql');
36
	$install = (_request('exec') == 'install');
37
38
	// Premiere connexion ?
39
	if (!($old = isset($connexions[$index]))) {
40
		$f = (!preg_match('/^[\w\.]*$/', $serveur))
41
		? '' // nom de serveur mal ecrit
42
		: ($serveur ?
43
		   ( _DIR_CONNECT. $serveur . '.php') // serveur externe
44
		    : (_FILE_CONNECT ? _FILE_CONNECT // serveur principal ok
45
		       : ($install ? _FILE_CONNECT_TMP // init du serveur principal
46
			 : ''))); // installation pas faite
47
48
		unset($GLOBALS['db_ok']);
49
		unset($GLOBALS['spip_connect_version']);
50
		if ($f) { 
51
			if (is_readable($f)) { 
52
				include($f);
53
			} elseif ($serveur AND !$install) {
54
				// chercher une declaration de serveur dans le path
55
				// qui pourra un jour servir a declarer des bases sqlite
56
				// par des plugins. Et sert aussi aux boucles POUR.
57
				find_in_path("$serveur.php",'connect/',true);
58
			}
59
		}
60
		if (!isset($GLOBALS['db_ok'])) {
61
		  // fera mieux la prochaine fois
62
			if ($install) return false;
63
			spip_log("spip_connect: serveur $index mal defini dans '$f'. spip_connect_version: " . @$GLOBALS['spip_connect_version']);
64
			// ne plus reessayer si ce n'est pas l'install
65
			return $connexions[$index]=false;
66
		}
67
		$connexions[$index] = $GLOBALS['db_ok'];
68
	}
69
	// si la connexion a deja ete tentee mais a echoue, le dire!
70
	if (!$connexions[$index]) return false;
71
72
	// la connexion a reussi ou etait deja faite.
73
	// chargement de la version du jeu de fonctions
74
	// si pas dans le fichier par defaut
75
	$type = $GLOBALS['db_ok']['type'];
76
	$jeu = 'spip_' . $type .'_functions_' . $version;
77
	if (!isset($GLOBALS[$jeu])) {
78
		if (!find_in_path($type . '_' . $version . '.php', 'req/', true)){
79
		  spip_log("spip_connect: serveur $index version '$version' non defini pour '$type'");
80
			// ne plus reessayer
81
			return $connexions[$index][$version] = array();
82
		}
83
	}
84
	$connexions[$index][$version] = $GLOBALS[$jeu];
85
	if ($old) return $connexions[$index];
86
87
	$connexions[$index]['spip_connect_version'] = isset($GLOBALS['spip_connect_version']) ? $GLOBALS['spip_connect_version'] : 0;
88
89
	// initialisation de l'alphabet utilise dans les connexions SQL
90
	// si l'installation l'a determine.
91
	// Celui du serveur principal l'impose aux serveurs secondaires
92
	// s'ils le connaissent
93
94
	if (!$serveur) {
95
		$charset = spip_connect_main($GLOBALS[$jeu]);
96
		if (!$charset) {
97
			unset($connexions[$index]);
98
			spip_log("spip_connect: absence de charset");
99
			return false;
100
		}
101
	} else	{
102
		if ($connexions[$index]['spip_connect_version']
103
		AND $r = sql_getfetsel('valeur', 'spip_meta', "nom='charset_sql_connexion'",'','','','',$serveur))
104
			$charset = $r;
105
		else $charset = -1;
106
	}
107
	if ($charset != -1) {
108
		$f = $GLOBALS[$jeu]['set_charset'];
109
		if (function_exists($f))
110
			$f($charset, $serveur);
111
	}
112
	return $connexions[$index];
113
}
114
115
function spip_sql_erreur($serveur='')
116
{
117
	$connexion = spip_connect($serveur);
118
	$e = sql_errno($serveur);
119
	$t = (isset($connexion['type']) ? $connexion['type'] : 'sql');
120
	$m = "Erreur $e de $t: " . sql_error($serveur) . "\n" . $connexion['last'];
121
	$f = $t . $serveur;
122
	spip_log($m, $f);
123
}
124
125
// Cette fonction ne doit etre appelee qu'a travers la fonction sql_serveur
126
// definie dans base/abstract_sql
127
// Elle existe en tant que gestionnaire de versions,
128
// connue seulement des convertisseurs automatiques
129
130
// http://doc.spip.org/@spip_connect_sql
131
function spip_connect_sql($version, $ins='', $serveur='', $cont=false) {
132
	$desc = spip_connect($serveur, $version);
133
	if (function_exists($f = @$desc[$version][$ins])) return $f;
134
	if ($cont) return $desc;
135
	if ($ins)
136
		spip_log("Le serveur '$serveur' version $version n'a pas '$ins'");
137
	include_spip('inc/minipres');
138
	echo minipres(_T('info_travaux_titre'), _T('titre_probleme_technique'));
139
	exit;
0 ignored issues
show
Coding Style Compatibility introduced by
The function spip_connect_sql() 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...
140
}
141
142
// Fonction appelee par le fichier cree dans config/ a l'instal'.
143
// Il contient un appel direct a cette fonction avec comme arguments
144
// les identifants de connexion.
145
// Si la connexion reussit, la globale db_ok memorise sa description.
146
// C'est un tableau egalement retourne en valeur, pour les appels a l'install'
147
148
// http://doc.spip.org/@spip_connect_db
149
function spip_connect_db($host, $port, $login, $pass, $db='', $type='mysql', $prefixe='', $auth='') {
150
	global $db_ok;
151
152
	## TODO : mieux differencier les serveurs
153
	$f = _DIR_TMP . $type . 'out';
154
155
	if (@file_exists($f)
156
	AND (time() - @filemtime($f) < 30)
157
	AND !defined('_ECRIRE_INSTALL')) {
158
		spip_log("Echec : $f recent. Pas de tentative de connexion");
159
		return;
160
	}
161
	if (!$prefixe)
162
		$prefixe = isset($GLOBALS['table_prefix'])
163
		? $GLOBALS['table_prefix'] : $db;
164
	$h = charger_fonction($type, 'req', true);
165
	if (!$h) {
166
		spip_log("les requetes $type ne sont pas fournies");
167
		return;
168
	}
169
	if ($g = $h($host, $port, $login, $pass, $db, $prefixe)) {
170
171
		if (!is_array($auth)) {
172
			// compatibilite version 0.7 initiale
173
			$g['ldap'] = $auth;
174
			$auth = array('ldap' => $auth);
175
		}
176
		$g['authentification'] = $auth;
177
		$g['type'] = $type;
178
		return $db_ok = $g;
179
	}
180
	// En cas d'indisponibilite du serveur, eviter de le bombarder
181
	if (!defined('_ECRIRE_INSTALL')) {
182
		@touch($f);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
183
		spip_log("Echec connexion serveur $type : host[$host] port[$port] login[$login] base[$db]", $type);
184
	}
185
}
186
187
// Premiere connexion au serveur principal:
188
// retourner le charset donnee par la table principale
189
// mais verifier que le fichier de connexion n'est pas trop vieux
190
// Version courante = 0.7 
191
// La version 0.7 indique un serveur d'authentification comme 8e arg
192
// La version 0.6 indique le prefixe comme 7e arg
193
// La version 0.5 indique le serveur comme 6e arg
194
//
195
// La version 0.0 (non numerotee) doit etre refaite par un admin
196
// les autres fonctionnent toujours, meme si :
197
// - la version 0.1 est moins performante que la 0.2
198
// - la 0.2 fait un include_ecrire('inc_db_mysql.php3').
199
200
// http://doc.spip.org/@spip_connect_main
201
function spip_connect_main($connexion)
202
{
203
	if ($GLOBALS['spip_connect_version']< 0.1 AND _DIR_RESTREINT){
204
		include_spip('inc/headers');
205
		redirige_url_ecrire('upgrade', 'reinstall=oui');
206
	}
207
208
	if (!($f = $connexion['select'])) return false;
209
	if (!$r = $f('valeur','spip_meta', "nom='charset_sql_connexion'"))
210
		return false;
211
	if (!($f = $connexion['fetch'])) return false;
212
	$r = $f($r);
213
	return ($r['valeur'] ? $r['valeur'] : -1);
214
}
215
216
// compatibilite
217
function spip_connect_ldap($serveur='') {
218
	include_spip('auth/ldap');
219
	return auth_ldap_connect($serveur);
220
}
221
222
// 1 interface de abstract_sql a demenager dans base/abstract_sql a terme
223
224
// http://doc.spip.org/@_q
225
function _q ($a) {
226
	return (is_numeric($a)) ? strval($a) :
227
		(!is_array($a) ? ("'" . addslashes($a) . "'")
228
		 : join(",", array_map('_q', $a)));
229
}
230
231
// Nommage bizarre des tables d'objets
232
// http://doc.spip.org/@table_objet
233
function table_objet($type) {
234
	static $surnoms = null;
235
	if (!$type) return;
236
	if (!$surnoms){
237
		// passer dans un pipeline qui permet aux plugins de declarer leurs exceptions
238
		$surnoms = pipeline('declarer_tables_objets_surnoms',
239
			array(
240
				'article' => 'articles',
241
				'auteur' => 'auteurs',
242
				'breve' => 'breves',
243
				'document' => 'documents',
244
				'doc' => 'documents', # pour les modeles
245
				'img' => 'documents',
246
				'emb' => 'documents',
247
				'groupe_mots' => 'groupes_mots', # hum
248
				'groupe_mot' => 'groupes_mots', # hum
249
				'groupe' => 'groupes_mots', # hum (EXPOSE)
250
				'message' => 'messages',
251
				'mot' => 'mots',
252
				'petition' => 'petitions',
253
				'rubrique' => 'rubriques',
254
				'signature' => 'signatures',
255
				'syndic' => 'syndic',
256
				'site' => 'syndic', # hum hum
257
				'syndic_article' => 'syndic_articles',
258
				'type_document' => 'types_documents', # hum
259
				'extension' => 'types_documents' # hum
260
			));
261
	}
262
	return isset($surnoms[$type])
263
		? $surnoms[$type]
264
		: preg_replace(',ss$,', 's', $type."s");
265
}
266
267
// http://doc.spip.org/@table_objet_sql
268
function table_objet_sql($type) {
269
	global $table_des_tables;
270
	$nom = table_objet($type);
271
	include_spip('public/interfaces');
272
	if (isset($table_des_tables[$nom])) {
273
		$t = $table_des_tables[$nom];
274
		$nom = 'spip_' . $t;
275
	}
276
	return $nom ;
277
}
278
279
// http://doc.spip.org/@id_table_objet
280
function id_table_objet($type,$serveur='') {
281
	$type = preg_replace(',^spip_|s$,', '', $type);
282
	if ($type == 'type')
283
		return 'extension';
284
	else {
285
		if (!$type) return;
286
		$t = table_objet($type);
287
		$trouver_table = charger_fonction('trouver_table', 'base');
288
		$desc = $trouver_table($t,$serveur);
289
		return @$desc['key']["PRIMARY KEY"];
290
	}
291
}
292
293
// http://doc.spip.org/@objet_type
294
function objet_type($table_objet){
295
	static $surnoms = null;
296
	if (!$surnoms){
297
		// passer dans un pipeline qui permet aux plugins de declarer leurs exceptions
298
		$surnoms = pipeline('declarer_type_surnoms', array());
299
	}
300
	
301
	// scenario de base
302
	// le type est decline a partir du nom de la table en enlevant le prefixe eventuel
303
	// et la marque du pluriel
304
	$type = preg_replace(',^spip_|s$,', '', $table_objet);
305
	if (isset($surnoms[$type]))
306
		return $surnoms[$type];
307
308
	// si le type redonne bien la table c'est bon
309
	if ( (table_objet($type)==$table_objet)
310
	  OR (table_objet_sql($type)==$table_objet))
311
	  return $type;
312
313
	// sinon on passe par la cle primaire id_xx pour trouver le type
314
	// car le s a la fin est incertain
315
	// notamment en cas de pluriel derogatoire
316
	// id_jeu/spip_jeux id_journal/spip_journaux qui necessitent tout deux
317
	// une declaration jeu => jeux, journal => journaux
318
	// dans le pipeline declarer_tables_objets_surnoms
319
	$trouver_table = charger_fonction('trouver_table', 'base');
320
	if ($desc = $trouver_table($table_objet)
321
	  AND isset($desc['key']["PRIMARY KEY"])){
322
		$primary = $desc['key']["PRIMARY KEY"];
323
		$primary = explode(',',$primary);
324
		$primary = reset($primary);
325
		$type = preg_replace(',^id_,', '', $primary);
326
	}
327
	// on a fait ce qu'on a pu
328
	return $type;
329
}
330
331
// Recuperer le nom de la table de jointure xxxx sur l'objet yyyy
332
// http://doc.spip.org/@table_jointure
333
function table_jointure($x, $y) {
334
	$trouver_table = charger_fonction('trouver_table', 'base');
335
	$xdesc = $trouver_table(table_objet($x));
336
	$ydesc = $trouver_table(table_objet($y));
337
	$tx = $xdesc['table'];
338
	$ty = $ydesc['table'];
339
	$ix = @$xdesc['key']["PRIMARY KEY"];
340
	$iy = @$ydesc['key']["PRIMARY KEY"];
341
	if ($table = $GLOBALS['tables_jointures'][$ty][$ix]) return $table;
342
	if ($table = $GLOBALS['tables_jointures'][$tx][$iy]) return $table;
343
	return '';
344
}
345
346
/**
347
 * Echapper les textes entre ' ' ou " " d'une requete SQL
348
 * avant son pre-traitement
349
 * On renvoi la query sans textes et les textes separes, dans
350
 * leur ordre d'apparition dans la query
351
 *
352
 * @param string $query
353
 * @return array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<string|false|array>.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
354
 */
355
function query_echappe_textes($query){
356
	static $codeEchappements = array("''"=>"\x1@##@\x1", "\'"=>"\x2@##@\x2", "\\\""=>"\x3@##@\x3");
357
	$query = str_replace(array_keys($codeEchappements), array_values($codeEchappements), $query);
358
	if (preg_match_all("/((['])[^']*(\\2))|(([\"])[^\"]*(\\5))/S",$query,$textes)){
359
		$textes = reset($textes); // indice 0 du match
360
		switch(count($textes)){
361
			case 0:$replace=array();break;
362
			case 1:$replace=array('%1$s');break;
363
			case 2:$replace=array('%1$s','%2$s');break;
364
			case 3:$replace=array('%1$s','%2$s','%3$s');break;
365
			case 4:$replace=array('%1$s','%2$s','%3$s','%4$s');break;
366
			case 5:$replace=array('%1$s','%2$s','%3$s','%4$s','%5$s');break;
367
			default:
368
				$replace = range(1,count($textes));
369
				$replace = '%'.implode('$s,%',$replace).'$s';
370
				$replace = explode(',',$replace);
371
				break;
372
		}
373
		$query = str_replace($textes,$replace,$query);
374
	}
375
	else
376
		$textes = array();
377
378
	return array($query, $textes);
379
}
380
381
/**
382
 * Reinjecter les textes d'une requete SQL a leur place initiale,
383
 * apres traitement de la requete
384
 *
385
 * @param string $query
386
 * @param array $textes
387
 * @return string
388
 */
389
function query_reinjecte_textes($query, $textes){
390
	static $codeEchappements = array("''"=>"\x1@##@\x1", "\'"=>"\x2@##@\x2", "\\\""=>"\x3@##@\x3");
391
	# debug de la substitution
392
	#if (($c1=substr_count($query,"%"))!=($c2=count($textes))){
393
	#	spip_log("$c1 ::". $query,"tradquery"._LOG_ERREUR);
394
	#	spip_log("$c2 ::". var_export($textes,1),"tradquery"._LOG_ERREUR);
395
	#	spip_log("ini ::". $qi,"tradquery"._LOG_ERREUR);
396
	#}
397
	switch (count($textes)){
398
		case 0:break;
399
		case 1:$query=sprintf($query,$textes[0]);break;
400
		case 2:$query=sprintf($query,$textes[0],$textes[1]);break;
401
		case 3:$query=sprintf($query,$textes[0],$textes[1],$textes[2]);break;
402 View Code Duplication
		case 4:$query=sprintf($query,$textes[0],$textes[1],$textes[2],$textes[3]);break;
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...
403 View Code Duplication
		case 5:$query=sprintf($query,$textes[0],$textes[1],$textes[2],$textes[3],$textes[4]);break;
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...
404
		default:
405
			array_unshift($textes,$query);
406
			$query = call_user_func_array('sprintf',$textes);
407
			break;
408
	}
409
410
	$query = str_replace(array_values($codeEchappements), array_keys($codeEchappements), $query);
411
412
	return $query;
413
}
414
415
// Pour compatibilite. Ne plus utiliser.
416
// http://doc.spip.org/@spip_query
417
function spip_query($query, $serveur='') {
418
	global $spip_sql_version;
419
	$f = spip_connect_sql($spip_sql_version, 'query', $serveur, true);
420
	return function_exists($f) ? $f($query, $serveur) : false;
421
}
422
423
?>
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...
424