public function current() { $value = parent::current(); if ($this->valueField === null) { return $value; } return PropertyPath::get($value, $this->valueField); }
/** * Retrieve non-deleted model-data by id. * * @return mixed data */ public function get($id, $config) { $data = $this->backend->get($id, $config); if (PropertyPath::get($this->path, $data)) { throw new Exception('Record was deleted'); } return $data; }
/** * Replace the placeholder with the referenced object. */ private function __replacePlaceholder() { if (is_string($this->__placeholder) === false) { // Is the placeholder already replaced? // Multiple lookups are valid use-case. // The property (as placeholder) could be passed to another function as a value. return; } $parts = explode('/', $this->__placeholder); $repositoryId = array_shift($parts); $model = array_shift($parts); $property = implode('/', $parts); $self = PropertyPath::get($property, $this->__container); if ($self !== $this) { notice('This placeholder belongs to an other object', 'Did you clone the object?'); $this->__placeholder = $self; return; } $repo = Repository::instance($repositoryId); $this->__placeholder = $repo->resolveProperty($this->__container, $property, array('model' => $model)); }
/** * Return the instance the Placeholder points to. * * @param BelongsToPlaceholder|Junction $wrapper * @param ModelConfig $config */ protected function resolveInstance($wrapper, $config) { if ($wrapper instanceof BelongsToPlaceholder === false && $wrapper instanceof Junction === false) { throw new Exception('Parameter $placeholder must be a BelongsToPlaceholder or Junction'); } if ($wrapper instanceof Junction && PropertyPath::get($config->properties[$config->id[0]], $wrapper) === null) { foreach ($this->created[$config->name] as $index => $created) { $isAMatch = true; foreach (get_object_vars($created) as $property => $value) { if ($wrapper->{$property} !== $value) { $isAMatch = false; break; } } if ($isAMatch) { return $created; } } } $index = $this->resolveIndex($wrapper, $config); if (empty($this->objects[$config->name][$index]['instance'])) { throw new Exception('Placeholder "' . $model . ' ' . $index . '" not loaded'); } $instance = $this->objects[$config->name][$index]['instance']; foreach (get_object_vars($instance) as $property => $value) { if ($wrapper->{$property} !== $value) { throw new Exception('Placeholder belongs to another model'); } } return $instance; }
public function test_PropertyPath_get() { $array = array('id' => '1'); $object = (object) array('id' => '2'); $this->assertSame(PropertyPath::get('.', 'me'), 'me', 'Path "." should return the input'); // autodetect type $this->assertSame(PropertyPath::get('id', $array), '1', 'Path "id" should work on arrays'); $this->assertSame(PropertyPath::get('id', $object), '2', 'Path "id" should also work on objects'); // force array element $this->assertSame(PropertyPath::get('[id]', $array), '1', 'Path "[id]" should work on arrays'); // force object property $this->assertSame(PropertyPath::get('->id', $object), '2', 'Path "->id" should work on objects'); $object->property = array('id' => '3'); $this->assertSame(PropertyPath::get('property[id]', $object), '3', 'Path "property[id]" should work on objects'); $this->assertSame(PropertyPath::get('->property[id]', $object), '3', 'Path "->property[id]" should work on objects'); $object->object = (object) array('id' => '4'); $this->assertSame(PropertyPath::get('object->id', $object), '4', 'Path "object->id" should work on objects in objects'); $this->assertSame(PropertyPath::get('->object->id', $object), '4', 'Path "->object->id" should work on objects in objects'); $object->property['element'] = (object) array('id' => '5'); $this->assertSame(PropertyPath::get('property[element]->id', $object), '5'); $this->assertSame(PropertyPath::get('->property[element]->id', $object), '5'); $array['object'] = (object) array('id' => 6); $this->assertSame(PropertyPath::get('object->id', $array), 6); $this->assertSame(PropertyPath::get('[object]->id', $array), 6); // optional $this->assertSame(PropertyPath::get('id?', $array), '1', 'Path "id?" should work on arrays'); $this->assertSame(PropertyPath::get('id?', $object), '2', 'Path "id?" should work on objects'); $this->assertSame(PropertyPath::get('undefined?', $array), null, 'Path "id?" should work on arrays'); $this->assertSame(PropertyPath::get('undefined?', $object), null, 'Path "id?" should work on objects'); $this->assertSame(PropertyPath::get('[id?]', $array), '1', 'Path "->id?" should work on arrays'); $this->assertSame(PropertyPath::get('->id?', $object), '2', 'Path "->id?" should work on objects'); // $this->assertSame(PropertyPath::get($array, 'undefined?'), null, 'Path "id?" should work on arrays'); // $this->assertSame(PropertyPath::get($object, 'undefined?'), null, 'Path "id?" should work on objects'); // @todo Add UnitTest for method notation "getFilename()" $sequence = array(array('id' => 1), array('id' => 3), array('id' => 5)); $this->assertSame(PropertyPath::get('[*].id', $sequence), array(1, 3, 5)); PHPUnit_Framework_Error_Notice::$enabled = false; $error_log = ini_get('error_log'); ini_set('error_log', '/dev/null'); ob_start(); $this->assertSame(PropertyPath::get('->property->element', $object), null); $this->assertRegExp('/Unexpected type: array, expecting an object/', ob_get_clean()); ob_start(); $this->assertSame(PropertyPath::get('->id', $array), null, 'Path "->id" should NOT work on arrays'); $this->assertRegExp('/Unexpected type: array, expecting an object/', ob_get_clean()); ob_start(); $this->assertSame(PropertyPath::get('[id]', $object), null, 'Path "[id]" should NOT work on objects'); $this->assertRegExp('/Unexpected type: object, expecting an array/', ob_get_clean()); // PropertyPath::get('->id?', $array) // PropertyPath::get('[id?]', $object) PHPUnit_Framework_Error_Notice::$enabled = true; ini_set('error_log', $error_log); }
public function add($data, $config) { $key = PropertyPath::get($config['key'], $data); if ($key === null) { $this->items[] = $data; $keys = array_keys($this->items); $key = array_pop($keys); $key = PropertyPath::set($config['key'], $key, $data); return $data; } $this->getKey($data, $config); return $data; }
/** * Build a closure which validates an item with the gives $conditions. * * @param mixed $conditions array|Closure|expression See Collection::where() for condition options * * @return callable */ protected function buildFilter($conditions) { if (\Sledgehammer\is_closure($conditions)) { return $conditions; } if (is_array($conditions)) { // Create filter that checks all conditions $logicalOperator = \Sledgehammer\extract_logical_operator($conditions); if ($logicalOperator === false) { if (count($conditions) > 1) { \Sledgehammer\notice('Conditions with multiple conditions require a logical operator.', "Example: array('AND', 'x' => 1, 'y' => 5)"); } $logicalOperator = 'AND'; } else { unset($conditions[0]); } $operators = []; foreach ($conditions as $path => $expectation) { if (preg_match('/^(.*) (' . \Sledgehammer\COMPARE_OPERATORS . ')$/', $path, $matches)) { unset($conditions[$path]); $conditions[$matches[1]] = $expectation; $operators[$matches[1]] = $matches[2]; } else { $operators[$path] = false; } } // @todo Build an optimized closure for when a single conditions is given. if ($logicalOperator === 'AND') { return function ($item) use($conditions, $operators) { foreach ($conditions as $path => $expectation) { $actual = PropertyPath::get($path, $item); $operator = $operators[$path]; if ($operator) { if (\Sledgehammer\compare($actual, $operator, $expectation) === false) { return false; } } elseif (\Sledgehammer\equals($actual, $expectation) === false) { return false; } } return true; // All conditions are met. }; } elseif ($logicalOperator === 'OR') { return function ($item) use($conditions, $operators) { foreach ($conditions as $path => $expectation) { $actual = PropertyPath::get($path, $item); $operator = $operators[$path]; if ($operator) { if (\Sledgehammer\compare($actual, $operator, $expectation) !== false) { return true; } } elseif (\Sledgehammer\equals($actual, $expectation) !== false) { return true; } } return false; // None of conditions are met. }; } else { throw new Exception('Unsupported logical operator "' . $logicalOperator . '", expecting "AND" or "OR"'); } } //'<= 5' or '10' // Compare the item directly with value given as $condition. if (is_string($conditions) && preg_match('/^(' . \Sledgehammer\COMPARE_OPERATORS . ') (.*)$/', $conditions, $matches)) { $operator = $matches[1]; $expectation = $matches[2]; } else { $expectation = $conditions; $operator = '=='; } return function ($value) use($expectation, $operator) { return \Sledgehammer\compare($value, $operator, $expectation); }; }
/** * Compile a path into a closure function. * The generated function expected 1 parameter (The $data for the property get). * * @param string $path * return Closure */ public static function compile($path) { static $cache = []; if (isset($cache[$path])) { return $cache[$path]; } $cache[$path] = function ($data) use($path) { return PropertyPath::get($path, $data); }; return $cache[$path]; }