first commit
This commit is contained in:
		
							
								
								
									
										12
									
								
								vendor/myclabs/deep-copy/.github/FUNDING.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								vendor/myclabs/deep-copy/.github/FUNDING.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,12 @@
 | 
			
		||||
# These are supported funding model platforms
 | 
			
		||||
 | 
			
		||||
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
 | 
			
		||||
patreon: # Replace with a single Patreon username
 | 
			
		||||
open_collective: # Replace with a single Open Collective username
 | 
			
		||||
ko_fi: # Replace with a single Ko-fi username
 | 
			
		||||
tidelift: "packagist/myclabs/deep-copy"
 | 
			
		||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
 | 
			
		||||
liberapay: # Replace with a single Liberapay username
 | 
			
		||||
issuehunt: # Replace with a single IssueHunt username
 | 
			
		||||
otechie: # Replace with a single Otechie username
 | 
			
		||||
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
 | 
			
		||||
							
								
								
									
										101
									
								
								vendor/myclabs/deep-copy/.github/workflows/ci.yaml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								vendor/myclabs/deep-copy/.github/workflows/ci.yaml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,101 @@
 | 
			
		||||
name: "Continuous Integration"
 | 
			
		||||
 | 
			
		||||
on:
 | 
			
		||||
  - pull_request
 | 
			
		||||
  - push
 | 
			
		||||
 | 
			
		||||
env:
 | 
			
		||||
  COMPOSER_ROOT_VERSION: 1.99
 | 
			
		||||
 | 
			
		||||
jobs:
 | 
			
		||||
  composer-json-lint:
 | 
			
		||||
    name: "Lint composer.json"
 | 
			
		||||
 | 
			
		||||
    runs-on: "ubuntu-latest"
 | 
			
		||||
 | 
			
		||||
    strategy:
 | 
			
		||||
      matrix:
 | 
			
		||||
        php-version:
 | 
			
		||||
          - "8.1"
 | 
			
		||||
 | 
			
		||||
    steps:
 | 
			
		||||
      - name: "Checkout"
 | 
			
		||||
        uses: "actions/checkout@v2"
 | 
			
		||||
 | 
			
		||||
      - name: "Install PHP"
 | 
			
		||||
        uses: "shivammathur/setup-php@v2"
 | 
			
		||||
        with:
 | 
			
		||||
          coverage: "none"
 | 
			
		||||
          php-version: "${{ matrix.php-version }}"
 | 
			
		||||
          tools: composer-normalize
 | 
			
		||||
 | 
			
		||||
      - name: "Get composer cache directory"
 | 
			
		||||
        id: composercache
 | 
			
		||||
        run: echo "::set-output name=dir::$(composer config cache-files-dir)"
 | 
			
		||||
 | 
			
		||||
      - name: "Cache dependencies"
 | 
			
		||||
        uses: actions/cache@v2
 | 
			
		||||
        with:
 | 
			
		||||
          path: ${{ steps.composercache.outputs.dir }}
 | 
			
		||||
          key: ${{ runner.os }}-php-${{ matrix.php-version }}-${{ matrix.dependencies }}-composer-${{ hashFiles('**/composer.json') }}
 | 
			
		||||
          restore-keys: ${{ runner.os }}-php-${{ matrix.php-version }}-${{ matrix.dependencies }}-composer-
 | 
			
		||||
 | 
			
		||||
      - name: "Install dependencies"
 | 
			
		||||
        run: "composer update --no-interaction --no-progress"
 | 
			
		||||
 | 
			
		||||
      - name: "Validate composer.json"
 | 
			
		||||
        run: "composer validate --strict"
 | 
			
		||||
 | 
			
		||||
      - name: "Normalize composer.json"
 | 
			
		||||
        run: "composer-normalize --dry-run"
 | 
			
		||||
 | 
			
		||||
  tests:
 | 
			
		||||
    name: "Tests"
 | 
			
		||||
 | 
			
		||||
    runs-on: "ubuntu-latest"
 | 
			
		||||
 | 
			
		||||
    strategy:
 | 
			
		||||
      matrix:
 | 
			
		||||
        php-version:
 | 
			
		||||
          - "7.1"
 | 
			
		||||
          - "7.2"
 | 
			
		||||
          - "7.3"
 | 
			
		||||
          - "7.4"
 | 
			
		||||
          - "8.0"
 | 
			
		||||
          - "8.1"
 | 
			
		||||
        dependencies:
 | 
			
		||||
          - "lowest"
 | 
			
		||||
          - "highest"
 | 
			
		||||
 | 
			
		||||
    steps:
 | 
			
		||||
      - name: "Checkout"
 | 
			
		||||
        uses: "actions/checkout@v2"
 | 
			
		||||
 | 
			
		||||
      - name: "Install PHP"
 | 
			
		||||
        uses: "shivammathur/setup-php@v2"
 | 
			
		||||
        with:
 | 
			
		||||
          php-version: "${{ matrix.php-version }}"
 | 
			
		||||
          ini-values: zend.assertions=1
 | 
			
		||||
 | 
			
		||||
      - name: "Get composer cache directory"
 | 
			
		||||
        id: composercache
 | 
			
		||||
        run: echo "::set-output name=dir::$(composer config cache-files-dir)"
 | 
			
		||||
 | 
			
		||||
      - name: "Cache dependencies"
 | 
			
		||||
        uses: actions/cache@v2
 | 
			
		||||
        with:
 | 
			
		||||
          path: ${{ steps.composercache.outputs.dir }}
 | 
			
		||||
          key: ${{ runner.os }}-php-${{ matrix.php-version }}-${{ matrix.dependencies }}-composer-${{ hashFiles('**/composer.json') }}
 | 
			
		||||
          restore-keys: ${{ runner.os }}-php-${{ matrix.php-version }}-${{ matrix.dependencies }}-composer-
 | 
			
		||||
 | 
			
		||||
      - name: "Install lowest dependencies"
 | 
			
		||||
        if: ${{ matrix.dependencies == 'lowest' }}
 | 
			
		||||
        run: "composer update --no-interaction --no-progress --prefer-lowest"
 | 
			
		||||
 | 
			
		||||
      - name: "Install highest dependencies"
 | 
			
		||||
        if: ${{ matrix.dependencies == 'highest' }}
 | 
			
		||||
        run: "composer update --no-interaction --no-progress"
 | 
			
		||||
 | 
			
		||||
      - name: "Run tests"
 | 
			
		||||
        timeout-minutes: 3
 | 
			
		||||
        run: "vendor/bin/phpunit"
 | 
			
		||||
							
								
								
									
										20
									
								
								vendor/myclabs/deep-copy/LICENSE
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								vendor/myclabs/deep-copy/LICENSE
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,20 @@
 | 
			
		||||
The MIT License (MIT)
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2013 My C-Sense
 | 
			
		||||
 | 
			
		||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
 | 
			
		||||
this software and associated documentation files (the "Software"), to deal in
 | 
			
		||||
the Software without restriction, including without limitation the rights to
 | 
			
		||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 | 
			
		||||
the Software, and to permit persons to whom the Software is furnished to do so,
 | 
			
		||||
subject to the following conditions:
 | 
			
		||||
 | 
			
		||||
The above copyright notice and this permission notice shall be included in all
 | 
			
		||||
copies or substantial portions of the Software.
 | 
			
		||||
 | 
			
		||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 | 
			
		||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 | 
			
		||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 | 
			
		||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 | 
			
		||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
			
		||||
							
								
								
									
										373
									
								
								vendor/myclabs/deep-copy/README.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										373
									
								
								vendor/myclabs/deep-copy/README.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,373 @@
 | 
			
		||||
# DeepCopy
 | 
			
		||||
 | 
			
		||||
DeepCopy helps you create deep copies (clones) of your objects. It is designed to handle cycles in the association graph.
 | 
			
		||||
 | 
			
		||||
[](https://packagist.org/packages/myclabs/deep-copy)
 | 
			
		||||
[](https://github.com/myclabs/DeepCopy/actions)
 | 
			
		||||
 | 
			
		||||
## Table of Contents
 | 
			
		||||
 | 
			
		||||
1. [How](#how)
 | 
			
		||||
1. [Why](#why)
 | 
			
		||||
    1. [Using simply `clone`](#using-simply-clone)
 | 
			
		||||
    1. [Overriding `__clone()`](#overriding-__clone)
 | 
			
		||||
    1. [With `DeepCopy`](#with-deepcopy)
 | 
			
		||||
1. [How it works](#how-it-works)
 | 
			
		||||
1. [Going further](#going-further)
 | 
			
		||||
    1. [Matchers](#matchers)
 | 
			
		||||
        1. [Property name](#property-name)
 | 
			
		||||
        1. [Specific property](#specific-property)
 | 
			
		||||
        1. [Type](#type)
 | 
			
		||||
    1. [Filters](#filters)
 | 
			
		||||
        1. [`SetNullFilter`](#setnullfilter-filter)
 | 
			
		||||
        1. [`KeepFilter`](#keepfilter-filter)
 | 
			
		||||
        1. [`DoctrineCollectionFilter`](#doctrinecollectionfilter-filter)
 | 
			
		||||
        1. [`DoctrineEmptyCollectionFilter`](#doctrineemptycollectionfilter-filter)
 | 
			
		||||
        1. [`DoctrineProxyFilter`](#doctrineproxyfilter-filter)
 | 
			
		||||
        1. [`ReplaceFilter`](#replacefilter-type-filter)
 | 
			
		||||
        1. [`ShallowCopyFilter`](#shallowcopyfilter-type-filter)
 | 
			
		||||
1. [Edge cases](#edge-cases)
 | 
			
		||||
1. [Contributing](#contributing)
 | 
			
		||||
    1. [Tests](#tests)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## How?
 | 
			
		||||
 | 
			
		||||
Install with Composer:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
composer require myclabs/deep-copy
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Use it:
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
use DeepCopy\DeepCopy;
 | 
			
		||||
 | 
			
		||||
$copier = new DeepCopy();
 | 
			
		||||
$myCopy = $copier->copy($myObject);
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Why?
 | 
			
		||||
 | 
			
		||||
- How do you create copies of your objects?
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
$myCopy = clone $myObject;
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
- How do you create **deep** copies of your objects (i.e. copying also all the objects referenced in the properties)?
 | 
			
		||||
 | 
			
		||||
You use [`__clone()`](http://www.php.net/manual/en/language.oop5.cloning.php#object.clone) and implement the behavior
 | 
			
		||||
yourself.
 | 
			
		||||
 | 
			
		||||
- But how do you handle **cycles** in the association graph?
 | 
			
		||||
 | 
			
		||||
Now you're in for a big mess :(
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### Using simply `clone`
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### Overriding `__clone()`
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### With `DeepCopy`
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## How it works
 | 
			
		||||
 | 
			
		||||
DeepCopy recursively traverses all the object's properties and clones them. To avoid cloning the same object twice it
 | 
			
		||||
keeps a hash map of all instances and thus preserves the object graph.
 | 
			
		||||
 | 
			
		||||
To use it:
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
use function DeepCopy\deep_copy;
 | 
			
		||||
 | 
			
		||||
$copy = deep_copy($var);
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Alternatively, you can create your own `DeepCopy` instance to configure it differently for example:
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
use DeepCopy\DeepCopy;
 | 
			
		||||
 | 
			
		||||
$copier = new DeepCopy(true);
 | 
			
		||||
 | 
			
		||||
$copy = $copier->copy($var);
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
You may want to roll your own deep copy function:
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
namespace Acme;
 | 
			
		||||
 | 
			
		||||
use DeepCopy\DeepCopy;
 | 
			
		||||
 | 
			
		||||
function deep_copy($var)
 | 
			
		||||
{
 | 
			
		||||
    static $copier = null;
 | 
			
		||||
    
 | 
			
		||||
    if (null === $copier) {
 | 
			
		||||
        $copier = new DeepCopy(true);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    return $copier->copy($var);
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Going further
 | 
			
		||||
 | 
			
		||||
You can add filters to customize the copy process.
 | 
			
		||||
 | 
			
		||||
The method to add a filter is `DeepCopy\DeepCopy::addFilter($filter, $matcher)`,
 | 
			
		||||
with `$filter` implementing `DeepCopy\Filter\Filter`
 | 
			
		||||
and `$matcher` implementing `DeepCopy\Matcher\Matcher`.
 | 
			
		||||
 | 
			
		||||
We provide some generic filters and matchers.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### Matchers
 | 
			
		||||
 | 
			
		||||
  - `DeepCopy\Matcher` applies on a object attribute.
 | 
			
		||||
  - `DeepCopy\TypeMatcher` applies on any element found in graph, including array elements.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#### Property name
 | 
			
		||||
 | 
			
		||||
The `PropertyNameMatcher` will match a property by its name:
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
use DeepCopy\Matcher\PropertyNameMatcher;
 | 
			
		||||
 | 
			
		||||
// Will apply a filter to any property of any objects named "id"
 | 
			
		||||
$matcher = new PropertyNameMatcher('id');
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#### Specific property
 | 
			
		||||
 | 
			
		||||
The `PropertyMatcher` will match a specific property of a specific class:
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
use DeepCopy\Matcher\PropertyMatcher;
 | 
			
		||||
 | 
			
		||||
// Will apply a filter to the property "id" of any objects of the class "MyClass"
 | 
			
		||||
$matcher = new PropertyMatcher('MyClass', 'id');
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#### Type
 | 
			
		||||
 | 
			
		||||
The `TypeMatcher` will match any element by its type (instance of a class or any value that could be parameter of
 | 
			
		||||
[gettype()](http://php.net/manual/en/function.gettype.php) function):
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
use DeepCopy\TypeMatcher\TypeMatcher;
 | 
			
		||||
 | 
			
		||||
// Will apply a filter to any object that is an instance of Doctrine\Common\Collections\Collection
 | 
			
		||||
$matcher = new TypeMatcher('Doctrine\Common\Collections\Collection');
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### Filters
 | 
			
		||||
 | 
			
		||||
- `DeepCopy\Filter` applies a transformation to the object attribute matched by `DeepCopy\Matcher`
 | 
			
		||||
- `DeepCopy\TypeFilter` applies a transformation to any element matched by `DeepCopy\TypeMatcher`
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#### `SetNullFilter` (filter)
 | 
			
		||||
 | 
			
		||||
Let's say for example that you are copying a database record (or a Doctrine entity), so you want the copy not to have
 | 
			
		||||
any ID:
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
use DeepCopy\DeepCopy;
 | 
			
		||||
use DeepCopy\Filter\SetNullFilter;
 | 
			
		||||
use DeepCopy\Matcher\PropertyNameMatcher;
 | 
			
		||||
 | 
			
		||||
$object = MyClass::load(123);
 | 
			
		||||
echo $object->id; // 123
 | 
			
		||||
 | 
			
		||||
$copier = new DeepCopy();
 | 
			
		||||
$copier->addFilter(new SetNullFilter(), new PropertyNameMatcher('id'));
 | 
			
		||||
 | 
			
		||||
$copy = $copier->copy($object);
 | 
			
		||||
 | 
			
		||||
echo $copy->id; // null
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#### `KeepFilter` (filter)
 | 
			
		||||
 | 
			
		||||
If you want a property to remain untouched (for example, an association to an object):
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
use DeepCopy\DeepCopy;
 | 
			
		||||
use DeepCopy\Filter\KeepFilter;
 | 
			
		||||
use DeepCopy\Matcher\PropertyMatcher;
 | 
			
		||||
 | 
			
		||||
$copier = new DeepCopy();
 | 
			
		||||
$copier->addFilter(new KeepFilter(), new PropertyMatcher('MyClass', 'category'));
 | 
			
		||||
 | 
			
		||||
$copy = $copier->copy($object);
 | 
			
		||||
// $copy->category has not been touched
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#### `DoctrineCollectionFilter` (filter)
 | 
			
		||||
 | 
			
		||||
If you use Doctrine and want to copy an entity, you will need to use the `DoctrineCollectionFilter`:
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
use DeepCopy\DeepCopy;
 | 
			
		||||
use DeepCopy\Filter\Doctrine\DoctrineCollectionFilter;
 | 
			
		||||
use DeepCopy\Matcher\PropertyTypeMatcher;
 | 
			
		||||
 | 
			
		||||
$copier = new DeepCopy();
 | 
			
		||||
$copier->addFilter(new DoctrineCollectionFilter(), new PropertyTypeMatcher('Doctrine\Common\Collections\Collection'));
 | 
			
		||||
 | 
			
		||||
$copy = $copier->copy($object);
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#### `DoctrineEmptyCollectionFilter` (filter)
 | 
			
		||||
 | 
			
		||||
If you use Doctrine and want to copy an entity who contains a `Collection` that you want to be reset, you can use the
 | 
			
		||||
`DoctrineEmptyCollectionFilter`
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
use DeepCopy\DeepCopy;
 | 
			
		||||
use DeepCopy\Filter\Doctrine\DoctrineEmptyCollectionFilter;
 | 
			
		||||
use DeepCopy\Matcher\PropertyMatcher;
 | 
			
		||||
 | 
			
		||||
$copier = new DeepCopy();
 | 
			
		||||
$copier->addFilter(new DoctrineEmptyCollectionFilter(), new PropertyMatcher('MyClass', 'myProperty'));
 | 
			
		||||
 | 
			
		||||
$copy = $copier->copy($object);
 | 
			
		||||
 | 
			
		||||
// $copy->myProperty will return an empty collection
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#### `DoctrineProxyFilter` (filter)
 | 
			
		||||
 | 
			
		||||
If you use Doctrine and use cloning on lazy loaded entities, you might encounter errors mentioning missing fields on a
 | 
			
		||||
Doctrine proxy class (...\\\_\_CG\_\_\Proxy).
 | 
			
		||||
You can use the `DoctrineProxyFilter` to load the actual entity behind the Doctrine proxy class.
 | 
			
		||||
**Make sure, though, to put this as one of your very first filters in the filter chain so that the entity is loaded
 | 
			
		||||
before other filters are applied!**
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
use DeepCopy\DeepCopy;
 | 
			
		||||
use DeepCopy\Filter\Doctrine\DoctrineProxyFilter;
 | 
			
		||||
use DeepCopy\Matcher\Doctrine\DoctrineProxyMatcher;
 | 
			
		||||
 | 
			
		||||
$copier = new DeepCopy();
 | 
			
		||||
$copier->addFilter(new DoctrineProxyFilter(), new DoctrineProxyMatcher());
 | 
			
		||||
 | 
			
		||||
$copy = $copier->copy($object);
 | 
			
		||||
 | 
			
		||||
// $copy should now contain a clone of all entities, including those that were not yet fully loaded.
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#### `ReplaceFilter` (type filter)
 | 
			
		||||
 | 
			
		||||
1. If you want to replace the value of a property:
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
use DeepCopy\DeepCopy;
 | 
			
		||||
use DeepCopy\Filter\ReplaceFilter;
 | 
			
		||||
use DeepCopy\Matcher\PropertyMatcher;
 | 
			
		||||
 | 
			
		||||
$copier = new DeepCopy();
 | 
			
		||||
$callback = function ($currentValue) {
 | 
			
		||||
  return $currentValue . ' (copy)'
 | 
			
		||||
};
 | 
			
		||||
$copier->addFilter(new ReplaceFilter($callback), new PropertyMatcher('MyClass', 'title'));
 | 
			
		||||
 | 
			
		||||
$copy = $copier->copy($object);
 | 
			
		||||
 | 
			
		||||
// $copy->title will contain the data returned by the callback, e.g. 'The title (copy)'
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
2. If you want to replace whole element:
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
use DeepCopy\DeepCopy;
 | 
			
		||||
use DeepCopy\TypeFilter\ReplaceFilter;
 | 
			
		||||
use DeepCopy\TypeMatcher\TypeMatcher;
 | 
			
		||||
 | 
			
		||||
$copier = new DeepCopy();
 | 
			
		||||
$callback = function (MyClass $myClass) {
 | 
			
		||||
  return get_class($myClass);
 | 
			
		||||
};
 | 
			
		||||
$copier->addTypeFilter(new ReplaceFilter($callback), new TypeMatcher('MyClass'));
 | 
			
		||||
 | 
			
		||||
$copy = $copier->copy([new MyClass, 'some string', new MyClass]);
 | 
			
		||||
 | 
			
		||||
// $copy will contain ['MyClass', 'some string', 'MyClass']
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
The `$callback` parameter of the `ReplaceFilter` constructor accepts any PHP callable.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#### `ShallowCopyFilter` (type filter)
 | 
			
		||||
 | 
			
		||||
Stop *DeepCopy* from recursively copying element, using standard `clone` instead:
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
use DeepCopy\DeepCopy;
 | 
			
		||||
use DeepCopy\TypeFilter\ShallowCopyFilter;
 | 
			
		||||
use DeepCopy\TypeMatcher\TypeMatcher;
 | 
			
		||||
use Mockery as m;
 | 
			
		||||
 | 
			
		||||
$this->deepCopy = new DeepCopy();
 | 
			
		||||
$this->deepCopy->addTypeFilter(
 | 
			
		||||
	new ShallowCopyFilter,
 | 
			
		||||
	new TypeMatcher(m\MockInterface::class)
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
$myServiceWithMocks = new MyService(m::mock(MyDependency1::class), m::mock(MyDependency2::class));
 | 
			
		||||
// All mocks will be just cloned, not deep copied
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Edge cases
 | 
			
		||||
 | 
			
		||||
The following structures cannot be deep-copied with PHP Reflection. As a result they are shallow cloned and filters are
 | 
			
		||||
not applied. There is two ways for you to handle them:
 | 
			
		||||
 | 
			
		||||
- Implement your own `__clone()` method
 | 
			
		||||
- Use a filter with a type matcher
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Contributing
 | 
			
		||||
 | 
			
		||||
DeepCopy is distributed under the MIT license.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### Tests
 | 
			
		||||
 | 
			
		||||
Running the tests is simple:
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
vendor/bin/phpunit
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Support
 | 
			
		||||
 | 
			
		||||
Get professional support via [the Tidelift Subscription](https://tidelift.com/subscription/pkg/packagist-myclabs-deep-copy?utm_source=packagist-myclabs-deep-copy&utm_medium=referral&utm_campaign=readme).
 | 
			
		||||
							
								
								
									
										42
									
								
								vendor/myclabs/deep-copy/composer.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								vendor/myclabs/deep-copy/composer.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,42 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "myclabs/deep-copy",
 | 
			
		||||
    "description": "Create deep copies (clones) of your objects",
 | 
			
		||||
    "license": "MIT",
 | 
			
		||||
    "type": "library",
 | 
			
		||||
    "keywords": [
 | 
			
		||||
        "clone",
 | 
			
		||||
        "copy",
 | 
			
		||||
        "duplicate",
 | 
			
		||||
        "object",
 | 
			
		||||
        "object graph"
 | 
			
		||||
    ],
 | 
			
		||||
    "require": {
 | 
			
		||||
        "php": "^7.1 || ^8.0"
 | 
			
		||||
    },
 | 
			
		||||
    "require-dev": {
 | 
			
		||||
        "doctrine/collections": "^1.6.8",
 | 
			
		||||
        "doctrine/common": "^2.13.3 || ^3.2.2",
 | 
			
		||||
        "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13"
 | 
			
		||||
    },
 | 
			
		||||
    "conflict": {
 | 
			
		||||
        "doctrine/collections": "<1.6.8",
 | 
			
		||||
        "doctrine/common": "<2.13.3 || >=3,<3.2.2"
 | 
			
		||||
    },
 | 
			
		||||
    "autoload": {
 | 
			
		||||
        "psr-4": {
 | 
			
		||||
            "DeepCopy\\": "src/DeepCopy/"
 | 
			
		||||
        },
 | 
			
		||||
        "files": [
 | 
			
		||||
            "src/DeepCopy/deep_copy.php"
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    "autoload-dev": {
 | 
			
		||||
        "psr-4": {
 | 
			
		||||
            "DeepCopy\\": "fixtures/",
 | 
			
		||||
            "DeepCopyTest\\": "tests/DeepCopyTest/"
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    "config": {
 | 
			
		||||
        "sort-packages": true
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										303
									
								
								vendor/myclabs/deep-copy/src/DeepCopy/DeepCopy.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										303
									
								
								vendor/myclabs/deep-copy/src/DeepCopy/DeepCopy.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,303 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DeepCopy;
 | 
			
		||||
 | 
			
		||||
use ArrayObject;
 | 
			
		||||
use DateInterval;
 | 
			
		||||
use DateTimeInterface;
 | 
			
		||||
use DateTimeZone;
 | 
			
		||||
use DeepCopy\Exception\CloneException;
 | 
			
		||||
use DeepCopy\Filter\Filter;
 | 
			
		||||
use DeepCopy\Matcher\Matcher;
 | 
			
		||||
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 SplDoublyLinkedList;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @final
 | 
			
		||||
 */
 | 
			
		||||
class DeepCopy
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * @var object[] List of objects copied.
 | 
			
		||||
     */
 | 
			
		||||
    private $hashMap = [];
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Filters to apply.
 | 
			
		||||
     *
 | 
			
		||||
     * @var array Array of ['filter' => Filter, 'matcher' => Matcher] pairs.
 | 
			
		||||
     */
 | 
			
		||||
    private $filters = [];
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Type Filters to apply.
 | 
			
		||||
     *
 | 
			
		||||
     * @var array Array of ['filter' => Filter, 'matcher' => Matcher] pairs.
 | 
			
		||||
     */
 | 
			
		||||
    private $typeFilters = [];
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @var bool
 | 
			
		||||
     */
 | 
			
		||||
    private $skipUncloneable = false;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @var bool
 | 
			
		||||
     */
 | 
			
		||||
    private $useCloneMethod;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @param bool $useCloneMethod   If set to true, when an object implements the __clone() function, it will be used
 | 
			
		||||
     *                               instead of the regular deep cloning.
 | 
			
		||||
     */
 | 
			
		||||
    public function __construct($useCloneMethod = false)
 | 
			
		||||
    {
 | 
			
		||||
        $this->useCloneMethod = $useCloneMethod;
 | 
			
		||||
 | 
			
		||||
        $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));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Deep copies the given object.
 | 
			
		||||
     *
 | 
			
		||||
     * @param mixed $object
 | 
			
		||||
     *
 | 
			
		||||
     * @return mixed
 | 
			
		||||
     */
 | 
			
		||||
    public function copy($object)
 | 
			
		||||
    {
 | 
			
		||||
        $this->hashMap = [];
 | 
			
		||||
 | 
			
		||||
        return $this->recursiveCopy($object);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function addFilter(Filter $filter, Matcher $matcher)
 | 
			
		||||
    {
 | 
			
		||||
        $this->filters[] = [
 | 
			
		||||
            'matcher' => $matcher,
 | 
			
		||||
            'filter'  => $filter,
 | 
			
		||||
        ];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function prependFilter(Filter $filter, Matcher $matcher)
 | 
			
		||||
    {
 | 
			
		||||
        array_unshift($this->filters, [
 | 
			
		||||
            'matcher' => $matcher,
 | 
			
		||||
            'filter'  => $filter,
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function addTypeFilter(TypeFilter $filter, TypeMatcher $matcher)
 | 
			
		||||
    {
 | 
			
		||||
        $this->typeFilters[] = [
 | 
			
		||||
            'matcher' => $matcher,
 | 
			
		||||
            'filter'  => $filter,
 | 
			
		||||
        ];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function recursiveCopy($var)
 | 
			
		||||
    {
 | 
			
		||||
        // Matches Type Filter
 | 
			
		||||
        if ($filter = $this->getFirstMatchedTypeFilter($this->typeFilters, $var)) {
 | 
			
		||||
            return $filter->apply($var);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Resource
 | 
			
		||||
        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);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Copy an array
 | 
			
		||||
     * @param array $array
 | 
			
		||||
     * @return array
 | 
			
		||||
     */
 | 
			
		||||
    private function copyArray(array $array)
 | 
			
		||||
    {
 | 
			
		||||
        foreach ($array as $key => $value) {
 | 
			
		||||
            $array[$key] = $this->recursiveCopy($value);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $array;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Copies an object.
 | 
			
		||||
     *
 | 
			
		||||
     * @param object $object
 | 
			
		||||
     *
 | 
			
		||||
     * @throws CloneException
 | 
			
		||||
     *
 | 
			
		||||
     * @return object
 | 
			
		||||
     */
 | 
			
		||||
    private function copyObject($object)
 | 
			
		||||
    {
 | 
			
		||||
        $objectHash = spl_object_hash($object);
 | 
			
		||||
 | 
			
		||||
        if (isset($this->hashMap[$objectHash])) {
 | 
			
		||||
            return $this->hashMap[$objectHash];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $reflectedObject = new ReflectionObject($object);
 | 
			
		||||
        $isCloneable = $reflectedObject->isCloneable();
 | 
			
		||||
 | 
			
		||||
        if (false === $isCloneable) {
 | 
			
		||||
            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 $newObject;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if ($newObject instanceof DateTimeInterface || $newObject instanceof DateTimeZone) {
 | 
			
		||||
            return $newObject;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        foreach (ReflectionHelper::getProperties($reflectedObject) as $property) {
 | 
			
		||||
            $this->copyObjectProperty($newObject, $property);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $newObject;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function copyObjectProperty($object, ReflectionProperty $property)
 | 
			
		||||
    {
 | 
			
		||||
        // Ignore static properties
 | 
			
		||||
        if ($property->isStatic()) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Apply the filters
 | 
			
		||||
        foreach ($this->filters as $item) {
 | 
			
		||||
            /** @var Matcher $matcher */
 | 
			
		||||
            $matcher = $item['matcher'];
 | 
			
		||||
            /** @var Filter $filter */
 | 
			
		||||
            $filter = $item['filter'];
 | 
			
		||||
 | 
			
		||||
            if ($matcher->matches($object, $property->getName())) {
 | 
			
		||||
                $filter->apply(
 | 
			
		||||
                    $object,
 | 
			
		||||
                    $property->getName(),
 | 
			
		||||
                    function ($object) {
 | 
			
		||||
                        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
 | 
			
		||||
        $property->setValue($object, $this->recursiveCopy($propertyValue));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 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)
 | 
			
		||||
    {
 | 
			
		||||
        $matched = $this->first(
 | 
			
		||||
            $filterRecords,
 | 
			
		||||
            function (array $record) use ($var) {
 | 
			
		||||
                /* @var TypeMatcher $matcher */
 | 
			
		||||
                $matcher = $record['matcher'];
 | 
			
		||||
 | 
			
		||||
                return $matcher->matches($var);
 | 
			
		||||
            }
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        return isset($matched) ? $matched['filter'] : null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 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 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)
 | 
			
		||||
    {
 | 
			
		||||
        foreach ($elements as $element) {
 | 
			
		||||
            if (call_user_func($predicate, $element)) {
 | 
			
		||||
                return $element;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										9
									
								
								vendor/myclabs/deep-copy/src/DeepCopy/Exception/CloneException.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								vendor/myclabs/deep-copy/src/DeepCopy/Exception/CloneException.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,9 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DeepCopy\Exception;
 | 
			
		||||
 | 
			
		||||
use UnexpectedValueException;
 | 
			
		||||
 | 
			
		||||
class CloneException extends UnexpectedValueException
 | 
			
		||||
{
 | 
			
		||||
} 
 | 
			
		||||
							
								
								
									
										9
									
								
								vendor/myclabs/deep-copy/src/DeepCopy/Exception/PropertyException.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								vendor/myclabs/deep-copy/src/DeepCopy/Exception/PropertyException.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,9 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DeepCopy\Exception;
 | 
			
		||||
 | 
			
		||||
use ReflectionException;
 | 
			
		||||
 | 
			
		||||
class PropertyException extends ReflectionException
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										33
									
								
								vendor/myclabs/deep-copy/src/DeepCopy/Filter/Doctrine/DoctrineCollectionFilter.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								vendor/myclabs/deep-copy/src/DeepCopy/Filter/Doctrine/DoctrineCollectionFilter.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,33 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DeepCopy\Filter\Doctrine;
 | 
			
		||||
 | 
			
		||||
use DeepCopy\Filter\Filter;
 | 
			
		||||
use DeepCopy\Reflection\ReflectionHelper;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @final
 | 
			
		||||
 */
 | 
			
		||||
class DoctrineCollectionFilter implements Filter
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * Copies the object property doctrine collection.
 | 
			
		||||
     *
 | 
			
		||||
     * {@inheritdoc}
 | 
			
		||||
     */
 | 
			
		||||
    public function apply($object, $property, $objectCopier)
 | 
			
		||||
    {
 | 
			
		||||
        $reflectionProperty = ReflectionHelper::getProperty($object, $property);
 | 
			
		||||
 | 
			
		||||
        $reflectionProperty->setAccessible(true);
 | 
			
		||||
        $oldCollection = $reflectionProperty->getValue($object);
 | 
			
		||||
 | 
			
		||||
        $newCollection = $oldCollection->map(
 | 
			
		||||
            function ($item) use ($objectCopier) {
 | 
			
		||||
                return $objectCopier($item);
 | 
			
		||||
            }
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        $reflectionProperty->setValue($object, $newCollection);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										28
									
								
								vendor/myclabs/deep-copy/src/DeepCopy/Filter/Doctrine/DoctrineEmptyCollectionFilter.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								vendor/myclabs/deep-copy/src/DeepCopy/Filter/Doctrine/DoctrineEmptyCollectionFilter.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,28 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DeepCopy\Filter\Doctrine;
 | 
			
		||||
 | 
			
		||||
use DeepCopy\Filter\Filter;
 | 
			
		||||
use DeepCopy\Reflection\ReflectionHelper;
 | 
			
		||||
use Doctrine\Common\Collections\ArrayCollection;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @final
 | 
			
		||||
 */
 | 
			
		||||
class DoctrineEmptyCollectionFilter implements Filter
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * Sets the object property to an empty doctrine collection.
 | 
			
		||||
     *
 | 
			
		||||
     * @param object   $object
 | 
			
		||||
     * @param string   $property
 | 
			
		||||
     * @param callable $objectCopier
 | 
			
		||||
     */
 | 
			
		||||
    public function apply($object, $property, $objectCopier)
 | 
			
		||||
    {
 | 
			
		||||
        $reflectionProperty = ReflectionHelper::getProperty($object, $property);
 | 
			
		||||
        $reflectionProperty->setAccessible(true);
 | 
			
		||||
 | 
			
		||||
        $reflectionProperty->setValue($object, new ArrayCollection());
 | 
			
		||||
    }
 | 
			
		||||
} 
 | 
			
		||||
							
								
								
									
										22
									
								
								vendor/myclabs/deep-copy/src/DeepCopy/Filter/Doctrine/DoctrineProxyFilter.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								vendor/myclabs/deep-copy/src/DeepCopy/Filter/Doctrine/DoctrineProxyFilter.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,22 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DeepCopy\Filter\Doctrine;
 | 
			
		||||
 | 
			
		||||
use DeepCopy\Filter\Filter;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @final
 | 
			
		||||
 */
 | 
			
		||||
class DoctrineProxyFilter implements Filter
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * Triggers the magic method __load() on a Doctrine Proxy class to load the
 | 
			
		||||
     * actual entity from the database.
 | 
			
		||||
     *
 | 
			
		||||
     * {@inheritdoc}
 | 
			
		||||
     */
 | 
			
		||||
    public function apply($object, $property, $objectCopier)
 | 
			
		||||
    {
 | 
			
		||||
        $object->__load();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										18
									
								
								vendor/myclabs/deep-copy/src/DeepCopy/Filter/Filter.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								vendor/myclabs/deep-copy/src/DeepCopy/Filter/Filter.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,18 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DeepCopy\Filter;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Filter to apply to a property while copying an object
 | 
			
		||||
 */
 | 
			
		||||
interface Filter
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * Applies the filter to the object.
 | 
			
		||||
     *
 | 
			
		||||
     * @param object   $object
 | 
			
		||||
     * @param string   $property
 | 
			
		||||
     * @param callable $objectCopier
 | 
			
		||||
     */
 | 
			
		||||
    public function apply($object, $property, $objectCopier);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										16
									
								
								vendor/myclabs/deep-copy/src/DeepCopy/Filter/KeepFilter.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								vendor/myclabs/deep-copy/src/DeepCopy/Filter/KeepFilter.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,16 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DeepCopy\Filter;
 | 
			
		||||
 | 
			
		||||
class KeepFilter implements Filter
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * Keeps the value of the object property.
 | 
			
		||||
     *
 | 
			
		||||
     * {@inheritdoc}
 | 
			
		||||
     */
 | 
			
		||||
    public function apply($object, $property, $objectCopier)
 | 
			
		||||
    {
 | 
			
		||||
        // Nothing to do
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										39
									
								
								vendor/myclabs/deep-copy/src/DeepCopy/Filter/ReplaceFilter.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								vendor/myclabs/deep-copy/src/DeepCopy/Filter/ReplaceFilter.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,39 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DeepCopy\Filter;
 | 
			
		||||
 | 
			
		||||
use DeepCopy\Reflection\ReflectionHelper;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @final
 | 
			
		||||
 */
 | 
			
		||||
class ReplaceFilter implements Filter
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * @var callable
 | 
			
		||||
     */
 | 
			
		||||
    protected $callback;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @param callable $callable Will be called to get the new value for each property to replace
 | 
			
		||||
     */
 | 
			
		||||
    public function __construct(callable $callable)
 | 
			
		||||
    {
 | 
			
		||||
        $this->callback = $callable;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Replaces the object property by the result of the callback called with the object property.
 | 
			
		||||
     *
 | 
			
		||||
     * {@inheritdoc}
 | 
			
		||||
     */
 | 
			
		||||
    public function apply($object, $property, $objectCopier)
 | 
			
		||||
    {
 | 
			
		||||
        $reflectionProperty = ReflectionHelper::getProperty($object, $property);
 | 
			
		||||
        $reflectionProperty->setAccessible(true);
 | 
			
		||||
 | 
			
		||||
        $value = call_user_func($this->callback, $reflectionProperty->getValue($object));
 | 
			
		||||
 | 
			
		||||
        $reflectionProperty->setValue($object, $value);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										24
									
								
								vendor/myclabs/deep-copy/src/DeepCopy/Filter/SetNullFilter.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								vendor/myclabs/deep-copy/src/DeepCopy/Filter/SetNullFilter.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,24 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DeepCopy\Filter;
 | 
			
		||||
 | 
			
		||||
use DeepCopy\Reflection\ReflectionHelper;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @final
 | 
			
		||||
 */
 | 
			
		||||
class SetNullFilter implements Filter
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * Sets the object property to null.
 | 
			
		||||
     *
 | 
			
		||||
     * {@inheritdoc}
 | 
			
		||||
     */
 | 
			
		||||
    public function apply($object, $property, $objectCopier)
 | 
			
		||||
    {
 | 
			
		||||
        $reflectionProperty = ReflectionHelper::getProperty($object, $property);
 | 
			
		||||
 | 
			
		||||
        $reflectionProperty->setAccessible(true);
 | 
			
		||||
        $reflectionProperty->setValue($object, null);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										22
									
								
								vendor/myclabs/deep-copy/src/DeepCopy/Matcher/Doctrine/DoctrineProxyMatcher.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								vendor/myclabs/deep-copy/src/DeepCopy/Matcher/Doctrine/DoctrineProxyMatcher.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,22 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DeepCopy\Matcher\Doctrine;
 | 
			
		||||
 | 
			
		||||
use DeepCopy\Matcher\Matcher;
 | 
			
		||||
use Doctrine\Persistence\Proxy;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @final
 | 
			
		||||
 */
 | 
			
		||||
class DoctrineProxyMatcher implements Matcher
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * Matches a Doctrine Proxy class.
 | 
			
		||||
     *
 | 
			
		||||
     * {@inheritdoc}
 | 
			
		||||
     */
 | 
			
		||||
    public function matches($object, $property)
 | 
			
		||||
    {
 | 
			
		||||
        return $object instanceof Proxy;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										14
									
								
								vendor/myclabs/deep-copy/src/DeepCopy/Matcher/Matcher.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								vendor/myclabs/deep-copy/src/DeepCopy/Matcher/Matcher.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,14 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DeepCopy\Matcher;
 | 
			
		||||
 | 
			
		||||
interface Matcher
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * @param object $object
 | 
			
		||||
     * @param string $property
 | 
			
		||||
     *
 | 
			
		||||
     * @return boolean
 | 
			
		||||
     */
 | 
			
		||||
    public function matches($object, $property);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										39
									
								
								vendor/myclabs/deep-copy/src/DeepCopy/Matcher/PropertyMatcher.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								vendor/myclabs/deep-copy/src/DeepCopy/Matcher/PropertyMatcher.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,39 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DeepCopy\Matcher;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @final
 | 
			
		||||
 */
 | 
			
		||||
class PropertyMatcher implements Matcher
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * @var string
 | 
			
		||||
     */
 | 
			
		||||
    private $class;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @var string
 | 
			
		||||
     */
 | 
			
		||||
    private $property;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @param string $class    Class name
 | 
			
		||||
     * @param string $property Property name
 | 
			
		||||
     */
 | 
			
		||||
    public function __construct($class, $property)
 | 
			
		||||
    {
 | 
			
		||||
        $this->class = $class;
 | 
			
		||||
        $this->property = $property;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Matches a specific property of a specific class.
 | 
			
		||||
     *
 | 
			
		||||
     * {@inheritdoc}
 | 
			
		||||
     */
 | 
			
		||||
    public function matches($object, $property)
 | 
			
		||||
    {
 | 
			
		||||
        return ($object instanceof $this->class) && $property == $this->property;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										32
									
								
								vendor/myclabs/deep-copy/src/DeepCopy/Matcher/PropertyNameMatcher.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								vendor/myclabs/deep-copy/src/DeepCopy/Matcher/PropertyNameMatcher.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,32 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DeepCopy\Matcher;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @final
 | 
			
		||||
 */
 | 
			
		||||
class PropertyNameMatcher implements Matcher
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * @var string
 | 
			
		||||
     */
 | 
			
		||||
    private $property;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @param string $property Property name
 | 
			
		||||
     */
 | 
			
		||||
    public function __construct($property)
 | 
			
		||||
    {
 | 
			
		||||
        $this->property = $property;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Matches a property by its name.
 | 
			
		||||
     *
 | 
			
		||||
     * {@inheritdoc}
 | 
			
		||||
     */
 | 
			
		||||
    public function matches($object, $property)
 | 
			
		||||
    {
 | 
			
		||||
        return $property == $this->property;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										52
									
								
								vendor/myclabs/deep-copy/src/DeepCopy/Matcher/PropertyTypeMatcher.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								vendor/myclabs/deep-copy/src/DeepCopy/Matcher/PropertyTypeMatcher.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,52 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DeepCopy\Matcher;
 | 
			
		||||
 | 
			
		||||
use DeepCopy\Reflection\ReflectionHelper;
 | 
			
		||||
use ReflectionException;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Matches a property by its type.
 | 
			
		||||
 *
 | 
			
		||||
 * It is recommended to use {@see DeepCopy\TypeFilter\TypeFilter} instead, as it applies on all occurrences
 | 
			
		||||
 * of given type in copied context (eg. array elements), not just on object properties.
 | 
			
		||||
 *
 | 
			
		||||
 * @final
 | 
			
		||||
 */
 | 
			
		||||
class PropertyTypeMatcher implements Matcher
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * @var string
 | 
			
		||||
     */
 | 
			
		||||
    private $propertyType;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @param string $propertyType Property type
 | 
			
		||||
     */
 | 
			
		||||
    public function __construct($propertyType)
 | 
			
		||||
    {
 | 
			
		||||
        $this->propertyType = $propertyType;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * {@inheritdoc}
 | 
			
		||||
     */
 | 
			
		||||
    public function matches($object, $property)
 | 
			
		||||
    {
 | 
			
		||||
        try {
 | 
			
		||||
            $reflectionProperty = ReflectionHelper::getProperty($object, $property);
 | 
			
		||||
        } catch (ReflectionException $exception) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $reflectionProperty->setAccessible(true);
 | 
			
		||||
 | 
			
		||||
        // Uninitialized properties (for PHP >7.4)
 | 
			
		||||
        if (method_exists($reflectionProperty, 'isInitialized') && !$reflectionProperty->isInitialized($object)) {
 | 
			
		||||
            // null instanceof $this->propertyType
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $reflectionProperty->getValue($object) instanceof $this->propertyType;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										78
									
								
								vendor/myclabs/deep-copy/src/DeepCopy/Reflection/ReflectionHelper.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								vendor/myclabs/deep-copy/src/DeepCopy/Reflection/ReflectionHelper.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,78 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DeepCopy\Reflection;
 | 
			
		||||
 | 
			
		||||
use DeepCopy\Exception\PropertyException;
 | 
			
		||||
use ReflectionClass;
 | 
			
		||||
use ReflectionException;
 | 
			
		||||
use ReflectionObject;
 | 
			
		||||
use ReflectionProperty;
 | 
			
		||||
 | 
			
		||||
class ReflectionHelper
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * Retrieves all properties (including private ones), from object and all its ancestors.
 | 
			
		||||
     *
 | 
			
		||||
     * Standard \ReflectionClass->getProperties() does not return private properties from ancestor classes.
 | 
			
		||||
     *
 | 
			
		||||
     * @author muratyaman@gmail.com
 | 
			
		||||
     * @see http://php.net/manual/en/reflectionclass.getproperties.php
 | 
			
		||||
     *
 | 
			
		||||
     * @param ReflectionClass $ref
 | 
			
		||||
     *
 | 
			
		||||
     * @return ReflectionProperty[]
 | 
			
		||||
     */
 | 
			
		||||
    public static function getProperties(ReflectionClass $ref)
 | 
			
		||||
    {
 | 
			
		||||
        $props = $ref->getProperties();
 | 
			
		||||
        $propsArr = array();
 | 
			
		||||
 | 
			
		||||
        foreach ($props as $prop) {
 | 
			
		||||
            $propertyName = $prop->getName();
 | 
			
		||||
            $propsArr[$propertyName] = $prop;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if ($parentClass = $ref->getParentClass()) {
 | 
			
		||||
            $parentPropsArr = self::getProperties($parentClass);
 | 
			
		||||
            foreach ($propsArr as $key => $property) {
 | 
			
		||||
                $parentPropsArr[$key] = $property;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return $parentPropsArr;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $propsArr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Retrieves property by name from object and all its ancestors.
 | 
			
		||||
     *
 | 
			
		||||
     * @param object|string $object
 | 
			
		||||
     * @param string $name
 | 
			
		||||
     *
 | 
			
		||||
     * @throws PropertyException
 | 
			
		||||
     * @throws ReflectionException
 | 
			
		||||
     *
 | 
			
		||||
     * @return ReflectionProperty
 | 
			
		||||
     */
 | 
			
		||||
    public static function getProperty($object, $name)
 | 
			
		||||
    {
 | 
			
		||||
        $reflection = is_object($object) ? new ReflectionObject($object) : new ReflectionClass($object);
 | 
			
		||||
 | 
			
		||||
        if ($reflection->hasProperty($name)) {
 | 
			
		||||
            return $reflection->getProperty($name);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if ($parentClass = $reflection->getParentClass()) {
 | 
			
		||||
            return self::getProperty($parentClass->getName(), $name);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        throw new PropertyException(
 | 
			
		||||
            sprintf(
 | 
			
		||||
                'The class "%s" doesn\'t have a property with the given name: "%s".',
 | 
			
		||||
                is_object($object) ? get_class($object) : $object,
 | 
			
		||||
                $name
 | 
			
		||||
            )
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										33
									
								
								vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/Date/DateIntervalFilter.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/Date/DateIntervalFilter.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,33 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DeepCopy\TypeFilter\Date;
 | 
			
		||||
 | 
			
		||||
use DateInterval;
 | 
			
		||||
use DeepCopy\TypeFilter\TypeFilter;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @final
 | 
			
		||||
 *
 | 
			
		||||
 * @deprecated Will be removed in 2.0. This filter will no longer be necessary in PHP 7.1+.
 | 
			
		||||
 */
 | 
			
		||||
class DateIntervalFilter implements TypeFilter
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * {@inheritdoc}
 | 
			
		||||
     *
 | 
			
		||||
     * @param DateInterval $element
 | 
			
		||||
     *
 | 
			
		||||
     * @see http://news.php.net/php.bugs/205076
 | 
			
		||||
     */
 | 
			
		||||
    public function apply($element)
 | 
			
		||||
    {
 | 
			
		||||
        $copy = new DateInterval('P0D');
 | 
			
		||||
 | 
			
		||||
        foreach ($element as $propertyName => $propertyValue) {
 | 
			
		||||
            $copy->{$propertyName} = $propertyValue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $copy;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										30
									
								
								vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/ReplaceFilter.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/ReplaceFilter.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,30 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DeepCopy\TypeFilter;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @final
 | 
			
		||||
 */
 | 
			
		||||
class ReplaceFilter implements TypeFilter
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * @var callable
 | 
			
		||||
     */
 | 
			
		||||
    protected $callback;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @param callable $callable Will be called to get the new value for each element to replace
 | 
			
		||||
     */
 | 
			
		||||
    public function __construct(callable $callable)
 | 
			
		||||
    {
 | 
			
		||||
        $this->callback = $callable;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * {@inheritdoc}
 | 
			
		||||
     */
 | 
			
		||||
    public function apply($element)
 | 
			
		||||
    {
 | 
			
		||||
        return call_user_func($this->callback, $element);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										17
									
								
								vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/ShallowCopyFilter.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/ShallowCopyFilter.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,17 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DeepCopy\TypeFilter;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @final
 | 
			
		||||
 */
 | 
			
		||||
class ShallowCopyFilter implements TypeFilter
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * {@inheritdoc}
 | 
			
		||||
     */
 | 
			
		||||
    public function apply($element)
 | 
			
		||||
    {
 | 
			
		||||
        return clone $element;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										36
									
								
								vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/Spl/ArrayObjectFilter.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/Spl/ArrayObjectFilter.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,36 @@
 | 
			
		||||
<?php
 | 
			
		||||
namespace DeepCopy\TypeFilter\Spl;
 | 
			
		||||
 | 
			
		||||
use DeepCopy\DeepCopy;
 | 
			
		||||
use DeepCopy\TypeFilter\TypeFilter;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * In PHP 7.4 the storage of an ArrayObject isn't returned as
 | 
			
		||||
 * ReflectionProperty. So we deep copy its array copy.
 | 
			
		||||
 */
 | 
			
		||||
final class ArrayObjectFilter implements TypeFilter
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * @var DeepCopy
 | 
			
		||||
     */
 | 
			
		||||
    private $copier;
 | 
			
		||||
 | 
			
		||||
    public function __construct(DeepCopy $copier)
 | 
			
		||||
    {
 | 
			
		||||
        $this->copier = $copier;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * {@inheritdoc}
 | 
			
		||||
     */
 | 
			
		||||
    public function apply($arrayObject)
 | 
			
		||||
    {
 | 
			
		||||
        $clone = clone $arrayObject;
 | 
			
		||||
        foreach ($arrayObject->getArrayCopy() as $k => $v) {
 | 
			
		||||
            $clone->offsetSet($k, $this->copier->copy($v));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $clone;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										10
									
								
								vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/Spl/SplDoublyLinkedList.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/Spl/SplDoublyLinkedList.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,10 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DeepCopy\TypeFilter\Spl;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @deprecated Use {@see SplDoublyLinkedListFilter} instead.
 | 
			
		||||
 */
 | 
			
		||||
class SplDoublyLinkedList extends SplDoublyLinkedListFilter
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										51
									
								
								vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/Spl/SplDoublyLinkedListFilter.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/Spl/SplDoublyLinkedListFilter.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,51 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DeepCopy\TypeFilter\Spl;
 | 
			
		||||
 | 
			
		||||
use Closure;
 | 
			
		||||
use DeepCopy\DeepCopy;
 | 
			
		||||
use DeepCopy\TypeFilter\TypeFilter;
 | 
			
		||||
use SplDoublyLinkedList;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @final
 | 
			
		||||
 */
 | 
			
		||||
class SplDoublyLinkedListFilter implements TypeFilter
 | 
			
		||||
{
 | 
			
		||||
    private $copier;
 | 
			
		||||
 | 
			
		||||
    public function __construct(DeepCopy $copier)
 | 
			
		||||
    {
 | 
			
		||||
        $this->copier = $copier;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * {@inheritdoc}
 | 
			
		||||
     */
 | 
			
		||||
    public function apply($element)
 | 
			
		||||
    {
 | 
			
		||||
        $newElement = clone $element;
 | 
			
		||||
 | 
			
		||||
        $copy = $this->createCopyClosure();
 | 
			
		||||
 | 
			
		||||
        return $copy($newElement);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function createCopyClosure()
 | 
			
		||||
    {
 | 
			
		||||
        $copier = $this->copier;
 | 
			
		||||
 | 
			
		||||
        $copy = function (SplDoublyLinkedList $list) use ($copier) {
 | 
			
		||||
            // Replace each element in the list with a deep copy of itself
 | 
			
		||||
            for ($i = 1; $i <= $list->count(); $i++) {
 | 
			
		||||
                $copy = $copier->recursiveCopy($list->shift());
 | 
			
		||||
 | 
			
		||||
                $list->push($copy);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return $list;
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        return Closure::bind($copy, null, DeepCopy::class);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										13
									
								
								vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/TypeFilter.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/TypeFilter.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,13 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DeepCopy\TypeFilter;
 | 
			
		||||
 | 
			
		||||
interface TypeFilter
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * Applies the filter to the object.
 | 
			
		||||
     *
 | 
			
		||||
     * @param mixed $element
 | 
			
		||||
     */
 | 
			
		||||
    public function apply($element);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										29
									
								
								vendor/myclabs/deep-copy/src/DeepCopy/TypeMatcher/TypeMatcher.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								vendor/myclabs/deep-copy/src/DeepCopy/TypeMatcher/TypeMatcher.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,29 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DeepCopy\TypeMatcher;
 | 
			
		||||
 | 
			
		||||
class TypeMatcher
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * @var string
 | 
			
		||||
     */
 | 
			
		||||
    private $type;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @param string $type
 | 
			
		||||
     */
 | 
			
		||||
    public function __construct($type)
 | 
			
		||||
    {
 | 
			
		||||
        $this->type = $type;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @param mixed $element
 | 
			
		||||
     *
 | 
			
		||||
     * @return boolean
 | 
			
		||||
     */
 | 
			
		||||
    public function matches($element)
 | 
			
		||||
    {
 | 
			
		||||
        return is_object($element) ? is_a($element, $this->type) : gettype($element) === $this->type;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										20
									
								
								vendor/myclabs/deep-copy/src/DeepCopy/deep_copy.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								vendor/myclabs/deep-copy/src/DeepCopy/deep_copy.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,20 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DeepCopy;
 | 
			
		||||
 | 
			
		||||
use function function_exists;
 | 
			
		||||
 | 
			
		||||
if (false === function_exists('DeepCopy\deep_copy')) {
 | 
			
		||||
    /**
 | 
			
		||||
     * Deep copies the given value.
 | 
			
		||||
     *
 | 
			
		||||
     * @param mixed $value
 | 
			
		||||
     * @param bool  $useCloneMethod
 | 
			
		||||
     *
 | 
			
		||||
     * @return mixed
 | 
			
		||||
     */
 | 
			
		||||
    function deep_copy($value, $useCloneMethod = false)
 | 
			
		||||
    {
 | 
			
		||||
        return (new DeepCopy($useCloneMethod))->copy($value);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user