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.2 API

  • Overview
  • Tree
  • Deprecated
  • Version:
    • 1.2
      • 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
  • BehaviorCollection
  • Cache
  • CacheEngine
  • CacheHelper
  • CakeErrorController
  • CakeLog
  • CakeSchema
  • CakeSession
  • CakeSocket
  • ClassRegistry
  • Component
  • Configure
  • ConnectionManager
  • ConsoleShell
  • ContainableBehavior
  • Controller
  • ControllerTask
  • CookieComponent
  • DataSource
  • DbAcl
  • DbAclSchema
  • DbConfigTask
  • DboAdodb
  • DboDb2
  • DboFirebird
  • DboMssql
  • DboMysql
  • DboMysqlBase
  • DboMysqli
  • DboOdbc
  • DboOracle
  • DboPostgres
  • DboSource
  • DboSqlite
  • DboSybase
  • Debugger
  • EmailComponent
  • ErrorHandler
  • ExtractTask
  • File
  • FileEngine
  • Flay
  • Folder
  • FormHelper
  • Helper
  • HtmlHelper
  • HttpSocket
  • I18n
  • I18nModel
  • i18nSchema
  • I18nShell
  • Inflector
  • IniAcl
  • JavascriptHelper
  • JsHelper
  • JsHelperObject
  • L10n
  • MagicDb
  • MagicFileResource
  • MediaView
  • MemcacheEngine
  • Model
  • ModelBehavior
  • ModelTask
  • Multibyte
  • NumberHelper
  • Object
  • Overloadable
  • Overloadable2
  • PagesController
  • PaginatorHelper
  • Permission
  • PluginTask
  • ProjectTask
  • RequestHandlerComponent
  • Router
  • RssHelper
  • Sanitize
  • Scaffold
  • ScaffoldView
  • SchemaShell
  • Security
  • SecurityComponent
  • SessionComponent
  • SessionHelper
  • SessionsSchema
  • Set
  • Shell
  • String
  • TestSuiteShell
  • TestTask
  • TextHelper
  • ThemeView
  • TimeHelper
  • TranslateBehavior
  • TreeBehavior
  • Validation
  • View
  • ViewTask
  • XcacheEngine
  • Xml
  • XmlElement
  • XmlHelper
  • XmlManager
  • XmlNode
  • XmlTextNode

Functions

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