Completed
Push — master ( 5a91ad...cf2deb )
by cam
04:25
created

fonctions.php ➔ filtre_pagination_affiche_texte_lien_page_dist()   B

Complexity

Conditions 10
Paths 10

Size

Total Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 10
nc 10
nop 3
dl 0
loc 25
rs 7.6666
c 0
b 0
f 0

How to fix   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, Système de publication pour l'internet                           *
5
 *                                                                         *
6
 *  Copyright © avec tendresse depuis 2001                                 *
7
 *  Arnaud Martin, Antoine Pitrou, Philippe Rivière, Emmanuel Saint-James  *
8
 *                                                                         *
9
 *  Ce programme est un logiciel libre distribué sous licence GNU/GPL.     *
10
 *  Pour plus de détails voir le fichier COPYING.txt ou l'aide en ligne.   *
11
\***************************************************************************/
12
13
/**
14
 * Des fonctions diverses utilisees lors du calcul d'une page ; ces fonctions
15
 * bien pratiques n'ont guere de logique organisationnelle ; elles sont
16
 * appelees par certaines balises ou criteres au moment du calcul des pages. (Peut-on
17
 * trouver un modele de donnees qui les associe physiquement au fichier
18
 * definissant leur balise ???)
19
 *
20
 * Ce ne sont pas des filtres à part entière, il n'est donc pas logique de les retrouver dans inc/filtres
21
 *
22
 * @package SPIP\Core\Compilateur\Composer
23
 **/
24
25
if (!defined('_ECRIRE_INC_VERSION')) {
26
	return;
27
}
28
29
30
/**
31
 * Calcul d'une introduction
32
 *
33
 * L'introduction est prise dans le descriptif s'il est renseigné,
34
 * sinon elle est calculée depuis le texte : à ce moment là,
35
 * l'introduction est prise dans le contenu entre les balises
36
 * `<intro>` et `</intro>` si présentes, sinon en coupant le
37
 * texte à la taille indiquée.
38
 *
39
 * Cette fonction est utilisée par la balise #INTRODUCTION
40
 *
41
 * @param string $descriptif
42
 *     Descriptif de l'introduction
43
 * @param string $texte
44
 *     Texte à utiliser en absence de descriptif
45
 * @param string $longueur
46
 *     Longueur de l'introduction
47
 * @param string $connect
48
 *     Nom du connecteur à la base de données
49
 * @param string $suite
0 ignored issues
show
Documentation introduced by
Should the type for parameter $suite not be string|null?

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...
50
 *     points de suite si on coupe (par defaut _INTRODUCTION_SUITE et sinon &nbsp;(...)
51
 * @return string
52
 *     Introduction calculée
53
 **/
54
function filtre_introduction_dist($descriptif, $texte, $longueur, $connect, $suite = null) {
55
	// Si un descriptif est envoye, on l'utilise directement
56
	if (strlen($descriptif)) {
57
		return appliquer_traitement_champ($descriptif, 'introduction', '', array(), $connect);
58
	}
59
60
	// De preference ce qui est marque <intro>...</intro>
61
	$intro = '';
62
	$texte = preg_replace(",(</?)intro>,i", "\\1intro>", $texte); // minuscules
63
	while ($fin = strpos($texte, "</intro>")) {
64
		$zone = substr($texte, 0, $fin);
65
		$texte = substr($texte, $fin + strlen("</intro>"));
66
		if ($deb = strpos($zone, "<intro>") or substr($zone, 0, 7) == "<intro>") {
67
			$zone = substr($zone, $deb + 7);
68
		}
69
		$intro .= $zone;
70
	}
71
72
	// [12025] On ne *PEUT* pas couper simplement ici car c'est du texte brut,
73
	// qui inclus raccourcis et modeles
74
	// un simple <articlexx> peut etre ensuite transforme en 1000 lignes ...
75
	// par ailleurs le nettoyage des raccourcis ne tient pas compte
76
	// des surcharges et enrichissement de propre
77
	// couper doit se faire apres propre
78
	//$texte = nettoyer_raccourcis_typo($intro ? $intro : $texte, $connect);
79
80
	// Cependant pour des questions de perfs on coupe quand meme, en prenant
81
	// large et en se mefiant des tableaux #1323
82
83
	if (strlen($intro)) {
84
		$texte = $intro;
85
	} else {
86
		if (strpos("\n" . $texte, "\n|") === false
87
			and strlen($texte) > 2.5 * $longueur
88
		) {
89
			if (strpos($texte, "<multi") !== false) {
90
				$texte = extraire_multi($texte);
91
			}
92
			$texte = couper($texte, 2 * $longueur);
93
		}
94
	}
95
96
	// ne pas tenir compte des notes
97
	if ($notes = charger_fonction('notes', 'inc', true)) {
98
		$notes('', 'empiler');
99
	}
100
	// Supprimer les modèles avant le propre afin d'éviter qu'ils n'ajoutent du texte indésirable
101
	// dans l'introduction.
102
	$texte = supprime_img($texte, '');
103
	$texte = appliquer_traitement_champ($texte, 'introduction', '', array(), $connect);
104
105
	if ($notes) {
106
		$notes('', 'depiler');
107
	}
108
109
	if (is_null($suite) and defined('_INTRODUCTION_SUITE')) {
110
		$suite = _INTRODUCTION_SUITE;
111
	}
112
	$texte = couper($texte, $longueur, $suite);
113
	// comme on a coupe il faut repasser la typo (on a perdu les insecables)
114
	$texte = typo($texte, true, $connect, array());
115
116
	// et reparagrapher si necessaire (coherence avec le cas descriptif)
117
	// une introduction a tojours un <p>
118
	if ($GLOBALS['toujours_paragrapher']) // Fermer les paragraphes
119
	{
120
		$texte = paragrapher($texte, $GLOBALS['toujours_paragrapher']);
121
	}
122
123
	return $texte;
124
}
125
126
127
/**
128
 * Filtre calculant une pagination, utilisé par la balise `#PAGINATION`
129
 *
130
 * Le filtre cherche le modèle `pagination.html` par défaut, mais peut
131
 * chercher un modèle de pagination particulier avec l'argument `$modele`.
132
 * S'il `$modele='prive'`, le filtre cherchera le modèle `pagination_prive.html`.
133
 *
134
 * @filtre
135
 * @see balise_PAGINATION_dist()
136
 *
137
 * @param int $total
138
 *     Nombre total d'éléments
139
 * @param string $nom
140
 *     Nom identifiant la pagination
141
 * @param int $position
142
 *     Page à afficher (tel que la 3è page)
143
 * @param int $pas
144
 *     Nombre d'éléments par page
145
 * @param bool $liste
146
 *     - True pour afficher toute la liste des éléments,
147
 *     - False pour n'afficher que l'ancre
148
 * @param string $modele
149
 *     Nom spécifique du modèle de pagination
150
 * @param string $connect
151
 *     Nom du connecteur à la base de données
152
 * @param array $env
153
 *     Environnement à transmettre au modèle
154
 * @return string
155
 *     Code HTML de la pagination
156
 **/
157
function filtre_pagination_dist(
158
	$total,
159
	$nom,
160
	$position,
161
	$pas,
162
	$liste = true,
163
	$modele = '',
164
	$connect = '',
165
	$env = array()
166
) {
167
	static $ancres = array();
168
	if ($pas < 1) {
169
		return '';
170
	}
171
	$ancre = 'pagination' . $nom; // #pagination_articles
172
	$debut = 'debut' . $nom; // 'debut_articles'
173
174
	// n'afficher l'ancre qu'une fois
175
	if (!isset($ancres[$ancre])) {
176
		$bloc_ancre = $ancres[$ancre] = "<a id='" . $ancre . "' class='pagination_ancre'></a>";
177
	} else {
178
		$bloc_ancre = '';
179
	}
180
	// liste = false : on ne veut que l'ancre
181
	if (!$liste) {
182
		return $ancres[$ancre];
183
	}
184
185
	$self = (empty($env['self']) ? self() : $env['self']);
186
	$pagination = array(
187
		'debut' => $debut,
188
		'url' => parametre_url($self, 'fragment', ''), // nettoyer l'id ahah eventuel
189
		'total' => $total,
190
		'position' => intval($position),
191
		'pas' => $pas,
192
		'nombre_pages' => floor(($total - 1) / $pas) + 1,
193
		'page_courante' => floor(intval($position) / $pas) + 1,
194
		'ancre' => $ancre,
195
		'bloc_ancre' => $bloc_ancre
196
	);
197
	if (is_array($env)) {
198
		$pagination = array_merge($env, $pagination);
199
	}
200
201
	// Pas de pagination
202
	if ($pagination['nombre_pages'] <= 1) {
203
		return '';
204
	}
205
206
	if ($modele) {
207
		$pagination['type_pagination'] = $modele;
208
		if (trouver_fond('pagination_'.$modele, 'modeles')) {
209
			$modele = '_' . $modele;
210
		}
211
		else {
212
			$modele = '';
213
		}
214
	}
215
216
	if (!defined('_PAGINATION_NOMBRE_LIENS_MAX')) {
217
		define('_PAGINATION_NOMBRE_LIENS_MAX', 10);
218
	}
219
	if (!defined('_PAGINATION_NOMBRE_LIENS_MAX_ECRIRE')) {
220
		define('_PAGINATION_NOMBRE_LIENS_MAX_ECRIRE', 5);
221
	}
222
223
224
	return recuperer_fond("modeles/pagination$modele", $pagination, array('trim' => true), $connect);
225
}
226
227
228
/**
229
 * Calcule les bornes d'une pagination
230
 *
231
 * @filtre
232
 *
233
 * @param int $courante
234
 *     Page courante
235
 * @param int $nombre
236
 *     Nombre de pages
237
 * @param int $max
238
 *     Nombre d'éléments par page
239
 * @return int[]
0 ignored issues
show
Documentation introduced by
Should the return type not be array<integer|double>?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
240
 *     Liste (première page, dernière page).
241
 **/
242
function filtre_bornes_pagination_dist($courante, $nombre, $max = 10) {
243
	if ($max <= 0 or $max >= $nombre) {
244
		return array(1, $nombre);
245
	}
246
	if ($max <= 1) {
247
		return array($courante, $courante);
248
	}
249
250
	$premiere = max(1, $courante - floor(($max - 1) / 2));
251
	$derniere = min($nombre, $premiere + $max - 2);
252
	$premiere = $derniere == $nombre ? $derniere - $max + 1 : $premiere;
253
254
	return array($premiere, $derniere);
255
}
256
257
function filtre_pagination_affiche_texte_lien_page_dist($type_pagination, $numero_page, $rang_item) {
258
	if ($numero_page === 'tous') {
259
		return '&#8734;';
260
	}
261
	if ($numero_page === 'prev') {
262
		return '&lt;';
263
	}
264
	if ($numero_page === 'next') {
265
		return '&gt;';
266
	}
267
268
	switch ($type_pagination) {
269
		case 'resultats':
270
			return $rang_item + 1; // 1 11 21 31...
271
		case 'naturel':
272
			return $rang_item ? $rang_item : 1; // 1 10 20 30...
273
		case 'rang':
274
			return $rang_item; // 0 10 20 30...
275
276
		case 'page':
277
		case 'prive':
278
		default:
279
			return $numero_page; // 1 2 3 4 5...
280
	}
281
}
282
283
/**
284
 * Retourne pour une clé primaire d'objet donnée les identifiants ayant un logo
285
 *
286
 * @param string $type
287
 *     Nom de la clé primaire de l'objet
288
 * @return string
289
 *     Liste des identifiants ayant un logo (séparés par une virgule)
290
 **/
291
function lister_objets_avec_logos($type) {
292
293
	$objet = objet_type($type);
294
	$ids = sql_allfetsel("L.id_objet", "spip_documents AS D JOIN spip_documents_liens AS L ON L.id_document=D.id_document", "D.mode=".sql_quote('logoon')." AND L.objet=".sql_quote($objet));
295
	if ($ids) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $ids 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...
296
		$ids = array_column($ids, 'id_objet');
297
		return implode(',', $ids);
298
	}
299
	else {
300
		return "0";
301
	}
302
}
303
304
305
/**
306
 * Renvoie l'état courant des notes, le purge et en prépare un nouveau
307
 *
308
 * Fonction appelée par la balise `#NOTES`
309
 *
310
 * @see  balise_NOTES_dist()
311
 * @uses inc_notes_dist()
312
 *
313
 * @return string
314
 *     Code HTML des notes
315
 **/
316
function calculer_notes() {
317
	$r = '';
318
	if ($notes = charger_fonction('notes', 'inc', true)) {
319
		$r = $notes(array());
320
		$notes('', 'depiler');
321
		$notes('', 'empiler');
322
	}
323
324
	return $r;
325
}
326
327
328
/**
329
 * Retrouver le rang du lien entre un objet source et un obet lie
330
 * utilisable en direct dans un formulaire d'edition des liens, mais #RANG doit faire le travail automatiquement
331
 * [(#ENV{objet_source}|rang_lien{#ID_AUTEUR,#ENV{objet},#ENV{id_objet},#ENV{_objet_lien}})]
332
 *
333
 * @param $objet_source
334
 * @param $ids
335
 * @param $objet_lie
336
 * @param $idl
337
 * @param $objet_lien
338
 * @return string
339
 */
340
function retrouver_rang_lien($objet_source, $ids, $objet_lie, $idl, $objet_lien){
341
	$res = lister_objets_liens($objet_source, $objet_lie, $idl, $objet_lien);
342
	$res = array_column($res, 'rang_lien', $objet_source);
343
344
	return (isset($res[$ids]) ? $res[$ids] : '');
345
}
346
347
348
/**
349
 * Lister les liens en le memoizant dans une static
350
 * pour utilisation commune par lister_objets_lies et retrouver_rang_lien dans un formuluaire d'edition de liens
351
 * (evite de multiplier les requetes)
352
 *
353
 * @param $objet_source
354
 * @param $objet
355
 * @param $id_objet
356
 * @param $objet_lien
357
 * @return mixed
358
 * @private
359
 */
360
function lister_objets_liens($objet_source, $objet, $id_objet, $objet_lien) {
361
	static $liens = array();
362
	if (!isset($liens["$objet_source-$objet-$id_objet-$objet_lien"])) {
363
		include_spip('action/editer_liens');
364
		// quand $objet == $objet_lien == $objet_source on reste sur le cas par defaut de $objet_lien == $objet_source
365 View Code Duplication
		if ($objet_lien == $objet and $objet_lien !== $objet_source) {
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...
366
			$res = objet_trouver_liens(array($objet => $id_objet), array($objet_source => '*'));
367
		} else {
368
			$res = objet_trouver_liens(array($objet_source => '*'), array($objet => $id_objet));
369
		}
370
371
		$liens["$objet_source-$objet-$id_objet-$objet_lien"] = $res;
372
	}
373
	return $liens["$objet_source-$objet-$id_objet-$objet_lien"];
374
}
375
376
/**
377
 * Calculer la balise #RANG
378
 * quand ce n'est pas un champ rang :
379
 * peut etre le num titre, le champ rang_lien ou le rang du lien en edition des liens, a retrouver avec les infos du formulaire
380
 * @param $titre
381
 * @param $objet_source
382
 * @param $id
383
 * @param $env
384
 * @return int|string
385
 */
386
function calculer_rang_smart($titre, $objet_source, $id, $env) {
387
	// Cas du #RANG utilisé dans #FORMULAIRE_EDITER_LIENS -> attraper le rang du lien
388
	// permet de voir le rang du lien si il y en a un en base, meme avant un squelette xxxx-lies.html ne gerant pas les liens
389
	if (isset($env['form']) and $env['form']
390
		and isset($env['_objet_lien']) and $env['_objet_lien']
391
		and (function_exists('lien_triables') or include_spip('action/editer_liens'))
392
		and $r = objet_associable($env['_objet_lien'])
393
		and list($p, $table_lien) = $r
394
	  and lien_triables($table_lien)
395
	  and isset($env['objet']) and $env['objet']
396
		and isset($env['id_objet']) and $env['id_objet']
397
		and $objet_source
398
		and $id = intval($id)
399
	) {
400
		$rang = retrouver_rang_lien($objet_source, $id, $env['objet'], $env['id_objet'], $env['_objet_lien']);
401
		return ($rang ? $rang : '');
402
	}
403
	return recuperer_numero($titre);
404
}
405
406
407
/**
408
 * Proteger les champs passes dans l'url et utiliser dans {tri ...}
409
 * preserver l'espace pour interpreter ensuite num xxx et multi xxx
410
 * on permet d'utiliser les noms de champ prefixes
411
 * articles.titre
412
 * et les propriete json
413
 * properties.gis[0].ville
414
 *
415
 * @param string $t
416
 * @return string
417
 */
418
function tri_protege_champ($t) {
419
	return preg_replace(',[^\s\w.+\[\]],', '', $t);
420
}
421
422
/**
423
 * Interpreter les multi xxx et num xxx utilise comme tri
424
 * pour la clause order
425
 * 'multi xxx' devient simplement 'multi' qui est calcule dans le select
426
 *
427
 * @param string $t
428
 * @param array $from
0 ignored issues
show
Documentation introduced by
Should the type for parameter $from not be array|null? Also, consider making the array more specific, something like array<String>, or 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. In addition it looks for parameters that have the generic type array and suggests a stricter type like array<String>.

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

Loading history...
429
 * @return string
430
 */
431
function tri_champ_order($t, $from = null) {
432
	if (strncmp($t, 'multi ', 6) == 0) {
433
		return "multi";
434
	}
435
436
	$champ = $t;
437
438
	if (strncmp($t, 'num ', 4) == 0) {
439
		$champ = substr($t, 4);
440
	}
441
	// enlever les autres espaces non evacues par tri_protege_champ
442
	$champ = preg_replace(',\s,', '', $champ);
443
444
	if (is_array($from)) {
445
		$trouver_table = charger_fonction('trouver_table', 'base');
446
		foreach ($from as $idt => $table_sql) {
447
			if ($desc = $trouver_table($table_sql)
448
				and isset($desc['field'][$champ])
449
			) {
450
				$champ = "$idt.$champ";
451
				break;
452
			}
453
		}
454
	}
455
	if (strncmp($t, 'num ', 4) == 0) {
456
		return "0+$champ";
457
	} else {
458
		return $champ;
459
	}
460
}
461
462
/**
463
 * Interpreter les multi xxx et num xxx utilise comme tri
464
 * pour la clause select
465
 * 'multi xxx' devient select "...." as multi
466
 * les autres cas ne produisent qu'une chaine vide '' en select
467
 * 'hasard' devient 'rand() AS hasard' dans le select
468
 *
469
 * @param string $t
470
 * @return string
471
 */
472
function tri_champ_select($t) {
473
	if (strncmp($t, 'multi ', 6) == 0) {
474
		$t = substr($t, 6);
475
		$t = preg_replace(',\s,', '', $t);
476
		$t = sql_multi($t, $GLOBALS['spip_lang']);
477
478
		return $t;
479
	}
480
	if (trim($t) == 'hasard') {
481
		return 'rand() AS hasard';
482
	}
483
484
	return "''";
485
}
486
487
/**
488
 * Fonction de mise en forme utilisee par le critere {par_ordre_liste..}
489
 * @see critere_par_ordre_liste_dist()
490
 *
491
 * @param array $valeurs
492
 * @param string $serveur
493
 * @return string
494
 */
495
function formate_liste_critere_par_ordre_liste($valeurs, $serveur = ''){
496
	if (!is_array($valeurs)){
497
		return '';
498
	}
499
	$f = sql_serveur('quote', $serveur, true);
500
	if (!is_string($f) or !$f){
501
		return '';
502
	}
503
	$valeurs = implode(',', array_map($f, array_unique($valeurs)));
504
505
	return $valeurs;
506
}
507
508
/**
509
 * Applique un filtre s'il existe, sinon retourne la valeur par défaut indiquée
510
 *
511
 * @internal
512
 * @uses trouver_filtre_matrice()
513
 * @uses chercher_filtre()
514
 *
515
 * @param mixed $arg
516
 *     Texte (le plus souvent) sur lequel appliquer le filtre
517
 * @param string $filtre
518
 *     Nom du filtre à appliquer
519
 * @param array $args
520
 *     Arguments reçus par la fonction parente (appliquer_filtre ou appliquer_si_filtre).
521
 * @param mixed $defaut
522
 *     Valeur par défaut à retourner en cas d'absence du filtre.
523
 * @return string
524
 *     Texte traité par le filtre si le filtre existe,
525
 *     Valeur $defaut sinon.
526
 **/
527
function appliquer_filtre_sinon($arg, $filtre, $args, $defaut = '') {
528
	// Si c'est un filtre d'image, on utilise image_filtrer()
529
	// Attention : les 2 premiers arguments sont inversés dans ce cas
530
	if (trouver_filtre_matrice($filtre) and substr($filtre, 0, 6) == 'image_') {
531
		$args[1] = $args[0];
532
		$args[0] = $filtre;
533
		return image_graver(image_filtrer($args));
534
	}
535
536
	$f = chercher_filtre($filtre);
537
	if (!$f) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $f of type null|string is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
538
		return $defaut;
539
	}
540
	array_shift($args); // enlever $arg
541
	array_shift($args); // enlever $filtre
542
	array_unshift($args, $arg); // remettre $arg
543
	return call_user_func_array($f, $args);
544
}
545