Completed
Push — master ( 1a3b2f...b50fb4 )
by cam
09:59
created

IterateurDATA::current()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
/***************************************************************************\
4
 *  SPIP, Systeme de publication pour l'internet                           *
5
 *                                                                         *
6
 *  Copyright (c) 2001-2018                                                *
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
/**
14
 * Gestion de l'itérateur DATA
15
 *
16
 * @package SPIP\Core\Iterateur\DATA
17
 **/
18
19
if (!defined('_ECRIRE_INC_VERSION')) {
20
	return;
21
}
22
23
if (!defined('_DATA_SOURCE_MAX_SIZE')) {
24
	define('_DATA_SOURCE_MAX_SIZE', 2 * 1048576);
25
}
26
27
28
/**
29
 * Créer une boucle sur un itérateur DATA
30
 *
31
 * Annonce au compilateur les "champs" disponibles, c'est à dire
32
 * 'cle', 'valeur' et '*' (tout nom possible).
33
 *
34
 * On ne peut effectivement pas connaître à la compilation la structure
35
 * des données qui seront obtenues. On indique donc au compilateur que
36
 * toute balise utilisée dans la boucle est possiblement un champ
37
 * des données reçues.
38
 *
39
 * @param Boucle $b
40
 *     Description de la boucle
41
 * @return Boucle
42
 *     Description de la boucle complétée des champs
43
 */
44
function iterateur_DATA_dist($b) {
45
	$b->iterateur = 'DATA'; # designe la classe d'iterateur
46
	$b->show = array(
47
		'field' => array(
48
			'cle' => 'STRING',
49
			'valeur' => 'STRING',
50
			'*' => 'ALL' // Champ joker *
51
		)
52
	);
53
	$b->select[] = '.valeur';
54
55
	return $b;
56
}
57
58
59
/**
60
 * Itérateur DATA
61
 *
62
 * Pour itérer sur des données quelconques (transformables en tableau)
63
 */
64
class IterateurDATA implements Iterator {
65
	/**
66
	 * tableau de donnees
67
	 *
68
	 * @var array
69
	 */
70
	protected $tableau = array();
71
72
	/**
73
	 * Conditions de filtrage
74
	 * ie criteres de selection
75
	 *
76
	 * @var array
77
	 */
78
	protected $filtre = array();
79
80
81
	/**
82
	 * Cle courante
83
	 *
84
	 * @var null
85
	 */
86
	protected $cle = null;
87
88
	/**
89
	 * Valeur courante
90
	 *
91
	 * @var null
92
	 */
93
	protected $valeur = null;
94
95
	/**
96
	 * Erreur presente ?
97
	 *
98
	 * @var bool
99
	 **/
100
	public $err = false;
101
102
	/**
103
	 * Calcul du total des elements
104
	 *
105
	 * @var int|null
106
	 **/
107
	public $total = null;
108
109
	/**
110
	 * Constructeur
111
	 *
112
	 * @param  $command
113
	 * @param array $info
114
	 */
115
	public function __construct($command, $info = array()) {
116
		$this->type = 'DATA';
0 ignored issues
show
Bug introduced by
The property type does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
117
		$this->command = $command;
0 ignored issues
show
Bug introduced by
The property command does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
118
		$this->info = $info;
0 ignored issues
show
Bug introduced by
The property info does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
119
120
		$this->select($command);
121
	}
122
123
	/**
124
	 * Revenir au depart
125
	 *
126
	 * @return void
127
	 */
128 View Code Duplication
	public function rewind() {
0 ignored issues
show
Duplication introduced by
This method 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...
129
		reset($this->tableau);
130
		$this->cle = key($this->tableau);
131
		$this->valeur = current($this->tableau);
132
		next($this->tableau);
133
	}
134
135
	/**
136
	 * Déclarer les critères exceptions
137
	 *
138
	 * @return array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use string[].

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...
139
	 */
140
	public function exception_des_criteres() {
141
		return array('tableau');
142
	}
143
144
	/**
145
	 * Récupérer depuis le cache si possible
146
	 *
147
	 * @param string $cle
148
	 * @return mixed
149
	 */
150
	protected function cache_get($cle) {
151
		if (!$cle) {
152
			return;
153
		}
154
		# utiliser memoization si dispo
155
		if (!function_exists('cache_get')) {
156
			return;
157
		}
158
159
		return cache_get($cle);
160
	}
161
162
	/**
163
	 * Stocker en cache si possible
164
	 *
165
	 * @param string $cle
166
	 * @param int $ttl
167
	 * @param null|mixed $valeur
168
	 * @return bool
169
	 */
170
	protected function cache_set($cle, $ttl, $valeur = null) {
171
		if (!$cle) {
172
			return;
173
		}
174
		if (is_null($valeur)) {
175
			$valeur = $this->tableau;
176
		}
177
		# utiliser memoization si dispo
178
		if (!function_exists('cache_set')) {
179
			return;
180
		}
181
182
		return cache_set($cle,
183
			array(
184
				'data' => $valeur,
185
				'time' => time(),
186
				'ttl' => $ttl
187
			),
188
			3600 + $ttl);
189
		# conserver le cache 1h de plus que la validite demandee,
190
		# pour le cas ou le serveur distant ne reponde plus
191
	}
192
193
	/**
194
	 * Aller chercher les données de la boucle DATA
195
	 *
196
	 * @throws Exception
197
	 * @param array $command
198
	 * @return void
199
	 */
200
	protected function select($command) {
201
202
		// l'iterateur DATA peut etre appele en passant (data:type)
203
		// le type se retrouve dans la commande 'from'
204
		// dans ce cas la le critere {source}, si present, n'a pas besoin du 1er argument
205
		if (isset($this->command['from'][0])) {
206
			if (isset($this->command['source']) and is_array($this->command['source'])) {
207
				array_unshift($this->command['source'], $this->command['sourcemode']);
208
			}
209
			$this->command['sourcemode'] = $this->command['from'][0];
210
		}
211
212
		// cherchons differents moyens de creer le tableau de donnees
213
		// les commandes connues pour l'iterateur DATA
214
		// sont : {tableau #ARRAY} ; {cle=...} ; {valeur=...}
215
216
		// {source format, [URL], [arg2]...}
217
		if (isset($this->command['source'])
218
			and isset($this->command['sourcemode'])
219
		) {
220
			$this->select_source();
221
		}
222
223
		// Critere {liste X1, X2, X3}
224
		if (isset($this->command['liste'])) {
225
			$this->select_liste();
226
		}
227
		if (isset($this->command['enum'])) {
228
			$this->select_enum();
229
		}
230
231
		// Si a ce stade on n'a pas de table, il y a un bug
232
		if (!is_array($this->tableau)) {
233
			$this->err = true;
234
			spip_log("erreur datasource " . var_export($command, true));
235
		}
236
237
		// {datapath query.results}
238
		// extraire le chemin "query.results" du tableau de donnees
239
		if (!$this->err
240
			and isset($this->command['datapath'])
241
			and is_array($this->command['datapath'])
242
		) {
243
			$this->select_datapath();
244
		}
245
246
		// tri {par x}
247
		if ($this->command['orderby']) {
248
			$this->select_orderby();
249
		}
250
251
		// grouper les resultats {fusion /x/y/z} ;
252
		if ($this->command['groupby']) {
253
			$this->select_groupby();
254
		}
255
256
		$this->rewind();
257
		#var_dump($this->tableau);
258
	}
259
260
261
	/**
262
	 * Aller chercher les donnees de la boucle DATA
263
	 * depuis une source
264
	 * {source format, [URL], [arg2]...}
265
	 */
266
	protected function select_source() {
267
		# un peu crado : avant de charger le cache il faut charger
268
		# les class indispensables, sinon PHP ne saura pas gerer
269
		# l'objet en cache ; cf plugins/icalendar
270
		# perf : pas de fonction table_to_array ! (table est deja un array)
271
		if (isset($this->command['sourcemode'])
272
			and !in_array($this->command['sourcemode'], array('table', 'array', 'tableau'))
273
		) {
274
			charger_fonction($this->command['sourcemode'] . '_to_array', 'inc', true);
275
		}
276
277
		# le premier argument peut etre un array, une URL etc.
278
		$src = $this->command['source'][0];
279
280
		# avons-nous un cache dispo ?
281
		$cle = null;
282
		if (is_string($src)) {
283
			$cle = 'datasource_' . md5($this->command['sourcemode'] . ':' . var_export($this->command['source'], true));
284
		}
285
286
		$cache = $this->cache_get($cle);
287
		if (isset($this->command['datacache'])) {
288
			$ttl = intval($this->command['datacache']);
289
		}
290
		if ($cache
291
			and ($cache['time'] + (isset($ttl) ? $ttl : $cache['ttl'])
292
				> time())
293
			and !(_request('var_mode') === 'recalcul'
294
				and include_spip('inc/autoriser')
295
				and autoriser('recalcul')
296
			)
297
		) {
298
			$this->tableau = $cache['data'];
299
		} else {
300
			try {
301
				# dommage que ca ne soit pas une option de yql_to_array...
302
				if ($this->command['sourcemode'] == 'yql') {
303
					if (!isset($ttl)) {
304
						$ttl = 3600;
305
					}
306
				}
307
308
				if (isset($this->command['sourcemode'])
309
					and in_array($this->command['sourcemode'],
310
						array('table', 'array', 'tableau'))
311
				) {
312
					if (is_array($a = $src)
313
						or (is_string($a)
314
							and $a = str_replace('&quot;', '"', $a) # fragile!
315
							and is_array($a = @unserialize($a)))
316
					) {
317
						$this->tableau = $a;
318
					}
319
				} else {
320
					if (tester_url_absolue($src)) {
321
						include_spip('inc/distant');
322
						$u = recuperer_page($src, false, false, _DATA_SOURCE_MAX_SIZE);
0 ignored issues
show
Deprecated Code introduced by
The function recuperer_page() has been deprecated.

This function has been deprecated.

Loading history...
323
						if (!$u) {
324
							throw new Exception("404");
325
						}
326
						if (!isset($ttl)) {
327
							$ttl = 24 * 3600;
328
						}
329
					} else {
330
						if (@is_dir($src)) {
331
							$u = $src;
332
							if (!isset($ttl)) {
333
								$ttl = 10;
334
							}
335
						} else {
336
							if (@is_readable($src) && @is_file($src)) {
337
								$u = spip_file_get_contents($src);
338
								if (!isset($ttl)) {
339
									$ttl = 10;
340
								}
341
							} else {
342
								$u = $src;
343
								if (!isset($ttl)) {
344
									$ttl = 10;
345
								}
346
							}
347
						}
348
					}
349
					if (!$this->err
350
						and $g = charger_fonction($this->command['sourcemode'] . '_to_array', 'inc', true)
351
					) {
352
						$args = $this->command['source'];
353
						$args[0] = $u;
354
						if (is_array($a = call_user_func_array($g, $args))) {
355
							$this->tableau = $a;
356
						}
357
					}
358
				}
359
360
				if (!is_array($this->tableau)) {
361
					$this->err = true;
362
				}
363
364
				if (!$this->err and isset($ttl) and $ttl > 0) {
365
					$this->cache_set($cle, $ttl);
366
				}
367
368
			} catch (Exception $e) {
369
				$e = $e->getMessage();
370
				$err = sprintf("[%s, %s] $e",
371
					$src,
372
					$this->command['sourcemode']);
373
				erreur_squelette(array($err, array()));
374
				$this->err = true;
375
			}
376
		}
377
378
		# en cas d'erreur, utiliser le cache si encore dispo
379
		if ($this->err
380
			and $cache
381
		) {
382
			$this->tableau = $cache['data'];
383
			$this->err = false;
384
		}
385
	}
386
387
388
	/**
389
	 * Retourne un tableau donne depuis un critère liste
390
	 *
391
	 * Critère `{liste X1, X2, X3}`
392
	 *
393
	 * @see critere_DATA_liste_dist()
394
	 *
395
	 **/
396
	protected function select_liste() {
397
		# s'il n'y a qu'une valeur dans la liste, sans doute une #BALISE
398 View Code Duplication
		if (!isset($this->command['liste'][1])) {
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...
399
			if (!is_array($this->command['liste'][0])) {
400
				$this->command['liste'] = explode(',', $this->command['liste'][0]);
401
			} else {
402
				$this->command['liste'] = $this->command['liste'][0];
403
			}
404
		}
405
		$this->tableau = $this->command['liste'];
406
	}
407
408
	/**
409
	 * Retourne un tableau donne depuis un critere liste
410
	 * Critere {enum Xmin, Xmax}
411
	 *
412
	 **/
413
	protected function select_enum() {
414
		# s'il n'y a qu'une valeur dans la liste, sans doute une #BALISE
415 View Code Duplication
		if (!isset($this->command['enum'][1])) {
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...
416
			if (!is_array($this->command['enum'][0])) {
417
				$this->command['enum'] = explode(',', $this->command['enum'][0]);
418
			} else {
419
				$this->command['enum'] = $this->command['enum'][0];
420
			}
421
		}
422
		if (count($this->command['enum']) >= 3) {
423
			$enum = range(array_shift($this->command['enum']), array_shift($this->command['enum']),
424
				array_shift($this->command['enum']));
425
		} else {
426
			$enum = range(array_shift($this->command['enum']), array_shift($this->command['enum']));
427
		}
428
		$this->tableau = $enum;
429
	}
430
431
432
	/**
433
	 * extraire le chemin "query.results" du tableau de donnees
434
	 * {datapath query.results}
435
	 *
436
	 **/
437
	protected function select_datapath() {
438
		$base = reset($this->command['datapath']);
439
		if (strlen($base = ltrim(trim($base), "/"))) {
440
			$this->tableau = table_valeur($this->tableau, $base);
0 ignored issues
show
Documentation Bug introduced by
It seems like table_valeur($this->tableau, $base) of type * is incompatible with the declared type array of property $tableau.

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...
441
			if (!is_array($this->tableau)) {
442
				$this->tableau = array();
443
				$this->err = true;
444
				spip_log("datapath '$base' absent");
445
			}
446
		}
447
	}
448
449
	/**
450
	 * Ordonner les resultats
451
	 * {par x}
452
	 *
453
	 **/
454
	protected function select_orderby() {
455
		$sortfunc = '';
456
		$aleas = 0;
0 ignored issues
show
Unused Code introduced by
$aleas 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...
457
		foreach ($this->command['orderby'] as $tri) {
458
			// virer le / initial pour les criteres de la forme {par /xx}
459
			if (preg_match(',^\.?([/\w]+)( DESC)?$,iS', ltrim($tri, '/'), $r)) {
460
				$r = array_pad($r, 3, null);
461
462
				// tri par cle
463
				if ($r[1] == 'cle') {
464
					if (isset($r[2]) and $r[2]) {
465
						krsort($this->tableau);
466
					} else {
467
						ksort($this->tableau);
468
					}
469
				} # {par hasard}
470
				else {
471
					if ($r[1] == 'hasard') {
472
						$k = array_keys($this->tableau);
473
						shuffle($k);
474
						$v = array();
475
						foreach ($k as $cle) {
476
							$v[$cle] = $this->tableau[$cle];
477
						}
478
						$this->tableau = $v;
479
					} else {
480
						# {par valeur}
481
						if ($r[1] == 'valeur') {
482
							$tv = '%s';
483
						} # {par valeur/xx/yy} ??
484
						else {
485
							$tv = 'table_valeur(%s, ' . var_export($r[1], true) . ')';
486
						}
487
						$sortfunc .= '
488
					$a = ' . sprintf($tv, '$aa') . ';
489
					$b = ' . sprintf($tv, '$bb') . ';
490
					if ($a <> $b)
491
						return ($a ' . (!empty($r[2]) ? '>' : '<') . ' $b) ? -1 : 1;';
492
					}
493
				}
494
			}
495
		}
496
497
		if ($sortfunc) {
498
			$sortfunc .= "\n return 0;";
499
			uasort($this->tableau, function($aa, $bb) use ($sortfunc) {
0 ignored issues
show
Unused Code introduced by
The parameter $aa 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 $bb 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...
500
				return eval($sortfunc);
501
			});
502
		}
503
	}
504
505
506
	/**
507
	 * Grouper les resultats
508
	 * {fusion /x/y/z}
509
	 *
510
	 **/
511
	protected function select_groupby() {
512
		// virer le / initial pour les criteres de la forme {fusion /xx}
513
		if (strlen($fusion = ltrim($this->command['groupby'][0], '/'))) {
514
			$vu = array();
515
			foreach ($this->tableau as $k => $v) {
516
				$val = table_valeur($v, $fusion);
517
				if (isset($vu[$val])) {
518
					unset($this->tableau[$k]);
519
				} else {
520
					$vu[$val] = true;
521
				}
522
			}
523
		}
524
	}
525
526
527
	/**
528
	 * L'iterateur est-il encore valide ?
529
	 *
530
	 * @return bool
531
	 */
532
	public function valid() {
533
		return !is_null($this->cle);
534
	}
535
536
	/**
537
	 * Retourner la valeur
538
	 *
539
	 * @return null
540
	 */
541
	public function current() {
542
		return $this->valeur;
543
	}
544
545
	/**
546
	 * Retourner la cle
547
	 *
548
	 * @return null
549
	 */
550
	public function key() {
551
		return $this->cle;
552
	}
553
554
	/**
555
	 * Passer a la valeur suivante
556
	 *
557
	 * @return void
558
	 */
559 View Code Duplication
	public function next() {
0 ignored issues
show
Duplication introduced by
This method 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...
560
		if ($this->valid()) {
561
			$this->cle = key($this->tableau);
562
			$this->valeur = current($this->tableau);
563
			next($this->tableau);
564
		}
565
	}
566
567
	/**
568
	 * Compter le nombre total de resultats
569
	 *
570
	 * @return int
571
	 */
572
	public function count() {
573
		if (is_null($this->total)) {
574
			$this->total = count($this->tableau);
575
		}
576
577
		return $this->total;
578
	}
579
}
580
581
/*
582
 * Fonctions de transformation donnee => tableau
583
 */
584
585
/**
586
 * file -> tableau
587
 *
588
 * @param  string $u
589
 * @return array
590
 */
591
function inc_file_to_array_dist($u) {
592
	return preg_split('/\r?\n/', $u);
593
}
594
595
/**
596
 * plugins -> tableau
597
 *
598
 * @return unknown
0 ignored issues
show
Documentation introduced by
Should the return type not be array? Also, consider making the array more specific, something like array<String>, or String[].

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.

If the return type contains the type array, this check recommends the use of a more specific type like String[] or array<String>.

Loading history...
599
 */
600
function inc_plugins_to_array_dist() {
601
	include_spip('inc/plugin');
602
603
	return liste_chemin_plugin_actifs();
604
}
605
606
/**
607
 * xml -> tableau
608
 *
609
 * @param  string $u
610
 * @return array
611
 */
612
function inc_xml_to_array_dist($u) {
613
	return @XMLObjectToArray(new SimpleXmlIterator($u));
614
}
615
616
/**
617
 *
618
 * object -> tableau
619
 *
620
 * @param    object $object The object to convert
621
 * @return   array
622
 *
623
 */
624
function inc_object_to_array($object) {
625
	if (!is_object($object) && !is_array($object)) {
626
		return $object;
627
	}
628
	if (is_object($object)) {
629
		$object = get_object_vars($object);
630
	}
631
632
	return array_map('inc_object_to_array', $object);
633
}
634
635
/**
636
 * yql -> tableau
637
 *
638
 * @throws Exception
639
 * @param  string $u
640
 * @return array|bool
641
 */
642
function inc_yql_to_array_dist($u) {
643
	define('_YQL_ENDPOINT', 'https://query.yahooapis.com/v1/public/yql?&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys&q=');
644
	$v = recuperer_url($url = _YQL_ENDPOINT . urlencode($u) . '&format=json');
645
	if (!$v['page']
646
		or !$w = json_decode($v['page'], true)
647
	) {
648
		throw new Exception('YQL: r&#233;ponse vide ou mal form&#233;e');
649
	}
650
	if (isset($w['error'])) {
651
		throw new Exception($w['error']['description']);
652
	}
653
654
	return inc_object_to_array($w);
655
}
656
657
/**
658
 * sql -> tableau
659
 *
660
 * @param string $u
661
 * @return array|bool
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array|false.

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...
662
 */
663
function inc_sql_to_array_dist($u) {
664
	# sortir le connecteur de $u
665
	preg_match(',^(?:(\w+):)?(.*)$,S', $u, $v);
666
	$serveur = (string)$v[1];
667
	$req = trim($v[2]);
668
	if ($s = sql_query($req, $serveur)) {
669
		$r = array();
670
		while ($t = sql_fetch($s)) {
671
			$r[] = $t;
672
		}
673
674
		return $r;
675
	}
676
677
	return false;
678
}
679
680
/**
681
 * json -> tableau
682
 *
683
 * @param string $u
684
 * @return array|bool
0 ignored issues
show
Documentation introduced by
Should the return type not be array|null? Also, consider making the array more specific, something like array<String>, or String[].

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.

If the return type contains the type array, this check recommends the use of a more specific type like String[] or array<String>.

Loading history...
685
 */
686
function inc_json_to_array_dist($u) {
687
	if (is_array($json = json_decode($u))
688
		or is_object($json)
689
	) {
690
		return (array)$json;
691
	}
692
}
693
694
/**
695
 * csv -> tableau
696
 *
697
 * @param string $u
698
 * @return array|bool
699
 */
700
function inc_csv_to_array_dist($u) {
701
	include_spip('inc/csv');
702
	list($entete, $csv) = analyse_csv($u);
703
	array_unshift($csv, $entete);
704
705
	include_spip('inc/charsets');
706
	$i = 1;
707
	foreach ($entete as $k => $v) {
708
		if (trim($v) == "") {
709
			$v = "col" . $i;
710
		} // reperer des eventuelles cases vides
711
		if (is_numeric($v) and $v < 0) {
712
			$v = "__" . $v;
713
		} // ne pas risquer d'ecraser une cle numerique
714
		if (is_numeric($v)) {
715
			$v = "_" . $v;
716
		} // ne pas risquer d'ecraser une cle numerique
717
		$v = strtolower(preg_replace(',\W+,', '_', translitteration($v)));
718
		foreach ($csv as &$item) {
719
			$item[$v] = &$item[$k];
720
		}
721
		$i++;
722
	}
723
724
	return $csv;
725
}
726
727
/**
728
 * RSS -> tableau
729
 *
730
 * @param string $u
731
 * @return array|bool
732
 */
733
function inc_rss_to_array_dist($u) {
734
	include_spip('inc/syndic');
735
	if (is_array($rss = analyser_backend($u))) {
736
		$tableau = $rss;
737
	}
738
739
	return $tableau;
0 ignored issues
show
Bug introduced by
The variable $tableau 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...
740
}
741
742
/**
743
 * atom, alias de rss -> tableau
744
 *
745
 * @param string $u
746
 * @return array|bool
747
 */
748
function inc_atom_to_array_dist($u) {
749
	$g = charger_fonction('rss_to_array', 'inc');
750
751
	return $g($u);
752
}
753
754
/**
755
 * glob -> tableau
756
 * lister des fichiers selon un masque, pour la syntaxe cf php.net/glob
757
 *
758
 * @param string $u
759
 * @return array|bool
760
 */
761
function inc_glob_to_array_dist($u) {
762
	$a = glob($u,
763
		GLOB_MARK | GLOB_NOSORT | GLOB_BRACE
764
	);
765
766
	return $a ? $a : array();
767
}
768
769
/**
770
 * YAML -> tableau
771
 *
772
 * @param string $u
773
 * @return bool|array
774
 * @throws Exception
775
 */
776
function inc_yaml_to_array_dist($u) {
777
	include_spip('inc/yaml-mini');
778
	if (!function_exists("yaml_decode")) {
779
		throw new Exception('YAML: impossible de trouver la fonction yaml_decode');
780
781
		return false;
0 ignored issues
show
Unused Code introduced by
return false; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
782
	}
783
784
	return yaml_decode($u);
785
}
786
787
788
/**
789
 * pregfiles -> tableau
790
 * lister des fichiers a partir d'un dossier de base et selon une regexp.
791
 * pour la syntaxe cf la fonction spip preg_files
792
 *
793
 * @param string $dir
794
 * @param string $regexp
0 ignored issues
show
Documentation introduced by
Should the type for parameter $regexp not be integer?

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...
795
 * @param int $limit
796
 * @return array|bool
797
 */
798
function inc_pregfiles_to_array_dist($dir, $regexp = -1, $limit = 10000) {
799
	return (array)preg_files($dir, $regexp, $limit);
800
}
801
802
/**
803
 * ls -> tableau
804
 * ls : lister des fichiers selon un masque glob
805
 * et renvoyer aussi leurs donnees php.net/stat
806
 *
807
 * @param string $u
808
 * @return array|bool
809
 */
810
function inc_ls_to_array_dist($u) {
811
	$glob = charger_fonction('glob_to_array', 'inc');
812
	$a = $glob($u);
813
	foreach ($a as &$v) {
814
		$b = (array)@stat($v);
815
		foreach ($b as $k => $ignore) {
816
			if (is_numeric($k)) {
817
				unset($b[$k]);
818
			}
819
		}
820
		$b['file'] = preg_replace('`/$`','',$v) ;
821
		$v = array_merge(
822
			pathinfo($v),
823
			$b
824
		);
825
	}
826
827
	return $a;
828
}
829
830
/**
831
 * Object -> tableau
832
 *
833
 * @param Object $object
834
 * @return array|bool
835
 */
836
function XMLObjectToArray($object) {
837
	$xml_array = array();
838
	for ($object->rewind(); $object->valid(); $object->next()) {
839
		if (array_key_exists($key = $object->key(), $xml_array)) {
840
			$key .= '-' . uniqid();
841
		}
842
		$vars = get_object_vars($object->current());
843
		if (isset($vars['@attributes'])) {
844
			foreach ($vars['@attributes'] as $k => $v) {
845
				$xml_array[$key][$k] = $v;
846
			}
847
		}
848
		if ($object->hasChildren()) {
849
			$xml_array[$key][] = XMLObjectToArray(
850
				$object->current());
851
		} else {
852
			$xml_array[$key][] = strval($object->current());
853
		}
854
	}
855
856
	return $xml_array;
857
}
858