Joomla Platform  13.1
Documentation des API du framework Joomla Platform
 Tout Classes Espaces de nommage Fichiers Fonctions Variables Pages
arrayhelper.php
Aller à la documentation de ce fichier.
1 <?php
2 /**
3  * @package Joomla.Platform
4  * @subpackage Utilities
5  *
6  * @copyright Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved
7  * @license GNU General Public License version 2 or later; see LICENSE
8  */
9 
10 defined('JPATH_PLATFORM') or die;
11 
12 /**
13  * JArrayHelper is an array utility class for doing all sorts of odds and ends with arrays.
14  *
15  * @package Joomla.Platform
16  * @subpackage Utilities
17  * @since 11.1
18  */
19 abstract class JArrayHelper
20 {
21  /**
22  * Option to perform case-sensitive sorts.
23  *
24  * @var mixed Boolean or array of booleans.
25  * @since 11.3
26  */
27  protected static $sortCase;
28 
29  /**
30  * Option to set the sort direction.
31  *
32  * @var mixed Integer or array of integers.
33  * @since 11.3
34  */
35  protected static $sortDirection;
36 
37  /**
38  * Option to set the object key to sort on.
39  *
40  * @var string
41  * @since 11.3
42  */
43  protected static $sortKey;
44 
45  /**
46  * Option to perform a language aware sort.
47  *
48  * @var mixed Boolean or array of booleans.
49  * @since 11.3
50  */
51  protected static $sortLocale;
52 
53  /**
54  * Function to convert array to integer values
55  *
56  * @param array &$array The source array to convert
57  * @param mixed $default A default value (int|array) to assign if $array is not an array
58  *
59  * @return void
60  *
61  * @since 11.1
62  */
63  public static function toInteger(&$array, $default = null)
64  {
65  if (is_array($array))
66  {
67  foreach ($array as $i => $v)
68  {
69  $array[$i] = (int) $v;
70  }
71  }
72  else
73  {
74  if ($default === null)
75  {
76  $array = array();
77  }
78  elseif (is_array($default))
79  {
80  self::toInteger($default, null);
81  $array = $default;
82  }
83  else
84  {
85  $array = array((int) $default);
86  }
87  }
88  }
89 
90  /**
91  * Utility function to map an array to a stdClass object.
92  *
93  * @param array &$array The array to map.
94  * @param string $class Name of the class to create
95  *
96  * @return object The object mapped from the given array
97  *
98  * @since 11.1
99  */
100  public static function toObject(&$array, $class = 'stdClass')
101  {
102  $obj = null;
103 
104  if (is_array($array))
105  {
106  $obj = new $class;
107 
108  foreach ($array as $k => $v)
109  {
110  if (is_array($v))
111  {
112  $obj->$k = self::toObject($v, $class);
113  }
114  else
115  {
116  $obj->$k = $v;
117  }
118  }
119  }
120  return $obj;
121  }
122 
123  /**
124  * Utility function to map an array to a string.
125  *
126  * @param array $array The array to map.
127  * @param string $inner_glue The glue (optional, defaults to '=') between the key and the value.
128  * @param string $outer_glue The glue (optional, defaults to ' ') between array elements.
129  * @param boolean $keepOuterKey True if final key should be kept.
130  *
131  * @return string The string mapped from the given array
132  *
133  * @since 11.1
134  */
135  public static function toString($array = null, $inner_glue = '=', $outer_glue = ' ', $keepOuterKey = false)
136  {
137  $output = array();
138 
139  if (is_array($array))
140  {
141  foreach ($array as $key => $item)
142  {
143  if (is_array($item))
144  {
145  if ($keepOuterKey)
146  {
147  $output[] = $key;
148  }
149  // This is value is an array, go and do it again!
150  $output[] = self::toString($item, $inner_glue, $outer_glue, $keepOuterKey);
151  }
152  else
153  {
154  $output[] = $key . $inner_glue . '"' . $item . '"';
155  }
156  }
157  }
158 
159  return implode($outer_glue, $output);
160  }
161 
162  /**
163  * Utility function to map an object to an array
164  *
165  * @param object $p_obj The source object
166  * @param boolean $recurse True to recurse through multi-level objects
167  * @param string $regex An optional regular expression to match on field names
168  *
169  * @return array The array mapped from the given object
170  *
171  * @since 11.1
172  */
173  public static function fromObject($p_obj, $recurse = true, $regex = null)
174  {
175  if (is_object($p_obj))
176  {
177  return self::_fromObject($p_obj, $recurse, $regex);
178  }
179  else
180  {
181  return null;
182  }
183  }
184 
185  /**
186  * Utility function to map an object or array to an array
187  *
188  * @param mixed $item The source object or array
189  * @param boolean $recurse True to recurse through multi-level objects
190  * @param string $regex An optional regular expression to match on field names
191  *
192  * @return array The array mapped from the given object
193  *
194  * @since 11.1
195  */
196  protected static function _fromObject($item, $recurse, $regex)
197  {
198  if (is_object($item))
199  {
200  $result = array();
201 
202  foreach (get_object_vars($item) as $k => $v)
203  {
204  if (!$regex || preg_match($regex, $k))
205  {
206  if ($recurse)
207  {
208  $result[$k] = self::_fromObject($v, $recurse, $regex);
209  }
210  else
211  {
212  $result[$k] = $v;
213  }
214  }
215  }
216  }
217  elseif (is_array($item))
218  {
219  $result = array();
220 
221  foreach ($item as $k => $v)
222  {
223  $result[$k] = self::_fromObject($v, $recurse, $regex);
224  }
225  }
226  else
227  {
228  $result = $item;
229  }
230  return $result;
231  }
232 
233  /**
234  * Extracts a column from an array of arrays or objects
235  *
236  * @param array &$array The source array
237  * @param string $index The index of the column or name of object property
238  *
239  * @return array Column of values from the source array
240  *
241  * @since 11.1
242  */
243  public static function getColumn(&$array, $index)
244  {
245  $result = array();
246 
247  if (is_array($array))
248  {
249  foreach ($array as &$item)
250  {
251  if (is_array($item) && isset($item[$index]))
252  {
253  $result[] = $item[$index];
254  }
255  elseif (is_object($item) && isset($item->$index))
256  {
257  $result[] = $item->$index;
258  }
259  // Else ignore the entry
260  }
261  }
262  return $result;
263  }
264 
265  /**
266  * Utility function to return a value from a named array or a specified default
267  *
268  * @param array &$array A named array
269  * @param string $name The key to search for
270  * @param mixed $default The default value to give if no key found
271  * @param string $type Return type for the variable (INT, FLOAT, STRING, WORD, BOOLEAN, ARRAY)
272  *
273  * @return mixed The value from the source array
274  *
275  * @since 11.1
276  */
277  public static function getValue(&$array, $name, $default = null, $type = '')
278  {
279  $result = null;
280 
281  if (isset($array[$name]))
282  {
283  $result = $array[$name];
284  }
285 
286  // Handle the default case
287  if (is_null($result))
288  {
289  $result = $default;
290  }
291 
292  // Handle the type constraint
293  switch (strtoupper($type))
294  {
295  case 'INT':
296  case 'INTEGER':
297  // Only use the first integer value
298  @preg_match('/-?[0-9]+/', $result, $matches);
299  $result = @(int) $matches[0];
300  break;
301 
302  case 'FLOAT':
303  case 'DOUBLE':
304  // Only use the first floating point value
305  @preg_match('/-?[0-9]+(\.[0-9]+)?/', $result, $matches);
306  $result = @(float) $matches[0];
307  break;
308 
309  case 'BOOL':
310  case 'BOOLEAN':
311  $result = (bool) $result;
312  break;
313 
314  case 'ARRAY':
315  if (!is_array($result))
316  {
317  $result = array($result);
318  }
319  break;
320 
321  case 'STRING':
322  $result = (string) $result;
323  break;
324 
325  case 'WORD':
326  $result = (string) preg_replace('#\W#', '', $result);
327  break;
328 
329  case 'NONE':
330  default:
331  // No casting necessary
332  break;
333  }
334  return $result;
335  }
336 
337  /**
338  * Takes an associative array of arrays and inverts the array keys to values using the array values as keys.
339  *
340  * Example:
341  * $input = array(
342  * 'New' => array('1000', '1500', '1750'),
343  * 'Used' => array('3000', '4000', '5000', '6000')
344  * );
345  * $output = JArrayHelper::invert($input);
346  *
347  * Output would be equal to:
348  * $output = array(
349  * '1000' => 'New',
350  * '1500' => 'New',
351  * '1750' => 'New',
352  * '3000' => 'Used',
353  * '4000' => 'Used',
354  * '5000' => 'Used',
355  * '6000' => 'Used'
356  * );
357  *
358  * @param array $array The source array.
359  *
360  * @return array The inverted array.
361  *
362  * @since 12.3
363  */
364  public static function invert($array)
365  {
366  $return = array();
367 
368  foreach ($array as $base => $values)
369  {
370  if (!is_array($values))
371  {
372  continue;
373  }
374 
375  foreach ($values as $key)
376  {
377  // If the key isn't scalar then ignore it.
378  if (is_scalar($key))
379  {
380  $return[$key] = $base;
381  }
382  }
383  }
384  return $return;
385  }
386 
387  /**
388  * Method to determine if an array is an associative array.
389  *
390  * @param array $array An array to test.
391  *
392  * @return boolean True if the array is an associative array.
393  *
394  * @since 11.1
395  */
396  public static function isAssociative($array)
397  {
398  if (is_array($array))
399  {
400  foreach (array_keys($array) as $k => $v)
401  {
402  if ($k !== $v)
403  {
404  return true;
405  }
406  }
407  }
408 
409  return false;
410  }
411 
412  /**
413  * Pivots an array to create a reverse lookup of an array of scalars, arrays or objects.
414  *
415  * @param array $source The source array.
416  * @param string $key Where the elements of the source array are objects or arrays, the key to pivot on.
417  *
418  * @return array An array of arrays pivoted either on the value of the keys, or an individual key of an object or array.
419  *
420  * @since 11.3
421  */
422  public static function pivot($source, $key = null)
423  {
424  $result = array();
425  $counter = array();
426 
427  foreach ($source as $index => $value)
428  {
429  // Determine the name of the pivot key, and its value.
430  if (is_array($value))
431  {
432  // If the key does not exist, ignore it.
433  if (!isset($value[$key]))
434  {
435  continue;
436  }
437 
438  $resultKey = $value[$key];
439  $resultValue = &$source[$index];
440  }
441  elseif (is_object($value))
442  {
443  // If the key does not exist, ignore it.
444  if (!isset($value->$key))
445  {
446  continue;
447  }
448 
449  $resultKey = $value->$key;
450  $resultValue = &$source[$index];
451  }
452  else
453  {
454  // Just a scalar value.
455  $resultKey = $value;
456  $resultValue = $index;
457  }
458 
459  // The counter tracks how many times a key has been used.
460  if (empty($counter[$resultKey]))
461  {
462  // The first time around we just assign the value to the key.
463  $result[$resultKey] = $resultValue;
464  $counter[$resultKey] = 1;
465  }
466  elseif ($counter[$resultKey] == 1)
467  {
468  // If there is a second time, we convert the value into an array.
469  $result[$resultKey] = array(
470  $result[$resultKey],
471  $resultValue,
472  );
473  $counter[$resultKey]++;
474  }
475  else
476  {
477  // After the second time, no need to track any more. Just append to the existing array.
478  $result[$resultKey][] = $resultValue;
479  }
480  }
481 
482  unset($counter);
483 
484  return $result;
485  }
486 
487  /**
488  * Utility function to sort an array of objects on a given field
489  *
490  * @param array &$a An array of objects
491  * @param mixed $k The key (string) or a array of key to sort on
492  * @param mixed $direction Direction (integer) or an array of direction to sort in [1 = Ascending] [-1 = Descending]
493  * @param mixed $caseSensitive Boolean or array of booleans to let sort occur case sensitive or insensitive
494  * @param mixed $locale Boolean or array of booleans to let sort occur using the locale language or not
495  *
496  * @return array The sorted array of objects
497  *
498  * @since 11.1
499  */
500  public static function sortObjects(&$a, $k, $direction = 1, $caseSensitive = true, $locale = false)
501  {
502  if (!is_array($locale) || !is_array($locale[0]))
503  {
504  $locale = array($locale);
505  }
506 
507  self::$sortCase = (array) $caseSensitive;
508  self::$sortDirection = (array) $direction;
509  self::$sortKey = (array) $k;
510  self::$sortLocale = $locale;
511 
512  usort($a, array(__CLASS__, '_sortObjects'));
513 
514  self::$sortCase = null;
515  self::$sortDirection = null;
516  self::$sortKey = null;
517  self::$sortLocale = null;
518 
519  return $a;
520  }
521 
522  /**
523  * Callback function for sorting an array of objects on a key
524  *
525  * @param array &$a An array of objects
526  * @param array &$b An array of objects
527  *
528  * @return integer Comparison status
529  *
530  * @see JArrayHelper::sortObjects()
531  * @since 11.1
532  */
533  protected static function _sortObjects(&$a, &$b)
534  {
535  $key = self::$sortKey;
536 
537  for ($i = 0, $count = count($key); $i < $count; $i++)
538  {
539  if (isset(self::$sortDirection[$i]))
540  {
541  $direction = self::$sortDirection[$i];
542  }
543 
544  if (isset(self::$sortCase[$i]))
545  {
546  $caseSensitive = self::$sortCase[$i];
547  }
548 
549  if (isset(self::$sortLocale[$i]))
550  {
551  $locale = self::$sortLocale[$i];
552  }
553 
554  $va = $a->$key[$i];
555  $vb = $b->$key[$i];
556 
557  if ((is_bool($va) || is_numeric($va)) && (is_bool($vb) || is_numeric($vb)))
558  {
559  $cmp = $va - $vb;
560  }
561  elseif ($caseSensitive)
562  {
563  $cmp = JString::strcmp($va, $vb, $locale);
564  }
565  else
566  {
567  $cmp = JString::strcasecmp($va, $vb, $locale);
568  }
569 
570  if ($cmp > 0)
571  {
572 
573  return $direction;
574  }
575 
576  if ($cmp < 0)
577  {
578  return -$direction;
579  }
580  }
581 
582  return 0;
583  }
584 
585  /**
586  * Multidimensional array safe unique test
587  *
588  * @param array $myArray The array to make unique.
589  *
590  * @return array
591  *
592  * @see http://php.net/manual/en/function.array-unique.php
593  * @since 11.2
594  */
595  public static function arrayUnique($myArray)
596  {
597  if (!is_array($myArray))
598  {
599  return $myArray;
600  }
601 
602  foreach ($myArray as &$myvalue)
603  {
604  $myvalue = serialize($myvalue);
605  }
606 
607  $myArray = array_unique($myArray);
608 
609  foreach ($myArray as &$myvalue)
610  {
611  $myvalue = unserialize($myvalue);
612  }
613 
614  return $myArray;
615  }
616 }