CHANGELOG.md 0000666 00000002006 13605043205 0006355 0 ustar 00 # Changelog
All notable changes to this project will be documented in this file, in reverse chronological order by release.
## 1.0.0 - 2015-09-17
Initial release. This ports all hydrator classes and functionality from
[laminas-stdlib](https://github.com/laminas/laminas-stdlib) to a standalone
repository. All final keywords are removed, to allow a deprecation cycle in the
laminas-stdlib component.
Please note: the following classes will be marked as `final` for a version 2.0.0
release to immediately follow 1.0.0:
- `Laminas\Hydrator\NamingStrategy\IdentityNamingStrategy`
- `Laminas\Hydrator\NamingStrategy\ArrayMapNamingStrategy`
- `Laminas\Hydrator\NamingStrategy\CompositeNamingStrategy`
- `Laminas\Hydrator\Strategy\ExplodeStrategy`
- `Laminas\Hydrator\Strategy\StrategyChain`
- `Laminas\Hydrator\Strategy\DateTimeFormatterStrategy`
- `Laminas\Hydrator\Strategy\BooleanStrategy`
As such, you should not extend them.
### Added
- Nothing.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- Nothing.
COPYRIGHT.md 0000666 00000000127 13605043205 0006440 0 ustar 00 Copyright (c) 2019, Laminas Foundation.
All rights reserved. (https://getlaminas.org/)
LICENSE.md 0000666 00000002725 13605043205 0006160 0 ustar 00 Copyright (c) 2019, Laminas Foundation
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of Laminas Foundation nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
README.md 0000666 00000001211 13605043205 0006020 0 ustar 00 # laminas-hydrator
[![Build Status](https://travis-ci.org/laminas/laminas-hydrator.svg?branch=master)](https://travis-ci.org/laminas/laminas-hydrator)
[![Coverage Status](https://coveralls.io/repos/laminas/laminas-hydrator/badge.svg?branch=master)](https://coveralls.io/r/laminas/laminas-hydrator?branch=master)
`Laminas\Hydrator` provides utilities for mapping arrays to objects, and vice
versa, including facilities for filtering which data is mapped as well as
providing mechanisms for mapping nested structures.
- File issues at https://github.com/laminas/laminas-hydrator/issues
- Documentation is at https://docs.laminas.dev/laminas-stdlib
composer.json 0000666 00000003611 13605043205 0007271 0 ustar 00 {
"name": "laminas/laminas-hydrator",
"description": " ",
"license": "BSD-3-Clause",
"keywords": [
"laminas",
"hydrator"
],
"homepage": "https://laminas.dev",
"support": {
"docs": "https://docs.laminas.dev/laminas-hydrator/",
"issues": "https://github.com/laminas/laminas-hydrator/issues",
"source": "https://github.com/laminas/laminas-hydrator",
"rss": "https://github.com/laminas/laminas-hydrator/releases.atom",
"chat": "https://laminas.dev/chat",
"forum": "https://discourse.laminas.dev"
},
"config": {
"sort-packages": true
},
"extra": {
"branch-alias": {
"dev-master": "1.0-dev",
"dev-develop": "1.1-dev"
}
},
"require": {
"php": ">=5.5",
"laminas/laminas-stdlib": "^2.5.1",
"laminas/laminas-zendframework-bridge": "^1.0"
},
"require-dev": {
"laminas/laminas-eventmanager": "^2.5.1",
"laminas/laminas-filter": "^2.5.1",
"laminas/laminas-inputfilter": "^2.5.1",
"laminas/laminas-serializer": "^2.5.1",
"laminas/laminas-servicemanager": "^2.5.1",
"phpunit/phpunit": "~4.0",
"squizlabs/php_codesniffer": "^2.0@dev"
},
"suggest": {
"laminas/laminas-eventmanager": "^2.5.1, to support aggregate hydrator usage",
"laminas/laminas-filter": "^2.5.1, to support naming strategy hydrator usage",
"laminas/laminas-serializer": "^2.5.1, to use the SerializableStrategy",
"laminas/laminas-servicemanager": "^2.5.1, to support hydrator plugin manager usage"
},
"autoload": {
"psr-4": {
"Laminas\\Hydrator\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"LaminasTest\\Hydrator\\": "test/"
}
},
"replace": {
"zendframework/zend-hydrator": "self.version"
}
}
src/AbstractHydrator.php 0000666 00000016771 13605043205 0011342 0 ustar 00 strategies = new ArrayObject();
$this->filterComposite = new Filter\FilterComposite();
}
/**
* Gets the strategy with the given name.
*
* @param string $name The name of the strategy to get.
*
* @throws Exception\InvalidArgumentException
* @return Strategy\StrategyInterface
*/
public function getStrategy($name)
{
if (isset($this->strategies[$name])) {
return $this->strategies[$name];
}
if (!isset($this->strategies['*'])) {
throw new Exception\InvalidArgumentException(sprintf(
'%s: no strategy by name of "%s", and no wildcard strategy present',
__METHOD__,
$name
));
}
return $this->strategies['*'];
}
/**
* Checks if the strategy with the given name exists.
*
* @param string $name The name of the strategy to check for.
* @return bool
*/
public function hasStrategy($name)
{
return array_key_exists($name, $this->strategies)
|| array_key_exists('*', $this->strategies);
}
/**
* Adds the given strategy under the given name.
*
* @param string $name The name of the strategy to register.
* @param Strategy\StrategyInterface $strategy The strategy to register.
* @return HydratorInterface
*/
public function addStrategy($name, Strategy\StrategyInterface $strategy)
{
$this->strategies[$name] = $strategy;
return $this;
}
/**
* Removes the strategy with the given name.
*
* @param string $name The name of the strategy to remove.
* @return HydratorInterface
*/
public function removeStrategy($name)
{
unset($this->strategies[$name]);
return $this;
}
/**
* Converts a value for extraction. If no strategy exists the plain value is returned.
*
* @param string $name The name of the strategy to use.
* @param mixed $value The value that should be converted.
* @param mixed $object The object is optionally provided as context.
* @return mixed
*/
public function extractValue($name, $value, $object = null)
{
if ($this->hasStrategy($name)) {
$strategy = $this->getStrategy($name);
$value = $strategy->extract($value, $object);
}
return $value;
}
/**
* Converts a value for hydration. If no strategy exists the plain value is returned.
*
* @param string $name The name of the strategy to use.
* @param mixed $value The value that should be converted.
* @param array $data The whole data is optionally provided as context.
* @return mixed
*/
public function hydrateValue($name, $value, $data = null)
{
if ($this->hasStrategy($name)) {
$strategy = $this->getStrategy($name);
$value = $strategy->hydrate($value, $data);
}
return $value;
}
/**
* Convert a name for extraction. If no naming strategy exists, the plain value is returned.
*
* @param string $name The name to convert.
* @param null $object The object is optionally provided as context.
* @return mixed
*/
public function extractName($name, $object = null)
{
if ($this->hasNamingStrategy()) {
$name = $this->getNamingStrategy()->extract($name, $object);
}
return $name;
}
/**
* Converts a value for hydration. If no naming strategy exists, the plain value is returned.
*
* @param string $name The name to convert.
* @param array $data The whole data is optionally provided as context.
* @return mixed
*/
public function hydrateName($name, $data = null)
{
if ($this->hasNamingStrategy()) {
$name = $this->getNamingStrategy()->hydrate($name, $data);
}
return $name;
}
/**
* Get the filter instance
*
* @return Filter\FilterComposite
*/
public function getFilter()
{
return $this->filterComposite;
}
/**
* Add a new filter to take care of what needs to be hydrated.
* To exclude e.g. the method getServiceLocator:
*
*
* $composite->addFilter("servicelocator",
* function ($property) {
* list($class, $method) = explode('::', $property);
* if ($method === 'getServiceLocator') {
* return false;
* }
* return true;
* }, FilterComposite::CONDITION_AND
* );
*
*
* @param string $name Index in the composite
* @param callable|Filter\FilterInterface $filter
* @param int $condition
* @return Filter\FilterComposite
*/
public function addFilter($name, $filter, $condition = Filter\FilterComposite::CONDITION_OR)
{
return $this->filterComposite->addFilter($name, $filter, $condition);
}
/**
* Check whether a specific filter exists at key $name or not
*
* @param string $name Index in the composite
* @return bool
*/
public function hasFilter($name)
{
return $this->filterComposite->hasFilter($name);
}
/**
* Remove a filter from the composition.
* To not extract "has" methods, you simply need to unregister it
*
*
* $filterComposite->removeFilter('has');
*
*
* @param $name
* @return Filter\FilterComposite
*/
public function removeFilter($name)
{
return $this->filterComposite->removeFilter($name);
}
/**
* Adds the given naming strategy
*
* @param NamingStrategy\NamingStrategyInterface $strategy The naming to register.
* @return self
*/
public function setNamingStrategy(NamingStrategy\NamingStrategyInterface $strategy)
{
$this->namingStrategy = $strategy;
return $this;
}
/**
* Gets the naming strategy.
*
* @return NamingStrategy\NamingStrategyInterface
*/
public function getNamingStrategy()
{
return $this->namingStrategy;
}
/**
* Checks if a naming strategy exists.
*
* @return bool
*/
public function hasNamingStrategy()
{
return isset($this->namingStrategy);
}
/**
* Removes the naming strategy
*
* @return self
*/
public function removeNamingStrategy()
{
$this->namingStrategy = null;
return $this;
}
}
src/Aggregate/AggregateHydrator.php 0000666 00000004141 13605043205 0013337 0 ustar 00 getEventManager()->attachAggregate(new HydratorListener($hydrator), $priority);
}
/**
* {@inheritDoc}
*/
public function extract($object)
{
$event = new ExtractEvent($this, $object);
$this->getEventManager()->trigger($event);
return $event->getExtractedData();
}
/**
* {@inheritDoc}
*/
public function hydrate(array $data, $object)
{
$event = new HydrateEvent($this, $object, $data);
$this->getEventManager()->trigger($event);
return $event->getHydratedObject();
}
/**
* {@inheritDoc}
*/
public function setEventManager(EventManagerInterface $eventManager)
{
$eventManager->setIdentifiers([__CLASS__, get_class($this)]);
$this->eventManager = $eventManager;
}
/**
* {@inheritDoc}
*/
public function getEventManager()
{
if (null === $this->eventManager) {
$this->setEventManager(new EventManager());
}
return $this->eventManager;
}
}
src/Aggregate/ExtractEvent.php 0000666 00000004041 13605043205 0012347 0 ustar 00 target = $target;
$this->extractionObject = $extractionObject;
}
/**
* Retrieves the object from which data is extracted
*
* @return object
*/
public function getExtractionObject()
{
return $this->extractionObject;
}
/**
* @param object $extractionObject
*
* @return void
*/
public function setExtractionObject($extractionObject)
{
$this->extractionObject = $extractionObject;
}
/**
* Retrieves the data that has been extracted
*
* @return array
*/
public function getExtractedData()
{
return $this->extractedData;
}
/**
* @param array $extractedData
*
* @return void
*/
public function setExtractedData(array $extractedData)
{
$this->extractedData = $extractedData;
}
/**
* Merge provided data with the extracted data
*
* @param array $additionalData
*
* @return void
*/
public function mergeExtractedData(array $additionalData)
{
$this->extractedData = array_merge($this->extractedData, $additionalData);
}
}
src/Aggregate/HydrateEvent.php 0000666 00000003422 13605043205 0012337 0 ustar 00 target = $target;
$this->hydratedObject = $hydratedObject;
$this->hydrationData = $hydrationData;
}
/**
* Retrieves the object that is being hydrated
*
* @return object
*/
public function getHydratedObject()
{
return $this->hydratedObject;
}
/**
* @param object $hydratedObject
*/
public function setHydratedObject($hydratedObject)
{
$this->hydratedObject = $hydratedObject;
}
/**
* Retrieves the data that is being used for hydration
*
* @return array
*/
public function getHydrationData()
{
return $this->hydrationData;
}
/**
* @param array $hydrationData
*/
public function setHydrationData(array $hydrationData)
{
$this->hydrationData = $hydrationData;
}
}
src/Aggregate/HydratorListener.php 0000666 00000003775 13605043205 0013252 0 ustar 00 hydrator = $hydrator;
}
/**
* {@inheritDoc}
*/
public function attach(EventManagerInterface $events, $priority = 1)
{
$this->listeners[] = $events->attach(HydrateEvent::EVENT_HYDRATE, [$this, 'onHydrate'], $priority);
$this->listeners[] = $events->attach(ExtractEvent::EVENT_EXTRACT, [$this, 'onExtract'], $priority);
}
/**
* Callback to be used when {@see HydrateEvent::EVENT_HYDRATE} is triggered
*
* @param HydrateEvent $event
* @return object
* @internal
*/
public function onHydrate(HydrateEvent $event)
{
$object = $this->hydrator->hydrate($event->getHydrationData(), $event->getHydratedObject());
$event->setHydratedObject($object);
return $object;
}
/**
* Callback to be used when {@see ExtractEvent::EVENT_EXTRACT} is triggered
*
* @param ExtractEvent $event
* @return array
* @internal
*/
public function onExtract(ExtractEvent $event)
{
$data = $this->hydrator->extract($event->getExtractionObject());
$event->mergeExtractedData($data);
return $data;
}
}
src/ArraySerializable.php 0000666 00000005077 13605043205 0011464 0 ustar 00 getArrayCopy();
$filter = $this->getFilter();
foreach ($data as $name => $value) {
if (!$filter->filter($name)) {
unset($data[$name]);
continue;
}
$extractedName = $this->extractName($name, $object);
// replace the original key with extracted, if differ
if ($extractedName !== $name) {
unset($data[$name]);
$name = $extractedName;
}
$data[$name] = $this->extractValue($name, $value, $object);
}
return $data;
}
/**
* Hydrate an object
*
* Hydrates an object by passing $data to either its exchangeArray() or
* populate() method.
*
* @param array $data
* @param object $object
* @return object
* @throws Exception\BadMethodCallException for an $object not implementing exchangeArray() or populate()
*/
public function hydrate(array $data, $object)
{
$replacement = [];
foreach ($data as $key => $value) {
$name = $this->hydrateName($key, $data);
$replacement[$name] = $this->hydrateValue($name, $value, $data);
}
if (is_callable([$object, 'exchangeArray'])) {
$object->exchangeArray($replacement);
} elseif (is_callable([$object, 'populate'])) {
$object->populate($replacement);
} else {
throw new Exception\BadMethodCallException(
sprintf('%s expects the provided object to implement exchangeArray() or populate()', __METHOD__)
);
}
return $object;
}
}
src/ClassMethods.php 0000666 00000020236 13605043205 0010442 0 ustar 00 setUnderscoreSeparatedKeys($underscoreSeparatedKeys);
$this->callableMethodFilter = new Filter\OptionalParametersFilter();
$this->filterComposite->addFilter('is', new Filter\IsFilter());
$this->filterComposite->addFilter('has', new Filter\HasFilter());
$this->filterComposite->addFilter('get', new Filter\GetFilter());
$this->filterComposite->addFilter(
'parameter',
new Filter\OptionalParametersFilter(),
Filter\FilterComposite::CONDITION_AND
);
}
/**
* @param array|Traversable $options
* @return ClassMethods
* @throws Exception\InvalidArgumentException
*/
public function setOptions($options)
{
if ($options instanceof Traversable) {
$options = ArrayUtils::iteratorToArray($options);
} elseif (!is_array($options)) {
throw new Exception\InvalidArgumentException(
'The options parameter must be an array or a Traversable'
);
}
if (isset($options['underscoreSeparatedKeys'])) {
$this->setUnderscoreSeparatedKeys($options['underscoreSeparatedKeys']);
}
return $this;
}
/**
* @param bool $underscoreSeparatedKeys
* @return ClassMethods
*/
public function setUnderscoreSeparatedKeys($underscoreSeparatedKeys)
{
$this->underscoreSeparatedKeys = (bool) $underscoreSeparatedKeys;
if ($this->underscoreSeparatedKeys) {
$this->setNamingStrategy(new NamingStrategy\UnderscoreNamingStrategy);
} elseif ($this->getNamingStrategy() instanceof NamingStrategy\UnderscoreNamingStrategy) {
$this->removeNamingStrategy();
}
return $this;
}
/**
* @return bool
*/
public function getUnderscoreSeparatedKeys()
{
return $this->underscoreSeparatedKeys;
}
/**
* Extract values from an object with class methods
*
* Extracts the getter/setter of the given $object.
*
* @param object $object
* @return array
* @throws Exception\BadMethodCallException for a non-object $object
*/
public function extract($object)
{
if (!is_object($object)) {
throw new Exception\BadMethodCallException(sprintf(
'%s expects the provided $object to be a PHP object)',
__METHOD__
));
}
$objectClass = get_class($object);
// reset the hydrator's hydrator's cache for this object, as the filter may be per-instance
if ($object instanceof Filter\FilterProviderInterface) {
$this->extractionMethodsCache[$objectClass] = null;
}
// pass 1 - finding out which properties can be extracted, with which methods (populate hydration cache)
if (! isset($this->extractionMethodsCache[$objectClass])) {
$this->extractionMethodsCache[$objectClass] = [];
$filter = $this->filterComposite;
$methods = get_class_methods($object);
if ($object instanceof Filter\FilterProviderInterface) {
$filter = new Filter\FilterComposite(
[$object->getFilter()],
[new Filter\MethodMatchFilter('getFilter')]
);
}
foreach ($methods as $method) {
$methodFqn = $objectClass . '::' . $method;
if (! ($filter->filter($methodFqn) && $this->callableMethodFilter->filter($methodFqn))) {
continue;
}
$attribute = $method;
if (strpos($method, 'get') === 0) {
$attribute = substr($method, 3);
if (!property_exists($object, $attribute)) {
$attribute = lcfirst($attribute);
}
}
$this->extractionMethodsCache[$objectClass][$method] = $attribute;
}
}
$values = [];
// pass 2 - actually extract data
foreach ($this->extractionMethodsCache[$objectClass] as $methodName => $attributeName) {
$realAttributeName = $this->extractName($attributeName, $object);
$values[$realAttributeName] = $this->extractValue($realAttributeName, $object->$methodName(), $object);
}
return $values;
}
/**
* Hydrate an object by populating getter/setter methods
*
* Hydrates an object by getter/setter methods of the object.
*
* @param array $data
* @param object $object
* @return object
* @throws Exception\BadMethodCallException for a non-object $object
*/
public function hydrate(array $data, $object)
{
if (!is_object($object)) {
throw new Exception\BadMethodCallException(sprintf(
'%s expects the provided $object to be a PHP object)',
__METHOD__
));
}
$objectClass = get_class($object);
foreach ($data as $property => $value) {
$propertyFqn = $objectClass . '::$' . $property;
if (! isset($this->hydrationMethodsCache[$propertyFqn])) {
$setterName = 'set' . ucfirst($this->hydrateName($property, $data));
$this->hydrationMethodsCache[$propertyFqn] = is_callable([$object, $setterName])
? $setterName
: false;
}
if ($this->hydrationMethodsCache[$propertyFqn]) {
$object->{$this->hydrationMethodsCache[$propertyFqn]}($this->hydrateValue($property, $value, $data));
}
}
return $object;
}
/**
* {@inheritDoc}
*/
public function addFilter($name, $filter, $condition = Filter\FilterComposite::CONDITION_OR)
{
$this->resetCaches();
return parent::addFilter($name, $filter, $condition);
}
/**
* {@inheritDoc}
*/
public function removeFilter($name)
{
$this->resetCaches();
return parent::removeFilter($name);
}
/**
* {@inheritDoc}
*/
public function setNamingStrategy(NamingStrategy\NamingStrategyInterface $strategy)
{
$this->resetCaches();
return parent::setNamingStrategy($strategy);
}
/**
* {@inheritDoc}
*/
public function removeNamingStrategy()
{
$this->resetCaches();
return parent::removeNamingStrategy();
}
/**
* Reset all local hydration/extraction caches
*/
private function resetCaches()
{
$this->hydrationMethodsCache = $this->extractionMethodsCache = [];
}
}
src/DelegatingHydrator.php 0000666 00000002370 13605043205 0011630 0 ustar 00 hydrators = $hydrators;
}
/**
* {@inheritdoc}
*/
public function hydrate(array $data, $object)
{
return $this->getHydrator($object)->hydrate($data, $object);
}
/**
* {@inheritdoc}
*/
public function extract($object)
{
return $this->getHydrator($object)->extract($object);
}
/**
* Gets hydrator of an object
*
* @param object $object
* @return HydratorInterface
*/
protected function getHydrator($object)
{
return $this->hydrators->get(get_class($object));
}
}
src/DelegatingHydratorFactory.php 0000666 00000001567 13605043205 0013167 0 ustar 00 orFilter = new ArrayObject($orFilter);
$this->andFilter = new ArrayObject($andFilter);
}
/**
* Add a filter to the composite. Has to be indexed with $name in
* order to identify a specific filter.
*
* This example will exclude all methods from the hydration, that starts with 'getService'
*
* $composite->addFilter('exclude',
* function ($method) {
* if (preg_match('/^getService/', $method) {
* return false;
* }
* return true;
* }, FilterComposite::CONDITION_AND
* );
*
*
* @param string $name
* @param callable|FilterInterface $filter
* @param int $condition Can be either
* FilterComposite::CONDITION_OR or FilterComposite::CONDITION_AND
* @throws InvalidArgumentException
* @return FilterComposite
*/
public function addFilter($name, $filter, $condition = self::CONDITION_OR)
{
if (!is_callable($filter) && !($filter instanceof FilterInterface)) {
throw new InvalidArgumentException(
'The value of ' . $name . ' should be either a callable or ' .
'an instance of Laminas\Stdlib\Hydrator\Filter\FilterInterface'
);
}
if ($condition === self::CONDITION_OR) {
$this->orFilter[$name] = $filter;
} elseif ($condition === self::CONDITION_AND) {
$this->andFilter[$name] = $filter;
}
return $this;
}
/**
* Remove a filter from the composition
*
* @param $name string Identifier for the filter
* @return FilterComposite
*/
public function removeFilter($name)
{
if (isset($this->orFilter[$name])) {
unset($this->orFilter[$name]);
}
if (isset($this->andFilter[$name])) {
unset($this->andFilter[$name]);
}
return $this;
}
/**
* Check if $name has a filter registered
*
* @param $name string Identifier for the filter
* @return bool
*/
public function hasFilter($name)
{
return isset($this->orFilter[$name]) || isset($this->andFilter[$name]);
}
/**
* Filter the composite based on the AND and OR condition
* Will return true if one from the "or conditions" and all from
* the "and condition" returns true. Otherwise false
*
* @param $property string Parameter will be e.g. Parent\Namespace\Class::method
* @return bool
*/
public function filter($property)
{
$andCount = count($this->andFilter);
$orCount = count($this->orFilter);
// return true if no filters are registered
if ($orCount === 0 && $andCount === 0) {
return true;
} elseif ($orCount === 0 && $andCount !== 0) {
$returnValue = true;
} else {
$returnValue = false;
}
// Check if 1 from the or filters return true
foreach ($this->orFilter as $filter) {
if (is_callable($filter)) {
if ($filter($property) === true) {
$returnValue = true;
break;
}
continue;
} else {
if ($filter->filter($property) === true) {
$returnValue = true;
break;
}
}
}
// Check if all of the and condition return true
foreach ($this->andFilter as $filter) {
if (is_callable($filter)) {
if ($filter($property) === false) {
return false;
}
continue;
} else {
if ($filter->filter($property) === false) {
return false;
}
}
}
return $returnValue;
}
}
src/Filter/FilterInterface.php 0000666 00000001063 13605043205 0012341 0 ustar 00 method = $method;
$this->exclude = $exclude;
}
public function filter($property)
{
$pos = strpos($property, '::');
if ($pos !== false) {
$pos += 2;
} else {
$pos = 0;
}
if (substr($property, $pos) === $this->method) {
return !$this->exclude;
}
return $this->exclude;
}
}
src/Filter/NumberOfParameterFilter.php 0000666 00000002514 13605043205 0014021 0 ustar 00 numberOfParameters = (int) $numberOfParameters;
}
/**
* @param string $property the name of the property
* @return bool
* @throws InvalidArgumentException
*/
public function filter($property)
{
try {
$reflectionMethod = new ReflectionMethod($property);
} catch (ReflectionException $exception) {
throw new InvalidArgumentException(
"Method $property doesn't exist"
);
}
return $reflectionMethod->getNumberOfParameters() === $this->numberOfParameters;
}
}
src/Filter/OptionalParametersFilter.php 0000666 00000003061 13605043205 0014252 0 ustar 00 getParameters(),
function (ReflectionParameter $parameter) {
return ! $parameter->isOptional();
}
);
return static::$propertiesCache[$property] = empty($mandatoryParameters);
}
}
src/FilterEnabledInterface.php 0000666 00000003265 13605043205 0012375 0 ustar 00
* $composite->addFilter(
* "servicelocator",
* function ($property) {
* list($class, $method) = explode('::', $property);
* if ($method === 'getServiceLocator') {
* return false;
* }
* return true;
* },
* FilterComposite::CONDITION_AND
* );
*
*
* @param string $name Index in the composite
* @param callable|Filter\FilterInterface $filter
* @param int $condition
* @return Filter\FilterComposite
*/
public function addFilter($name, $filter, $condition = Filter\FilterComposite::CONDITION_OR);
/**
* Check whether a specific filter exists at key $name or not
*
* @param string $name Index in the composite
* @return bool
*/
public function hasFilter($name);
/**
* Remove a filter from the composition.
* To not extract "has" methods, you simply need to unregister it
*
*
* $filterComposite->removeFilter('has');
*
*
* @param $name
* @return Filter\FilterComposite
*/
public function removeFilter($name);
}
src/HydrationInterface.php 0000666 00000001051 13605043205 0011625 0 ustar 00 hydrator = $hydrator;
return $this;
}
/**
* Retrieve hydrator
*
* @param void
* @return null|HydratorInterface
* @access public
*/
public function getHydrator()
{
return $this->hydrator;
}
}
src/HydratorInterface.php 0000666 00000000617 13605043205 0011467 0 ustar 00 'Laminas\Hydrator\DelegatingHydrator',
// Legacy Zend Framework aliases
// v2 normalized FQCNs
];
/**
* Default set of adapters
*
* @var array
*/
protected $invokableClasses = [
'arrayserializable' => 'Laminas\Hydrator\ArraySerializable',
'classmethods' => 'Laminas\Hydrator\ClassMethods',
'objectproperty' => 'Laminas\Hydrator\ObjectProperty',
'reflection' => 'Laminas\Hydrator\Reflection'
];
/**
* Default factory-based adapters
*
* @var array
*/
protected $factories = [
'Laminas\Hydrator\DelegatingHydrator' => 'Laminas\Hydrator\DelegatingHydratorFactory',
];
/**
* {@inheritDoc}
*/
public function validatePlugin($plugin)
{
if ($plugin instanceof HydratorInterface) {
// we're okay
return;
}
throw new Exception\RuntimeException(sprintf(
'Plugin of type %s is invalid; must implement Laminas\Hydrator\HydratorInterface',
(is_object($plugin) ? get_class($plugin) : gettype($plugin))
));
}
}
src/Iterator/HydratingArrayIterator.php 0000666 00000001644 13605043205 0014306 0 ustar 00 setHydrator($hydrator);
$this->setPrototype($prototype);
parent::__construct($data);
}
/**
* @inheritdoc
*/
public function setPrototype($prototype)
{
if (is_object($prototype)) {
$this->prototype = $prototype;
return;
}
if (!class_exists($prototype)) {
throw new InvalidArgumentException(
sprintf('Method %s was passed an invalid class name: %s', __METHOD__, $prototype)
);
}
$this->prototype = new $prototype;
}
/**
* @inheritdoc
*/
public function setHydrator(HydratorInterface $hydrator)
{
$this->hydrator = $hydrator;
}
/**
* @return object Returns hydrated clone of $prototype
*/
public function current()
{
$currentValue = parent::current();
$object = clone $this->prototype;
$this->hydrator->hydrate($currentValue, $object);
return $object;
}
}
src/NamingStrategy/ArrayMapNamingStrategy.php 0000666 00000002365 13605043205 0015401 0 ustar 00 extractionMap = $extractionMap;
$this->hydrationMap = array_flip($extractionMap);
}
/**
* {@inheritDoc}
*/
public function hydrate($name)
{
return isset($this->hydrationMap[$name]) ? $this->hydrationMap[$name] : $name;
}
/**
* {@inheritDoc}
*/
public function extract($name)
{
return isset($this->extractionMap[$name]) ? $this->extractionMap[$name] : $name;
}
}
src/NamingStrategy/CompositeNamingStrategy.php 0000666 00000003346 13605043205 0015627 0 ustar 00 namingStrategies = array_map(
function (NamingStrategyInterface $strategy) {
// this callback is here only to ensure type-safety
return $strategy;
},
$strategies
);
$this->defaultNamingStrategy = $defaultNamingStrategy ?: new IdentityNamingStrategy();
}
/**
* {@inheritDoc}
*/
public function extract($name)
{
$strategy = isset($this->namingStrategies[$name])
? $this->namingStrategies[$name]
: $this->defaultNamingStrategy;
return $strategy->extract($name);
}
/**
* {@inheritDoc}
*/
public function hydrate($name)
{
$strategy = isset($this->namingStrategies[$name])
? $this->namingStrategies[$name]
: $this->defaultNamingStrategy;
return $strategy->hydrate($name);
}
}
src/NamingStrategy/IdentityNamingStrategy.php 0000666 00000001147 13605043205 0015453 0 ustar 00 mapping = $mapping;
$this->reverse = $reverse ?: $this->flipMapping($mapping);
}
/**
* Safelly flip mapping array.
*
* @param array $array Array to flip
* @return array Flipped array
* @throws InvalidArgumentException
*/
protected function flipMapping(array $array)
{
array_walk($array, function ($value) {
if (!is_string($value) && !is_int($value)) {
throw new InvalidArgumentException('Mapping array can\'t be flipped because of invalid value');
}
});
return array_flip($array);
}
/**
* Converts the given name so that it can be extracted by the hydrator.
*
* @param string $name The original name
* @return mixed The hydrated name
*/
public function hydrate($name)
{
if (array_key_exists($name, $this->mapping)) {
return $this->mapping[$name];
}
return $name;
}
/**
* Converts the given name so that it can be hydrated by the hydrator.
*
* @param string $name The original name
* @return mixed The extracted name
*/
public function extract($name)
{
if (array_key_exists($name, $this->reverse)) {
return $this->reverse[$name];
}
return $name;
}
}
src/NamingStrategy/NamingStrategyInterface.php 0000666 00000002001 13605043205 0015550 0 ustar 00 getUnderscoreToStudlyCaseFilter()->filter($name);
}
/**
* Remove capitalized letters and prepend underscores.
*
* @param string $name
* @return string
*/
public function extract($name)
{
return $this->getCamelCaseToUnderscoreFilter()->filter($name);
}
/**
* @return FilterChain
*/
protected function getUnderscoreToStudlyCaseFilter()
{
if (static::$underscoreToStudlyCaseFilter instanceof FilterChain) {
return static::$underscoreToStudlyCaseFilter;
}
$filter = new FilterChain();
$filter->attachByName('WordUnderscoreToStudlyCase');
return static::$underscoreToStudlyCaseFilter = $filter;
}
/**
* @return FilterChain
*/
protected function getCamelCaseToUnderscoreFilter()
{
if (static::$camelCaseToUnderscoreFilter instanceof FilterChain) {
return static::$camelCaseToUnderscoreFilter;
}
$filter = new FilterChain();
$filter->attachByName('WordCamelCaseToUnderscore');
$filter->attachByName('StringToLower');
return static::$camelCaseToUnderscoreFilter = $filter;
}
}
src/NamingStrategyEnabledInterface.php 0000666 00000002014 13605043205 0014073 0 ustar 00 getFilter();
foreach ($data as $name => $value) {
// Filter keys, removing any we don't want
if (! $filter->filter($name)) {
unset($data[$name]);
continue;
}
// Replace name if extracted differ
$extracted = $this->extractName($name, $object);
if ($extracted !== $name) {
unset($data[$name]);
$name = $extracted;
}
$data[$name] = $this->extractValue($name, $value, $object);
}
return $data;
}
/**
* {@inheritDoc}
*
* Hydrate an object by populating public properties
*
* Hydrates an object by setting public properties of the object.
*
* @throws Exception\BadMethodCallException for a non-object $object
*/
public function hydrate(array $data, $object)
{
if (!is_object($object)) {
throw new Exception\BadMethodCallException(
sprintf('%s expects the provided $object to be a PHP object)', __METHOD__)
);
}
$properties = & self::$skippedPropertiesCache[get_class($object)];
if (! isset($properties)) {
$reflection = new ReflectionClass($object);
$properties = array_fill_keys(
array_map(
function (ReflectionProperty $property) {
return $property->getName();
},
$reflection->getProperties(
ReflectionProperty::IS_PRIVATE
+ ReflectionProperty::IS_PROTECTED
+ ReflectionProperty::IS_STATIC
)
),
true
);
}
foreach ($data as $name => $value) {
$property = $this->hydrateName($name, $data);
if (isset($properties[$property])) {
continue;
}
$object->$property = $this->hydrateValue($property, $value, $data);
}
return $object;
}
}
src/Reflection.php 0000666 00000005415 13605043205 0010145 0 ustar 00 extractName($property->getName(), $object);
if (!$this->filterComposite->filter($propertyName)) {
continue;
}
$value = $property->getValue($object);
$result[$propertyName] = $this->extractValue($propertyName, $value, $object);
}
return $result;
}
/**
* Hydrate $object with the provided $data.
*
* @param array $data
* @param object $object
* @return object
*/
public function hydrate(array $data, $object)
{
$reflProperties = self::getReflProperties($object);
foreach ($data as $key => $value) {
$name = $this->hydrateName($key, $data);
if (isset($reflProperties[$name])) {
$reflProperties[$name]->setValue($object, $this->hydrateValue($name, $value, $data));
}
}
return $object;
}
/**
* Get a reflection properties from in-memory cache and lazy-load if
* class has not been loaded.
*
* @param string|object $input
* @throws Exception\InvalidArgumentException
* @return ReflectionProperty[]
*/
protected static function getReflProperties($input)
{
if (is_object($input)) {
$input = get_class($input);
} elseif (!is_string($input)) {
throw new Exception\InvalidArgumentException('Input must be a string or an object.');
}
if (isset(static::$reflProperties[$input])) {
return static::$reflProperties[$input];
}
static::$reflProperties[$input] = [];
$reflClass = new ReflectionClass($input);
$reflProperties = $reflClass->getProperties();
foreach ($reflProperties as $property) {
$property->setAccessible(true);
static::$reflProperties[$input][$property->getName()] = $property;
}
return static::$reflProperties[$input];
}
}
src/Strategy/BooleanStrategy.php 0000666 00000006224 13605043205 0012756 0 ustar 00 trueValue = $trueValue;
$this->falseValue = $falseValue;
}
/**
* Converts the given value so that it can be extracted by the hydrator.
*
* @param bool $value The original value.
* @throws InvalidArgumentException
* @return int|string Returns the value that should be extracted.
*/
public function extract($value)
{
if (!is_bool($value)) {
throw new InvalidArgumentException(sprintf(
'Unable to extract. Expected bool. %s was given.',
is_object($value) ? get_class($value) : gettype($value)
));
}
return $value === true ? $this->trueValue : $this->falseValue;
}
/**
* Converts the given value so that it can be hydrated by the hydrator.
*
* @param int|string $value The original value.
* @throws InvalidArgumentException
* @return bool Returns the value that should be hydrated.
*/
public function hydrate($value)
{
if (!is_string($value) && !is_int($value)) {
throw new InvalidArgumentException(sprintf(
'Unable to hydrate. Expected string or int. %s was given.',
is_object($value) ? get_class($value) : gettype($value)
));
}
if ($value === $this->trueValue) {
return true;
}
if ($value === $this->falseValue) {
return false;
}
throw new InvalidArgumentException(sprintf(
'Unexpected value %s can\'t be hydrated. Expect %s or %s as Value.',
$value,
$this->trueValue,
$this->falseValue
));
}
}
src/Strategy/ClosureStrategy.php 0000666 00000005770 13605043205 0013020 0 ustar 00
* function ($value) {
* return $value;
* };
*
*
* @var callable
*/
protected $extractFunc = null;
/**
* Function, used in hydrate method, default:
*
*
* function ($value) {
* return $value;
* };
*
*
* @var callable
*/
protected $hydrateFunc = null;
/**
* You can describe how your values will extract and hydrate, like this:
*
*
* $hydrator->addStrategy('category', new ClosureStrategy(
* function (Category $value) {
* return (int) $value->id;
* },
* function ($value) {
* return new Category((int) $value);
* }
* ));
*
*
* @param callable $extractFunc - anonymous function, that extract values
* from object
* @param callable $hydrateFunc - anonymous function, that hydrate values
* into object
*/
public function __construct($extractFunc = null, $hydrateFunc = null)
{
if (isset($extractFunc)) {
if (!is_callable($extractFunc)) {
throw new \Exception('$extractFunc must be callable');
}
$this->extractFunc = $extractFunc;
} else {
$this->extractFunc = function ($value) {
return $value;
};
}
if (isset($hydrateFunc)) {
if (!is_callable($hydrateFunc)) {
throw new \Exception('$hydrateFunc must be callable');
}
$this->hydrateFunc = $hydrateFunc;
} else {
$this->hydrateFunc = function ($value) {
return $value;
};
}
}
/**
* Converts the given value so that it can be extracted by the hydrator.
*
* @param mixed $value The original value.
* @param array $object The object is optionally provided as context.
* @return mixed Returns the value that should be extracted.
*/
public function extract($value, $object = null)
{
$func = $this->extractFunc;
return $func($value, $object);
}
/**
* Converts the given value so that it can be hydrated by the hydrator.
*
* @param mixed $value The original value.
* @param array $data The whole data is optionally provided as context.
* @return mixed Returns the value that should be hydrated.
*/
public function hydrate($value, $data = null)
{
$func = $this->hydrateFunc;
return $func($value, $data);
}
}
src/Strategy/DateTimeFormatterStrategy.php 0000666 00000003371 13605043205 0014757 0 ustar 00 format = (string) $format;
$this->timezone = $timezone;
}
/**
* {@inheritDoc}
*
* Converts to date time string
*
* @param mixed|DateTime $value
*
* @return mixed|string
*/
public function extract($value)
{
if ($value instanceof DateTime) {
return $value->format($this->format);
}
return $value;
}
/**
* Converts date time string to DateTime instance for injecting to object
*
* {@inheritDoc}
*
* @param mixed|string $value
*
* @return mixed|DateTime
*/
public function hydrate($value)
{
if ($value === '' || $value === null) {
return;
}
if ($this->timezone) {
$hydrated = DateTime::createFromFormat($this->format, $value, $this->timezone);
} else {
$hydrated = DateTime::createFromFormat($this->format, $value);
}
return $hydrated ?: $value;
}
}
src/Strategy/DefaultStrategy.php 0000666 00000001664 13605043205 0012766 0 ustar 00 setValueDelimiter($delimiter);
$this->explodeLimit = ($explodeLimit === null) ? null : (int) $explodeLimit;
}
/**
* Sets the delimiter string that the values will be split upon
*
* @param string $delimiter
* @return self
*/
private function setValueDelimiter($delimiter)
{
if (!is_string($delimiter)) {
throw new Exception\InvalidArgumentException(sprintf(
'%s expects Delimiter to be string, %s provided instead',
__METHOD__,
is_object($delimiter) ? get_class($delimiter) : gettype($delimiter)
));
}
if (empty($delimiter)) {
throw new Exception\InvalidArgumentException('Delimiter cannot be empty.');
}
$this->valueDelimiter = $delimiter;
}
/**
* {@inheritDoc}
*
* Split a string by delimiter
*
* @param string|null $value
*
* @return string[]
*
* @throws Exception\InvalidArgumentException
*/
public function hydrate($value)
{
if (null === $value) {
return [];
}
if (!(is_string($value) || is_numeric($value))) {
throw new Exception\InvalidArgumentException(sprintf(
'%s expects argument 1 to be string, %s provided instead',
__METHOD__,
is_object($value) ? get_class($value) : gettype($value)
));
}
if ($this->explodeLimit !== null) {
return explode($this->valueDelimiter, $value, $this->explodeLimit);
}
return explode($this->valueDelimiter, $value);
}
/**
* {@inheritDoc}
*
* Join array elements with delimiter
*
* @param string[] $value The original value.
*
* @return string|null
*/
public function extract($value)
{
if (!is_array($value)) {
throw new Exception\InvalidArgumentException(sprintf(
'%s expects argument 1 to be array, %s provided instead',
__METHOD__,
is_object($value) ? get_class($value) : gettype($value)
));
}
return empty($value) ? null : implode($this->valueDelimiter, $value);
}
}
src/Strategy/SerializableStrategy.php 0000666 00000006660 13605043205 0014011 0 ustar 00 setSerializer($serializer);
if ($serializerOptions) {
$this->setSerializerOptions($serializerOptions);
}
}
/**
* Serialize the given value so that it can be extracted by the hydrator.
*
* @param mixed $value The original value.
* @return mixed Returns the value that should be extracted.
*/
public function extract($value)
{
$serializer = $this->getSerializer();
return $serializer->serialize($value);
}
/**
* Unserialize the given value so that it can be hydrated by the hydrator.
*
* @param mixed $value The original value.
* @return mixed Returns the value that should be hydrated.
*/
public function hydrate($value)
{
$serializer = $this->getSerializer();
return $serializer->unserialize($value);
}
/**
* Set serializer
*
* @param string|SerializerAdapter $serializer
* @return SerializableStrategy
*/
public function setSerializer($serializer)
{
if (!is_string($serializer) && !$serializer instanceof SerializerAdapter) {
throw new InvalidArgumentException(sprintf(
'%s expects either a string serializer name or Laminas\Serializer\Adapter\AdapterInterface instance; '
. 'received "%s"',
__METHOD__,
(is_object($serializer) ? get_class($serializer) : gettype($serializer))
));
}
$this->serializer = $serializer;
return $this;
}
/**
* Get serializer
*
* @return SerializerAdapter
*/
public function getSerializer()
{
if (is_string($this->serializer)) {
$options = $this->getSerializerOptions();
$this->setSerializer(SerializerFactory::factory($this->serializer, $options));
} elseif (null === $this->serializer) {
$this->setSerializer(SerializerFactory::getDefaultAdapter());
}
return $this->serializer;
}
/**
* Set configuration options for instantiating a serializer adapter
*
* @param mixed $serializerOptions
* @return SerializableStrategy
*/
public function setSerializerOptions($serializerOptions)
{
$this->serializerOptions = $serializerOptions;
return $this;
}
/**
* Get configuration options for instantiating a serializer adapter
*
* @return mixed
*/
public function getSerializerOptions()
{
return $this->serializerOptions;
}
}
src/Strategy/StrategyChain.php 0000666 00000003302 13605043205 0012413 0 ustar 00 extractionStrategies = array_map(
function (StrategyInterface $strategy) {
// this callback is here only to ensure type-safety
return $strategy;
},
$extractionStrategies
);
$this->hydrationStrategies = array_reverse($extractionStrategies);
}
/**
* {@inheritDoc}
*/
public function extract($value)
{
foreach ($this->extractionStrategies as $strategy) {
$value = $strategy->extract($value);
}
return $value;
}
/**
* {@inheritDoc}
*/
public function hydrate($value)
{
foreach ($this->hydrationStrategies as $strategy) {
$value = $strategy->hydrate($value);
}
return $value;
}
}
src/Strategy/StrategyInterface.php 0000666 00000002055 13605043205 0013275 0 ustar 00