Completed
Push — master ( b6e73f...0af572 )
by cam
04:04
created

data.php ➔ inc_yql_to_array_dist()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
nc 3
nop 1
dl 0
loc 14
rs 9.7998
c 0
b 0
f 0
1
<?php
2
3
/***************************************************************************\
4
 *  SPIP, Systeme de publication pour l'internet                           *
5
 *                                                                         *
6
 *  Copyright (c) 2001-2019                                                *
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
				if (isset($this->command['sourcemode'])
302
					and in_array($this->command['sourcemode'],
303
						array('table', 'array', 'tableau'))
304
				) {
305
					if (is_array($a = $src)
306
						or (is_string($a)
307
							and $a = str_replace('&quot;', '"', $a) # fragile!
308
							and is_array($a = @unserialize($a)))
309
					) {
310
						$this->tableau = $a;
311
					}
312
				} else {
313
					if (tester_url_absolue($src)) {
314
						include_spip('inc/distant');
315
						$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...
316
						if (!$u) {
317
							throw new Exception("404");
318
						}
319
						if (!isset($ttl)) {
320
							$ttl = 24 * 3600;
321
						}
322
					} else {
323
						if (@is_dir($src)) {
324
							$u = $src;
325
							if (!isset($ttl)) {
326
								$ttl = 10;
327
							}
328
						} else {
329
							if (@is_readable($src) && @is_file($src)) {
330
								$u = spip_file_get_contents($src);
331
								if (!isset($ttl)) {
332
									$ttl = 10;
333
								}
334
							} else {
335
								$u = $src;
336
								if (!isset($ttl)) {
337
									$ttl = 10;
338
								}
339
							}
340
						}
341
					}
342
					if (!$this->err
343
						and $g = charger_fonction($this->command['sourcemode'] . '_to_array', 'inc', true)
344
					) {
345
						$args = $this->command['source'];
346
						$args[0] = $u;
347
						if (is_array($a = call_user_func_array($g, $args))) {
348
							$this->tableau = $a;
349
						}
350
					}
351
				}
352
353
				if (!is_array($this->tableau)) {
354
					$this->err = true;
355
				}
356
357
				if (!$this->err and isset($ttl) and $ttl > 0) {
358
					$this->cache_set($cle, $ttl);
359
				}
360
361
			} catch (Exception $e) {
362
				$e = $e->getMessage();
363
				$err = sprintf("[%s, %s] $e",
364
					$src,
365
					$this->command['sourcemode']);
366
				erreur_squelette(array($err, array()));
367
				$this->err = true;
368
			}
369
		}
370
371
		# en cas d'erreur, utiliser le cache si encore dispo
372
		if ($this->err
373
			and $cache
374
		) {
375
			$this->tableau = $cache['data'];
376
			$this->err = false;
377
		}
378
	}
379
380
381
	/**
382
	 * Retourne un tableau donne depuis un critère liste
383
	 *
384
	 * Critère `{liste X1, X2, X3}`
385
	 *
386
	 * @see critere_DATA_liste_dist()
387
	 *
388
	 **/
389
	protected function select_liste() {
390
		# s'il n'y a qu'une valeur dans la liste, sans doute une #BALISE
391 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...
392
			if (!is_array($this->command['liste'][0])) {
393
				$this->command['liste'] = explode(',', $this->command['liste'][0]);
394
			} else {
395
				$this->command['liste'] = $this->command['liste'][0];
396
			}
397
		}
398
		$this->tableau = $this->command['liste'];
399
	}
400
401
	/**
402
	 * Retourne un tableau donne depuis un critere liste
403
	 * Critere {enum Xmin, Xmax}
404
	 *
405
	 **/
406
	protected function select_enum() {
407
		# s'il n'y a qu'une valeur dans la liste, sans doute une #BALISE
408 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...
409
			if (!is_array($this->command['enum'][0])) {
410
				$this->command['enum'] = explode(',', $this->command['enum'][0]);
411
			} else {
412
				$this->command['enum'] = $this->command['enum'][0];
413
			}
414
		}
415
		if (count($this->command['enum']) >= 3) {
416
			$enum = range(array_shift($this->command['enum']), array_shift($this->command['enum']),
417
				array_shift($this->command['enum']));
418
		} else {
419
			$enum = range(array_shift($this->command['enum']), array_shift($this->command['enum']));
420
		}
421
		$this->tableau = $enum;
422
	}
423
424
425
	/**
426
	 * extraire le chemin "query.results" du tableau de donnees
427
	 * {datapath query.results}
428
	 *
429
	 **/
430
	protected function select_datapath() {
431
		$base = reset($this->command['datapath']);
432
		if (strlen($base = ltrim(trim($base), "/"))) {
433
			$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...
434
			if (!is_array($this->tableau)) {
435
				$this->tableau = array();
436
				$this->err = true;
437
				spip_log("datapath '$base' absent");
438
			}
439
		}
440
	}
441
442
	/**
443
	 * Ordonner les resultats
444
	 * {par x}
445
	 *
446
	 **/
447
	protected function select_orderby() {
448
		$sortfunc = '';
449
		$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...
450
		foreach ($this->command['orderby'] as $tri) {
451
			// virer le / initial pour les criteres de la forme {par /xx}
452
			if (preg_match(',^\.?([/\w]+)( DESC)?$,iS', ltrim($tri, '/'), $r)) {
453
				$r = array_pad($r, 3, null);
454
455
				// tri par cle
456
				if ($r[1] == 'cle') {
457
					if (isset($r[2]) and $r[2]) {
458
						krsort($this->tableau);
459
					} else {
460
						ksort($this->tableau);
461
					}
462
				} # {par hasard}
463
				else {
464
					if ($r[1] == 'hasard') {
465
						$k = array_keys($this->tableau);
466
						shuffle($k);
467
						$v = array();
468
						foreach ($k as $cle) {
469
							$v[$cle] = $this->tableau[$cle];
470
						}
471
						$this->tableau = $v;
472
					} else {
473
						# {par valeur}
474
						if ($r[1] == 'valeur') {
475
							$tv = '%s';
476
						} # {par valeur/xx/yy} ??
477
						else {
478
							$tv = 'table_valeur(%s, ' . var_export($r[1], true) . ')';
479
						}
480
						$sortfunc .= '
481
					$a = ' . sprintf($tv, '$aa') . ';
482
					$b = ' . sprintf($tv, '$bb') . ';
483
					if ($a <> $b)
484
						return ($a ' . (!empty($r[2]) ? '>' : '<') . ' $b) ? -1 : 1;';
485
					}
486
				}
487
			}
488
		}
489
490
		if ($sortfunc) {
491
			$sortfunc .= "\n return 0;";
492
			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...
493
				return eval($sortfunc);
494
			});
495
		}
496
	}
497
498
499
	/**
500
	 * Grouper les resultats
501
	 * {fusion /x/y/z}
502
	 *
503
	 **/
504
	protected function select_groupby() {
505
		// virer le / initial pour les criteres de la forme {fusion /xx}
506
		if (strlen($fusion = ltrim($this->command['groupby'][0], '/'))) {
507
			$vu = array();
508
			foreach ($this->tableau as $k => $v) {
509
				$val = table_valeur($v, $fusion);
510
				if (isset($vu[$val])) {
511
					unset($this->tableau[$k]);
512
				} else {
513
					$vu[$val] = true;
514
				}
515
			}
516
		}
517
	}
518
519
520
	/**
521
	 * L'iterateur est-il encore valide ?
522
	 *
523
	 * @return bool
524
	 */
525
	public function valid() {
526
		return !is_null($this->cle);
527
	}
528
529
	/**
530
	 * Retourner la valeur
531
	 *
532
	 * @return null
533
	 */
534
	public function current() {
535
		return $this->valeur;
536
	}
537
538
	/**
539
	 * Retourner la cle
540
	 *
541
	 * @return null
542
	 */
543
	public function key() {
544
		return $this->cle;
545
	}
546
547
	/**
548
	 * Passer a la valeur suivante
549
	 *
550
	 * @return void
551
	 */
552 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...
553
		if ($this->valid()) {
554
			$this->cle = key($this->tableau);
555
			$this->valeur = current($this->tableau);
556
			next($this->tableau);
557
		}
558
	}
559
560
	/**
561
	 * Compter le nombre total de resultats
562
	 *
563
	 * @return int
564
	 */
565
	public function count() {
566
		if (is_null($this->total)) {
567
			$this->total = count($this->tableau);
568
		}
569
570
		return $this->total;
571
	}
572
}
573
574
/*
575
 * Fonctions de transformation donnee => tableau
576
 */
577
578
/**
579
 * file -> tableau
580
 *
581
 * @param  string $u
582
 * @return array
583
 */
584
function inc_file_to_array_dist($u) {
585
	return preg_split('/\r?\n/', $u);
586
}
587
588
/**
589
 * plugins -> tableau
590
 *
591
 * @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...
592
 */
593
function inc_plugins_to_array_dist() {
594
	include_spip('inc/plugin');
595
596
	return liste_chemin_plugin_actifs();
597
}
598
599
/**
600
 * xml -> tableau
601
 *
602
 * @param  string $u
603
 * @return array
604
 */
605
function inc_xml_to_array_dist($u) {
606
	return @XMLObjectToArray(new SimpleXmlIterator($u));
607
}
608
609
/**
610
 *
611
 * object -> tableau
612
 *
613
 * @param    object $object The object to convert
614
 * @return   array
615
 *
616
 */
617
function inc_object_to_array($object) {
618
	if (!is_object($object) && !is_array($object)) {
619
		return $object;
620
	}
621
	if (is_object($object)) {
622
		$object = get_object_vars($object);
623
	}
624
625
	return array_map('inc_object_to_array', $object);
626
}
627
628
/**
629
 * sql -> tableau
630
 *
631
 * @param string $u
632
 * @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...
633
 */
634
function inc_sql_to_array_dist($u) {
635
	# sortir le connecteur de $u
636
	preg_match(',^(?:(\w+):)?(.*)$,S', $u, $v);
637
	$serveur = (string)$v[1];
638
	$req = trim($v[2]);
639
	if ($s = sql_query($req, $serveur)) {
640
		$r = array();
641
		while ($t = sql_fetch($s)) {
642
			$r[] = $t;
643
		}
644
645
		return $r;
646
	}
647
648
	return false;
649
}
650
651
/**
652
 * json -> tableau
653
 *
654
 * @param string $u
655
 * @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...
656
 */
657
function inc_json_to_array_dist($u) {
658
	if (is_array($json = json_decode($u))
659
		or is_object($json)
660
	) {
661
		return (array)$json;
662
	}
663
}
664
665
/**
666
 * csv -> tableau
667
 *
668
 * @param string $u
669
 * @return array|bool
670
 */
671
function inc_csv_to_array_dist($u) {
672
	include_spip('inc/csv');
673
	list($entete, $csv) = analyse_csv($u);
674
	array_unshift($csv, $entete);
675
676
	include_spip('inc/charsets');
677
	$i = 1;
678
	foreach ($entete as $k => $v) {
679
		if (trim($v) == "") {
680
			$v = "col" . $i;
681
		} // reperer des eventuelles cases vides
682
		if (is_numeric($v) and $v < 0) {
683
			$v = "__" . $v;
684
		} // ne pas risquer d'ecraser une cle numerique
685
		if (is_numeric($v)) {
686
			$v = "_" . $v;
687
		} // ne pas risquer d'ecraser une cle numerique
688
		$v = strtolower(preg_replace(',\W+,', '_', translitteration($v)));
689
		foreach ($csv as &$item) {
690
			$item[$v] = &$item[$k];
691
		}
692
		$i++;
693
	}
694
695
	return $csv;
696
}
697
698
/**
699
 * RSS -> tableau
700
 *
701
 * @param string $u
702
 * @return array|bool
703
 */
704
function inc_rss_to_array_dist($u) {
705
	include_spip('inc/syndic');
706
	if (is_array($rss = analyser_backend($u))) {
707
		$tableau = $rss;
708
	}
709
710
	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...
711
}
712
713
/**
714
 * atom, alias de rss -> tableau
715
 *
716
 * @param string $u
717
 * @return array|bool
718
 */
719
function inc_atom_to_array_dist($u) {
720
	$g = charger_fonction('rss_to_array', 'inc');
721
722
	return $g($u);
723
}
724
725
/**
726
 * glob -> tableau
727
 * lister des fichiers selon un masque, pour la syntaxe cf php.net/glob
728
 *
729
 * @param string $u
730
 * @return array|bool
731
 */
732
function inc_glob_to_array_dist($u) {
733
	$a = glob($u,
734
		GLOB_MARK | GLOB_NOSORT | GLOB_BRACE
735
	);
736
737
	return $a ? $a : array();
738
}
739
740
/**
741
 * YAML -> tableau
742
 *
743
 * @param string $u
744
 * @return bool|array
745
 * @throws Exception
746
 */
747
function inc_yaml_to_array_dist($u) {
748
	include_spip('inc/yaml-mini');
749
	if (!function_exists("yaml_decode")) {
750
		throw new Exception('YAML: impossible de trouver la fonction yaml_decode');
751
752
		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...
753
	}
754
755
	return yaml_decode($u);
756
}
757
758
759
/**
760
 * pregfiles -> tableau
761
 * lister des fichiers a partir d'un dossier de base et selon une regexp.
762
 * pour la syntaxe cf la fonction spip preg_files
763
 *
764
 * @param string $dir
765
 * @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...
766
 * @param int $limit
767
 * @return array|bool
768
 */
769
function inc_pregfiles_to_array_dist($dir, $regexp = -1, $limit = 10000) {
770
	return (array)preg_files($dir, $regexp, $limit);
771
}
772
773
/**
774
 * ls -> tableau
775
 * ls : lister des fichiers selon un masque glob
776
 * et renvoyer aussi leurs donnees php.net/stat
777
 *
778
 * @param string $u
779
 * @return array|bool
780
 */
781
function inc_ls_to_array_dist($u) {
782
	$glob = charger_fonction('glob_to_array', 'inc');
783
	$a = $glob($u);
784
	foreach ($a as &$v) {
785
		$b = (array)@stat($v);
786
		foreach ($b as $k => $ignore) {
787
			if (is_numeric($k)) {
788
				unset($b[$k]);
789
			}
790
		}
791
		$b['file'] = preg_replace('`/$`','',$v) ;
792
		$v = array_merge(
793
			pathinfo($v),
794
			$b
795
		);
796
	}
797
798
	return $a;
799
}
800
801
/**
802
 * Object -> tableau
803
 *
804
 * @param Object $object
805
 * @return array|bool
806
 */
807
function XMLObjectToArray($object) {
808
	$xml_array = array();
809
	for ($object->rewind(); $object->valid(); $object->next()) {
810
		if (array_key_exists($key = $object->key(), $xml_array)) {
811
			$key .= '-' . uniqid();
812
		}
813
		$vars = get_object_vars($object->current());
814
		if (isset($vars['@attributes'])) {
815
			foreach ($vars['@attributes'] as $k => $v) {
816
				$xml_array[$key][$k] = $v;
817
			}
818
		}
819
		if ($object->hasChildren()) {
820
			$xml_array[$key][] = XMLObjectToArray(
821
				$object->current());
822
		} else {
823
			$xml_array[$key][] = strval($object->current());
824
		}
825
	}
826
827
	return $xml_array;
828
}
829