JOOMLA中国
  • Joomla中国首页
  • 社区
  • 教程
  • 应用市场
  • B计划
Joomla! Framework TM
  • Namespace
  • Class
  • Tree
  • Deprecated

Namespaces

  • Composer
    • Autoload
  • Joomla
    • Application
      • Cli
        • Output
          • Processor
      • Web
    • Data
    • DI
      • Exception
    • Event
    • Filter
    • Input
    • Ldap
    • Registry
      • Format
    • Session
      • Storage
    • String
    • Uri
    • Utilities
  • None
  • PasswordCompat
    • binary
  • PHP
  • Psr
    • Log
  • Symfony
    • Component
      • Yaml
        • Exception
    • Polyfill
      • Util

Classes

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