CakePHP
  • Documentation
    • Book
    • API
    • Videos
    • Reporting Security Issues
    • Privacy Policy
    • Logos & Trademarks
  • Business Solutions
  • Swag
  • Road Trip
  • Team
  • Community
    • Community
    • Get Involved
    • Issues (GitHub)
    • Bakery
    • Featured Resources
    • Training
    • Meetups
    • My CakePHP
    • CakeFest
    • Newsletter
    • Linkedin
    • YouTube
    • Facebook
    • Twitter
    • Mastodon
    • Help & Support
    • Forum
    • Stack Overflow
    • Slack
    • Paid Support
CakePHP

C CakePHP 1.3 API

  • Overview
  • Tree
  • Deprecated
  • Version:
    • 1.3
      • 4.2
      • 4.1
      • 4.0
      • 3.9
      • 3.8
      • 3.7
      • 3.6
      • 3.5
      • 3.4
      • 3.3
      • 3.2
      • 3.1
      • 3.0
      • 2.10
      • 2.9
      • 2.8
      • 2.7
      • 2.6
      • 2.5
      • 2.4
      • 2.3
      • 2.2
      • 2.1
      • 2.0
      • 1.3
      • 1.2

Classes

  • AclBase
  • AclBehavior
  • AclComponent
  • AclNode
  • AclShell
  • Aco
  • AcoAction
  • AjaxHelper
  • ApcEngine
  • ApiShell
  • App
  • AppController
  • AppHelper
  • AppModel
  • Aro
  • AuthComponent
  • BakeShell
  • BakeTask
  • BehaviorCollection
  • Cache
  • CacheEngine
  • CacheHelper
  • CakeErrorController
  • CakeLog
  • CakeRoute
  • CakeSchema
  • CakeSession
  • CakeSocket
  • ClassRegistry
  • Component
  • Configure
  • ConnectionManager
  • ConsoleShell
  • ContainableBehavior
  • Controller
  • ControllerTask
  • CookieComponent
  • DataSource
  • DbAcl
  • DbConfigTask
  • DboMssql
  • DboMysql
  • DboMysqlBase
  • DboMysqli
  • DboOracle
  • DboPostgres
  • DboSource
  • DboSqlite
  • Debugger
  • EmailComponent
  • ErrorHandler
  • ExtractTask
  • File
  • FileEngine
  • FileLog
  • FixtureTask
  • Folder
  • FormHelper
  • Helper
  • HtmlHelper
  • HttpSocket
  • I18n
  • I18nModel
  • I18nShell
  • Inflector
  • IniAcl
  • JavascriptHelper
  • JqueryEngineHelper
  • JsBaseEngineHelper
  • JsHelper
  • L10n
  • MagicDb
  • MagicFileResource
  • MediaView
  • MemcacheEngine
  • Model
  • ModelBehavior
  • ModelTask
  • MootoolsEngineHelper
  • Multibyte
  • NumberHelper
  • Object
  • Overloadable
  • Overloadable2
  • PagesController
  • PaginatorHelper
  • Permission
  • PluginShortRoute
  • PluginTask
  • ProjectTask
  • PrototypeEngineHelper
  • RequestHandlerComponent
  • Router
  • RssHelper
  • Sanitize
  • Scaffold
  • ScaffoldView
  • SchemaShell
  • Security
  • SecurityComponent
  • SessionComponent
  • SessionHelper
  • Set
  • Shell
  • String
  • TemplateTask
  • TestSuiteShell
  • TestTask
  • TextHelper
  • ThemeView
  • TimeHelper
  • TranslateBehavior
  • TreeBehavior
  • Validation
  • View
  • ViewTask
  • XcacheEngine
  • Xml
  • XmlElement
  • XmlHelper
  • XmlManager
  • XmlNode
  • XmlTextNode

Functions

  • mb_encode_mimeheader
  • mb_stripos
  • mb_stristr
  • mb_strlen
  • mb_strpos
  • mb_strrchr
  • mb_strrichr
  • mb_strripos
  • mb_strrpos
  • mb_strstr
  • mb_strtolower
  • mb_strtoupper
  • mb_substr
  • mb_substr_count
   1: <?php
   2: /**
   3:  * Library of array functions for Cake.
   4:  *
   5:  * PHP versions 4 and 5
   6:  *
   7:  * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
   8:  * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
   9:  *
  10:  * Licensed under The MIT License
  11:  * Redistributions of files must retain the above copyright notice.
  12:  *
  13:  * @copyright     Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
  14:  * @link          http://cakephp.org CakePHP(tm) Project
  15:  * @package       cake
  16:  * @subpackage    cake.cake.libs
  17:  * @since         CakePHP(tm) v 1.2.0
  18:  * @license       MIT License (http://www.opensource.org/licenses/mit-license.php)
  19:  */
  20: 
  21: /**
  22:  * Class used for manipulation of arrays.
  23:  *
  24:  * @package       cake
  25:  * @subpackage    cake.cake.libs
  26:  */
  27: class Set {
  28: 
  29: /**
  30:  * This function can be thought of as a hybrid between PHP's array_merge and array_merge_recursive. The difference
  31:  * to the two is that if an array key contains another array then the function behaves recursive (unlike array_merge)
  32:  * but does not do if for keys containing strings (unlike array_merge_recursive).
  33:  * See the unit test for more information.
  34:  *
  35:  * Note: This function will work with an unlimited amount of arguments and typecasts non-array parameters into arrays.
  36:  *
  37:  * @param array $arr1 Array to be merged
  38:  * @param array $arr2 Array to merge with
  39:  * @return array Merged array
  40:  * @access public
  41:  * @static
  42:  */
  43:     function merge($arr1, $arr2 = null) {
  44:         $args = func_get_args();
  45: 
  46:         $r = (array)current($args);
  47:         while (($arg = next($args)) !== false) {
  48:             foreach ((array)$arg as $key => $val)    {
  49:                 if (is_array($val) && isset($r[$key]) && is_array($r[$key])) {
  50:                     $r[$key] = Set::merge($r[$key], $val);
  51:                 } elseif (is_int($key)) {
  52:                     $r[] = $val;
  53:                 } else {
  54:                     $r[$key] = $val;
  55:                 }
  56:             }
  57:         }
  58:         return $r;
  59:     }
  60: 
  61: /**
  62:  * Filters empty elements out of a route array, excluding '0'.
  63:  *
  64:  * @param mixed $var Either an array to filter, or value when in callback
  65:  * @param boolean $isArray Force to tell $var is an array when $var is empty
  66:  * @return mixed Either filtered array, or true/false when in callback
  67:  * @access public
  68:  * @static
  69:  */
  70:     function filter($var, $isArray = false) {
  71:         if (is_array($var) && (!empty($var) || $isArray)) {
  72:             return array_filter($var, array('Set', 'filter'));
  73:         }
  74: 
  75:         if ($var === 0 || $var === '0' || !empty($var)) {
  76:             return true;
  77:         }
  78:         return false;
  79:     }
  80: 
  81: /**
  82:  * Pushes the differences in $array2 onto the end of $array
  83:  *
  84:  * @param mixed $array Original array
  85:  * @param mixed $array2 Differences to push
  86:  * @return array Combined array
  87:  * @access public
  88:  * @static
  89:  */
  90:     function pushDiff($array, $array2) {
  91:         if (empty($array) && !empty($array2)) {
  92:             return $array2;
  93:         }
  94:         if (!empty($array) && !empty($array2)) {
  95:             foreach ($array2 as $key => $value) {
  96:                 if (!array_key_exists($key, $array)) {
  97:                     $array[$key] = $value;
  98:                 } else {
  99:                     if (is_array($value)) {
 100:                         $array[$key] = Set::pushDiff($array[$key], $array2[$key]);
 101:                     }
 102:                 }
 103:             }
 104:         }
 105:         return $array;
 106:     }
 107: 
 108: /**
 109:  * Maps the contents of the Set object to an object hierarchy.
 110:  * Maintains numeric keys as arrays of objects
 111:  *
 112:  * @param string $class A class name of the type of object to map to
 113:  * @param string $tmp A temporary class name used as $class if $class is an array
 114:  * @return object Hierarchical object
 115:  * @access public
 116:  * @static
 117:  */
 118:     function map($class = 'stdClass', $tmp = 'stdClass') {
 119:         if (is_array($class)) {
 120:             $val = $class;
 121:             $class = $tmp;
 122:         }
 123: 
 124:         if (empty($val)) {
 125:             return null;
 126:         }
 127:         return Set::__map($val, $class);
 128:     }
 129: 
 130: /**
 131:  * Get the array value of $array. If $array is null, it will return
 132:  * the current array Set holds. If it is an object of type Set, it
 133:  * will return its value. If it is another object, its object variables.
 134:  * If it is anything else but an array, it will return an array whose first
 135:  * element is $array.
 136:  *
 137:  * @param mixed $array Data from where to get the array.
 138:  * @return array Array from $array.
 139:  * @access private
 140:  */
 141:     function __array($array) {
 142:         if (empty($array)) {
 143:             $array = array();
 144:         } elseif (is_object($array)) {
 145:             $array = get_object_vars($array);
 146:         } elseif (!is_array($array)) {
 147:             $array = array($array);
 148:         }
 149:         return $array;
 150:     }
 151: 
 152: /**
 153:  * Maps the given value as an object. If $value is an object,
 154:  * it returns $value. Otherwise it maps $value as an object of
 155:  * type $class, and if primary assign _name_ $key on first array.
 156:  * If $value is not empty, it will be used to set properties of
 157:  * returned object (recursively). If $key is numeric will maintain array
 158:  * structure
 159:  *
 160:  * @param mixed $value Value to map
 161:  * @param string $class Class name
 162:  * @param boolean $primary whether to assign first array key as the _name_
 163:  * @return mixed Mapped object
 164:  * @access private
 165:  * @static
 166:  */
 167:     function __map(&$array, $class, $primary = false) {
 168:         if ($class === true) {
 169:             $out = new stdClass;
 170:         } else {
 171:             $out = new $class;
 172:         }
 173:         if (is_array($array)) {
 174:             $keys = array_keys($array);
 175:             foreach ($array as $key => $value) {
 176:                 if ($keys[0] === $key && $class !== true) {
 177:                     $primary = true;
 178:                 }
 179:                 if (is_numeric($key)) {
 180:                     if (is_object($out)) {
 181:                         $out = get_object_vars($out);
 182:                     }
 183:                     $out[$key] = Set::__map($value, $class);
 184:                     if (is_object($out[$key])) {
 185:                         if ($primary !== true && is_array($value) && Set::countDim($value, true) === 2) {
 186:                             if (!isset($out[$key]->_name_)) {
 187:                                 $out[$key]->_name_ = $primary;
 188:                             }
 189:                         }
 190:                     }
 191:                 } elseif (is_array($value)) {
 192:                     if ($primary === true) {
 193:                         if (!isset($out->_name_)) {
 194:                             $out->_name_ = $key;
 195:                         }
 196:                         $primary = false;
 197:                         foreach ($value as $key2 => $value2) {
 198:                             $out->{$key2} = Set::__map($value2, true);
 199:                         }
 200:                     } else {
 201:                         if (!is_numeric($key)) {
 202:                             $out->{$key} = Set::__map($value, true, $key);
 203:                             if (is_object($out->{$key}) && !is_numeric($key)) {
 204:                                 if (!isset($out->{$key}->_name_)) {
 205:                                     $out->{$key}->_name_ = $key;
 206:                                 }
 207:                             }
 208:                         } else {
 209:                             $out->{$key} = Set::__map($value, true);
 210:                         }
 211:                     }
 212:                 } else {
 213:                     $out->{$key} = $value;
 214:                 }
 215:             }
 216:         } else {
 217:             $out = $array;
 218:         }
 219:         return $out;
 220:     }
 221: 
 222: /**
 223:  * Checks to see if all the values in the array are numeric
 224:  *
 225:  * @param array $array The array to check.  If null, the value of the current Set object
 226:  * @return boolean true if values are numeric, false otherwise
 227:  * @access public
 228:  * @static
 229:  */
 230:     function numeric($array = null) {
 231:         if (empty($array)) {
 232:             return null;
 233:         }
 234: 
 235:         if ($array === range(0, count($array) - 1)) {
 236:             return true;
 237:         }
 238: 
 239:         $numeric = true;
 240:         $keys = array_keys($array);
 241:         $count = count($keys);
 242: 
 243:         for ($i = 0; $i < $count; $i++) {
 244:             if (!is_numeric($array[$keys[$i]])) {
 245:                 $numeric = false;
 246:                 break;
 247:             }
 248:         }
 249:         return $numeric;
 250:     }
 251: 
 252: /**
 253:  * Return a value from an array list if the key exists.
 254:  *
 255:  * If a comma separated $list is passed arrays are numeric with the key of the first being 0
 256:  * $list = 'no, yes' would translate to  $list = array(0 => 'no', 1 => 'yes');
 257:  *
 258:  * If an array is used, keys can be strings example: array('no' => 0, 'yes' => 1);
 259:  *
 260:  * $list defaults to 0 = no 1 = yes if param is not passed
 261:  *
 262:  * @param mixed $select Key in $list to return
 263:  * @param mixed $list can be an array or a comma-separated list.
 264:  * @return string the value of the array key or null if no match
 265:  * @access public
 266:  * @static
 267:  */
 268:     function enum($select, $list = null) {
 269:         if (empty($list)) {
 270:             $list = array('no', 'yes');
 271:         }
 272: 
 273:         $return = null;
 274:         $list = Set::normalize($list, false);
 275: 
 276:         if (array_key_exists($select, $list)) {
 277:             $return = $list[$select];
 278:         }
 279:         return $return;
 280:     }
 281: 
 282: /**
 283:  * Returns a series of values extracted from an array, formatted in a format string.
 284:  *
 285:  * @param array $data Source array from which to extract the data
 286:  * @param string $format Format string into which values will be inserted, see sprintf()
 287:  * @param array $keys An array containing one or more Set::extract()-style key paths
 288:  * @return array An array of strings extracted from $keys and formatted with $format
 289:  * @access public
 290:  * @static
 291:  */
 292:     function format($data, $format, $keys) {
 293: 
 294:         $extracted = array();
 295:         $count = count($keys);
 296: 
 297:         if (!$count) {
 298:             return;
 299:         }
 300: 
 301:         for ($i = 0; $i < $count; $i++) {
 302:             $extracted[] = Set::extract($data, $keys[$i]);
 303:         }
 304:         $out = array();
 305:         $data = $extracted;
 306:         $count = count($data[0]);
 307: 
 308:         if (preg_match_all('/\{([0-9]+)\}/msi', $format, $keys2) && isset($keys2[1])) {
 309:             $keys = $keys2[1];
 310:             $format = preg_split('/\{([0-9]+)\}/msi', $format);
 311:             $count2 = count($format);
 312: 
 313:             for ($j = 0; $j < $count; $j++) {
 314:                 $formatted = '';
 315:                 for ($i = 0; $i <= $count2; $i++) {
 316:                     if (isset($format[$i])) {
 317:                         $formatted .= $format[$i];
 318:                     }
 319:                     if (isset($keys[$i]) && isset($data[$keys[$i]][$j])) {
 320:                         $formatted .= $data[$keys[$i]][$j];
 321:                     }
 322:                 }
 323:                 $out[] = $formatted;
 324:             }
 325:         } else {
 326:             $count2 = count($data);
 327:             for ($j = 0; $j < $count; $j++) {
 328:                 $args = array();
 329:                 for ($i = 0; $i < $count2; $i++) {
 330:                     if (array_key_exists($j, $data[$i])) {
 331:                         $args[] = $data[$i][$j];
 332:                     }
 333:                 }
 334:                 $out[] = vsprintf($format, $args);
 335:             }
 336:         }
 337:         return $out;
 338:     }
 339: 
 340: /**
 341:  * Implements partial support for XPath 2.0. If $path is an array or $data is empty it the call
 342:  * is delegated to Set::classicExtract.
 343:  *
 344:  * #### Currently implemented selectors:
 345:  *
 346:  * - /User/id (similar to the classic {n}.User.id)
 347:  * - /User[2]/name (selects the name of the second User)
 348:  * - /User[id>2] (selects all Users with an id > 2)
 349:  * - /User[id>2][<5] (selects all Users with an id > 2 but < 5)
 350:  * - /Post/Comment[author_name=john]/../name (Selects the name of all Posts that have at least one Comment written by john)
 351:  * - /Posts[name] (Selects all Posts that have a 'name' key)
 352:  * - /Comment/.[1] (Selects the contents of the first comment)
 353:  * - /Comment/.[:last] (Selects the last comment)
 354:  * - /Comment/.[:first] (Selects the first comment)
 355:  * - /Comment[text=/cakephp/i] (Selects the all comments that have a text matching the regex /cakephp/i)
 356:  * - /Comment/@* (Selects the all key names of all comments)
 357:  *
 358:  * #### Other limitations:
 359:  *
 360:  * - Only absolute paths starting with a single '/' are supported right now
 361:  *
 362:  * **Warning**: Even so it has plenty of unit tests the XPath support has not gone through a lot of
 363:  * real-world testing. Please report Bugs as you find them. Suggestions for additional features to
 364:  * implement are also very welcome!
 365:  *
 366:  * @param string $path An absolute XPath 2.0 path
 367:  * @param array $data An array of data to extract from
 368:  * @param array $options Currently only supports 'flatten' which can be disabled for higher XPath-ness
 369:  * @return array An array of matched items
 370:  * @access public
 371:  * @static
 372:  */
 373:     function extract($path, $data = null, $options = array()) {
 374:         if (is_string($data)) {
 375:             $tmp = $data;
 376:             $data = $path;
 377:             $path = $tmp;
 378:         }
 379:         if (strpos($path, '/') === false) {
 380:             return Set::classicExtract($data, $path);
 381:         }
 382:         if (empty($data)) {
 383:             return array();
 384:         }
 385:         if ($path === '/') {
 386:             return $data;
 387:         }
 388:         $contexts = $data;
 389:         $options = array_merge(array('flatten' => true), $options);
 390:         if (!isset($contexts[0])) {
 391:             $current = current($data);
 392:             if ((is_array($current) && count($data) < 1) || !is_array($current) || !Set::numeric(array_keys($data))) {
 393:                 $contexts = array($data);
 394:             }
 395:         }
 396:         $tokens = array_slice(preg_split('/(?<!=|\\\\)\/(?![a-z-\s]*\])/', $path), 1);
 397: 
 398:         do {
 399:             $token = array_shift($tokens);
 400:             $conditions = false;
 401:             if (preg_match_all('/\[([^=]+=\/[^\/]+\/|[^\]]+)\]/', $token, $m)) {
 402:                 $conditions = $m[1];
 403:                 $token = substr($token, 0, strpos($token, '['));
 404:             }
 405:             $matches = array();
 406:             foreach ($contexts as $key => $context) {
 407:                 if (!isset($context['trace'])) {
 408:                     $context = array('trace' => array(null), 'item' => $context, 'key' => $key);
 409:                 }
 410:                 if ($token === '..') {
 411:                     if (count($context['trace']) == 1) {
 412:                         $context['trace'][] = $context['key'];
 413:                     }
 414:                     $parent = implode('/', $context['trace']) . '/.';
 415:                     $context['item'] = Set::extract($parent, $data);
 416:                     $context['key'] = array_pop($context['trace']);
 417:                     if (isset($context['trace'][1]) && $context['trace'][1] > 0) {
 418:                         $context['item'] = $context['item'][0];
 419:                     } elseif (!empty($context['item'][$key])) {
 420:                         $context['item'] = $context['item'][$key];
 421:                     } else {
 422:                         $context['item'] = array_shift($context['item']);
 423:                     }
 424:                     $matches[] = $context;
 425:                     continue;
 426:                 }
 427:                 $match = false;
 428:                 if ($token === '@*' && is_array($context['item'])) {
 429:                     $matches[] = array(
 430:                         'trace' => array_merge($context['trace'], (array)$key),
 431:                         'key' => $key,
 432:                         'item' => array_keys($context['item']),
 433:                     );
 434:                 } elseif (is_array($context['item'])
 435:                     && array_key_exists($token, $context['item'])
 436:                     && !(strval($key) === strval($token) && count($tokens) == 1 && $tokens[0] === '.')) {
 437:                     $items = $context['item'][$token];
 438:                     if (!is_array($items)) {
 439:                         $items = array($items);
 440:                     } elseif (!isset($items[0])) {
 441:                         $current = current($items);
 442:                         $currentKey = key($items);
 443:                         if (!is_array($current) || (is_array($current) && count($items) <= 1 && !is_numeric($currentKey))) {
 444:                             $items = array($items);
 445:                         }
 446:                     }
 447: 
 448:                     foreach ($items as $key => $item) {
 449:                         $ctext = array($context['key']);
 450:                         if (!is_numeric($key)) {
 451:                             $ctext[] = $token;
 452:                             $tok = array_shift($tokens);
 453:                             if (isset($items[$tok])) {
 454:                                 $ctext[] = $tok;
 455:                                 $item = $items[$tok];
 456:                                 $matches[] = array(
 457:                                     'trace' => array_merge($context['trace'], $ctext),
 458:                                     'key' => $tok,
 459:                                     'item' => $item,
 460:                                 );
 461:                                 break;
 462:                             } elseif ($tok !== null) {
 463:                                 array_unshift($tokens, $tok);
 464:                             }
 465:                         } else {
 466:                             $key = $token;
 467:                         }
 468: 
 469:                         $matches[] = array(
 470:                             'trace' => array_merge($context['trace'], $ctext),
 471:                             'key' => $key,
 472:                             'item' => $item,
 473:                         );
 474:                     }
 475:                 } elseif ($key === $token || (ctype_digit($token) && $key == $token) || $token === '.') {
 476:                     $context['trace'][] = $key;
 477:                     $matches[] = array(
 478:                         'trace' => $context['trace'],
 479:                         'key' => $key,
 480:                         'item' => $context['item'],
 481:                     );
 482:                 }
 483:             }
 484:             if ($conditions) {
 485:                 foreach ($conditions as $condition) {
 486:                     $filtered = array();
 487:                     $length = count($matches);
 488:                     foreach ($matches as $i => $match) {
 489:                         if (Set::matches(array($condition), $match['item'], $i + 1, $length)) {
 490:                             $filtered[$i] = $match;
 491:                         }
 492:                     }
 493:                     $matches = $filtered;
 494:                 }
 495:             }
 496:             $contexts = $matches;
 497: 
 498:             if (empty($tokens)) {
 499:                 break;
 500:             }
 501:         } while(1);
 502: 
 503:         $r = array();
 504: 
 505:         foreach ($matches as $match) {
 506:             if ((!$options['flatten'] || is_array($match['item'])) && !is_int($match['key'])) {
 507:                 $r[] = array($match['key'] => $match['item']);
 508:             } else {
 509:                 $r[] = $match['item'];
 510:             }
 511:         }
 512:         return $r;
 513:     }
 514: 
 515: /**
 516:  * This function can be used to see if a single item or a given xpath match certain conditions.
 517:  *
 518:  * @param mixed $conditions An array of condition strings or an XPath expression
 519:  * @param array $data  An array of data to execute the match on
 520:  * @param integer $i Optional: The 'nth'-number of the item being matched.
 521:  * @return boolean
 522:  * @access public
 523:  * @static
 524:  */
 525:     function matches($conditions, $data = array(), $i = null, $length = null) {
 526:         if (empty($conditions)) {
 527:             return true;
 528:         }
 529:         if (is_string($conditions)) {
 530:             return !!Set::extract($conditions, $data);
 531:         }
 532:         foreach ($conditions as $condition) {
 533:             if ($condition === ':last') {
 534:                 if ($i != $length) {
 535:                     return false;
 536:                 }
 537:                 continue;
 538:             } elseif ($condition === ':first') {
 539:                 if ($i != 1) {
 540:                     return false;
 541:                 }
 542:                 continue;
 543:             }
 544:             if (!preg_match('/(.+?)([><!]?[=]|[><])(.*)/', $condition, $match)) {
 545:                 if (ctype_digit($condition)) {
 546:                     if ($i != $condition) {
 547:                         return false;
 548:                     }
 549:                 } elseif (preg_match_all('/(?:^[0-9]+|(?<=,)[0-9]+)/', $condition, $matches)) {
 550:                     return in_array($i, $matches[0]);
 551:                 } elseif (!array_key_exists($condition, $data)) {
 552:                     return false;
 553:                 }
 554:                 continue;
 555:             }
 556:             list(,$key,$op,$expected) = $match;
 557:             if (!isset($data[$key])) {
 558:                 return false;
 559:             }
 560: 
 561:             $val = $data[$key];
 562: 
 563:             if ($op === '=' && $expected && $expected{0} === '/') {
 564:                 return preg_match($expected, $val);
 565:             }
 566:             if ($op === '=' && $val != $expected) {
 567:                 return false;
 568:             }
 569:             if ($op === '!=' && $val == $expected) {
 570:                 return false;
 571:             }
 572:             if ($op === '>' && $val <= $expected) {
 573:                 return false;
 574:             }
 575:             if ($op === '<' && $val >= $expected) {
 576:                 return false;
 577:             }
 578:             if ($op === '<=' && $val > $expected) {
 579:                 return false;
 580:             }
 581:             if ($op === '>=' && $val < $expected) {
 582:                 return false;
 583:             }
 584:         }
 585:         return true;
 586:     }
 587: 
 588: /**
 589:  * Gets a value from an array or object that is contained in a given path using an array path syntax, i.e.:
 590:  * "{n}.Person.{[a-z]+}" - Where "{n}" represents a numeric key, "Person" represents a string literal,
 591:  * and "{[a-z]+}" (i.e. any string literal enclosed in brackets besides {n} and {s}) is interpreted as
 592:  * a regular expression.
 593:  *
 594:  * @param array $data Array from where to extract
 595:  * @param mixed $path As an array, or as a dot-separated string.
 596:  * @return array Extracted data
 597:  * @access public
 598:  * @static
 599:  */
 600:     function classicExtract($data, $path = null) {
 601:         if (empty($path)) {
 602:             return $data;
 603:         }
 604:         if (is_object($data)) {
 605:             $data = get_object_vars($data);
 606:         }
 607:         if (!is_array($data)) {
 608:             return $data;
 609:         }
 610: 
 611:         if (!is_array($path)) {
 612:             if (!class_exists('String')) {
 613:                 App::import('Core', 'String');
 614:             }
 615:             $path = String::tokenize($path, '.', '{', '}');
 616:         }
 617:         $tmp = array();
 618: 
 619:         if (!is_array($path) || empty($path)) {
 620:             return null;
 621:         }
 622: 
 623:         foreach ($path as $i => $key) {
 624:             if (is_numeric($key) && intval($key) > 0 || $key === '0') {
 625:                 if (isset($data[intval($key)])) {
 626:                     $data = $data[intval($key)];
 627:                 } else {
 628:                     return null;
 629:                 }
 630:             } elseif ($key === '{n}') {
 631:                 foreach ($data as $j => $val) {
 632:                     if (is_int($j)) {
 633:                         $tmpPath = array_slice($path, $i + 1);
 634:                         if (empty($tmpPath)) {
 635:                             $tmp[] = $val;
 636:                         } else {
 637:                             $tmp[] = Set::classicExtract($val, $tmpPath);
 638:                         }
 639:                     }
 640:                 }
 641:                 return $tmp;
 642:             } elseif ($key === '{s}') {
 643:                 foreach ($data as $j => $val) {
 644:                     if (is_string($j)) {
 645:                         $tmpPath = array_slice($path, $i + 1);
 646:                         if (empty($tmpPath)) {
 647:                             $tmp[] = $val;
 648:                         } else {
 649:                             $tmp[] = Set::classicExtract($val, $tmpPath);
 650:                         }
 651:                     }
 652:                 }
 653:                 return $tmp;
 654:             } elseif (false !== strpos($key,'{') && false !== strpos($key,'}')) {
 655:                 $pattern = substr($key, 1, -1);
 656: 
 657:                 foreach ($data as $j => $val) {
 658:                     if (preg_match('/^'.$pattern.'/s', $j) !== 0) {
 659:                         $tmpPath = array_slice($path, $i + 1);
 660:                         if (empty($tmpPath)) {
 661:                             $tmp[$j] = $val;
 662:                         } else {
 663:                             $tmp[$j] = Set::classicExtract($val, $tmpPath);
 664:                         }
 665:                     }
 666:                 }
 667:                 return $tmp;
 668:             } else {
 669:                 if (isset($data[$key])) {
 670:                     $data = $data[$key];
 671:                 } else {
 672:                     return null;
 673:                 }
 674:             }
 675:         }
 676:         return $data;
 677:     }
 678: 
 679: /**
 680:  * Inserts $data into an array as defined by $path.
 681:  *
 682:  * @param mixed $list Where to insert into
 683:  * @param mixed $path A dot-separated string.
 684:  * @param mixed $data Data to insert
 685:  * @return array
 686:  * @access public
 687:  * @static
 688:  */
 689:     function insert($list, $path, $data = null) {
 690:         if (!is_array($path)) {
 691:             $path = explode('.', $path);
 692:         }
 693:         $_list =& $list;
 694: 
 695:         foreach ($path as $i => $key) {
 696:             if (is_numeric($key) && intval($key) > 0 || $key === '0') {
 697:                 $key = intval($key);
 698:             }
 699:             if ($i === count($path) - 1) {
 700:                 $_list[$key] = $data;
 701:             } else {
 702:                 if (!isset($_list[$key])) {
 703:                     $_list[$key] = array();
 704:                 }
 705:                 $_list =& $_list[$key];
 706:             }
 707:             if (!is_array($_list)) {
 708:                 return array();
 709:             }
 710:         }
 711:         return $list;
 712:     }
 713: 
 714: /**
 715:  * Removes an element from a Set or array as defined by $path.
 716:  *
 717:  * @param mixed $list From where to remove
 718:  * @param mixed $path A dot-separated string.
 719:  * @return array Array with $path removed from its value
 720:  * @access public
 721:  * @static
 722:  */
 723:     function remove($list, $path = null) {
 724:         if (empty($path)) {
 725:             return $list;
 726:         }
 727:         if (!is_array($path)) {
 728:             $path = explode('.', $path);
 729:         }
 730:         $_list =& $list;
 731: 
 732:         foreach ($path as $i => $key) {
 733:             if (is_numeric($key) && intval($key) > 0 || $key === '0') {
 734:                 $key = intval($key);
 735:             }
 736:             if ($i === count($path) - 1) {
 737:                 unset($_list[$key]);
 738:             } else {
 739:                 if (!isset($_list[$key])) {
 740:                     return $list;
 741:                 }
 742:                 $_list =& $_list[$key];
 743:             }
 744:         }
 745:         return $list;
 746:     }
 747: 
 748: /**
 749:  * Checks if a particular path is set in an array
 750:  *
 751:  * @param mixed $data Data to check on
 752:  * @param mixed $path A dot-separated string.
 753:  * @return boolean true if path is found, false otherwise
 754:  * @access public
 755:  * @static
 756:  */
 757:     function check($data, $path = null) {
 758:         if (empty($path)) {
 759:             return $data;
 760:         }
 761:         if (!is_array($path)) {
 762:             $path = explode('.', $path);
 763:         }
 764: 
 765:         foreach ($path as $i => $key) {
 766:             if (is_numeric($key) && intval($key) > 0 || $key === '0') {
 767:                 $key = intval($key);
 768:             }
 769:             if ($i === count($path) - 1) {
 770:                 return (is_array($data) && array_key_exists($key, $data));
 771:             }
 772: 
 773:             if (!is_array($data) || !array_key_exists($key, $data)) {
 774:                 return false;
 775:             }
 776:             $data =& $data[$key];
 777:         }
 778:         return true;
 779:     }
 780: 
 781: /**
 782:  * Computes the difference between a Set and an array, two Sets, or two arrays
 783:  *
 784:  * @param mixed $val1 First value
 785:  * @param mixed $val2 Second value
 786:  * @return array Returns the key => value pairs that are not common in $val1 and $val2
 787:  * The expression for this function is ($val1 - $val2) + ($val2 - ($val1 - $val2))
 788:  * @access public
 789:  * @static
 790:  */
 791:     function diff($val1, $val2 = null) {
 792:         if (empty($val1)) {
 793:             return (array)$val2;
 794:         }
 795:         if (empty($val2)) {
 796:             return (array)$val1;
 797:         }
 798:         $intersection = array_intersect_key($val1, $val2);
 799:         while (($key = key($intersection)) !== null) {
 800:             if ($val1[$key] == $val2[$key]) {
 801:                 unset($val1[$key]);
 802:                 unset($val2[$key]);
 803:             }
 804:             next($intersection);
 805:         }
 806: 
 807:         return $val1 + $val2;
 808:     }
 809: 
 810: /**
 811:  * Determines if one Set or array contains the exact keys and values of another.
 812:  *
 813:  * @param array $val1 First value
 814:  * @param array $val2 Second value
 815:  * @return boolean true if $val1 contains $val2, false otherwise
 816:  * @access public
 817:  * @static
 818:  */
 819:     function contains($val1, $val2 = null) {
 820:         if (empty($val1) || empty($val2)) {
 821:             return false;
 822:         }
 823: 
 824:         foreach ($val2 as $key => $val) {
 825:             if (is_numeric($key)) {
 826:                 Set::contains($val, $val1);
 827:             } else {
 828:                 if (!isset($val1[$key]) || $val1[$key] != $val) {
 829:                     return false;
 830:                 }
 831:             }
 832:         }
 833:         return true;
 834:     }
 835: 
 836: /**
 837:  * Counts the dimensions of an array. If $all is set to false (which is the default) it will
 838:  * only consider the dimension of the first element in the array.
 839:  *
 840:  * @param array $array Array to count dimensions on
 841:  * @param boolean $all Set to true to count the dimension considering all elements in array
 842:  * @param integer $count Start the dimension count at this number
 843:  * @return integer The number of dimensions in $array
 844:  * @access public
 845:  * @static
 846:  */
 847:     function countDim($array = null, $all = false, $count = 0) {
 848:         if ($all) {
 849:             $depth = array($count);
 850:             if (is_array($array) && reset($array) !== false) {
 851:                 foreach ($array as $value) {
 852:                     $depth[] = Set::countDim($value, true, $count + 1);
 853:                 }
 854:             }
 855:             $return = max($depth);
 856:         } else {
 857:             if (is_array(reset($array))) {
 858:                 $return = Set::countDim(reset($array)) + 1;
 859:             } else {
 860:                 $return = 1;
 861:             }
 862:         }
 863:         return $return;
 864:     }
 865: 
 866: /**
 867:  * Normalizes a string or array list.
 868:  *
 869:  * @param mixed $list List to normalize
 870:  * @param boolean $assoc If true, $list will be converted to an associative array
 871:  * @param string $sep If $list is a string, it will be split into an array with $sep
 872:  * @param boolean $trim If true, separated strings will be trimmed
 873:  * @return array
 874:  * @access public
 875:  * @static
 876:  */
 877:     function normalize($list, $assoc = true, $sep = ',', $trim = true) {
 878:         if (is_string($list)) {
 879:             $list = explode($sep, $list);
 880:             if ($trim) {
 881:                 foreach ($list as $key => $value) {
 882:                     $list[$key] = trim($value);
 883:                 }
 884:             }
 885:             if ($assoc) {
 886:                 return Set::normalize($list);
 887:             }
 888:         } elseif (is_array($list)) {
 889:             $keys = array_keys($list);
 890:             $count = count($keys);
 891:             $numeric = true;
 892: 
 893:             if (!$assoc) {
 894:                 for ($i = 0; $i < $count; $i++) {
 895:                     if (!is_int($keys[$i])) {
 896:                         $numeric = false;
 897:                         break;
 898:                     }
 899:                 }
 900:             }
 901:             if (!$numeric || $assoc) {
 902:                 $newList = array();
 903:                 for ($i = 0; $i < $count; $i++) {
 904:                     if (is_int($keys[$i])) {
 905:                         $newList[$list[$keys[$i]]] = null;
 906:                     } else {
 907:                         $newList[$keys[$i]] = $list[$keys[$i]];
 908:                     }
 909:                 }
 910:                 $list = $newList;
 911:             }
 912:         }
 913:         return $list;
 914:     }
 915: 
 916: /**
 917:  * Creates an associative array using a $path1 as the path to build its keys, and optionally
 918:  * $path2 as path to get the values. If $path2 is not specified, all values will be initialized
 919:  * to null (useful for Set::merge). You can optionally group the values by what is obtained when
 920:  * following the path specified in $groupPath.
 921:  *
 922:  * @param mixed $data Array or object from where to extract keys and values
 923:  * @param mixed $path1 As an array, or as a dot-separated string.
 924:  * @param mixed $path2 As an array, or as a dot-separated string.
 925:  * @param string $groupPath As an array, or as a dot-separated string.
 926:  * @return array Combined array
 927:  * @access public
 928:  * @static
 929:  */
 930:     function combine($data, $path1 = null, $path2 = null, $groupPath = null) {
 931:         if (empty($data)) {
 932:             return array();
 933:         }
 934: 
 935:         if (is_object($data)) {
 936:             $data = get_object_vars($data);
 937:         }
 938: 
 939:         if (is_array($path1)) {
 940:             $format = array_shift($path1);
 941:             $keys = Set::format($data, $format, $path1);
 942:         } else {
 943:             $keys = Set::extract($data, $path1);
 944:         }
 945:         if (empty($keys)) {
 946:             return array();
 947:         }
 948: 
 949:         if (!empty($path2) && is_array($path2)) {
 950:             $format = array_shift($path2);
 951:             $vals = Set::format($data, $format, $path2);
 952: 
 953:         } elseif (!empty($path2)) {
 954:             $vals = Set::extract($data, $path2);
 955: 
 956:         } else {
 957:             $count = count($keys);
 958:             for ($i = 0; $i < $count; $i++) {
 959:                 $vals[$i] = null;
 960:             }
 961:         }
 962: 
 963:         if ($groupPath != null) {
 964:             $group = Set::extract($data, $groupPath);
 965:             if (!empty($group)) {
 966:                 $c = count($keys);
 967:                 for ($i = 0; $i < $c; $i++) {
 968:                     if (!isset($group[$i])) {
 969:                         $group[$i] = 0;
 970:                     }
 971:                     if (!isset($out[$group[$i]])) {
 972:                         $out[$group[$i]] = array();
 973:                     }
 974:                     $out[$group[$i]][$keys[$i]] = $vals[$i];
 975:                 }
 976:                 return $out;
 977:             }
 978:         }
 979:         if (empty($vals)) {
 980:             return array();
 981:         }
 982:         return array_combine($keys, $vals);
 983:     }
 984: 
 985: /**
 986:  * Converts an object into an array.
 987:  * @param object $object Object to reverse
 988:  * @return array Array representation of given object
 989:  * @public
 990:  * @static
 991:  */
 992:     function reverse($object) {
 993:         $out = array();
 994:         if (is_a($object, 'XmlNode')) {
 995:             $out = $object->toArray();
 996:             return $out;
 997:         } else if (is_object($object)) {
 998:             $keys = get_object_vars($object);
 999:             if (isset($keys['_name_'])) {
1000:                 $identity = $keys['_name_'];
1001:                 unset($keys['_name_']);
1002:             }
1003:             $new = array();
1004:             foreach ($keys as $key => $value) {
1005:                 if (is_array($value)) {
1006:                     $new[$key] = (array)Set::reverse($value);
1007:                 } else {
1008:                     if (isset($value->_name_)) {
1009:                         $new = array_merge($new, Set::reverse($value));
1010:                     } else {
1011:                         $new[$key] = Set::reverse($value);
1012:                     }
1013:                 }
1014:             }
1015:             if (isset($identity)) {
1016:                 $out[$identity] = $new;
1017:             } else {
1018:                 $out = $new;
1019:             }
1020:         } elseif (is_array($object)) {
1021:             foreach ($object as $key => $value) {
1022:                 $out[$key] = Set::reverse($value);
1023:             }
1024:         } else {
1025:             $out = $object;
1026:         }
1027:         return $out;
1028:     }
1029: 
1030: /**
1031:  * Collapses a multi-dimensional array into a single dimension, using a delimited array path for
1032:  * each array element's key, i.e. array(array('Foo' => array('Bar' => 'Far'))) becomes
1033:  * array('0.Foo.Bar' => 'Far').
1034:  *
1035:  * @param array $data Array to flatten
1036:  * @param string $separator String used to separate array key elements in a path, defaults to '.'
1037:  * @return array
1038:  * @access public
1039:  * @static
1040:  */
1041:     function flatten($data, $separator = '.') {
1042:         $result = array();
1043:         $path = null;
1044: 
1045:         if (is_array($separator)) {
1046:             extract($separator, EXTR_OVERWRITE);
1047:         }
1048: 
1049:         if (!is_null($path)) {
1050:             $path .= $separator;
1051:         }
1052: 
1053:         foreach ($data as $key => $val) {
1054:             if (is_array($val)) {
1055:                 $result += (array)Set::flatten($val, array(
1056:                     'separator' => $separator,
1057:                     'path' => $path . $key
1058:                 ));
1059:             } else {
1060:                 $result[$path . $key] = $val;
1061:             }
1062:         }
1063:         return $result;
1064:     }
1065: 
1066: /**
1067:  * Flattens an array for sorting
1068:  *
1069:  * @param array $results
1070:  * @param string $key
1071:  * @return array
1072:  * @access private
1073:  */
1074:     function __flatten($results, $key = null) {
1075:         $stack = array();
1076:         foreach ($results as $k => $r) {
1077:             $id = $k;
1078:             if (!is_null($key)) {
1079:                 $id = $key;
1080:             }
1081:             if (is_array($r) && !empty($r)) {
1082:                 $stack = array_merge($stack, Set::__flatten($r, $id));
1083:             } else {
1084:                 $stack[] = array('id' => $id, 'value' => $r);
1085:             }
1086:         }
1087:         return $stack;
1088:     }
1089: 
1090: /**
1091:  * Sorts an array by any value, determined by a Set-compatible path
1092:  *
1093:  * @param array $data An array of data to sort
1094:  * @param string $path A Set-compatible path to the array value
1095:  * @param string $dir Direction of sorting - either ascending (ASC), or descending (DESC)
1096:  * @return array Sorted array of data
1097:  * @static
1098:  */
1099:     function sort($data, $path, $dir) {
1100:         $originalKeys = array_keys($data);
1101:         if (is_numeric(implode('', $originalKeys))) {
1102:             $data = array_values($data);
1103:         }
1104:         $result = Set::__flatten(Set::extract($data, $path));
1105:         list($keys, $values) = array(Set::extract($result, '{n}.id'), Set::extract($result, '{n}.value'));
1106: 
1107:         $dir = strtolower($dir);
1108:         if ($dir === 'asc') {
1109:             $dir = SORT_ASC;
1110:         } elseif ($dir === 'desc') {
1111:             $dir = SORT_DESC;
1112:         }
1113:         array_multisort($values, $dir, $keys, $dir);
1114:         $sorted = array();
1115:         $keys = array_unique($keys);
1116: 
1117:         foreach ($keys as $k) {
1118:             $sorted[] = $data[$k];
1119:         }
1120:         return $sorted;
1121:     }
1122: 
1123: /**
1124:  * Allows the application of a callback method to elements of an
1125:  * array extracted by a Set::extract() compatible path.
1126:  *
1127:  * @param mixed $path Set-compatible path to the array value
1128:  * @param array $data An array of data to extract from & then process with the $callback.
1129:  * @param mixed $callback Callback method to be applied to extracted data.
1130:  * See http://ca2.php.net/manual/en/language.pseudo-types.php#language.types.callback for examples
1131:  * of callback formats.
1132:  * @param array $options Options are:
1133:  *                       - type : can be pass, map, or reduce. Map will handoff the given callback
1134:  *                                to array_map, reduce will handoff to array_reduce, and pass will
1135:  *                                use call_user_func_array().
1136:  * @return mixed Result of the callback when applied to extracted data
1137:  * @access public
1138:  * @static
1139:  */
1140:     function apply($path, $data, $callback, $options = array()) {
1141:         $defaults = array('type' => 'pass');
1142:         $options = array_merge($defaults, $options);
1143: 
1144:         $extracted = Set::extract($path, $data);
1145: 
1146:         if ($options['type'] === 'map') {
1147:             $result = array_map($callback, $extracted);
1148: 
1149:         } elseif ($options['type'] === 'reduce') {
1150:             $result = array_reduce($extracted, $callback);
1151: 
1152:         } elseif ($options['type'] === 'pass') {
1153:             $result = call_user_func_array($callback, array($extracted));
1154:         } else {
1155:             return null;
1156:         }
1157: 
1158:         return  $result;
1159:     }
1160: }
1161: 
OpenHub
Rackspace
Rackspace
  • Business Solutions
  • Showcase
  • Documentation
  • Book
  • API
  • Videos
  • Reporting Security Issues
  • Privacy Policy
  • Logos & Trademarks
  • Community
  • Get Involved
  • Issues (GitHub)
  • Bakery
  • Featured Resources
  • Training
  • Meetups
  • My CakePHP
  • CakeFest
  • Newsletter
  • Linkedin
  • YouTube
  • Facebook
  • Twitter
  • Mastodon
  • Help & Support
  • Forum
  • Stack Overflow
  • Slack
  • Paid Support

Generated using CakePHP API Docs