extract() public static method

Implements partial support for XPath 2.0.
public static extract ( array $data, string $path = null, array $options = [] ) : array
$data array An array of data to extract from.
$path string An absolute XPath 2.0 path. Only absolute paths starting with a single slash are supported right now. Implemented selectors: - `'/User/id'`: Similar to the classic {n}.User.id. - `'/User[2]/name'`: Selects the name of the second User. - `'/User[id>2]'`: Selects all Users with an id > 2. - `'/User[id>2][<5]'`: Selects all Users with an id > 2 but < 5. - `'/Post/Comment[author_name=John]/../name'`: Selects the name of all posts that have at least one comment written by John. - `'/Posts[name]'`: Selects all Posts that have a `'name'` key. - `'/Comment/.[1]'`: Selects the contents of the first comment. - `'/Comment/.[:last]'`: Selects the last comment. - `'/Comment/.[:first]'`: Selects the first comment. - `'/Comment[text=/lithium/i]`': Selects the all comments that have a text matching the regex `/lithium/i`. - `'/Comment/@*'`: Selects all key names of all comments.
$options array Currently only supports `'flatten'` which can be disabled for higher XPath-ness.
return array An array of matched items.
Example #1
0
 /**
  * returns rendered content
  *
  * @param string $content input content
  * @param string $data field to retrieve from configuration
  * @param array $options an array with additional options
  * @return string content as given
  * @filter
  */
 public function get($content, $data = null, array $options = array())
 {
     $defaults = array('default' => array(), 'flat' => false);
     $options += $defaults;
     $params = compact('content', 'data', 'options');
     return $this->_filter(__METHOD__, $params, function ($self, $params) {
         extract($params);
         try {
             $config = NeonFormatter::decode($content);
         } catch (NeonException $e) {
             return $options['default'];
         } catch (Exception $e) {
             return $options['default'];
         }
         if (!empty($data) && is_scalar($data)) {
             if (array_key_exists($data, (array) $config)) {
                 return $config[$data];
             }
         }
         if ($data) {
             $data = '/' . str_replace('.', '/', $data) . '/.';
             $result = current(Set::extract((array) $config, $data));
             return !empty($result) ? $result : null;
         }
         return $options['flat'] ? Set::flatten($config) : $config;
     });
 }
Example #2
0
 /**
  * returns rendered content
  *
  * @param string $content input content
  * @param string $data field to retrieve from configuration
  * @param array $options an array with additional options
  * @return string content as given
  * @filter
  */
 public function get($content, $data = null, array $options = array())
 {
     $defaults = array('default' => null, 'flat' => false);
     $options += $defaults;
     $params = compact('content', 'data', 'options');
     return $this->_filter(__METHOD__, $params, function ($self, $params) {
         extract($params);
         try {
             $config = IniFormat::parse($content);
         } catch (IniFormatException $e) {
             return $options['default'];
         } catch (Exception $e) {
             return $options['default'];
         }
         if (empty($data)) {
             return $options['flat'] ? Set::flatten($config) : $config;
         }
         if (is_scalar($data) && isset($config[$data])) {
             return $config[$data];
         }
         $data = '/' . str_replace('.', '/', (string) $data) . '/.';
         $result = current(Set::extract((array) $config, $data));
         if (!empty($result)) {
             return $result;
         }
         return $options['default'];
     });
 }
Example #3
0
 /**
  * Checks a single-use hash key against the session token that generated it, using
  * a cryptographically-secure verification method. Accepts either the request key as a string,
  * or a `Request` object with a `$data` property containing a `['security']['token']` key.
  *
  * For example, the following two controller code samples are equivalent:
  *
  * {{{
  * $key = $this->request->data['security']['token'];
  *
  * if (!RequestToken::check($key)) {
  * 	// Handle invalid request...
  * }
  * }}}
  *
  * {{{
  * if (!RequestToken::check($this->request)) {
  * 	// Handle invalid request...
  * }
  * }}}
  *
  * @param mixed $key Either the actual key as a string, or a `Request` object containing the
  *              key.
  * @param array $options The options to use when matching the key to the token:
  *              - `'sessionKey'` _string_: The key used when reading the token from the session.
  * @return boolean Returns `true` if the hash key is a cryptographic match to the stored
  *         session token. Returns `false` on failure, which indicates a forged request attempt.
  */
 public static function check($key, array $options = array())
 {
     $defaults = array('sessionKey' => 'security.token');
     $options += $defaults;
     $session = static::$_classes['session'];
     if (is_object($key) && isset($key->data)) {
         $result = Set::extract($key->data, '/security/token');
         $key = $result ? $result[0] : null;
     }
     return Password::check($session::read($options['sessionKey']), (string) $key);
 }
Example #4
0
	public function testInsertAndRemoveWithFunkyKeys() {
		$set = Set::insert(array(), 'Session Test', "test");
		$result = Set::extract($set, '/Session Test');
		$this->assertEqual($result, array('test'));

		$set = Set::remove($set, 'Session Test');
		$this->assertFalse(Set::check($set, 'Session Test'));

		$this->assertTrue($set = Set::insert(array(), 'Session Test.Test Case', "test"));
		$this->assertTrue(Set::check($set, 'Session Test.Test Case'));
	}
Example #5
0
 public function testNodeWithNonStrictMode()
 {
     Fixtures::save('db');
     extract($this->_models);
     $result = Set::extract(Aco::node('root/printers/refill/unexisting', false), '/id');
     $expected = ['9', '6', '1'];
     $this->assertEqual($expected, $result);
 }
Example #6
0
 /**
  * Delete a value from the cookie store.
  *
  * @param string $key The key to be deleted from the cookie store.
  * @param array $options Options array.
  * @return \Closure Function returning boolean `true` on successful delete, `false` otherwise.
  */
 public function delete($key, array $options = array())
 {
     $config = $this->_config;
     $cookieClass = get_called_class();
     return function ($self, $params) use(&$config, $cookieClass) {
         $key = $params['key'];
         $path = '/' . str_replace('.', '/', $config['name'] . '.' . $key) . '/.';
         $cookies = current(Set::extract($_COOKIE, $path));
         if (is_array($cookies)) {
             $cookies = array_keys(Set::flatten($cookies));
             foreach ($cookies as &$name) {
                 $name = $key . '.' . $name;
             }
         } else {
             $cookies = array($key);
         }
         foreach ($cookies as &$name) {
             $name = $cookieClass::keyFormat($name, $config);
             $result = setcookie($name, "", 1, $config['path'], $config['domain'], $config['secure'], $config['httponly']);
             if (!$result) {
                 throw new RuntimeException("There was an error deleting {$name} cookie.");
             }
         }
         return true;
     };
 }
Example #7
0
 /**
  * Filter for connection->read to take alternate relations and call a batch ::find on appropiate relation
  */
 protected static function _connectionFilters()
 {
     $connection = static::connection();
     if (!isset($connection->_hasRelationFilter) || $connection->_hasRelationFilter == false) {
         $connection->_hasRelationFilter = true;
         $connection->applyFilter('read', function ($self, $params, $chain) {
             $data = $chain->next($self, $params, $chain);
             // check to see if there are any alternateRelations
             if (!empty($data) && is_object($data) && !empty($params) && isset($params['options']) && isset($params['options']['alternateWith']) && !empty($params['options']['alternateWith'])) {
                 $alternateRelations = $params['options']['model']::relations(null, 'alternate');
                 if (!empty($alternateRelations)) {
                     if (method_exists($data, 'map')) {
                         $records = $data->to('array');
                     } else {
                         $records[] = $data->to('array');
                     }
                     foreach ($params['options']['alternateWith'] as $key => $val) {
                         // TODO add support for 'Relation' => array(options)
                         if (is_int($key)) {
                             $relationKey = $val;
                         } else {
                             $relationKey = $key;
                         }
                         $relation = null;
                         if (isset($alternateRelations[$relationKey])) {
                             // get options from relationship
                             $relation = $alternateRelations[$relationKey]->data();
                             if (!is_int($key) && !empty($val)) {
                                 $relation = array_merge($relation, $val);
                             }
                         }
                         if (!empty($relation)) {
                             $relationModel = $relation['to'];
                             $searchAssociations = array();
                             $searchValues = array();
                             $keys = array_keys($relation['key']);
                             $from = (string) array_shift($keys);
                             $fromArray = explode('.', $from);
                             $to = (string) $relation['key'][$from];
                             if (!empty($relation['fieldName'])) {
                                 $field = $relation['fieldName'];
                             } else {
                                 $field = $class;
                             }
                             // grab all ids from ids to create one batch query
                             foreach ($records as $k => $record) {
                                 $searchValue = Set::extract($record, '/' . str_replace('.', '/', $from));
                                 $lastKey = array_slice($fromArray, -1, 1);
                                 $lastKey = $lastKey[0];
                                 if (!empty($searchValue) && (!is_array($searchValue[0]) || is_array($searchValue[0]) && !isset($searchValue[0][$lastKey]))) {
                                     if (!is_array($searchValue)) {
                                         $searchValue = array($searchValue);
                                     }
                                     $searchValues = array_merge($searchValues, $searchValue);
                                     $searchAssociations[$k] = $searchValue;
                                 } else {
                                     $searchAssociations[$k] = null;
                                 }
                             }
                             // if we have at least one id
                             if (!empty($searchValues)) {
                                 $searchValues = array_unique($searchValues);
                                 $relation['conditions'][$to] = $searchValues;
                                 $unsetSearchKey = false;
                                 if (is_array($relation['fields'])) {
                                     if (!in_array($to, $relation['fields'])) {
                                         $relation['fields'][] = $to;
                                         $unsetSearchKey = true;
                                     }
                                 } else {
                                     $relation['fields'] = null;
                                 }
                                 $relationalData = $relationModel::find('all', $relation);
                                 if (!empty($relationalData)) {
                                     $results = array();
                                     foreach ($relationalData as $item) {
                                         $ids = array();
                                         if (is_object($item) && isset($item->{$to})) {
                                             if (method_exists($item->{$to}, 'to')) {
                                                 $ids = $item->{$to}->to('array');
                                             } else {
                                                 $ids = array((string) $item->{$to});
                                             }
                                         }
                                         foreach ($ids as $id) {
                                             if (!empty($id)) {
                                                 if ($unsetSearchKey === true && isset($item->{$to})) {
                                                     unset($item->{$to});
                                                 }
                                                 $results[$id][] = $item;
                                             }
                                         }
                                     }
                                 }
                             }
                             // check to make sure we have at least one association
                             if (!empty($searchAssociations) && isset($results)) {
                                 foreach ($searchAssociations as $itemKey => $value) {
                                     if (isset($data[$itemKey])) {
                                         // create an associationResult to hold all of this items related data
                                         $associationResult = array();
                                         if (!is_null($value) && isset($results)) {
                                             if (is_array($value)) {
                                                 // sort values to populate in the order returned by mongo result
                                                 $value = array_keys(array_intersect_key($results, array_fill_keys($value, null)));
                                                 foreach ($value as $searchKey) {
                                                     $searchKey = (string) $searchKey;
                                                     if (isset($results[$searchKey])) {
                                                         $associationResult = array_merge($associationResult, $results[$searchKey]);
                                                     }
                                                 }
                                                 // add some processing for grouping - this was added for mongo, may not be needed
                                                 if (isset($relation['group'])) {
                                                     $groupedResult = array();
                                                     foreach ($associationResult as $k => $result) {
                                                         $comparison = array();
                                                         foreach ($relation['group'] as $group_item) {
                                                             if (isset($result->{$group_item})) {
                                                                 $comparison[] = $result->{$group_item};
                                                             } else {
                                                                 $comparison[] = null;
                                                             }
                                                         }
                                                         if (!empty($comparison)) {
                                                             $groupedResult[$k] = json_encode($comparison);
                                                         }
                                                     }
                                                     $groupedResult = array_unique($groupedResult);
                                                     $associationResult = array_values(array_intersect_key($associationResult, $groupedResult));
                                                 }
                                             }
                                         }
                                         $relationConnection = $relationModel::connection();
                                         // check to see if we have a result && if relation type is hasOne, if so shift result to one element
                                         if (count($associationResult) > 0) {
                                             if ($relation['type'] == 'hasOne') {
                                                 $associationResult = array_shift($associationResult);
                                             } else {
                                                 $associationResult = $relationConnection->item($relationModel, $associationResult, array('class' => 'set'));
                                             }
                                             // else if result is empty, create default empty response. hasMany defaults to connection collection & hasOne defaults to null - Same response as provided via ::find('all') vs ::find('first')
                                         } else {
                                             if ($relation['type'] == 'hasOne') {
                                                 $associationResult = null;
                                             } else {
                                                 $associationResult = $relationConnection->item($relationModel, array(), array('class' => 'set'));
                                             }
                                         }
                                         // finally, add the relation
                                         if (method_exists($data, 'map')) {
                                             $data[$itemKey]->{$field} = $associationResult;
                                         } else {
                                             $data->{$field} = $associationResult;
                                         }
                                     }
                                 }
                             }
                         }
                     }
                 }
             }
             return $data;
         });
     }
 }
Example #8
0
 public function _parseClass($class)
 {
     $data = array();
     // $methods = Inspector::methods($class, null, array('public' => false));
     $methods = get_class_methods($class);
     $properties = array_keys(get_class_vars($class));
     $ident = $class;
     $info = Inspector::info($ident);
     $info = Docblock::comment($info['comment']);
     $data = $this->_merge($data, array('id' => $info['description'], 'comments' => array($ident)));
     $this->_merge($data, array('id' => $info['text'], 'comments' => array($class)));
     foreach ($methods as $method) {
         $ident = "{$class}::{$method}()";
         $info = Inspector::info($ident);
         $info = Docblock::comment($info['comment']);
         $this->_merge($data, array('id' => $info['description'], 'comments' => array($ident)));
         $this->_merge($data, array('id' => $info['text'], 'comments' => array($ident)));
         if (isset($info['tags']['return'])) {
             $this->_merge($data, array('id' => $info['tags']['return'], 'comments' => array($ident)));
         }
         foreach (Set::extract($info, '/tags/params/text') as $text) {
             $this->_merge($data, array('id' => $text, 'comments' => array($ident)));
         }
     }
     foreach ($properties as $property) {
         $ident = "{$class}::\${$property}";
         $info = Inspector::info($ident);
         $info = Docblock::comment($info['comment']);
         $data = $this->_merge($data, array('id' => $info['description'], 'comments' => array($ident)));
         $data = $this->_merge($data, array('id' => $info['text'], 'comments' => array($ident)));
     }
     return $data;
 }
 protected function _readEmbeddedFilter()
 {
     // filter for relations
     self::applyFilter('read', function ($self, $params, $chain) {
         $results = $chain->next($self, $params, $chain);
         if (isset($params['options']['with']) && !empty($params['options']['with'])) {
             $model = is_object($params['query']) ? $params['query']->model() : null;
             $relations = $model::relations();
             foreach ($params['options']['with'] as $k => $name) {
                 if (isset($relations[$name])) {
                     $relation = $relations[$name]->data();
                     $relationModel = Libraries::locate('models', $relation['to']);
                     if (!empty($relationModel) && !empty($results) && isset($relation['embedded'])) {
                         $embedded_on = $relation['embedded'];
                         $resultsArray = $results->to('array');
                         foreach ($resultsArray as $k => $result) {
                             $relationalData = Set::extract($result, '/' . str_replace('.', '/', $embedded_on));
                             if (!empty($embedded_on)) {
                                 $keys = explode('.', $embedded_on);
                                 $lastKey = array_slice($keys, -1, 1);
                                 $lastKey = $lastKey[0];
                                 $data = array();
                                 foreach ($relationalData as $rk => $rv) {
                                     if (!empty($rv)) {
                                         if (!is_array($rv)) {
                                             $data[$rk] = $rv;
                                         } else {
                                             if (isset($rv[$lastKey]) && !empty($rv[$lastKey])) {
                                                 $data[$rk] = $rv[$lastKey];
                                             }
                                         }
                                     }
                                 }
                                 if (!empty($data)) {
                                     // TODO : Add support for conditions, fields, order, page, limit
                                     $validFields = array_fill_keys(array('with'), null);
                                     $options = array_intersect_key($relation, $validFields);
                                     $options['data'] = $data;
                                     if ($relation['type'] == 'hasMany') {
                                         $type = 'all';
                                     } else {
                                         $type = 'first';
                                     }
                                     $relationResult = $relationModel::find($type, $options);
                                 } else {
                                     if ($relation['type'] == 'hasMany') {
                                         $relationResult = $self->item($relationModel, array(), array('class' => 'set'));
                                     } else {
                                         $relationResult = null;
                                     }
                                 }
                                 // if fieldName === true, use the default lithium fieldName.
                                 // if fieldName != relationName, then it was manually set, so use it
                                 // else, just use the embedded key
                                 $relationName = $relation['type'] == 'hasOne' ? Inflector::pluralize($relation['name']) : $relation['name'];
                                 if ($relation['fieldName'] === true) {
                                     $relation['fieldName'] = lcfirst($relationName);
                                     $keys = explode('.', $relation['fieldName']);
                                 } else {
                                     if ($relation['fieldName'] != lcfirst($relationName)) {
                                         $keys = explode('.', $relation['fieldName']);
                                     }
                                 }
                                 $ref = $results[$k];
                                 foreach ($keys as $k => $key) {
                                     if (!isset($ref->{$key})) {
                                         $ref->{$key} = $self->item(null, array(), array('class' => 'entity'));
                                     }
                                     if (count($keys) - 1 == $k) {
                                         $ref->{$key} = $relationResult;
                                     } else {
                                         $ref = $ref->{$key};
                                     }
                                 }
                             }
                         }
                     }
                 }
             }
         }
         return $results;
     });
 }
Example #10
0
 /**
  * Get all permission access
  *
  * @param string $requester The requesting identifier (Aro).
  * @param string $controlled The controlled identifier (Aco).
  */
 public static function get($requester, $controlled)
 {
     $self = static::_object();
     $aro = $self->_classes['aro'];
     $aco = $self->_classes['aco'];
     if (!(($aroNodes = $aro::node($requester, false)) && ($acoNodes = $aco::node($controlled, false)))) {
         return false;
     }
     $privileges = [];
     $aro_id = key(static::relations('Aro')->key());
     $aco_id = key(static::relations('Aco')->key());
     $left = $aco::actsAs('Tree', true, 'left');
     $ids = Set::extract($acoNodes, '/' . $aco::meta('key'));
     foreach ($aroNodes as $node) {
         $id = $node[$aro::meta('key')];
         if ($datas = static::_permQuery($id, $ids, $aro_id, $aco_id, $left)) {
             foreach ($datas as $data) {
                 $privileges = $privileges + (array) json_decode($data['privileges'], true);
             }
         }
     }
     return $privileges;
 }