Upgrade framework
This commit is contained in:
115
vendor/myclabs/deep-copy/src/DeepCopy/DeepCopy.php
vendored
115
vendor/myclabs/deep-copy/src/DeepCopy/DeepCopy.php
vendored
@@ -2,37 +2,50 @@
|
||||
|
||||
namespace DeepCopy;
|
||||
|
||||
use ArrayObject;
|
||||
use DateInterval;
|
||||
use DateTimeInterface;
|
||||
use DateTimeZone;
|
||||
use DeepCopy\Exception\CloneException;
|
||||
use DeepCopy\Filter\Filter;
|
||||
use DeepCopy\Matcher\Matcher;
|
||||
use DeepCopy\TypeFilter\Spl\SplDoublyLinkedList;
|
||||
use DeepCopy\Reflection\ReflectionHelper;
|
||||
use DeepCopy\TypeFilter\Date\DateIntervalFilter;
|
||||
use DeepCopy\TypeFilter\Spl\ArrayObjectFilter;
|
||||
use DeepCopy\TypeFilter\Spl\SplDoublyLinkedListFilter;
|
||||
use DeepCopy\TypeFilter\TypeFilter;
|
||||
use DeepCopy\TypeMatcher\TypeMatcher;
|
||||
use ReflectionObject;
|
||||
use ReflectionProperty;
|
||||
use DeepCopy\Reflection\ReflectionHelper;
|
||||
use SplDoublyLinkedList;
|
||||
|
||||
/**
|
||||
* DeepCopy
|
||||
* @final
|
||||
*/
|
||||
class DeepCopy
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
* @var object[] List of objects copied.
|
||||
*/
|
||||
private $hashMap = [];
|
||||
|
||||
/**
|
||||
* Filters to apply.
|
||||
* @var array
|
||||
*
|
||||
* @var array Array of ['filter' => Filter, 'matcher' => Matcher] pairs.
|
||||
*/
|
||||
private $filters = [];
|
||||
|
||||
/**
|
||||
* Type Filters to apply.
|
||||
* @var array
|
||||
*
|
||||
* @var array Array of ['filter' => Filter, 'matcher' => Matcher] pairs.
|
||||
*/
|
||||
private $typeFilters = [];
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $skipUncloneable = false;
|
||||
|
||||
/**
|
||||
@@ -48,23 +61,30 @@ class DeepCopy
|
||||
{
|
||||
$this->useCloneMethod = $useCloneMethod;
|
||||
|
||||
$this->addTypeFilter(new SplDoublyLinkedList($this), new TypeMatcher('\SplDoublyLinkedList'));
|
||||
$this->addTypeFilter(new ArrayObjectFilter($this), new TypeMatcher(ArrayObject::class));
|
||||
$this->addTypeFilter(new DateIntervalFilter(), new TypeMatcher(DateInterval::class));
|
||||
$this->addTypeFilter(new SplDoublyLinkedListFilter($this), new TypeMatcher(SplDoublyLinkedList::class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Cloning uncloneable properties won't throw exception.
|
||||
* If enabled, will not throw an exception when coming across an uncloneable property.
|
||||
*
|
||||
* @param $skipUncloneable
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function skipUncloneable($skipUncloneable = true)
|
||||
{
|
||||
$this->skipUncloneable = $skipUncloneable;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a deep copy of the object.
|
||||
* Deep copies the given object.
|
||||
*
|
||||
* @param mixed $object
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function copy($object)
|
||||
@@ -82,6 +102,14 @@ class DeepCopy
|
||||
];
|
||||
}
|
||||
|
||||
public function prependFilter(Filter $filter, Matcher $matcher)
|
||||
{
|
||||
array_unshift($this->filters, [
|
||||
'matcher' => $matcher,
|
||||
'filter' => $filter,
|
||||
]);
|
||||
}
|
||||
|
||||
public function addTypeFilter(TypeFilter $filter, TypeMatcher $matcher)
|
||||
{
|
||||
$this->typeFilters[] = [
|
||||
@@ -90,7 +118,6 @@ class DeepCopy
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
private function recursiveCopy($var)
|
||||
{
|
||||
// Matches Type Filter
|
||||
@@ -102,14 +129,22 @@ class DeepCopy
|
||||
if (is_resource($var)) {
|
||||
return $var;
|
||||
}
|
||||
|
||||
// Array
|
||||
if (is_array($var)) {
|
||||
return $this->copyArray($var);
|
||||
}
|
||||
|
||||
// Scalar
|
||||
if (! is_object($var)) {
|
||||
return $var;
|
||||
}
|
||||
|
||||
// Enum
|
||||
if (PHP_VERSION_ID >= 80100 && enum_exists(get_class($var))) {
|
||||
return $var;
|
||||
}
|
||||
|
||||
// Object
|
||||
return $this->copyObject($var);
|
||||
}
|
||||
@@ -129,8 +164,12 @@ class DeepCopy
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy an object
|
||||
* Copies an object.
|
||||
*
|
||||
* @param object $object
|
||||
*
|
||||
* @throws CloneException
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
private function copyObject($object)
|
||||
@@ -141,29 +180,35 @@ class DeepCopy
|
||||
return $this->hashMap[$objectHash];
|
||||
}
|
||||
|
||||
$reflectedObject = new \ReflectionObject($object);
|
||||
|
||||
if (false === $isCloneable = $reflectedObject->isCloneable() and $this->skipUncloneable) {
|
||||
$this->hashMap[$objectHash] = $object;
|
||||
return $object;
|
||||
}
|
||||
$reflectedObject = new ReflectionObject($object);
|
||||
$isCloneable = $reflectedObject->isCloneable();
|
||||
|
||||
if (false === $isCloneable) {
|
||||
throw new CloneException(sprintf(
|
||||
'Class "%s" is not cloneable.',
|
||||
$reflectedObject->getName()
|
||||
));
|
||||
if ($this->skipUncloneable) {
|
||||
$this->hashMap[$objectHash] = $object;
|
||||
|
||||
return $object;
|
||||
}
|
||||
|
||||
throw new CloneException(
|
||||
sprintf(
|
||||
'The class "%s" is not cloneable.',
|
||||
$reflectedObject->getName()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$newObject = clone $object;
|
||||
$this->hashMap[$objectHash] = $newObject;
|
||||
if ($this->useCloneMethod && $reflectedObject->hasMethod('__clone')) {
|
||||
return $object;
|
||||
}
|
||||
|
||||
if ($newObject instanceof \DateTimeInterface) {
|
||||
if ($this->useCloneMethod && $reflectedObject->hasMethod('__clone')) {
|
||||
return $newObject;
|
||||
}
|
||||
|
||||
if ($newObject instanceof DateTimeInterface || $newObject instanceof DateTimeZone) {
|
||||
return $newObject;
|
||||
}
|
||||
|
||||
foreach (ReflectionHelper::getProperties($reflectedObject) as $property) {
|
||||
$this->copyObjectProperty($newObject, $property);
|
||||
}
|
||||
@@ -193,12 +238,19 @@ class DeepCopy
|
||||
return $this->recursiveCopy($object);
|
||||
}
|
||||
);
|
||||
|
||||
// If a filter matches, we stop processing this property
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$property->setAccessible(true);
|
||||
|
||||
// Ignore uninitialized properties (for PHP >7.4)
|
||||
if (method_exists($property, 'isInitialized') && !$property->isInitialized($object)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$propertyValue = $property->getValue($object);
|
||||
|
||||
// Copy the property
|
||||
@@ -206,10 +258,12 @@ class DeepCopy
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns first filter that matches variable, NULL if no such filter found.
|
||||
* Returns first filter that matches variable, `null` if no such filter found.
|
||||
*
|
||||
* @param array $filterRecords Associative array with 2 members: 'filter' with value of type {@see TypeFilter} and
|
||||
* 'matcher' with value of type {@see TypeMatcher}
|
||||
* @param mixed $var
|
||||
*
|
||||
* @return TypeFilter|null
|
||||
*/
|
||||
private function getFirstMatchedTypeFilter(array $filterRecords, $var)
|
||||
@@ -228,10 +282,13 @@ class DeepCopy
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns first element that matches predicate, NULL if no such element found.
|
||||
* @param array $elements
|
||||
* Returns first element that matches predicate, `null` if no such element found.
|
||||
*
|
||||
* @param array $elements Array of ['filter' => Filter, 'matcher' => Matcher] pairs.
|
||||
* @param callable $predicate Predicate arguments are: element.
|
||||
* @return mixed|null
|
||||
*
|
||||
* @return array|null Associative array with 2 members: 'filter' with value of type {@see TypeFilter} and 'matcher'
|
||||
* with value of type {@see TypeMatcher} or `null`.
|
||||
*/
|
||||
private function first(array $elements, callable $predicate)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user