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

propres.php ➔ urls_propres_dist()   F

Complexity

Conditions 31
Paths 4111

Size

Total Lines 140
Code Lines 85

Duplication

Lines 42
Ratio 30 %

Importance

Changes 0
Metric Value
cc 31
eloc 85
nc 4111
nop 4
dl 42
loc 140
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
define('URLS_PROPRES_EXEMPLE', 'Titre-de-l-article -Rubrique-');
16
17
// TODO: une interface permettant de verifier qu'on veut effectivment modifier
18
// une adresse existante
19
define('CONFIRMER_MODIFIER_URL', false);
20
21
/*
22
23
- Comment utiliser ce jeu d'URLs ?
24
25
Recopiez le fichier "htaccess.txt" du repertoire de base du site SPIP sous
26
le sous le nom ".htaccess" (attention a ne pas ecraser d'autres reglages
27
que vous pourriez avoir mis dans ce fichier) ; si votre site est en
28
"sous-repertoire", vous devrez aussi editer la ligne "RewriteBase" ce fichier.
29
Les URLs definies seront alors redirigees vers les fichiers de SPIP.
30
31
Dans les pages de configuration, choisissez 'propres' comme type d'url
32
33
SPIP calculera alors ses liens sous la forme
34
	"Mon-titre-d-article".
35
36
La variante 'propres2' ajoutera '.html' aux adresses generees : 
37
	"Mon-titre-d-article.html"
38
39
Variante 'qs' (experimentale) : ce systeme fonctionne en "Query-String",
40
c'est-a-dire sans utilisation de .htaccess ; les adresses sont de la forme
41
	"/?Mon-titre-d-article"
42
*/
43
44
define ('_terminaison_urls_propres', '');
45
define ('_debut_urls_propres', '');
46
47
// option pour tout passer en minuscules
48
define ('_url_minuscules',0);
49
50
// pour choisir le caractere de separation titre-id en cas de doublon
51
// (ne pas utiliser '/')
52
define ('_url_propres_sep_id',',');
53
54
// Ces chaines servaient de marqueurs a l'epoque ou les URL propres devaient
55
// indiquer la table ou les chercher (articles, auteurs etc),
56
// et elles etaient retirees par les preg_match dans la fonction ci-dessous.
57
// Elles peuvent a present etre definies a "" pour avoir des URL plus jolies.
58
// Les preg_match restent necessaires pour gerer les anciens signets.
59
60
define('_MARQUEUR_URL', serialize(array('rubrique1' => '-', 'rubrique2' => '-', 'breve1' => '+', 'breve2' => '+', 'site1' => '@', 'site2' => '@', 'auteur1' => '_', 'auteur2' => '_', 'mot1' => '+-', 'mot2' => '-+')));
61
62
// Retire les marqueurs de type dans une URL propre ancienne maniere
63
64
// http://doc.spip.org/@retirer_marqueurs_url_propre
65
function retirer_marqueurs_url_propre($url_propre) {
66
	if (preg_match(',^[+][-](.*?)[-][+]$,', $url_propre, $regs)) {
67
		return $regs[1];
68
	}
69
	else if (preg_match(',^([-+_@])(.*?)\1?$,', $url_propre, $regs)) {
70
		return $regs[2];
71
	}
72
	// les articles n'ont pas de marqueur
73
	return $url_propre;
74
}
75
76
77
// Pipeline pour creation d'une adresse : il recoit l'url propose par le
78
// precedent, un tableau indiquant le titre de l'objet, son type, son id,
79
// et doit donner en retour une chaine d'url, sans se soucier de la
80
// duplication eventuelle, qui sera geree apres
81
// http://doc.spip.org/@creer_chaine_url
82 View Code Duplication
function urls_propres_creer_chaine_url($x) {
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...
83
	// NB: ici url_old ne sert pas, mais un plugin qui ajouterait une date
84
	// pourrait l'utiliser pour juste ajouter la 
85
	$url_old = $x['data'];
0 ignored issues
show
Unused Code introduced by
$url_old 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...
86
	$objet = $x['objet'];
87
	include_spip('inc/filtres');
88
	if (!defined('_URLS_PROPRES_MAX')) define('_URLS_PROPRES_MAX', 35);
89
	if (!defined('_URLS_PROPRES_MIN')) define('_URLS_PROPRES_MIN', 3);
90
91
	include_spip('action/editer_url');
92
	if (!$url = url_nettoyer($objet['titre'],_URLS_PROPRES_MAX,_URLS_PROPRES_MIN,'-',_url_minuscules?'strtolower':''))
93
		$url = $objet['type'].$objet['id_objet'];
94
95
	$x['data'] = $url;
96
97
	return $x;
98
}
99
100
// Trouver l'URL associee a la n-ieme cle primaire d'une table SQL
101
102
// http://doc.spip.org/@declarer_url_propre
103
function declarer_url_propre($type, $id_objet) {
104
	$trouver_table = charger_fonction('trouver_table', 'base');
105
	$desc = $trouver_table(table_objet($type));
106
	$champ_titre = $desc['titre'];
107
	$col_id =  @$desc['key']["PRIMARY KEY"];
108
	//  $type doit designer une table, avec champ indiquant un titre
109
	if (!$col_id OR !$champ_titre) return false; 
110
111
	$table = $desc['table'];
112
	$id_objet = intval($id_objet);
113
114
	//  Recuperer une URL propre correspondant a l'objet.
115
	$row = sql_fetsel("U.url, U.date, O.$champ_titre", "$table AS O LEFT JOIN spip_urls AS U ON (U.type='$type' AND U.id_objet=O.$col_id)", "O.$col_id=$id_objet", '', 'U.date DESC', 1);
116
117
	if (!$row) return ""; # Quand $id_objet n'est pas un numero connu
118
119
	$url_propre = $row['url'];
120
121
	// Se contenter de cette URL si elle existe ;
122
	// sauf si on invoque par "voir en ligne" avec droit de modifier l'url
123
124
	// l'autorisation est verifiee apres avoir calcule la nouvelle url propre
125
	// car si elle ne change pas, cela ne sert a rien de verifier les autorisations
126
	// qui requetent en base
127
	$modifier_url = $GLOBALS['var_urls'];
128
	if ($url_propre AND !$modifier_url)
129
		return $url_propre;
130
131
	// Sinon, creer une URL
132
	$url = pipeline('propres_creer_chaine_url',
133
		array(
134
			'data' => $url_propre,  // le vieux url_propre
135
			'objet' => array_merge($row,
136
				array('type' => $type, 'id_objet' => $id_objet)
137
			)
138
		)
139
	);
140
141
	// Eviter de tamponner les URLs a l'ancienne (cas d'un article
142
	// intitule "auteur2")
143
	include_spip('inc/urls');
144
	$objets = urls_liste_objets();
145 View Code Duplication
	if (preg_match(',^('.$objets.')[0-9]+$,', $url, $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...
146
	AND $r[1] != $type)
147
		$url = $url._url_propres_sep_id.$id_objet;
148
149
	// Pas de changement d'url
150
	if ($url == $url_propre)
151
		return $url_propre;
152
153
	// verifier l'autorisation, maintenant qu'on est sur qu'on va agir
154
	if ($modifier_url) {
155
		include_spip('inc/autoriser');
156
		$modifier_url = autoriser('modifierurl', $type, $id_objet);
157
	}
158
159
	// Verifier si l'utilisateur veut effectivement changer l'URL
160 View Code Duplication
	if ($modifier_url
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...
161
		AND CONFIRMER_MODIFIER_URL
162
		AND $url_propre
163
		AND $url != preg_replace('/,.*/', '', $url_propre))
164
		$confirmer = true;
165
	else
166
		$confirmer = false;
167
168
	if ($confirmer AND !_request('ok')) {
169
		die ("vous changez d'url ? $url_propre -&gt; $url");
0 ignored issues
show
Coding Style Compatibility introduced by
The function declarer_url_propre() 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...
170
	}
171
172
	$set = array('url' => $url, 'type' => $type, 'id_objet' => $id_objet);
173
	include_spip('action/editer_url');
174
	if (!url_insert($set,$confirmer,_url_propres_sep_id))
175
		return $url_propre; //serveur out ? retourner au mieux
176
177
	return $set['url'];
178
}
179
180
// http://doc.spip.org/@_generer_url_propre
181
function _generer_url_propre($type, $id, $args='', $ancre='') {
182 View Code Duplication
	if ($generer_url_externe = charger_fonction("generer_url_$type",'urls',true)) {
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...
183
		$url = $generer_url_externe($id, $args, $ancre);
184
		if (NULL != $url) return $url;
185
	}
186
187
	if ($type == 'document') {
188
		include_spip('inc/documents');
189
		return generer_url_document_dist($id, $args, $ancre);
190
	}
191
192
	// Mode compatibilite pour conserver la distinction -Rubrique-
193 View Code Duplication
	if (_MARQUEUR_URL) {
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...
194
		$marqueur = unserialize(_MARQUEUR_URL);
195
		$marqueur1 = $marqueur[$type.'1']; // debut '+-'
196
		$marqueur2 = $marqueur[$type.'2']; // fin '-+'
197
	} else
198
		$marqueur1 = $marqueur2 = '';
199
	// fin
200
201
	// Mode propre
202
	$propre = declarer_url_propre($type, $id);
203
204
	if ($propre === false) return ''; // objet inconnu. raccourci ? 
205
206
	if ($propre) {
207
		$url = _debut_urls_propres
208
			. $marqueur1
209
			. $propre
210
			. $marqueur2
211
			. _terminaison_urls_propres;
212
213
		// Repositionne l'URL par rapport a la racine du site (#GLOBALS)
214
		$url = str_repeat('../', $GLOBALS['profondeur_url']).$url;
215 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...
216
217
		// objet connu mais sans possibilite d'URL lisible, revenir au defaut
218
		include_spip('base/connect_sql');
219
		$id_type = id_table_objet($type);
220
		$url = _DIR_RACINE . get_spip_script('./')."?"._SPIP_PAGE."=$type&$id_type=$id";
221
	}
222
223
	// Ajouter les args
224 View Code Duplication
	if ($args)
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...
225
		$url .= ((strpos($url, '?')===false) ? '?' : '&') . $args;
226
227
	// Ajouter l'ancre
228
	if ($ancre)
229
		$url .= "#$ancre";
230
231
	return $url;
232
}
233
234
// retrouve le fond et les parametres d'une URL propre
235
// ou produit une URL propre si on donne un parametre
236
// @return array([contexte],[type],[url_redirect],[fond]) : url decodee
237
// http://doc.spip.org/@urls_propres_dist
238
function urls_propres_dist($i, $entite, $args='', $ancre='') {
239
240
	if (is_numeric($i))
241
		return _generer_url_propre($entite, $i, $args, $ancre);
242
243
	$url = $i;
244
	$id_objet = $type = 0;
0 ignored issues
show
Unused Code introduced by
$id_objet 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...
245
	$url_redirect = null;
246
	// recuperer les &debut_xx;
247
	if (is_array($args))
248
		$contexte = $args;
249
	else
250
		parse_str($args,$contexte);
251
252
253
	// Migration depuis anciennes URLs ?
254
	// traiter les injections domain.tld/spip.php/n/importe/quoi/rubrique23
255 View Code Duplication
	if ($GLOBALS['profondeur_url']<=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...
256
	AND $_SERVER['REQUEST_METHOD'] != 'POST') {
257
		include_spip('inc/urls');
258
		$r = nettoyer_url_page($i, $contexte);
0 ignored issues
show
Bug introduced by
It seems like $contexte can also be of type null; however, nettoyer_url_page() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
259
		if ($r) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $r 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...
260
			list($contexte, $type,,, $suite) = $r;
261
			$_id = id_table_objet($type);
262
			$id_objet = $contexte[$_id];
263
			$url_propre = generer_url_entite($id_objet, $type);
264
			if (strlen($url_propre)
265
			AND !strstr($url,$url_propre)) {
266
				list(,$hash) = explode('#', $url_propre);
267
				$args = array();
268
				foreach(array_filter(explode('&', $suite)) as $fragment) {
269
					if ($fragment != "$_id=$id_objet")
270
						$args[] = $fragment;
271
				}
272
				$url_redirect = generer_url_entite($id_objet, $type, join('&',array_filter($args)), $hash);
273
274
				return array($contexte, $type, $url_redirect, $type);
275
			}
276
		}
277
	}
278
	/* Fin compatibilite anciennes urls */
279
	// Chercher les valeurs d'environnement qui indiquent l'url-propre
280 View Code Duplication
	if (isset($_SERVER['REDIRECT_url_propre']))
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...
281
		$url_propre = $_SERVER['REDIRECT_url_propre'];
282
	elseif (isset($_ENV['url_propre']))
283
		$url_propre = $_ENV['url_propre'];
284
	else {
285
		// ne prendre que le segment d'url qui correspond, en fonction de la profondeur calculee
286
		$url = ltrim($url,'/');
287
		$url = explode('/',$url);
288
		while (count($url)>$GLOBALS['profondeur_url']+1)
289
			array_shift($url);
290
		$url = implode('/',$url);
291
		$url_propre = preg_replace(',[?].*,', '', $url);
292
	}
293
294
	// Mode Query-String ?
295
	$is_qs = false;
296
	if (!$url_propre
297
	AND preg_match(',[?]([^=/?&]+)(&.*)?$,', $url, $r)) {
298
		$url_propre = $r[1];
299
		$is_qs = true;
300
	}
301
302
	if (!$url_propre) return; // qu'est-ce qu'il veut ???
303
	
304
	// gerer le cas de retour depuis des urls arbos
305
	// mais si url arbo ne trouve pas, on veut une 404 par securite
306
	if ($GLOBALS['profondeur_url']>0){
307
		$urls_anciennes = charger_fonction('arbo','urls');
308
		return $urls_anciennes($url_propre, $entite, $contexte);
309
	}
310
	
311
	include_spip('base/abstract_sql'); // chercher dans la table des URLS
312
313
	// Compatibilite avec propres2
314
	$url_propre = preg_replace(',\.html$,i', '', $url_propre);
315
316
	// Revenir en utf-8 si encodage type %D8%A7 (farsi)
317
	$url_propre = rawurldecode($url_propre);
318
319
	// Compatibilite avec les anciens marqueurs d'URL propres
320
	// Tester l'entree telle quelle (avec 'url_libre' des sites ont pu avoir des entrees avec marqueurs dans la table spip_urls)
321
	if (!$row = sql_fetsel('id_objet, type, date', 'spip_urls', 'url='.sql_quote($url_propre))) {
322
		// Sinon enlever les marqueurs eventuels
323
		$url_propre2 = retirer_marqueurs_url_propre($url_propre);
324
325
		$row = sql_fetsel('id_objet, type, date', 'spip_urls', 'url='.sql_quote($url_propre2));
326
	}
327
328
	if ($row) {
329
		$type = $row['type'];
330
		$col_id = id_table_objet($type);
331
		$contexte[$col_id] = $row['id_objet'];
332
		$entite = $row['type'];
333
334
		// Si l'url est vieux, donner le nouveau
335
		if ($recent = sql_fetsel('url, date', 'spip_urls',
336
		'type='.sql_quote($row['type']).' AND id_objet='.sql_quote($row['id_objet'])
337
		.' AND date>'.sql_quote($row['date']), '', 'date DESC', 1)) {
338
			// Mode compatibilite pour conserver la distinction -Rubrique-
339 View Code Duplication
			if (_MARQUEUR_URL) {
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...
340
				$marqueur = unserialize(_MARQUEUR_URL);
341
				$marqueur1 = $marqueur[$type.'1']; // debut '+-'
342
				$marqueur2 = $marqueur[$type.'2']; // fin '-+'
343
			} else
344
				$marqueur1 = $marqueur2 = '';
345
			$url_redirect = $marqueur1 . $recent['url'] . $marqueur2;
346
		}
347
	}
348
349
	if ($entite=='' OR $entite=='type_urls' /* compat .htaccess 2.0 */) {
350
		if ($type) {
351
			$entite =  ($type == 'syndic') ?  'site' : $type;
352
		} else {
353
			// Si ca ressemble a une URL d'objet, ce n'est pas la home
354
			// et on provoque un 404
355
			if (preg_match(',^.*/[^\.]+(\.html)?$,', $url)) {
356
				$entite = '404';
357
				$contexte['erreur'] = '';
358
359
				// l'url n'existe pas...
360
				// on ne sait plus dire de quel type d'objet il s'agit
361
				// sauf si on a le marqueur. et la c'est un peu sale...
362
				if (_MARQUEUR_URL) {
363
					$fmarqueur = @array_flip(unserialize(_MARQUEUR_URL));
364
					preg_match(',^([+][-]|[-+@_]),', $url_propre, $regs);
365
					$objet = $regs ? substr($fmarqueur[$regs[1]],0,n-1) : 'article';
366
					$contexte['erreur'] = _T(
367
						($objet=='rubrique' OR $objet=='breve')
368
							? 'public:aucune_'.$objet
369
							: 'public:aucun_'.$objet
370
					);
371
				}
372
			}
373
		}
374
	}
375
376
	return array($contexte, $entite, $url_redirect, $is_qs?$entite:null);
377
}
378
379
?>
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...
380