first commit
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Grav\Framework\Object
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2018 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Framework\Object\Access;
|
||||
|
||||
/**
|
||||
* ArrayAccess Object Trait
|
||||
* @package Grav\Framework\Object
|
||||
*/
|
||||
trait ArrayAccessTrait
|
||||
{
|
||||
/**
|
||||
* Whether or not an offset exists.
|
||||
*
|
||||
* @param mixed $offset An offset to check for.
|
||||
* @return bool Returns TRUE on success or FALSE on failure.
|
||||
*/
|
||||
public function offsetExists($offset)
|
||||
{
|
||||
return $this->hasProperty($offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value at specified offset.
|
||||
*
|
||||
* @param mixed $offset The offset to retrieve.
|
||||
* @return mixed Can return all value types.
|
||||
*/
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
return $this->getProperty($offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigns a value to the specified offset.
|
||||
*
|
||||
* @param mixed $offset The offset to assign the value to.
|
||||
* @param mixed $value The value to set.
|
||||
*/
|
||||
public function offsetSet($offset, $value)
|
||||
{
|
||||
$this->setProperty($offset, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsets an offset.
|
||||
*
|
||||
* @param mixed $offset The offset to unset.
|
||||
*/
|
||||
public function offsetUnset($offset)
|
||||
{
|
||||
$this->unsetProperty($offset);
|
||||
}
|
||||
|
||||
abstract public function hasProperty($property);
|
||||
abstract public function getProperty($property, $default = null);
|
||||
abstract public function setProperty($property, $value);
|
||||
abstract public function unsetProperty($property);
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Grav\Framework\Object
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2018 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Framework\Object\Access;
|
||||
|
||||
/**
|
||||
* Nested ArrayAccess Object Trait
|
||||
* @package Grav\Framework\Object
|
||||
*/
|
||||
trait NestedArrayAccessTrait
|
||||
{
|
||||
/**
|
||||
* Whether or not an offset exists.
|
||||
*
|
||||
* @param mixed $offset An offset to check for.
|
||||
* @return bool Returns TRUE on success or FALSE on failure.
|
||||
*/
|
||||
public function offsetExists($offset)
|
||||
{
|
||||
return $this->hasNestedProperty($offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value at specified offset.
|
||||
*
|
||||
* @param mixed $offset The offset to retrieve.
|
||||
* @return mixed Can return all value types.
|
||||
*/
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
return $this->getNestedProperty($offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigns a value to the specified offset.
|
||||
*
|
||||
* @param mixed $offset The offset to assign the value to.
|
||||
* @param mixed $value The value to set.
|
||||
*/
|
||||
public function offsetSet($offset, $value)
|
||||
{
|
||||
$this->setNestedProperty($offset, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsets an offset.
|
||||
*
|
||||
* @param mixed $offset The offset to unset.
|
||||
*/
|
||||
public function offsetUnset($offset)
|
||||
{
|
||||
$this->unsetNestedProperty($offset);
|
||||
}
|
||||
|
||||
abstract public function hasNestedProperty($property, $separator = null);
|
||||
abstract public function getNestedProperty($property, $default = null, $separator = null);
|
||||
abstract public function setNestedProperty($property, $value, $separator = null);
|
||||
abstract public function unsetNestedProperty($property, $separator = null);
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Grav\Framework\Object
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2018 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Framework\Object\Access;
|
||||
|
||||
use Grav\Framework\Object\Interfaces\NestedObjectInterface;
|
||||
|
||||
/**
|
||||
* Nested Properties Collection Trait
|
||||
* @package Grav\Framework\Object\Properties
|
||||
*/
|
||||
trait NestedPropertyCollectionTrait
|
||||
{
|
||||
/**
|
||||
* @param string $property Object property to be matched.
|
||||
* @param string $separator Separator, defaults to '.'
|
||||
* @return array Key/Value pairs of the properties.
|
||||
*/
|
||||
public function hasNestedProperty($property, $separator = null)
|
||||
{
|
||||
$list = [];
|
||||
|
||||
/** @var NestedObjectInterface $element */
|
||||
foreach ($this->getIterator() as $id => $element) {
|
||||
$list[$id] = $element->hasNestedProperty($property, $separator);
|
||||
}
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $property Object property to be fetched.
|
||||
* @param mixed $default Default value if not set.
|
||||
* @param string $separator Separator, defaults to '.'
|
||||
* @return array Key/Value pairs of the properties.
|
||||
*/
|
||||
public function getNestedProperty($property, $default = null, $separator = null)
|
||||
{
|
||||
$list = [];
|
||||
|
||||
/** @var NestedObjectInterface $element */
|
||||
foreach ($this->getIterator() as $id => $element) {
|
||||
$list[$id] = $element->getNestedProperty($property, $default, $separator);
|
||||
}
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $property Object property to be updated.
|
||||
* @param string $value New value.
|
||||
* @param string $separator Separator, defaults to '.'
|
||||
* @return $this
|
||||
*/
|
||||
public function setNestedProperty($property, $value, $separator = null)
|
||||
{
|
||||
/** @var NestedObjectInterface $element */
|
||||
foreach ($this->getIterator() as $element) {
|
||||
$element->setNestedProperty($property, $value, $separator);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $property Object property to be updated.
|
||||
* @param string $separator Separator, defaults to '.'
|
||||
* @return $this
|
||||
*/
|
||||
public function unsetNestedProperty($property, $separator = null)
|
||||
{
|
||||
/** @var NestedObjectInterface $element */
|
||||
foreach ($this->getIterator() as $element) {
|
||||
$element->unsetNestedProperty($property, $separator);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $property Object property to be updated.
|
||||
* @param string $default Default value.
|
||||
* @param string $separator Separator, defaults to '.'
|
||||
* @return $this
|
||||
*/
|
||||
public function defNestedProperty($property, $default, $separator = null)
|
||||
{
|
||||
/** @var NestedObjectInterface $element */
|
||||
foreach ($this->getIterator() as $element) {
|
||||
$element->defNestedProperty($property, $default, $separator);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Group items in the collection by a field.
|
||||
*
|
||||
* @param string $property Object property to be used to make groups.
|
||||
* @param string $separator Separator, defaults to '.'
|
||||
* @return array
|
||||
*/
|
||||
public function group($property, $separator = null)
|
||||
{
|
||||
$list = [];
|
||||
|
||||
/** @var NestedObjectInterface $element */
|
||||
foreach ($this->getIterator() as $element) {
|
||||
$list[(string) $element->getNestedProperty($property, null, $separator)][] = $element;
|
||||
}
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Traversable
|
||||
*/
|
||||
abstract public function getIterator();
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Grav\Framework\Object
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2018 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Framework\Object\Access;
|
||||
|
||||
use Grav\Framework\Object\Interfaces\ObjectInterface;
|
||||
|
||||
/**
|
||||
* Nested Property Object Trait
|
||||
* @package Grav\Framework\Object\Traits
|
||||
*/
|
||||
trait NestedPropertyTrait
|
||||
{
|
||||
/**
|
||||
* @param string $property Object property name.
|
||||
* @param string $separator Separator, defaults to '.'
|
||||
* @return bool True if property has been defined (can be null).
|
||||
*/
|
||||
public function hasNestedProperty($property, $separator = null)
|
||||
{
|
||||
$test = new \stdClass;
|
||||
|
||||
return $this->getNestedProperty($property, $test, $separator) !== $test;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $property Object property to be fetched.
|
||||
* @param mixed $default Default value if property has not been set.
|
||||
* @param string $separator Separator, defaults to '.'
|
||||
* @return mixed Property value.
|
||||
*/
|
||||
public function getNestedProperty($property, $default = null, $separator = null)
|
||||
{
|
||||
$separator = $separator ?: '.';
|
||||
$path = explode($separator, $property);
|
||||
$offset = array_shift($path);
|
||||
|
||||
if (!$this->hasProperty($offset)) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
$current = $this->getProperty($offset);
|
||||
|
||||
while ($path) {
|
||||
// Get property of nested Object.
|
||||
if ($current instanceof ObjectInterface) {
|
||||
if (method_exists($current, 'getNestedProperty')) {
|
||||
return $current->getNestedProperty(implode($separator, $path), $default, $separator);
|
||||
}
|
||||
return $current->getProperty(implode($separator, $path), $default);
|
||||
}
|
||||
|
||||
$offset = array_shift($path);
|
||||
|
||||
if ((is_array($current) || is_a($current, 'ArrayAccess')) && isset($current[$offset])) {
|
||||
$current = $current[$offset];
|
||||
} elseif (is_object($current) && isset($current->{$offset})) {
|
||||
$current = $current->{$offset};
|
||||
} else {
|
||||
return $default;
|
||||
}
|
||||
};
|
||||
|
||||
return $current;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $property Object property to be updated.
|
||||
* @param string $value New value.
|
||||
* @param string $separator Separator, defaults to '.'
|
||||
* @return $this
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function setNestedProperty($property, $value, $separator = null)
|
||||
{
|
||||
$separator = $separator ?: '.';
|
||||
$path = explode($separator, $property);
|
||||
$offset = array_shift($path);
|
||||
|
||||
if (!$path) {
|
||||
$this->setProperty($offset, $value);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
$current = &$this->doGetProperty($offset, null, true);
|
||||
|
||||
while ($path) {
|
||||
$offset = array_shift($path);
|
||||
|
||||
// Handle arrays and scalars.
|
||||
if ($current === null) {
|
||||
$current = [$offset => []];
|
||||
} elseif (is_array($current)) {
|
||||
if (!isset($current[$offset])) {
|
||||
$current[$offset] = [];
|
||||
}
|
||||
} else {
|
||||
throw new \RuntimeException('Cannot set nested property on non-array value');
|
||||
}
|
||||
|
||||
$current = &$current[$offset];
|
||||
};
|
||||
|
||||
$current = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $property Object property to be updated.
|
||||
* @param string $separator Separator, defaults to '.'
|
||||
* @return $this
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function unsetNestedProperty($property, $separator = null)
|
||||
{
|
||||
$separator = $separator ?: '.';
|
||||
$path = explode($separator, $property);
|
||||
$offset = array_shift($path);
|
||||
|
||||
if (!$path) {
|
||||
$this->unsetProperty($offset);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
$last = array_pop($path);
|
||||
$current = &$this->doGetProperty($offset, null, true);
|
||||
|
||||
while ($path) {
|
||||
$offset = array_shift($path);
|
||||
|
||||
// Handle arrays and scalars.
|
||||
if ($current === null) {
|
||||
return $this;
|
||||
}
|
||||
if (is_array($current)) {
|
||||
if (!isset($current[$offset])) {
|
||||
return $this;
|
||||
}
|
||||
} else {
|
||||
throw new \RuntimeException('Cannot set nested property on non-array value');
|
||||
}
|
||||
|
||||
$current = &$current[$offset];
|
||||
};
|
||||
|
||||
unset($current[$last]);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $property Object property to be updated.
|
||||
* @param string $default Default value.
|
||||
* @param string $separator Separator, defaults to '.'
|
||||
* @return $this
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function defNestedProperty($property, $default, $separator = null)
|
||||
{
|
||||
if (!$this->hasNestedProperty($property, $separator)) {
|
||||
$this->setNestedProperty($property, $default, $separator);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
abstract public function hasProperty($property);
|
||||
abstract public function getProperty($property, $default = null);
|
||||
abstract public function setProperty($property, $value);
|
||||
abstract public function unsetProperty($property);
|
||||
abstract protected function &doGetProperty($property, $default = null, $doCreate = false);
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Grav\Framework\Object
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2018 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Framework\Object\Access;
|
||||
|
||||
/**
|
||||
* Overloaded Property Object Trait
|
||||
* @package Grav\Framework\Object\Access
|
||||
*/
|
||||
trait OverloadedPropertyTrait
|
||||
{
|
||||
/**
|
||||
* Checks whether or not an offset exists.
|
||||
*
|
||||
* @param mixed $offset An offset to check for.
|
||||
* @return bool Returns TRUE on success or FALSE on failure.
|
||||
*/
|
||||
public function __isset($offset)
|
||||
{
|
||||
return $this->hasProperty($offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value at specified offset.
|
||||
*
|
||||
* @param mixed $offset The offset to retrieve.
|
||||
* @return mixed Can return all value types.
|
||||
*/
|
||||
public function __get($offset)
|
||||
{
|
||||
return $this->getProperty($offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigns a value to the specified offset.
|
||||
*
|
||||
* @param mixed $offset The offset to assign the value to.
|
||||
* @param mixed $value The value to set.
|
||||
*/
|
||||
public function __set($offset, $value)
|
||||
{
|
||||
$this->setProperty($offset, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic method to unset the attribute
|
||||
*
|
||||
* @param mixed $offset The name value to unset
|
||||
*/
|
||||
public function __unset($offset)
|
||||
{
|
||||
$this->unsetProperty($offset);
|
||||
}
|
||||
|
||||
abstract public function hasProperty($property);
|
||||
abstract public function getProperty($property, $default = null);
|
||||
abstract public function setProperty($property, $value);
|
||||
abstract public function unsetProperty($property);
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Grav\Framework\Object
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2018 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Framework\Object;
|
||||
|
||||
use Grav\Framework\Object\Access\NestedArrayAccessTrait;
|
||||
use Grav\Framework\Object\Access\NestedPropertyTrait;
|
||||
use Grav\Framework\Object\Access\OverloadedPropertyTrait;
|
||||
use Grav\Framework\Object\Base\ObjectTrait;
|
||||
use Grav\Framework\Object\Interfaces\NestedObjectInterface;
|
||||
use Grav\Framework\Object\Property\ArrayPropertyTrait;
|
||||
|
||||
/**
|
||||
* Array Object class.
|
||||
*
|
||||
* @package Grav\Framework\Object
|
||||
*/
|
||||
class ArrayObject implements NestedObjectInterface, \ArrayAccess
|
||||
{
|
||||
use ObjectTrait, ArrayPropertyTrait, NestedPropertyTrait, OverloadedPropertyTrait, NestedArrayAccessTrait;
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Grav\Framework\Object
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2018 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Framework\Object\Base;
|
||||
|
||||
use Grav\Framework\Object\Interfaces\ObjectInterface;
|
||||
|
||||
/**
|
||||
* ObjectCollection Trait
|
||||
* @package Grav\Framework\Object
|
||||
*/
|
||||
trait ObjectCollectionTrait
|
||||
{
|
||||
use ObjectTrait {
|
||||
setKey as public;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a copy from this collection by cloning all objects in the collection.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function copy()
|
||||
{
|
||||
$list = [];
|
||||
foreach ($this->getIterator() as $key => $value) {
|
||||
$list[$key] = is_object($value) ? clone $value : $value;
|
||||
}
|
||||
|
||||
// TODO: remove when PHP 5.6 is minimum (with doctrine/collections v1.4).
|
||||
if (!method_exists($this, 'createFrom')) {
|
||||
return new static($list);
|
||||
}
|
||||
|
||||
return $this->createFrom($list);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getObjectKeys()
|
||||
{
|
||||
return $this->call('getKey');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $property Object property to be matched.
|
||||
* @return array Key/Value pairs of the properties.
|
||||
*/
|
||||
public function doHasProperty($property)
|
||||
{
|
||||
$list = [];
|
||||
|
||||
/** @var ObjectInterface $element */
|
||||
foreach ($this->getIterator() as $id => $element) {
|
||||
$list[$id] = $element->hasProperty($property);
|
||||
}
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $property Object property to be fetched.
|
||||
* @param mixed $default Default value if not set.
|
||||
* @return array Key/Value pairs of the properties.
|
||||
*/
|
||||
public function doGetProperty($property, $default = null)
|
||||
{
|
||||
$list = [];
|
||||
|
||||
/** @var ObjectInterface $element */
|
||||
foreach ($this->getIterator() as $id => $element) {
|
||||
$list[$id] = $element->getProperty($property, $default);
|
||||
}
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $property Object property to be updated.
|
||||
* @param string $value New value.
|
||||
* @return $this
|
||||
*/
|
||||
public function doSetProperty($property, $value)
|
||||
{
|
||||
/** @var ObjectInterface $element */
|
||||
foreach ($this->getIterator() as $element) {
|
||||
$element->setProperty($property, $value);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $property Object property to be updated.
|
||||
* @return $this
|
||||
*/
|
||||
public function doUnsetProperty($property)
|
||||
{
|
||||
/** @var ObjectInterface $element */
|
||||
foreach ($this->getIterator() as $element) {
|
||||
$element->unsetProperty($property);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $property Object property to be updated.
|
||||
* @param string $default Default value.
|
||||
* @return $this
|
||||
*/
|
||||
public function doDefProperty($property, $default)
|
||||
{
|
||||
/** @var ObjectInterface $element */
|
||||
foreach ($this->getIterator() as $element) {
|
||||
$element->defProperty($property, $default);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $method Method name.
|
||||
* @param array $arguments List of arguments passed to the function.
|
||||
* @return array Return values.
|
||||
*/
|
||||
public function call($method, array $arguments = [])
|
||||
{
|
||||
$list = [];
|
||||
|
||||
foreach ($this->getIterator() as $id => $element) {
|
||||
$list[$id] = method_exists($element, $method)
|
||||
? call_user_func_array([$element, $method], $arguments) : null;
|
||||
}
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Group items in the collection by a field and return them as associated array.
|
||||
*
|
||||
* @param string $property
|
||||
* @return array
|
||||
*/
|
||||
public function group($property)
|
||||
{
|
||||
$list = [];
|
||||
|
||||
/** @var ObjectInterface $element */
|
||||
foreach ($this->getIterator() as $element) {
|
||||
$list[(string) $element->getProperty($property)][] = $element;
|
||||
}
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Group items in the collection by a field and return them as associated array of collections.
|
||||
*
|
||||
* @param string $property
|
||||
* @return static[]
|
||||
*/
|
||||
public function collectionGroup($property)
|
||||
{
|
||||
$collections = [];
|
||||
foreach ($this->group($property) as $id => $elements) {
|
||||
// TODO: remove when PHP 5.6 is minimum (with doctrine/collections v1.4).
|
||||
if (!method_exists($this, 'createFrom')) {
|
||||
$collection = new static($elements);
|
||||
} else {
|
||||
$collection = $this->createFrom($elements);
|
||||
}
|
||||
|
||||
$collections[$id] = $collection;
|
||||
}
|
||||
|
||||
return $collections;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Traversable
|
||||
*/
|
||||
abstract public function getIterator();
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Grav\Framework\Object
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2018 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Framework\Object\Base;
|
||||
|
||||
/**
|
||||
* Object trait.
|
||||
*
|
||||
* @package Grav\Framework\Object
|
||||
*/
|
||||
trait ObjectTrait
|
||||
{
|
||||
static protected $prefix;
|
||||
static protected $type;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $_key;
|
||||
|
||||
/**
|
||||
* @param bool $prefix
|
||||
* @return string
|
||||
*/
|
||||
public function getType($prefix = true)
|
||||
{
|
||||
if (static::$type) {
|
||||
return ($prefix ? static::$prefix : '') . static::$type;
|
||||
}
|
||||
|
||||
$class = get_class($this);
|
||||
return ($prefix ? static::$prefix : '') . strtolower(substr($class, strrpos($class, '\\') + 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getKey()
|
||||
{
|
||||
return $this->_key ?: $this->getType() . '@' . spl_object_hash($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $property Object property name.
|
||||
* @return bool True if property has been defined (can be null).
|
||||
*/
|
||||
public function hasProperty($property)
|
||||
{
|
||||
return $this->doHasProperty($property);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $property Object property to be fetched.
|
||||
* @param mixed $default Default value if property has not been set.
|
||||
* @return mixed Property value.
|
||||
*/
|
||||
public function getProperty($property, $default = null)
|
||||
{
|
||||
return $this->doGetProperty($property, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $property Object property to be updated.
|
||||
* @param string $value New value.
|
||||
* @return $this
|
||||
*/
|
||||
public function setProperty($property, $value)
|
||||
{
|
||||
$this->doSetProperty($property, $value);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $property Object property to be unset.
|
||||
* @return $this
|
||||
*/
|
||||
public function unsetProperty($property)
|
||||
{
|
||||
$this->doUnsetProperty($property);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $property Object property to be defined.
|
||||
* @param mixed $default Default value.
|
||||
* @return $this
|
||||
*/
|
||||
public function defProperty($property, $default)
|
||||
{
|
||||
if (!$this->hasProperty($property)) {
|
||||
$this->setProperty($property, $default);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements Serializable interface.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function serialize()
|
||||
{
|
||||
return serialize($this->jsonSerialize());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $serialized
|
||||
*/
|
||||
public function unserialize($serialized)
|
||||
{
|
||||
$data = unserialize($serialized);
|
||||
|
||||
if (method_exists($this, 'initObjectProperties')) {
|
||||
$this->initObjectProperties();
|
||||
}
|
||||
$this->doUnserialize($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $serialized
|
||||
*/
|
||||
protected function doUnserialize(array $serialized)
|
||||
{
|
||||
if (!isset($serialized['key'], $serialized['type'], $serialized['elements']) || $serialized['type'] !== $this->getType()) {
|
||||
throw new \InvalidArgumentException("Cannot unserialize '{$this->getType()}': Bad data");
|
||||
}
|
||||
|
||||
$this->setKey($serialized['key']);
|
||||
$this->setElements($serialized['elements']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements JsonSerializable interface.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function jsonSerialize()
|
||||
{
|
||||
return ['key' => $this->getKey(), 'type' => $this->getType(), 'elements' => $this->getElements()];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of this object.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return $this->getKey();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
*/
|
||||
protected function setKey($key)
|
||||
{
|
||||
$this->_key = (string) $key;
|
||||
}
|
||||
|
||||
abstract protected function doHasProperty($property);
|
||||
abstract protected function &doGetProperty($property, $default = null, $doCreate = false);
|
||||
abstract protected function doSetProperty($property, $value);
|
||||
abstract protected function doUnsetProperty($property);
|
||||
abstract protected function getElements();
|
||||
abstract protected function setElements(array $elements);
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Grav\Framework\Object
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2018 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Framework\Object\Interfaces;
|
||||
|
||||
/**
|
||||
* Object Interface
|
||||
* @package Grav\Framework\Object
|
||||
*/
|
||||
interface NestedObjectInterface extends ObjectInterface
|
||||
{
|
||||
/**
|
||||
* @param string $property Object property name.
|
||||
* @param string $separator Separator, defaults to '.'
|
||||
* @return bool True if property has been defined (can be null).
|
||||
*/
|
||||
public function hasNestedProperty($property, $separator = null);
|
||||
|
||||
/**
|
||||
* @param string $property Object property to be fetched.
|
||||
* @param mixed $default Default value if property has not been set.
|
||||
* @param string $separator Separator, defaults to '.'
|
||||
* @return mixed Property value.
|
||||
*/
|
||||
public function getNestedProperty($property, $default = null, $separator = null);
|
||||
|
||||
/**
|
||||
* @param string $property Object property to be updated.
|
||||
* @param string $value New value.
|
||||
* @param string $separator Separator, defaults to '.'
|
||||
* @return $this
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function setNestedProperty($property, $value, $separator = null);
|
||||
|
||||
/**
|
||||
* @param string $property Object property to be defined.
|
||||
* @param string $default Default value.
|
||||
* @param string $separator Separator, defaults to '.'
|
||||
* @return $this
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function defNestedProperty($property, $default, $separator = null);
|
||||
|
||||
/**
|
||||
* @param string $property Object property to be unset.
|
||||
* @param string $separator Separator, defaults to '.'
|
||||
* @return $this
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function unsetNestedProperty($property, $separator = null);
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Grav\Framework\Object
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2018 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Framework\Object\Interfaces;
|
||||
|
||||
use Grav\Framework\Collection\CollectionInterface;
|
||||
|
||||
/**
|
||||
* ObjectCollection Interface
|
||||
* @package Grav\Framework\Collection
|
||||
*/
|
||||
interface ObjectCollectionInterface extends CollectionInterface, ObjectInterface
|
||||
{
|
||||
/**
|
||||
* Create a copy from this collection by cloning all objects in the collection.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function copy();
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @return $this
|
||||
*/
|
||||
public function setKey($key);
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getObjectKeys();
|
||||
|
||||
/**
|
||||
* @param string $property Object property to be fetched.
|
||||
* @param mixed $default Default value if not set.
|
||||
* @return array Property value.
|
||||
*/
|
||||
public function getProperty($property, $default = null);
|
||||
|
||||
/**
|
||||
* @param string $name Method name.
|
||||
* @param array $arguments List of arguments passed to the function.
|
||||
* @return array Return values.
|
||||
*/
|
||||
public function call($name, array $arguments);
|
||||
|
||||
/**
|
||||
* Group items in the collection by a field and return them as associated array.
|
||||
*
|
||||
* @param string $property
|
||||
* @return array
|
||||
*/
|
||||
public function group($property);
|
||||
|
||||
/**
|
||||
* Group items in the collection by a field and return them as associated array of collections.
|
||||
*
|
||||
* @param string $property
|
||||
* @return static[]
|
||||
*/
|
||||
public function collectionGroup($property);
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Grav\Framework\Object
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2018 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Framework\Object\Interfaces;
|
||||
|
||||
/**
|
||||
* Object Interface
|
||||
* @package Grav\Framework\Object
|
||||
*/
|
||||
interface ObjectInterface extends \Serializable, \JsonSerializable
|
||||
{
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getType();
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getKey();
|
||||
|
||||
/**
|
||||
* @param string $property Object property name.
|
||||
* @return bool True if property has been defined (can be null).
|
||||
*/
|
||||
public function hasProperty($property);
|
||||
|
||||
/**
|
||||
* @param string $property Object property to be fetched.
|
||||
* @param mixed $default Default value if property has not been set.
|
||||
* @return mixed Property value.
|
||||
*/
|
||||
public function getProperty($property, $default = null);
|
||||
|
||||
/**
|
||||
* @param string $property Object property to be updated.
|
||||
* @param string $value New value.
|
||||
* @return $this
|
||||
*/
|
||||
public function setProperty($property, $value);
|
||||
|
||||
/**
|
||||
* @param string $property Object property to be defined.
|
||||
* @param mixed $default Default value.
|
||||
* @return $this
|
||||
*/
|
||||
public function defProperty($property, $default);
|
||||
|
||||
/**
|
||||
* @param string $property Object property to be unset.
|
||||
* @return $this
|
||||
*/
|
||||
public function unsetProperty($property);
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Grav\Framework\Object
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2018 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Framework\Object;
|
||||
|
||||
use Grav\Framework\Object\Access\NestedArrayAccessTrait;
|
||||
use Grav\Framework\Object\Access\NestedPropertyTrait;
|
||||
use Grav\Framework\Object\Access\OverloadedPropertyTrait;
|
||||
use Grav\Framework\Object\Base\ObjectTrait;
|
||||
use Grav\Framework\Object\Interfaces\NestedObjectInterface;
|
||||
use Grav\Framework\Object\Property\LazyPropertyTrait;
|
||||
|
||||
/**
|
||||
* Lazy Object class.
|
||||
*
|
||||
* @package Grav\Framework\Object
|
||||
*/
|
||||
class LazyObject implements NestedObjectInterface, \ArrayAccess
|
||||
{
|
||||
use ObjectTrait, LazyPropertyTrait, NestedPropertyTrait, OverloadedPropertyTrait, NestedArrayAccessTrait;
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Grav\Framework\Object
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2018 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Framework\Object;
|
||||
|
||||
use Grav\Framework\Collection\ArrayCollection;
|
||||
use Grav\Framework\Object\Access\NestedPropertyCollectionTrait;
|
||||
use Grav\Framework\Object\Base\ObjectCollectionTrait;
|
||||
use Grav\Framework\Object\Interfaces\NestedObjectInterface;
|
||||
use Grav\Framework\Object\Interfaces\ObjectCollectionInterface;
|
||||
|
||||
/**
|
||||
* Object Collection
|
||||
* @package Grav\Framework\Object
|
||||
*/
|
||||
class ObjectCollection extends ArrayCollection implements ObjectCollectionInterface, NestedObjectInterface
|
||||
{
|
||||
use ObjectCollectionTrait, NestedPropertyCollectionTrait {
|
||||
NestedPropertyCollectionTrait::group insteadof ObjectCollectionTrait;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $elements
|
||||
* @param string $key
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function __construct(array $elements = [], $key = null)
|
||||
{
|
||||
parent::__construct($this->setElements($elements));
|
||||
|
||||
$this->setKey($key);
|
||||
}
|
||||
|
||||
protected function getElements()
|
||||
{
|
||||
return $this->toArray();
|
||||
}
|
||||
|
||||
protected function setElements(array $elements)
|
||||
{
|
||||
return $elements;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Grav\Framework\Object
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2018 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Framework\Object\Property;
|
||||
|
||||
/**
|
||||
* Array Property Trait
|
||||
*
|
||||
* Stores all object properties into an array.
|
||||
*
|
||||
* @package Grav\Framework\Object\Property
|
||||
*/
|
||||
trait ArrayPropertyTrait
|
||||
{
|
||||
/**
|
||||
* Properties of the object.
|
||||
* @var array
|
||||
*/
|
||||
private $_elements;
|
||||
|
||||
/**
|
||||
* @param array $elements
|
||||
* @param string $key
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function __construct(array $elements = [], $key = null)
|
||||
{
|
||||
$this->setElements($elements);
|
||||
$this->setKey($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $property Object property name.
|
||||
* @return bool True if property has been defined (can be null).
|
||||
*/
|
||||
protected function doHasProperty($property)
|
||||
{
|
||||
return array_key_exists($property, $this->_elements);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $property Object property to be fetched.
|
||||
* @param mixed $default Default value if property has not been set.
|
||||
* @param bool $doCreate Set true to create variable.
|
||||
* @return mixed Property value.
|
||||
*/
|
||||
protected function &doGetProperty($property, $default = null, $doCreate = false)
|
||||
{
|
||||
if (!array_key_exists($property, $this->_elements)) {
|
||||
if ($doCreate) {
|
||||
$this->_elements[$property] = null;
|
||||
} else {
|
||||
return $default;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->_elements[$property];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $property Object property to be updated.
|
||||
* @param mixed $value New value.
|
||||
*/
|
||||
protected function doSetProperty($property, $value)
|
||||
{
|
||||
$this->_elements[$property] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $property Object property to be unset.
|
||||
*/
|
||||
protected function doUnsetProperty($property)
|
||||
{
|
||||
unset($this->_elements[$property]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $property
|
||||
* @param mixed|null $default
|
||||
* @return mixed|null
|
||||
*/
|
||||
protected function getElement($property, $default = null)
|
||||
{
|
||||
return array_key_exists($property, $this->_elements) ? $this->_elements[$property] : $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
protected function getElements()
|
||||
{
|
||||
return $this->_elements;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $elements
|
||||
*/
|
||||
protected function setElements(array $elements)
|
||||
{
|
||||
$this->_elements = $elements;
|
||||
}
|
||||
|
||||
abstract protected function setKey($key);
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Grav\Framework\Object
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2018 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Framework\Object\Property;
|
||||
|
||||
/**
|
||||
* Lazy Mixed Property Trait
|
||||
*
|
||||
* Stores defined object properties as class member variables and the rest into an array. Object properties are lazy
|
||||
* loaded from the array.
|
||||
*
|
||||
* You may define following methods for the member variables:
|
||||
* - `$this->offsetLoad($offset, $value)` called first time object property gets accessed
|
||||
* - `$this->offsetPrepare($offset, $value)` called on every object property set
|
||||
* - `$this->offsetSerialize($offset, $value)` called when the raw or serialized object property value is needed
|
||||
*
|
||||
* @package Grav\Framework\Object\Property
|
||||
*/
|
||||
trait LazyPropertyTrait
|
||||
{
|
||||
use ArrayPropertyTrait, ObjectPropertyTrait {
|
||||
ObjectPropertyTrait::__construct insteadof ArrayPropertyTrait;
|
||||
ArrayPropertyTrait::doHasProperty as hasArrayProperty;
|
||||
ArrayPropertyTrait::doGetProperty as getArrayProperty;
|
||||
ArrayPropertyTrait::doSetProperty as setArrayProperty;
|
||||
ArrayPropertyTrait::doUnsetProperty as unsetArrayProperty;
|
||||
ArrayPropertyTrait::getElement as getArrayElement;
|
||||
ArrayPropertyTrait::getElements as getArrayElements;
|
||||
ArrayPropertyTrait::setElements insteadof ObjectPropertyTrait;
|
||||
ObjectPropertyTrait::doHasProperty as hasObjectProperty;
|
||||
ObjectPropertyTrait::doGetProperty as getObjectProperty;
|
||||
ObjectPropertyTrait::doSetProperty as setObjectProperty;
|
||||
ObjectPropertyTrait::doUnsetProperty as unsetObjectProperty;
|
||||
ObjectPropertyTrait::getElement as getObjectElement;
|
||||
ObjectPropertyTrait::getElements as getObjectElements;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $property Object property name.
|
||||
* @return bool True if property has been defined (can be null).
|
||||
*/
|
||||
protected function doHasProperty($property)
|
||||
{
|
||||
return $this->hasArrayProperty($property) || $this->hasObjectProperty($property);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $property Object property to be fetched.
|
||||
* @param mixed $default Default value if property has not been set.
|
||||
* @return mixed Property value.
|
||||
*/
|
||||
protected function &doGetProperty($property, $default = null, $doCreate = false)
|
||||
{
|
||||
if ($this->hasObjectProperty($property)) {
|
||||
return $this->getObjectProperty($property, $default, function ($default = null) use ($property) {
|
||||
return $this->getArrayProperty($property, $default);
|
||||
});
|
||||
}
|
||||
|
||||
return $this->getArrayProperty($property, $default, $doCreate);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $property Object property to be updated.
|
||||
* @param mixed $value New value.
|
||||
* @return $this
|
||||
*/
|
||||
protected function doSetProperty($property, $value)
|
||||
{
|
||||
if ($this->hasObjectProperty($property)) {
|
||||
$this->setObjectProperty($property, $value);
|
||||
} else {
|
||||
$this->setArrayProperty($property, $value);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $property Object property to be unset.
|
||||
* @return $this
|
||||
*/
|
||||
protected function doUnsetProperty($property)
|
||||
{
|
||||
$this->hasObjectProperty($property) ?
|
||||
$this->unsetObjectProperty($property) : $this->unsetArrayProperty($property);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $property
|
||||
* @param mixed|null $default
|
||||
* @return mixed|null
|
||||
*/
|
||||
protected function getElement($property, $default = null)
|
||||
{
|
||||
if ($this->isPropertyLoaded($property)) {
|
||||
return $this->getObjectElement($property, $default);
|
||||
}
|
||||
|
||||
return $this->getArrayElement($property, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
protected function getElements()
|
||||
{
|
||||
return $this->getObjectElements() + $this->getArrayElements();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Grav\Framework\Object
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2018 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Framework\Object\Property;
|
||||
|
||||
/**
|
||||
* Mixed Property Trait
|
||||
*
|
||||
* Stores defined object properties as class member variables and the rest into an array.
|
||||
*
|
||||
* You may define following methods for member variables:
|
||||
* - `$this->offsetLoad($offset, $value)` called first time object property gets accessed
|
||||
* - `$this->offsetPrepare($offset, $value)` called on every object property set
|
||||
* - `$this->offsetSerialize($offset, $value)` called when the raw or serialized object property value is needed
|
||||
|
||||
*
|
||||
* @package Grav\Framework\Object\Property
|
||||
*/
|
||||
trait MixedPropertyTrait
|
||||
{
|
||||
use ArrayPropertyTrait, ObjectPropertyTrait {
|
||||
ObjectPropertyTrait::__construct insteadof ArrayPropertyTrait;
|
||||
ArrayPropertyTrait::doHasProperty as hasArrayProperty;
|
||||
ArrayPropertyTrait::doGetProperty as getArrayProperty;
|
||||
ArrayPropertyTrait::doSetProperty as setArrayProperty;
|
||||
ArrayPropertyTrait::doUnsetProperty as unsetArrayProperty;
|
||||
ArrayPropertyTrait::getElement as getArrayElement;
|
||||
ArrayPropertyTrait::getElements as getArrayElements;
|
||||
ArrayPropertyTrait::setElements as setArrayElements;
|
||||
ObjectPropertyTrait::doHasProperty as hasObjectProperty;
|
||||
ObjectPropertyTrait::doGetProperty as getObjectProperty;
|
||||
ObjectPropertyTrait::doSetProperty as setObjectProperty;
|
||||
ObjectPropertyTrait::doUnsetProperty as unsetObjectProperty;
|
||||
ObjectPropertyTrait::getElement as getObjectElement;
|
||||
ObjectPropertyTrait::getElements as getObjectElements;
|
||||
ObjectPropertyTrait::setElements as setObjectElements;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $property Object property name.
|
||||
* @return bool True if property has been defined (can be null).
|
||||
*/
|
||||
protected function doHasProperty($property)
|
||||
{
|
||||
return $this->hasArrayProperty($property) || $this->hasObjectProperty($property);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $property Object property to be fetched.
|
||||
* @param mixed $default Default value if property has not been set.
|
||||
* @return mixed Property value.
|
||||
*/
|
||||
protected function &doGetProperty($property, $default = null, $doCreate = false)
|
||||
{
|
||||
if ($this->hasObjectProperty($property)) {
|
||||
return $this->getObjectProperty($property);
|
||||
}
|
||||
|
||||
return $this->getArrayProperty($property, $default, $doCreate);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $property Object property to be updated.
|
||||
* @param mixed $value New value.
|
||||
* @return $this
|
||||
*/
|
||||
protected function doSetProperty($property, $value)
|
||||
{
|
||||
$this->hasObjectProperty($property)
|
||||
? $this->setObjectProperty($property, $value) : $this->setArrayProperty($property, $value);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $property Object property to be unset.
|
||||
* @return $this
|
||||
*/
|
||||
protected function doUnsetProperty($property)
|
||||
{
|
||||
$this->hasObjectProperty($property) ?
|
||||
$this->unsetObjectProperty($property) : $this->unsetArrayProperty($property);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $property
|
||||
* @param mixed|null $default
|
||||
* @return mixed|null
|
||||
*/
|
||||
protected function getElement($property, $default = null)
|
||||
{
|
||||
if ($this->hasObjectProperty($property)) {
|
||||
return $this->getObjectElement($property, $default);
|
||||
}
|
||||
|
||||
return $this->getArrayElement($property, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
protected function getElements()
|
||||
{
|
||||
return $this->getObjectElements() + $this->getArrayElements();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $elements
|
||||
*/
|
||||
protected function setElements(array $elements)
|
||||
{
|
||||
$this->setObjectElements(array_intersect_key($elements, $this->_definedProperties));
|
||||
$this->setArrayElements(array_diff_key($elements, $this->_definedProperties));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,203 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Grav\Framework\Object
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2018 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Framework\Object\Property;
|
||||
|
||||
/**
|
||||
* Object Property Trait
|
||||
*
|
||||
* Stores all properties as class member variables or object properties. All properties need to be defined as protected
|
||||
* properties. Undefined properties will throw an error.
|
||||
*
|
||||
* Additionally you may define following methods:
|
||||
* - `$this->offsetLoad($offset, $value)` called first time object property gets accessed
|
||||
* - `$this->offsetPrepare($offset, $value)` called on every object property set
|
||||
* - `$this->offsetSerialize($offset, $value)` called when the raw or serialized object property value is needed
|
||||
*
|
||||
* @package Grav\Framework\Object\Property
|
||||
*/
|
||||
trait ObjectPropertyTrait
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $_definedProperties;
|
||||
|
||||
/**
|
||||
* @param array $elements
|
||||
* @param string $key
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function __construct(array $elements = [], $key = null)
|
||||
{
|
||||
$this->initObjectProperties();
|
||||
$this->setElements($elements);
|
||||
$this->setKey($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $property Object property name.
|
||||
* @return bool True if property has been loaded.
|
||||
*/
|
||||
protected function isPropertyLoaded($property)
|
||||
{
|
||||
return !empty($this->_definedProperties[$property]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $offset
|
||||
* @param mixed $value
|
||||
* @return mixed
|
||||
*/
|
||||
protected function offsetLoad($offset, $value)
|
||||
{
|
||||
$methodName = "offsetLoad_{$offset}";
|
||||
|
||||
return method_exists($this, $methodName)? $this->{$methodName}($value) : $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $offset
|
||||
* @param mixed $value
|
||||
* @return mixed
|
||||
*/
|
||||
protected function offsetPrepare($offset, $value)
|
||||
{
|
||||
$methodName = "offsetPrepare_{$offset}";
|
||||
|
||||
return method_exists($this, $methodName) ? $this->{$methodName}($value) : $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $offset
|
||||
* @param mixed $value
|
||||
* @return mixed
|
||||
*/
|
||||
protected function offsetSerialize($offset, $value)
|
||||
{
|
||||
$methodName = "offsetSerialize_{$offset}";
|
||||
|
||||
return method_exists($this, $methodName) ? $this->{$methodName}($value) : $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $property Object property name.
|
||||
* @return bool True if property has been defined (can be null).
|
||||
*/
|
||||
protected function doHasProperty($property)
|
||||
{
|
||||
return array_key_exists($property, $this->_definedProperties);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $property Object property to be fetched.
|
||||
* @param mixed $default Default value if property has not been set.
|
||||
* @param bool $doCreate Set true to create variable.
|
||||
* @return mixed Property value.
|
||||
*/
|
||||
protected function &doGetProperty($property, $default = null, $doCreate = false)
|
||||
{
|
||||
if (!array_key_exists($property, $this->_definedProperties)) {
|
||||
throw new \InvalidArgumentException("Property '{$property}' does not exist in the object!");
|
||||
}
|
||||
|
||||
if (empty($this->_definedProperties[$property])) {
|
||||
if ($doCreate === true) {
|
||||
$this->_definedProperties[$property] = true;
|
||||
$this->{$property} = null;
|
||||
} elseif (is_callable($doCreate)) {
|
||||
$this->_definedProperties[$property] = true;
|
||||
$this->{$property} = $this->offsetLoad($property, $doCreate());
|
||||
} else {
|
||||
return $default;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->{$property};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $property Object property to be updated.
|
||||
* @param mixed $value New value.
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
protected function doSetProperty($property, $value)
|
||||
{
|
||||
if (!array_key_exists($property, $this->_definedProperties)) {
|
||||
throw new \InvalidArgumentException("Property '{$property}' does not exist in the object!");
|
||||
}
|
||||
|
||||
$this->_definedProperties[$property] = true;
|
||||
$this->{$property} = $this->offsetPrepare($property, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $property Object property to be unset.
|
||||
*/
|
||||
protected function doUnsetProperty($property)
|
||||
{
|
||||
if (!array_key_exists($property, $this->_definedProperties)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->_definedProperties[$property] = false;
|
||||
unset($this->{$property});
|
||||
}
|
||||
|
||||
protected function initObjectProperties()
|
||||
{
|
||||
$this->_definedProperties = [];
|
||||
foreach (get_object_vars($this) as $property => $value) {
|
||||
if ($property[0] !== '_') {
|
||||
$this->_definedProperties[$property] = ($value !== null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $property
|
||||
* @param mixed|null $default
|
||||
* @return mixed|null
|
||||
*/
|
||||
protected function getElement($property, $default = null)
|
||||
{
|
||||
if (empty($this->_definedProperties[$property])) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
return $this->offsetSerialize($property, $this->{$property});
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
protected function getElements()
|
||||
{
|
||||
$properties = array_intersect_key(get_object_vars($this), array_filter($this->_definedProperties));
|
||||
|
||||
$elements = [];
|
||||
foreach ($properties as $offset => $value) {
|
||||
$elements[$offset] = $this->offsetSerialize($offset, $value);
|
||||
}
|
||||
|
||||
return $elements;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $elements
|
||||
*/
|
||||
protected function setElements(array $elements)
|
||||
{
|
||||
foreach ($elements as $property => $value) {
|
||||
$this->setProperty($property, $value);
|
||||
}
|
||||
}
|
||||
|
||||
abstract public function setProperty($property, $value);
|
||||
abstract protected function setKey($key);
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Grav\Framework\Object
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2018 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Framework\Object;
|
||||
|
||||
use Grav\Framework\Object\Access\NestedArrayAccessTrait;
|
||||
use Grav\Framework\Object\Access\NestedPropertyTrait;
|
||||
use Grav\Framework\Object\Access\OverloadedPropertyTrait;
|
||||
use Grav\Framework\Object\Base\ObjectTrait;
|
||||
use Grav\Framework\Object\Interfaces\NestedObjectInterface;
|
||||
use Grav\Framework\Object\Property\ObjectPropertyTrait;
|
||||
|
||||
/**
|
||||
* Property Object class.
|
||||
*
|
||||
* @package Grav\Framework\Object
|
||||
*/
|
||||
class PropertyObject implements NestedObjectInterface, \ArrayAccess
|
||||
{
|
||||
use ObjectTrait, ObjectPropertyTrait, NestedPropertyTrait, OverloadedPropertyTrait, NestedArrayAccessTrait;
|
||||
}
|
||||
Reference in New Issue
Block a user