Completed
Push — master ( b53681...7022b4 )
by cam
04:31
created

fonctions.php ➔ filtre_bornes_pagination_dist()   A

Complexity

Conditions 5
Paths 4

Size

Total Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
nc 4
nop 3
dl 0
loc 14
rs 9.4888
c 0
b 0
f 0
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
		$modele = '_' . $modele;
208
	}
209
210
	if (!defined('_PAGINATION_NOMBRE_LIENS_MAX')) {
211
		define('_PAGINATION_NOMBRE_LIENS_MAX', 10);
212
	}
213
	if (!defined('_PAGINATION_NOMBRE_LIENS_MAX_ECRIRE')) {
214
		define('_PAGINATION_NOMBRE_LIENS_MAX_ECRIRE', 10);
215
	}
216
217
218
	return recuperer_fond("modeles/pagination$modele", $pagination, array('trim' => true), $connect);
219
}
220
221
222
/**
223
 * Calcule les bornes d'une pagination
224
 *
225
 * @filtre
226
 *
227
 * @param int $courante
228
 *     Page courante
229
 * @param int $nombre
230
 *     Nombre de pages
231
 * @param int $max
232
 *     Nombre d'éléments par page
233
 * @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...
234
 *     Liste (première page, dernière page).
235
 **/
236
function filtre_bornes_pagination_dist($courante, $nombre, $max = 10) {
237
	if ($max <= 0 or $max >= $nombre) {
238
		return array(1, $nombre);
239
	}
240
	if ($max <= 1) {
241
		return array($courante, $courante);
242
	}
243
244
	$premiere = max(1, $courante - floor(($max - 1) / 2));
245
	$derniere = min($nombre, $premiere + $max - 2);
246
	$premiere = $derniere == $nombre ? $derniere - $max + 1 : $premiere;
247
248
	return array($premiere, $derniere);
249
}
250
251
252
/**
253
 * Retourne pour une clé primaire d'objet donnée les identifiants ayant un logo
254
 *
255
 * @param string $type
256
 *     Nom de la clé primaire de l'objet
257
 * @return string
258
 *     Liste des identifiants ayant un logo (séparés par une virgule)
259
 **/
260
function lister_objets_avec_logos($type) {
261
262
	$objet = objet_type($type);
263
	$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));
264
	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...
265
		$ids = array_column($ids, 'id_objet');
266
		return implode(',', $ids);
267
	}
268
	else {
269
		return "0";
270
	}
271
}
272
273
274
/**
275
 * Renvoie l'état courant des notes, le purge et en prépare un nouveau
276
 *
277
 * Fonction appelée par la balise `#NOTES`
278
 *
279
 * @see  balise_NOTES_dist()
280
 * @uses inc_notes_dist()
281
 *
282
 * @return string
283
 *     Code HTML des notes
284
 **/
285
function calculer_notes() {
286
	$r = '';
287
	if ($notes = charger_fonction('notes', 'inc', true)) {
288
		$r = $notes(array());
289
		$notes('', 'depiler');
290
		$notes('', 'empiler');
291
	}
292
293
	return $r;
294
}
295
296
297
/**
298
 * Retrouver le rang du lien entre un objet source et un obet lie
299
 * utilisable en direct dans un formulaire d'edition des liens, mais #RANG doit faire le travail automatiquement
300
 * [(#ENV{objet_source}|rang_lien{#ID_AUTEUR,#ENV{objet},#ENV{id_objet},#ENV{_objet_lien}})]
301
 *
302
 * @param $objet_source
303
 * @param $ids
304
 * @param $objet_lie
305
 * @param $idl
306
 * @param $objet_lien
307
 * @return string
308
 */
309
function retrouver_rang_lien($objet_source, $ids, $objet_lie, $idl, $objet_lien){
310
	$res = lister_objets_liens($objet_source, $objet_lie, $idl, $objet_lien);
311
	$res = array_column($res, 'rang_lien', $objet_source);
312
313
	return (isset($res[$ids]) ? $res[$ids] : '');
314
}
315
316
317
/**
318
 * Lister les liens en le memoizant dans une static
319
 * pour utilisation commune par lister_objets_lies et retrouver_rang_lien dans un formuluaire d'edition de liens
320
 * (evite de multiplier les requetes)
321
 *
322
 * @param $objet_source
323
 * @param $objet
324
 * @param $id_objet
325
 * @param $objet_lien
326
 * @return mixed
327
 * @private
328
 */
329
function lister_objets_liens($objet_source, $objet, $id_objet, $objet_lien) {
330
	static $liens = array();
331
	if (!isset($liens["$objet_source-$objet-$id_objet-$objet_lien"])) {
332
		include_spip('action/editer_liens');
333
		// quand $objet == $objet_lien == $objet_source on reste sur le cas par defaut de $objet_lien == $objet_source
334 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...
335
			$res = objet_trouver_liens(array($objet => $id_objet), array($objet_source => '*'));
336
		} else {
337
			$res = objet_trouver_liens(array($objet_source => '*'), array($objet => $id_objet));
338
		}
339
340
		$liens["$objet_source-$objet-$id_objet-$objet_lien"] = $res;
341
	}
342
	return $liens["$objet_source-$objet-$id_objet-$objet_lien"];
343
}
344
345
/**
346
 * Calculer la balise #RANG
347
 * quand ce n'est pas un champ rang :
348
 * 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
349
 * @param $titre
350
 * @param $objet_source
351
 * @param $id
352
 * @param $env
353
 * @return int|string
354
 */
355
function calculer_rang_smart($titre, $objet_source, $id, $env) {
356
	// Cas du #RANG utilisé dans #FORMULAIRE_EDITER_LIENS -> attraper le rang du lien
357
	// 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
358
	if (isset($env['form']) and $env['form']
359
		and isset($env['_objet_lien']) and $env['_objet_lien']
360
		and (function_exists('lien_triables') or include_spip('action/editer_liens'))
361
		and $r = objet_associable($env['_objet_lien'])
362
		and list($p, $table_lien) = $r
363
	  and lien_triables($table_lien)
364
	  and isset($env['objet']) and $env['objet']
365
		and isset($env['id_objet']) and $env['id_objet']
366
		and $objet_source
367
		and $id = intval($id)
368
	) {
369
		$rang = retrouver_rang_lien($objet_source, $id, $env['objet'], $env['id_objet'], $env['_objet_lien']);
370
		return ($rang ? $rang : '');
371
	}
372
	return recuperer_numero($titre);
373
}
374
375
376
/**
377
 * Proteger les champs passes dans l'url et utiliser dans {tri ...}
378
 * preserver l'espace pour interpreter ensuite num xxx et multi xxx
379
 * on permet d'utiliser les noms de champ prefixes
380
 * articles.titre
381
 * et les propriete json
382
 * properties.gis[0].ville
383
 *
384
 * @param string $t
385
 * @return string
386
 */
387
function tri_protege_champ($t) {
388
	return preg_replace(',[^\s\w.+\[\]],', '', $t);
389
}
390
391
/**
392
 * Interpreter les multi xxx et num xxx utilise comme tri
393
 * pour la clause order
394
 * 'multi xxx' devient simplement 'multi' qui est calcule dans le select
395
 *
396
 * @param string $t
397
 * @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...
398
 * @return string
399
 */
400
function tri_champ_order($t, $from = null) {
401
	if (strncmp($t, 'multi ', 6) == 0) {
402
		return "multi";
403
	}
404
405
	$champ = $t;
406
407
	if (strncmp($t, 'num ', 4) == 0) {
408
		$champ = substr($t, 4);
409
	}
410
	// enlever les autres espaces non evacues par tri_protege_champ
411
	$champ = preg_replace(',\s,', '', $champ);
412
413
	if (is_array($from)) {
414
		$trouver_table = charger_fonction('trouver_table', 'base');
415
		foreach ($from as $idt => $table_sql) {
416
			if ($desc = $trouver_table($table_sql)
417
				and isset($desc['field'][$champ])
418
			) {
419
				$champ = "$idt.$champ";
420
				break;
421
			}
422
		}
423
	}
424
	if (strncmp($t, 'num ', 4) == 0) {
425
		return "0+$champ";
426
	} else {
427
		return $champ;
428
	}
429
}
430
431
/**
432
 * Interpreter les multi xxx et num xxx utilise comme tri
433
 * pour la clause select
434
 * 'multi xxx' devient select "...." as multi
435
 * les autres cas ne produisent qu'une chaine vide '' en select
436
 * 'hasard' devient 'rand() AS hasard' dans le select
437
 *
438
 * @param string $t
439
 * @return string
440
 */
441
function tri_champ_select($t) {
442
	if (strncmp($t, 'multi ', 6) == 0) {
443
		$t = substr($t, 6);
444
		$t = preg_replace(',\s,', '', $t);
445
		$t = sql_multi($t, $GLOBALS['spip_lang']);
446
447
		return $t;
448
	}
449
	if (trim($t) == 'hasard') {
450
		return 'rand() AS hasard';
451
	}
452
453
	return "''";
454
}
455
456
/**
457
 * Fonction de mise en forme utilisee par le critere {par_ordre_liste..}
458
 * @see critere_par_ordre_liste_dist()
459
 *
460
 * @param array $valeurs
461
 * @param string $serveur
462
 * @return string
463
 */
464
function formate_liste_critere_par_ordre_liste($valeurs, $serveur = ''){
465
	if (!is_array($valeurs)){
466
		return '';
467
	}
468
	$f = sql_serveur('quote', $serveur, true);
469
	if (!is_string($f) or !$f){
470
		return '';
471
	}
472
	$valeurs = implode(',', array_map($f, array_unique($valeurs)));
473
474
	return $valeurs;
475
}
476
477
/**
478
 * Applique un filtre s'il existe, sinon retourne la valeur par défaut indiquée
479
 *
480
 * @internal
481
 * @uses trouver_filtre_matrice()
482
 * @uses chercher_filtre()
483
 *
484
 * @param mixed $arg
485
 *     Texte (le plus souvent) sur lequel appliquer le filtre
486
 * @param string $filtre
487
 *     Nom du filtre à appliquer
488
 * @param array $args
489
 *     Arguments reçus par la fonction parente (appliquer_filtre ou appliquer_si_filtre).
490
 * @param mixed $defaut
491
 *     Valeur par défaut à retourner en cas d'absence du filtre.
492
 * @return string
493
 *     Texte traité par le filtre si le filtre existe,
494
 *     Valeur $defaut sinon.
495
 **/
496
function appliquer_filtre_sinon($arg, $filtre, $args, $defaut = '') {
497
	// Si c'est un filtre d'image, on utilise image_filtrer()
498
	// Attention : les 2 premiers arguments sont inversés dans ce cas
499
	if (trouver_filtre_matrice($filtre) and substr($filtre, 0, 6) == 'image_') {
500
		$args[1] = $args[0];
501
		$args[0] = $filtre;
502
		return image_graver(image_filtrer($args));
503
	}
504
505
	$f = chercher_filtre($filtre);
506
	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...
507
		return $defaut;
508
	}
509
	array_shift($args); // enlever $arg
510
	array_shift($args); // enlever $filtre
511
	array_unshift($args, $arg); // remettre $arg
512
	return call_user_func_array($f, $args);
513
}
514