Included vendor/ to the project

This commit is contained in:
Gregorio Chiko Putra 2017-09-13 09:35:32 +07:00
parent e72205ff09
commit 17f1643875
2483 changed files with 179073 additions and 0 deletions

7
vendor/autoload.php vendored Normal file
View File

@ -0,0 +1,7 @@
<?php
// autoload.php @generated by Composer
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInitb36dd9ca71acc5e09c36145e94adede4::getLoader();

1
vendor/bin/phpunit vendored Symbolic link
View File

@ -0,0 +1 @@
../phpunit/phpunit/phpunit

View File

@ -0,0 +1,35 @@
# Contributing
* Coding standard for the project is [PSR-2](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)
* The project will follow strict [object calisthenics](http://www.slideshare.net/guilhermeblanco/object-calisthenics-applied-to-php)
* Any contribution must provide tests for additional introduced conditions
* Any un-confirmed issue needs a failing test case before being accepted
* Pull requests must be sent from a new hotfix/feature branch, not from `master`.
## Installation
To install the project and run the tests, you need to clone it first:
```sh
$ git clone git://github.com/doctrine/instantiator.git
```
You will then need to run a composer installation:
```sh
$ cd Instantiator
$ curl -s https://getcomposer.org/installer | php
$ php composer.phar update
```
## Testing
The PHPUnit version to be used is the one installed as a dev- dependency via composer:
```sh
$ ./vendor/bin/phpunit
```
Accepted coverage for new contributions is 80%. Any contribution not satisfying this requirement
won't be merged.

19
vendor/doctrine/instantiator/LICENSE vendored Normal file
View File

@ -0,0 +1,19 @@
Copyright (c) 2014 Doctrine Project
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.

40
vendor/doctrine/instantiator/README.md vendored Normal file
View File

@ -0,0 +1,40 @@
# Instantiator
This library provides a way of avoiding usage of constructors when instantiating PHP classes.
[![Build Status](https://travis-ci.org/doctrine/instantiator.svg?branch=master)](https://travis-ci.org/doctrine/instantiator)
[![Code Coverage](https://scrutinizer-ci.com/g/doctrine/instantiator/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/doctrine/instantiator/?branch=master)
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/doctrine/instantiator/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/doctrine/instantiator/?branch=master)
[![Dependency Status](https://www.versioneye.com/package/php--doctrine--instantiator/badge.svg)](https://www.versioneye.com/package/php--doctrine--instantiator)
[![HHVM Status](http://hhvm.h4cc.de/badge/doctrine/instantiator.png)](http://hhvm.h4cc.de/package/doctrine/instantiator)
[![Latest Stable Version](https://poser.pugx.org/doctrine/instantiator/v/stable.png)](https://packagist.org/packages/doctrine/instantiator)
[![Latest Unstable Version](https://poser.pugx.org/doctrine/instantiator/v/unstable.png)](https://packagist.org/packages/doctrine/instantiator)
## Installation
The suggested installation method is via [composer](https://getcomposer.org/):
```sh
php composer.phar require "doctrine/instantiator:~1.0.3"
```
## Usage
The instantiator is able to create new instances of any class without using the constructor or any API of the class
itself:
```php
$instantiator = new \Doctrine\Instantiator\Instantiator();
$instance = $instantiator->instantiate(\My\ClassName\Here::class);
```
## Contributing
Please read the [CONTRIBUTING.md](CONTRIBUTING.md) contents if you wish to help out!
## Credits
This library was migrated from [ocramius/instantiator](https://github.com/Ocramius/Instantiator), which
has been donated to the doctrine organization, and which is now deprecated in favour of this package.

View File

@ -0,0 +1,29 @@
<?php
/*
* 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.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Instantiator\Exception;
/**
* Base exception marker interface for the instantiator component
*
* @author Marco Pivetta <ocramius@gmail.com>
*/
interface ExceptionInterface
{
}

View File

@ -0,0 +1,52 @@
<?php
/*
* 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.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Instantiator\Exception;
use InvalidArgumentException as BaseInvalidArgumentException;
use ReflectionClass;
/**
* Exception for invalid arguments provided to the instantiator
*
* @author Marco Pivetta <ocramius@gmail.com>
*/
class InvalidArgumentException extends BaseInvalidArgumentException implements ExceptionInterface
{
public static function fromNonExistingClass(string $className) : self
{
if (interface_exists($className)) {
return new self(sprintf('The provided type "%s" is an interface, and can not be instantiated', $className));
}
if (PHP_VERSION_ID >= 50400 && trait_exists($className)) {
return new self(sprintf('The provided type "%s" is a trait, and can not be instantiated', $className));
}
return new self(sprintf('The provided class "%s" does not exist', $className));
}
public static function fromAbstractClass(ReflectionClass $reflectionClass) : self
{
return new self(sprintf(
'The provided class "%s" is abstract, and can not be instantiated',
$reflectionClass->getName()
));
}
}

View File

@ -0,0 +1,66 @@
<?php
/*
* 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.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Instantiator\Exception;
use Exception;
use ReflectionClass;
use UnexpectedValueException as BaseUnexpectedValueException;
/**
* Exception for given parameters causing invalid/unexpected state on instantiation
*
* @author Marco Pivetta <ocramius@gmail.com>
*/
class UnexpectedValueException extends BaseUnexpectedValueException implements ExceptionInterface
{
public static function fromSerializationTriggeredException(
ReflectionClass $reflectionClass,
Exception $exception
) : self {
return new self(
sprintf(
'An exception was raised while trying to instantiate an instance of "%s" via un-serialization',
$reflectionClass->getName()
),
0,
$exception
);
}
public static function fromUncleanUnSerialization(
ReflectionClass $reflectionClass,
string $errorString,
int $errorCode,
string $errorFile,
int $errorLine
) : self {
return new self(
sprintf(
'Could not produce an instance of "%s" via un-serialization, since an error was triggered '
. 'in file "%s" at line "%d"',
$reflectionClass->getName(),
$errorFile,
$errorLine
),
0,
new Exception($errorString, $errorCode)
);
}
}

View File

@ -0,0 +1,216 @@
<?php
/*
* 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.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Instantiator;
use Doctrine\Instantiator\Exception\InvalidArgumentException;
use Doctrine\Instantiator\Exception\UnexpectedValueException;
use Exception;
use ReflectionClass;
/**
* {@inheritDoc}
*
* @author Marco Pivetta <ocramius@gmail.com>
*/
final class Instantiator implements InstantiatorInterface
{
/**
* Markers used internally by PHP to define whether {@see \unserialize} should invoke
* the method {@see \Serializable::unserialize()} when dealing with classes implementing
* the {@see \Serializable} interface.
*/
const SERIALIZATION_FORMAT_USE_UNSERIALIZER = 'C';
const SERIALIZATION_FORMAT_AVOID_UNSERIALIZER = 'O';
/**
* @var \callable[] used to instantiate specific classes, indexed by class name
*/
private static $cachedInstantiators = [];
/**
* @var object[] of objects that can directly be cloned, indexed by class name
*/
private static $cachedCloneables = [];
/**
* {@inheritDoc}
*/
public function instantiate($className)
{
if (isset(self::$cachedCloneables[$className])) {
return clone self::$cachedCloneables[$className];
}
if (isset(self::$cachedInstantiators[$className])) {
$factory = self::$cachedInstantiators[$className];
return $factory();
}
return $this->buildAndCacheFromFactory($className);
}
/**
* Builds the requested object and caches it in static properties for performance
*
* @return object
*/
private function buildAndCacheFromFactory(string $className)
{
$factory = self::$cachedInstantiators[$className] = $this->buildFactory($className);
$instance = $factory();
if ($this->isSafeToClone(new ReflectionClass($instance))) {
self::$cachedCloneables[$className] = clone $instance;
}
return $instance;
}
/**
* Builds a callable capable of instantiating the given $className without
* invoking its constructor.
*
* @throws InvalidArgumentException
* @throws UnexpectedValueException
* @throws \ReflectionException
*/
private function buildFactory(string $className) : callable
{
$reflectionClass = $this->getReflectionClass($className);
if ($this->isInstantiableViaReflection($reflectionClass)) {
return [$reflectionClass, 'newInstanceWithoutConstructor'];
}
$serializedString = sprintf(
'%s:%d:"%s":0:{}',
self::SERIALIZATION_FORMAT_AVOID_UNSERIALIZER,
strlen($className),
$className
);
$this->checkIfUnSerializationIsSupported($reflectionClass, $serializedString);
return function () use ($serializedString) {
return unserialize($serializedString);
};
}
/**
* @param string $className
*
* @return ReflectionClass
*
* @throws InvalidArgumentException
* @throws \ReflectionException
*/
private function getReflectionClass($className) : ReflectionClass
{
if (! class_exists($className)) {
throw InvalidArgumentException::fromNonExistingClass($className);
}
$reflection = new ReflectionClass($className);
if ($reflection->isAbstract()) {
throw InvalidArgumentException::fromAbstractClass($reflection);
}
return $reflection;
}
/**
* @param ReflectionClass $reflectionClass
* @param string $serializedString
*
* @throws UnexpectedValueException
*
* @return void
*/
private function checkIfUnSerializationIsSupported(ReflectionClass $reflectionClass, $serializedString) : void
{
set_error_handler(function ($code, $message, $file, $line) use ($reflectionClass, & $error) : void {
$error = UnexpectedValueException::fromUncleanUnSerialization(
$reflectionClass,
$message,
$code,
$file,
$line
);
});
$this->attemptInstantiationViaUnSerialization($reflectionClass, $serializedString);
restore_error_handler();
if ($error) {
throw $error;
}
}
/**
* @param ReflectionClass $reflectionClass
* @param string $serializedString
*
* @throws UnexpectedValueException
*
* @return void
*/
private function attemptInstantiationViaUnSerialization(ReflectionClass $reflectionClass, $serializedString) : void
{
try {
unserialize($serializedString);
} catch (Exception $exception) {
restore_error_handler();
throw UnexpectedValueException::fromSerializationTriggeredException($reflectionClass, $exception);
}
}
private function isInstantiableViaReflection(ReflectionClass $reflectionClass) : bool
{
return ! ($this->hasInternalAncestors($reflectionClass) && $reflectionClass->isFinal());
}
/**
* Verifies whether the given class is to be considered internal
*/
private function hasInternalAncestors(ReflectionClass $reflectionClass) : bool
{
do {
if ($reflectionClass->isInternal()) {
return true;
}
} while ($reflectionClass = $reflectionClass->getParentClass());
return false;
}
/**
* Checks if a class is cloneable
*
* Classes implementing `__clone` cannot be safely cloned, as that may cause side-effects.
*/
private function isSafeToClone(ReflectionClass $reflection) : bool
{
return $reflection->isCloneable() && ! $reflection->hasMethod('__clone');
}
}

View File

@ -0,0 +1,37 @@
<?php
/*
* 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.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Instantiator;
/**
* Instantiator provides utility methods to build objects without invoking their constructors
*
* @author Marco Pivetta <ocramius@gmail.com>
*/
interface InstantiatorInterface
{
/**
* @param string $className
*
* @return object
*
* @throws \Doctrine\Instantiator\Exception\ExceptionInterface
*/
public function instantiate($className);
}

37
vendor/myclabs/deep-copy/.travis.yml vendored Executable file
View File

@ -0,0 +1,37 @@
language: php
php:
- '5.5'
- '5.6'
- '7.0'
- '7.1'
- nightly
- hhvm
matrix:
fast_finish: true
include:
- php: '5.4'
env: COMPOSER_FLAGS="--prefer-lowest"
allow_failures:
- php: nightly
- php: hhvm
before_install:
- |
if [ "$TRAVIS_PHP_VERSION" = "nightly" ] || "$TRAVIS_PHP_VERSION" = "7.1" ]; then
COMPOSER_FLAGS="$COMPOSER_FLAGS --ignore-platform-reqs"
fi;
install:
- composer update -n --prefer-dist $COMPOSER_FLAGS
- wget https://github.com/satooshi/php-coveralls/releases/download/v1.0.0/coveralls.phar
before_script:
- mkdir -p build/logs
script:
- vendor/bin/phpunit --coverage-clover build/logs/clover.xml
after_script:
- php coveralls.phar -v

20
vendor/myclabs/deep-copy/LICENSE vendored Normal file
View 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.

290
vendor/myclabs/deep-copy/README.md vendored Normal file
View File

@ -0,0 +1,290 @@
# DeepCopy
DeepCopy helps you create deep copies (clones) of your objects. It is designed to handle cycles in the association graph.
[![Build Status](https://travis-ci.org/myclabs/DeepCopy.png?branch=master)](https://travis-ci.org/myclabs/DeepCopy) [![Coverage Status](https://coveralls.io/repos/myclabs/DeepCopy/badge.png?branch=master)](https://coveralls.io/r/myclabs/DeepCopy?branch=master) [![Scrutinizer Quality Score](https://scrutinizer-ci.com/g/myclabs/DeepCopy/badges/quality-score.png?s=2747100c19b275f93a777e3297c6c12d1b68b934)](https://scrutinizer-ci.com/g/myclabs/DeepCopy/)
[![Total Downloads](https://poser.pugx.org/myclabs/deep-copy/downloads.svg)](https://packagist.org/packages/myclabs/deep-copy)
## Table of Contents
1. [How](#how)
1. [Why](#why)
1. [Using simply `clone`](#using-simply-clone)
1. [Overridding `__clone()`](#overridding-__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)
1. [`KeepFilter`](#keepfilter)
1. [`ReplaceFilter`](#replacefilter)
1. [`ShallowCopyFilter`](#doctrinecollectionfilter)
1. [`DoctrineCollectionFilter`](#doctrinecollectionfilter)
1. [`DoctrineEmptyCollectionFilter`](#doctrineemptycollectionfilter)
1. [Contributing](#contributing)
1. [Tests](#tests)
## How?
Install with Composer:
```json
composer require myclabs/deep-copy
```
Use simply:
```php
use DeepCopy\DeepCopy;
$deepCopy = new DeepCopy();
$myCopy = $deepCopy->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 :(
![association graph](doc/graph.png)
### Using simply `clone`
![Using clone](doc/clone.png)
### Overridding `__clone()`
![Overridding __clone](doc/deep-clone.png)
### With `DeepCopy`
![With DeepCopy](doc/deep-copy.png)
## 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.
## Going further
You can add filters to customize the copy process.
The method to add a filter is `$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;
$matcher = new PropertyNameMatcher('id');
// will apply a filter to any property of any objects named "id"
```
#### Specific property
The `PropertyMatcher` will match a specific property of a specific class:
```php
use DeepCopy\Matcher\PropertyMatcher;
$matcher = new PropertyMatcher('MyClass', 'id');
// will apply a filter to the property "id" of any objects of the class "MyClass"
```
#### 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;
$matcher = new TypeMatcher('Doctrine\Common\Collections\Collection');
// will apply a filter to any object that is an instance of 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`
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;
$myObject = MyClass::load(123);
echo $myObject->id; // 123
$deepCopy = new DeepCopy();
$deepCopy->addFilter(new SetNullFilter(), new PropertyNameMatcher('id'));
$myCopy = $deepCopy->copy($myObject);
echo $myCopy->id; // null
```
#### `KeepFilter`
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;
$deepCopy = new DeepCopy();
$deepCopy->addFilter(new KeepFilter(), new PropertyMatcher('MyClass', 'category'));
$myCopy = $deepCopy->copy($myObject);
// $myCopy->category has not been touched
```
#### `ReplaceFilter`
1. If you want to replace the value of a property:
```php
use DeepCopy\DeepCopy;
use DeepCopy\Filter\ReplaceFilter;
use DeepCopy\Matcher\PropertyMatcher;
$deepCopy = new DeepCopy();
$callback = function ($currentValue) {
return $currentValue . ' (copy)'
};
$deepCopy->addFilter(new ReplaceFilter($callback), new PropertyMatcher('MyClass', 'title'));
$myCopy = $deepCopy->copy($myObject);
// $myCopy->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;
$deepCopy = new DeepCopy();
$callback = function (MyClass $myClass) {
return get_class($myClass);
};
$deepCopy->addTypeFilter(new ReplaceFilter($callback), new TypeMatcher('MyClass'));
$myCopy = $deepCopy->copy(array(new MyClass, 'some string', new MyClass));
// $myCopy will contain ['MyClass', 'some string', 'MyClass']
```
The `$callback` parameter of the `ReplaceFilter` constructor accepts any PHP callable.
#### `ShallowCopyFilter`
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
```
#### `DoctrineCollectionFilter`
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;
$deepCopy = new DeepCopy();
$deepCopy->addFilter(new DoctrineCollectionFilter(), new PropertyTypeMatcher('Doctrine\Common\Collections\Collection'));
$myCopy = $deepCopy->copy($myObject);
```
#### `DoctrineEmptyCollectionFilter`
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;
$deepCopy = new DeepCopy();
$deepCopy->addFilter(new DoctrineEmptyCollectionFilter(), new PropertyMatcher('MyClass', 'myProperty'));
$myCopy = $deepCopy->copy($myObject);
// $myCopy->myProperty will return an empty collection
```
#### `DoctrineProxyFilter`
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;
$deepCopy = new DeepCopy();
$deepCopy->addFilter(new DoctrineProxyFilter(), new DoctrineProxyMatcher());
$myCopy = $deepCopy->copy($myObject);
// $myCopy should now contain a clone of all entities, including those that were not yet fully loaded.
```
## Contributing
DeepCopy is distributed under the MIT license.
### Tests
Running the tests is simple:
```php
phpunit
```

BIN
vendor/myclabs/deep-copy/doc/clone.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
vendor/myclabs/deep-copy/doc/graph.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

View File

@ -0,0 +1,246 @@
<?php
namespace DeepCopy;
use DeepCopy\Exception\CloneException;
use DeepCopy\Filter\Filter;
use DeepCopy\Matcher\Matcher;
use DeepCopy\TypeFilter\Spl\SplDoublyLinkedList;
use DeepCopy\TypeFilter\TypeFilter;
use DeepCopy\TypeMatcher\TypeMatcher;
use ReflectionProperty;
use DeepCopy\Reflection\ReflectionHelper;
/**
* DeepCopy
*/
class DeepCopy
{
/**
* @var array
*/
private $hashMap = [];
/**
* Filters to apply.
* @var array
*/
private $filters = [];
/**
* Type Filters to apply.
* @var array
*/
private $typeFilters = [];
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 SplDoublyLinkedList($this), new TypeMatcher('\SplDoublyLinkedList'));
}
/**
* Cloning uncloneable properties won't throw exception.
* @param $skipUncloneable
* @return $this
*/
public function skipUncloneable($skipUncloneable = true)
{
$this->skipUncloneable = $skipUncloneable;
return $this;
}
/**
* Perform a deep copy of the 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 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;
}
// 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;
}
/**
* Copy an object
* @param object $object
* @return object
*/
private function copyObject($object)
{
$objectHash = spl_object_hash($object);
if (isset($this->hashMap[$objectHash])) {
return $this->hashMap[$objectHash];
}
$reflectedObject = new \ReflectionObject($object);
if (false === $isCloneable = $reflectedObject->isCloneable() and $this->skipUncloneable) {
$this->hashMap[$objectHash] = $object;
return $object;
}
if (false === $isCloneable) {
throw new CloneException(sprintf(
'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) {
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);
$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
* @param callable $predicate Predicate arguments are: element.
* @return mixed|null
*/
private function first(array $elements, callable $predicate)
{
foreach ($elements as $element) {
if (call_user_func($predicate, $element)) {
return $element;
}
}
return null;
}
}

View File

@ -0,0 +1,6 @@
<?php
namespace DeepCopy\Exception;
class CloneException extends \UnexpectedValueException
{
}

View File

@ -0,0 +1,31 @@
<?php
namespace DeepCopy\Filter\Doctrine;
use DeepCopy\Filter\Filter;
use ReflectionProperty;
/**
* Set a null value for a property
*/
class DoctrineCollectionFilter implements Filter
{
/**
* {@inheritdoc}
*/
public function apply($object, $property, $objectCopier)
{
$reflectionProperty = new ReflectionProperty($object, $property);
$reflectionProperty->setAccessible(true);
$oldCollection = $reflectionProperty->getValue($object);
$newCollection = $oldCollection->map(
function ($item) use ($objectCopier) {
return $objectCopier($item);
}
);
$reflectionProperty->setValue($object, $newCollection);
}
}

View File

@ -0,0 +1,24 @@
<?php
namespace DeepCopy\Filter\Doctrine;
use DeepCopy\Filter\Filter;
use Doctrine\Common\Collections\ArrayCollection;
class DoctrineEmptyCollectionFilter implements Filter
{
/**
* Apply the filter to the object.
*
* @param object $object
* @param string $property
* @param callable $objectCopier
*/
public function apply($object, $property, $objectCopier)
{
$reflectionProperty = new \ReflectionProperty($object, $property);
$reflectionProperty->setAccessible(true);
$reflectionProperty->setValue($object, new ArrayCollection());
}
}

View File

@ -0,0 +1,20 @@
<?php
namespace DeepCopy\Filter\Doctrine;
use DeepCopy\Filter\Filter;
/**
* Trigger the magic method __load() on a Doctrine Proxy class to load the
* actual entity from the database.
*/
class DoctrineProxyFilter implements Filter
{
/**
* {@inheritdoc}
*/
public function apply($object, $property, $objectCopier)
{
$object->__load();
}
}

View File

@ -0,0 +1,17 @@
<?php
namespace DeepCopy\Filter;
/**
* Filter to apply to a property while copying an object
*/
interface Filter
{
/**
* Apply the filter to the object.
* @param object $object
* @param string $property
* @param callable $objectCopier
*/
public function apply($object, $property, $objectCopier);
}

View File

@ -0,0 +1,17 @@
<?php
namespace DeepCopy\Filter;
/**
* Keep the value of a property
*/
class KeepFilter implements Filter
{
/**
* {@inheritdoc}
*/
public function apply($object, $property, $objectCopier)
{
// Nothing to do
}
}

View File

@ -0,0 +1,35 @@
<?php
namespace DeepCopy\Filter;
/**
* Replace the value of a property
*/
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;
}
/**
* {@inheritdoc}
*/
public function apply($object, $property, $objectCopier)
{
$reflectionProperty = new \ReflectionProperty($object, $property);
$reflectionProperty->setAccessible(true);
$value = call_user_func($this->callback, $reflectionProperty->getValue($object));
$reflectionProperty->setValue($object, $value);
}
}

View File

@ -0,0 +1,22 @@
<?php
namespace DeepCopy\Filter;
use ReflectionProperty;
/**
* Set a null value for a property
*/
class SetNullFilter implements Filter
{
/**
* {@inheritdoc}
*/
public function apply($object, $property, $objectCopier)
{
$reflectionProperty = new ReflectionProperty($object, $property);
$reflectionProperty->setAccessible(true);
$reflectionProperty->setValue($object, null);
}
}

View File

@ -0,0 +1,20 @@
<?php
namespace DeepCopy\Matcher\Doctrine;
use DeepCopy\Matcher\Matcher;
use Doctrine\Common\Persistence\Proxy;
/**
* Match a Doctrine Proxy class.
*/
class DoctrineProxyMatcher implements Matcher
{
/**
* {@inheritdoc}
*/
public function matches($object, $property)
{
return $object instanceof Proxy;
}
}

View File

@ -0,0 +1,16 @@
<?php
namespace DeepCopy\Matcher;
/**
* Matcher interface
*/
interface Matcher
{
/**
* @param object $object
* @param string $property
* @return boolean
*/
public function matches($object, $property);
}

View File

@ -0,0 +1,37 @@
<?php
namespace DeepCopy\Matcher;
/**
* Match a specific property of a specific class
*/
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;
}
/**
* {@inheritdoc}
*/
public function matches($object, $property)
{
return ($object instanceof $this->class) && ($property == $this->property);
}
}

View File

@ -0,0 +1,30 @@
<?php
namespace DeepCopy\Matcher;
/**
* Match a property by its name
*/
class PropertyNameMatcher implements Matcher
{
/**
* @var string
*/
private $property;
/**
* @param string $property Property name
*/
public function __construct($property)
{
$this->property = $property;
}
/**
* {@inheritdoc}
*/
public function matches($object, $property)
{
return $property == $this->property;
}
}

View File

@ -0,0 +1,38 @@
<?php
namespace DeepCopy\Matcher;
use ReflectionProperty;
/**
* Match 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.
*/
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)
{
$reflectionProperty = new ReflectionProperty($object, $property);
$reflectionProperty->setAccessible(true);
return $reflectionProperty->getValue($object) instanceof $this->propertyType;
}
}

View File

@ -0,0 +1,39 @@
<?php
namespace DeepCopy\Reflection;
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;
}
}

View File

@ -0,0 +1,27 @@
<?php
namespace DeepCopy\TypeFilter;
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);
}
}

View File

@ -0,0 +1,14 @@
<?php
namespace DeepCopy\TypeFilter;
class ShallowCopyFilter implements TypeFilter
{
/**
* {@inheritdoc}
*/
public function apply($element)
{
return clone $element;
}
}

View File

@ -0,0 +1,37 @@
<?php
namespace DeepCopy\TypeFilter\Spl;
use DeepCopy\DeepCopy;
use DeepCopy\TypeFilter\TypeFilter;
class SplDoublyLinkedList implements TypeFilter
{
/**
* @var DeepCopy
*/
private $deepCopy;
public function __construct(DeepCopy $deepCopy)
{
$this->deepCopy = $deepCopy;
}
/**
* {@inheritdoc}
*/
public function apply($element)
{
$newElement = clone $element;
if ($element instanceof \SplDoublyLinkedList) {
// Replace each element in the list with a deep copy of itself
for ($i = 1; $i <= $newElement->count(); $i++) {
$newElement->push($this->deepCopy->copy($newElement->shift()));
}
}
return $newElement;
}
}

View File

@ -0,0 +1,12 @@
<?php
namespace DeepCopy\TypeFilter;
interface TypeFilter
{
/**
* Apply the filter to the object.
* @param mixed $element
*/
public function apply($element);
}

View File

@ -0,0 +1,31 @@
<?php
namespace DeepCopy\TypeMatcher;
/**
* TypeMatcher class
*/
class TypeMatcher
{
/**
* @var string
*/
private $type;
/**
* @param string $type
*/
public function __construct($type)
{
$this->type = $type;
}
/**
* @param $element
* @return boolean
*/
public function matches($element)
{
return is_object($element) ? is_a($element, $this->type) : gettype($element) === $this->type;
}
}

67
vendor/phar-io/manifest/.php_cs vendored Normal file
View File

@ -0,0 +1,67 @@
<?php
$finder = Symfony\CS\Finder\DefaultFinder::create()
->files()
->in('src')
->in('tests')
->name('*.php');
return Symfony\CS\Config\Config::create()
->setUsingCache(true)
->level(\Symfony\CS\FixerInterface::NONE_LEVEL)
->fixers(
array(
'align_double_arrow',
'align_equals',
'concat_with_spaces',
'duplicate_semicolon',
'elseif',
'empty_return',
'encoding',
'eof_ending',
'extra_empty_lines',
'function_call_space',
'function_declaration',
'indentation',
'join_function',
'line_after_namespace',
'linefeed',
'list_commas',
'lowercase_constants',
'lowercase_keywords',
'method_argument_space',
'multiple_use',
'namespace_no_leading_whitespace',
'no_blank_lines_after_class_opening',
'no_empty_lines_after_phpdocs',
'parenthesis',
'php_closing_tag',
'phpdoc_indent',
'phpdoc_no_access',
'phpdoc_no_empty_return',
'phpdoc_no_package',
'phpdoc_params',
'phpdoc_scalar',
'phpdoc_separation',
'phpdoc_to_comment',
'phpdoc_trim',
'phpdoc_types',
'phpdoc_var_without_name',
'remove_lines_between_uses',
'return',
'self_accessor',
'short_array_syntax',
'short_tag',
'single_line_after_imports',
'single_quote',
'spaces_before_semicolon',
'spaces_cast',
'ternary_spaces',
'trailing_spaces',
'trim_array_spaces',
'unused_use',
'visibility',
'whitespacy_lines'
)
)
->finder($finder);

33
vendor/phar-io/manifest/.travis.yml vendored Normal file
View File

@ -0,0 +1,33 @@
os:
- linux
language: php
before_install:
- wget https://phar.io/releases/phive.phar
- wget https://phar.io/releases/phive.phar.asc
- gpg --keyserver hkps.pool.sks-keyservers.net --recv-keys 0x9B2D5D79
- gpg --verify phive.phar.asc phive.phar
- chmod +x phive.phar
- sudo mv phive.phar /usr/bin/phive
install:
- ant setup
script: ./tools/phpunit
php:
- 5.6
- 7.0
- 7.1
- 7.0snapshot
- 7.1snapshot
- master
matrix:
allow_failures:
- php: master
fast_finish: true
notifications:
email: false

31
vendor/phar-io/manifest/LICENSE vendored Normal file
View File

@ -0,0 +1,31 @@
manifest
Copyright (c) 2016 Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>, and contributors
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 Arne Blankerts nor the names of 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 HOLDER 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.

30
vendor/phar-io/manifest/README.md vendored Normal file
View File

@ -0,0 +1,30 @@
# Manifest
Component for reading [phar.io](https://phar.io/) manifest information from a [PHP Archive (PHAR)](http://php.net/phar).
[![Build Status](https://travis-ci.org/phar-io/manifest.svg?branch=master)](https://travis-ci.org/phar-io/manifest)
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/phar-io/manifest/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/phar-io/manifest/?branch=master)
[![SensioLabsInsight](https://insight.sensiolabs.com/projects/d8cc6035-69ad-477d-bd1a-ccc605480fd7/mini.png)](https://insight.sensiolabs.com/projects/d8cc6035-69ad-477d-bd1a-ccc605480fd7)
## Installation
You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/):
composer require phar-io/manifest
If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency:
composer require --dev phar-io/manifest
## Usage
```php
use PharIo\Manifest\ManifestLoader;
use PharIo\Manifest\ManifestSerializer;
$manifest = ManifestLoader::fromFile('manifest.xml');
var_dump($manifest);
echo (new ManifestSerializer)->serializeToString($manifest);
```

50
vendor/phar-io/manifest/build.xml vendored Normal file
View File

@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="manifest" default="setup">
<target name="setup" depends="clean,install-tools,install-dependencies"/>
<target name="clean" unless="clean.done" description="Cleanup build artifacts">
<delete dir="${basedir}/tools"/>
<delete dir="${basedir}/vendor"/>
<delete file="${basedir}/src/autoload.php"/>
<property name="clean.done" value="true"/>
</target>
<target name="prepare" unless="prepare.done" depends="clean" description="Prepare for build">
<property name="prepare.done" value="true"/>
</target>
<target name="install-dependencies" unless="dependencies-installed" depends="-dependencies-installed" description="Install dependencies with Composer">
<exec executable="composer" taskname="composer">
<env key="COMPOSER_DISABLE_XDEBUG_WARN" value="1"/>
<arg value="update"/>
<arg value="--no-interaction"/>
<arg value="--no-progress"/>
<arg value="--no-ansi"/>
<arg value="--no-suggest"/>
<arg value="--optimize-autoloader"/>
<arg value="--prefer-stable"/>
</exec>
</target>
<target name="install-tools" unless="tools-installed" depends="-tools-installed" description="Install tools with Phive">
<exec executable="phive" taskname="phive">
<arg value="install"/>
<arg value="--trust-gpg-keys" />
<arg value="4AA394086372C20A,2A8299CE842DD38C" />
</exec>
</target>
<target name="test" depends="install-tools,install-dependencies" description="Run tests">
<exec executable="${basedir}/tools/phpunit" taskname="phpunit"/>
</target>
<target name="-dependencies-installed">
<available file="${basedir}/composer.lock" property="dependencies-installed"/>
</target>
<target name="-tools-installed">
<available file="${basedir}/tools" property="tools-installed" type="dir"/>
</target>
</project>

View File

@ -0,0 +1,23 @@
<?php
/*
* This file is part of PharIo\Manifest.
*
* (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use PharIo\Manifest\ManifestLoader;
use PharIo\Manifest\ManifestSerializer;
require __DIR__ . '/../vendor/autoload.php';
$manifest = ManifestLoader::fromFile(__DIR__ . '/../tests/_fixture/phpunit-5.6.5.xml');
echo sprintf(
"Manifest for %s (%s):\n\n",
$manifest->getName(),
$manifest->getVersion()->getVersionString()
);
echo (new ManifestSerializer)->serializeToString($manifest);

4
vendor/phar-io/manifest/phive.xml vendored Normal file
View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<phive xmlns="https://phar.io/phive">
<phar name="phpunit" version="^5.7" installed="5.7.15" location="./tools/phpunit"/>
</phive>

View File

@ -0,0 +1,193 @@
<?php
/*
* This file is part of PharIo\Manifest.
*
* (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PharIo\Manifest;
use PharIo\Version\Version;
use PharIo\Version\Exception as VersionException;
use PharIo\Version\VersionConstraintParser;
class ManifestDocumentMapper {
/**
* @param ManifestDocument $document
*
* @returns Manifest
*
* @throws ManifestDocumentMapperException
*/
public function map(ManifestDocument $document) {
try {
$contains = $document->getContainsElement();
$type = $this->mapType($contains);
$copyright = $this->mapCopyright($document->getCopyrightElement());
$requirements = $this->mapRequirements($document->getRequiresElement());
$bundledComponents = $this->mapBundledComponents($document);
return new Manifest(
new ApplicationName($contains->getName()),
new Version($contains->getVersion()),
$type,
$copyright,
$requirements,
$bundledComponents
);
} catch (VersionException $e) {
throw new ManifestDocumentMapperException($e->getMessage(), $e->getCode(), $e);
} catch (Exception $e) {
throw new ManifestDocumentMapperException($e->getMessage(), $e->getCode(), $e);
}
}
/**
* @param ContainsElement $contains
*
* @return Type
*
* @throws ManifestDocumentMapperException
*/
private function mapType(ContainsElement $contains) {
switch ($contains->getType()) {
case 'application':
return Type::application();
case 'library':
return Type::library();
case 'extension':
return $this->mapExtension($contains->getExtensionElement());
}
throw new ManifestDocumentMapperException(
sprintf('Unsupported type %s', $contains->getType())
);
}
/**
* @param CopyrightElement $copyright
*
* @return CopyrightInformation
*
* @throws InvalidUrlException
* @throws InvalidEmailException
*/
private function mapCopyright(CopyrightElement $copyright) {
$authors = new AuthorCollection();
foreach($copyright->getAuthorElements() as $authorElement) {
$authors->add(
new Author(
$authorElement->getName(),
new Email($authorElement->getEmail())
)
);
}
$licenseElement = $copyright->getLicenseElement();
$license = new License(
$licenseElement->getType(),
new Url($licenseElement->getUrl())
);
return new CopyrightInformation(
$authors,
$license
);
}
/**
* @param RequiresElement $requires
*
* @return RequirementCollection
*
* @throws ManifestDocumentMapperException
*/
private function mapRequirements(RequiresElement $requires) {
$collection = new RequirementCollection();
$phpElement = $requires->getPHPElement();
$parser = new VersionConstraintParser;
try {
$versionConstraint = $parser->parse($phpElement->getVersion());
} catch (VersionException $e) {
throw new ManifestDocumentMapperException(
sprintf('Unsupported version constraint - %s', $e->getMessage()),
$e->getCode(),
$e
);
}
$collection->add(
new PhpVersionRequirement(
$versionConstraint
)
);
if (!$phpElement->hasExtElements()) {
return $collection;
}
foreach($phpElement->getExtElements() as $extElement) {
$collection->add(
new PhpExtensionRequirement($extElement->getName())
);
}
return $collection;
}
/**
* @param ManifestDocument $document
*
* @return BundledComponentCollection
*/
private function mapBundledComponents(ManifestDocument $document) {
$collection = new BundledComponentCollection();
if (!$document->hasBundlesElement()) {
return $collection;
}
foreach($document->getBundlesElement()->getComponentElements() as $componentElement) {
$collection->add(
new BundledComponent(
$componentElement->getName(),
new Version(
$componentElement->getVersion()
)
)
);
}
return $collection;
}
/**
* @param ExtensionElement $extension
*
* @return Extension
*
* @throws ManifestDocumentMapperException
*/
private function mapExtension(ExtensionElement $extension) {
try {
$parser = new VersionConstraintParser;
$versionConstraint = $parser->parse($extension->getCompatible());
return Type::extension(
new ApplicationName($extension->getFor()),
$versionConstraint
);
} catch (VersionException $e) {
throw new ManifestDocumentMapperException(
sprintf('Unsupported version constraint - %s', $e->getMessage()),
$e->getCode(),
$e
);
}
}
}

View File

@ -0,0 +1,66 @@
<?php
/*
* This file is part of PharIo\Manifest.
*
* (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PharIo\Manifest;
class ManifestLoader {
/**
* @param string $filename
*
* @return Manifest
*
* @throws ManifestLoaderException
*/
public static function fromFile($filename) {
try {
return (new ManifestDocumentMapper())->map(
ManifestDocument::fromFile($filename)
);
} catch (Exception $e) {
throw new ManifestLoaderException(
sprintf('Loading %s failed.', $filename),
$e->getCode(),
$e
);
}
}
/**
* @param string $filename
*
* @return Manifest
*
* @throws ManifestLoaderException
*/
public static function fromPhar($filename) {
return self::fromFile('phar://' . $filename . '/manifest.xml');
}
/**
* @param string $manifest
*
* @return Manifest
*
* @throws ManifestLoaderException
*/
public static function fromString($manifest) {
try {
return (new ManifestDocumentMapper())->map(
ManifestDocument::fromString($manifest)
);
} catch (Exception $e) {
throw new ManifestLoaderException(
'Processing string failed',
$e->getCode(),
$e
);
}
}
}

View File

@ -0,0 +1,163 @@
<?php
/*
* This file is part of PharIo\Manifest.
*
* (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PharIo\Manifest;
use PharIo\Version\AnyVersionConstraint;
use PharIo\Version\Version;
use PharIo\Version\VersionConstraint;
use XMLWriter;
class ManifestSerializer {
/**
* @var XMLWriter
*/
private $xmlWriter;
public function serializeToFile(Manifest $manifest, $filename) {
file_put_contents(
$filename,
$this->serializeToString($manifest)
);
}
public function serializeToString(Manifest $manifest) {
$this->startDocument();
$this->addContains($manifest->getName(), $manifest->getVersion(), $manifest->getType());
$this->addCopyright($manifest->getCopyrightInformation());
$this->addRequirements($manifest->getRequirements());
$this->addBundles($manifest->getBundledComponents());
return $this->finishDocument();
}
private function startDocument() {
$xmlWriter = new XMLWriter();
$xmlWriter->openMemory();
$xmlWriter->setIndent(true);
$xmlWriter->setIndentString(str_repeat(' ', 4));
$xmlWriter->startDocument('1.0', 'UTF-8');
$xmlWriter->startElement('phar');
$xmlWriter->writeAttribute('xmlns', 'https://phar.io/xml/manifest/1.0');
$this->xmlWriter = $xmlWriter;
}
private function finishDocument() {
$this->xmlWriter->endElement();
$this->xmlWriter->endDocument();
return $this->xmlWriter->outputMemory();
}
private function addContains($name, Version $version, Type $type) {
$this->xmlWriter->startElement('contains');
$this->xmlWriter->writeAttribute('name', $name);
$this->xmlWriter->writeAttribute('version', $version->getVersionString());
switch (true) {
case $type->isApplication(): {
$this->xmlWriter->writeAttribute('type', 'application');
break;
}
case $type->isLibrary(): {
$this->xmlWriter->writeAttribute('type', 'library');
break;
}
case $type->isExtension(): {
/* @var $type Extension */
$this->xmlWriter->writeAttribute('type', 'extension');
$this->addExtension($type->getApplicationName(), $type->getVersionConstraint());
break;
}
default: {
$this->xmlWriter->writeAttribute('type', 'custom');
}
}
$this->xmlWriter->endElement();
}
private function addCopyright(CopyrightInformation $copyrightInformation) {
$this->xmlWriter->startElement('copyright');
foreach($copyrightInformation->getAuthors() as $author) {
$this->xmlWriter->startElement('author');
$this->xmlWriter->writeAttribute('name', $author->getName());
$this->xmlWriter->writeAttribute('email', (string) $author->getEmail());
$this->xmlWriter->endElement();
}
$license = $copyrightInformation->getLicense();
$this->xmlWriter->startElement('license');
$this->xmlWriter->writeAttribute('type', $license->getName());
$this->xmlWriter->writeAttribute('url', $license->getUrl());
$this->xmlWriter->endElement();
$this->xmlWriter->endElement();
}
private function addRequirements(RequirementCollection $requirementCollection) {
$phpRequirement = new AnyVersionConstraint();
$extensions = [];
foreach($requirementCollection as $requirement) {
if ($requirement instanceof PhpVersionRequirement) {
$phpRequirement = $requirement->getVersionConstraint();
continue;
}
if ($requirement instanceof PhpExtensionRequirement) {
$extensions[] = (string) $requirement;
}
}
$this->xmlWriter->startElement('requires');
$this->xmlWriter->startElement('php');
$this->xmlWriter->writeAttribute('version', $phpRequirement->asString());
foreach($extensions as $extension) {
$this->xmlWriter->startElement('ext');
$this->xmlWriter->writeAttribute('name', $extension);
$this->xmlWriter->endElement();
}
$this->xmlWriter->endElement();
$this->xmlWriter->endElement();
}
private function addBundles(BundledComponentCollection $bundledComponentCollection) {
if (count($bundledComponentCollection) === 0) {
return;
}
$this->xmlWriter->startElement('bundles');
foreach($bundledComponentCollection as $bundledComponent) {
$this->xmlWriter->startElement('component');
$this->xmlWriter->writeAttribute('name', $bundledComponent->getName());
$this->xmlWriter->writeAttribute('version', $bundledComponent->getVersion()->getVersionString());
$this->xmlWriter->endElement();
}
$this->xmlWriter->endElement();
}
private function addExtension($application, VersionConstraint $versionConstraint) {
$this->xmlWriter->startElement('extension');
$this->xmlWriter->writeAttribute('for', $application);
$this->xmlWriter->writeAttribute('compatible', $versionConstraint->asString());
$this->xmlWriter->endElement();
}
}

View File

@ -0,0 +1,14 @@
<?php
/*
* This file is part of PharIo\Manifest.
*
* (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PharIo\Manifest;
interface Exception {
}

View File

@ -0,0 +1,16 @@
<?php
/*
* This file is part of PharIo\Manifest.
*
* (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PharIo\Manifest;
class InvalidApplicationNameException extends \InvalidArgumentException implements Exception {
const NotAString = 1;
const InvalidFormat = 2;
}

View File

@ -0,0 +1,14 @@
<?php
/*
* This file is part of PharIo\Manifest.
*
* (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PharIo\Manifest;
class InvalidEmailException extends \InvalidArgumentException implements Exception {
}

View File

@ -0,0 +1,14 @@
<?php
/*
* This file is part of PharIo\Manifest.
*
* (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PharIo\Manifest;
class InvalidUrlException extends \InvalidArgumentException implements Exception {
}

View File

@ -0,0 +1,6 @@
<?php
namespace PharIo\Manifest;
class ManifestDocumentException extends \RuntimeException implements Exception {
}

View File

@ -0,0 +1,6 @@
<?php
namespace PharIo\Manifest;
class ManifestDocumentMapperException extends \RuntimeException implements Exception {
}

View File

@ -0,0 +1,6 @@
<?php
namespace PharIo\Manifest;
class ManifestElementException extends \RuntimeException implements Exception {
}

View File

@ -0,0 +1,6 @@
<?php
namespace PharIo\Manifest;
class ManifestLoaderException extends \Exception implements Exception {
}

View File

@ -0,0 +1,20 @@
<?php
/*
* This file is part of PharIo\Manifest.
*
* (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PharIo\Manifest;
class Application extends Type {
/**
* @return bool
*/
public function isApplication() {
return true;
}
}

View File

@ -0,0 +1,65 @@
<?php
/*
* This file is part of PharIo\Manifest.
*
* (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PharIo\Manifest;
class ApplicationName {
/**
* @var string
*/
private $name;
/**
* ApplicationName constructor.
*
* @param string $name
*
* @throws InvalidApplicationNameException
*/
public function __construct($name) {
$this->ensureIsString($name);
$this->ensureValidFormat($name);
$this->name = $name;
}
/**
* @return string
*/
public function __toString() {
return $this->name;
}
public function isEqual(ApplicationName $name) {
return $this->name === $name->name;
}
/**
* @param string $name
*
* @throws InvalidApplicationNameException
*/
private function ensureValidFormat($name) {
if (!preg_match('#\w/\w#', $name)) {
throw new InvalidApplicationNameException(
sprintf('Format of name "%s" is not valid - expected: vendor/packagename', $name),
InvalidApplicationNameException::InvalidFormat
);
}
}
private function ensureIsString($name) {
if (!is_string($name)) {
throw new InvalidApplicationNameException(
'Name must be a string',
InvalidApplicationNameException::NotAString
);
}
}
}

View File

@ -0,0 +1,57 @@
<?php
/*
* This file is part of PharIo\Manifest.
*
* (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PharIo\Manifest;
class Author {
/**
* @var string
*/
private $name;
/**
* @var Email
*/
private $email;
/**
* @param string $name
* @param Email $email
*/
public function __construct($name, Email $email) {
$this->name = $name;
$this->email = $email;
}
/**
* @return string
*/
public function getName() {
return $this->name;
}
/**
* @return Email
*/
public function getEmail() {
return $this->email;
}
/**
* @return string
*/
public function __toString() {
return sprintf(
'%s <%s>',
$this->name,
$this->email
);
}
}

View File

@ -0,0 +1,43 @@
<?php
/*
* This file is part of PharIo\Manifest.
*
* (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PharIo\Manifest;
class AuthorCollection implements \Countable, \IteratorAggregate {
/**
* @var Author[]
*/
private $authors = [];
public function add(Author $author) {
$this->authors[] = $author;
}
/**
* @return Author[]
*/
public function getAuthors() {
return $this->authors;
}
/**
* @return int
*/
public function count() {
return count($this->authors);
}
/**
* @return AuthorCollectionIterator
*/
public function getIterator() {
return new AuthorCollectionIterator($this);
}
}

View File

@ -0,0 +1,56 @@
<?php
/*
* This file is part of PharIo\Manifest.
*
* (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PharIo\Manifest;
class AuthorCollectionIterator implements \Iterator {
/**
* @var Author[]
*/
private $authors = [];
/**
* @var int
*/
private $position;
public function __construct(AuthorCollection $authors) {
$this->authors = $authors->getAuthors();
}
public function rewind() {
$this->position = 0;
}
/**
* @return bool
*/
public function valid() {
return $this->position < count($this->authors);
}
/**
* @return int
*/
public function key() {
return $this->position;
}
/**
* @return Author
*/
public function current() {
return $this->authors[$this->position];
}
public function next() {
$this->position++;
}
}

View File

@ -0,0 +1,48 @@
<?php
/*
* This file is part of PharIo\Manifest.
*
* (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PharIo\Manifest;
use PharIo\Version\Version;
class BundledComponent {
/**
* @var string
*/
private $name;
/**
* @var Version
*/
private $version;
/**
* @param string $name
* @param Version $version
*/
public function __construct($name, Version $version) {
$this->name = $name;
$this->version = $version;
}
/**
* @return string
*/
public function getName() {
return $this->name;
}
/**
* @return Version
*/
public function getVersion() {
return $this->version;
}
}

View File

@ -0,0 +1,43 @@
<?php
/*
* This file is part of PharIo\Manifest.
*
* (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PharIo\Manifest;
class BundledComponentCollection implements \Countable, \IteratorAggregate {
/**
* @var BundledComponent[]
*/
private $bundledComponents = [];
public function add(BundledComponent $bundledComponent) {
$this->bundledComponents[] = $bundledComponent;
}
/**
* @return BundledComponent[]
*/
public function getBundledComponents() {
return $this->bundledComponents;
}
/**
* @return int
*/
public function count() {
return count($this->bundledComponents);
}
/**
* @return BundledComponentCollectionIterator
*/
public function getIterator() {
return new BundledComponentCollectionIterator($this);
}
}

View File

@ -0,0 +1,56 @@
<?php
/*
* This file is part of PharIo\Manifest.
*
* (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PharIo\Manifest;
class BundledComponentCollectionIterator implements \Iterator {
/**
* @var BundledComponent[]
*/
private $bundledComponents = [];
/**
* @var int
*/
private $position;
public function __construct(BundledComponentCollection $bundledComponents) {
$this->bundledComponents = $bundledComponents->getBundledComponents();
}
public function rewind() {
$this->position = 0;
}
/**
* @return bool
*/
public function valid() {
return $this->position < count($this->bundledComponents);
}
/**
* @return int
*/
public function key() {
return $this->position;
}
/**
* @return BundledComponent
*/
public function current() {
return $this->bundledComponents[$this->position];
}
public function next() {
$this->position++;
}
}

View File

@ -0,0 +1,42 @@
<?php
/*
* This file is part of PharIo\Manifest.
*
* (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PharIo\Manifest;
class CopyrightInformation {
/**
* @var AuthorCollection
*/
private $authors;
/**
* @var License
*/
private $license;
public function __construct(AuthorCollection $authors, License $license) {
$this->authors = $authors;
$this->license = $license;
}
/**
* @return AuthorCollection
*/
public function getAuthors() {
return $this->authors;
}
/**
* @return License
*/
public function getLicense() {
return $this->license;
}
}

View File

@ -0,0 +1,47 @@
<?php
/*
* This file is part of PharIo\Manifest.
*
* (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PharIo\Manifest;
class Email {
/**
* @var string
*/
private $email;
/**
* @param string $email
*
* @throws InvalidEmailException
*/
public function __construct($email) {
$this->ensureEmailIsValid($email);
$this->email = $email;
}
/**
* @return string
*/
public function __toString() {
return $this->email;
}
/**
* @param string $url
*
* @throws InvalidEmailException
*/
private function ensureEmailIsValid($url) {
if (filter_var($url, \FILTER_VALIDATE_EMAIL) === false) {
throw new InvalidEmailException;
}
}
}

View File

@ -0,0 +1,75 @@
<?php
/*
* This file is part of PharIo\Manifest.
*
* (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PharIo\Manifest;
use PharIo\Version\Version;
use PharIo\Version\VersionConstraint;
class Extension extends Type {
/**
* @var ApplicationName
*/
private $application;
/**
* @var VersionConstraint
*/
private $versionConstraint;
/**
* @param ApplicationName $application
* @param VersionConstraint $versionConstraint
*/
public function __construct(ApplicationName $application, VersionConstraint $versionConstraint) {
$this->application = $application;
$this->versionConstraint = $versionConstraint;
}
/**
* @return ApplicationName
*/
public function getApplicationName() {
return $this->application;
}
/**
* @return VersionConstraint
*/
public function getVersionConstraint() {
return $this->versionConstraint;
}
/**
* @return bool
*/
public function isExtension() {
return true;
}
/**
* @param ApplicationName $name
*
* @return bool
*/
public function isExtensionFor(ApplicationName $name) {
return $this->application->isEqual($name);
}
/**
* @param ApplicationName $name
* @param Version $version
*
* @return bool
*/
public function isCompatibleWith(ApplicationName $name, Version $version) {
return $this->isExtensionFor($name) && $this->versionConstraint->complies($version);
}
}

View File

@ -0,0 +1,20 @@
<?php
/*
* This file is part of PharIo\Manifest.
*
* (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PharIo\Manifest;
class Library extends Type {
/**
* @return bool
*/
public function isLibrary() {
return true;
}
}

View File

@ -0,0 +1,42 @@
<?php
/*
* This file is part of PharIo\Manifest.
*
* (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PharIo\Manifest;
class License {
/**
* @var string
*/
private $name;
/**
* @var Url
*/
private $url;
public function __construct($name, Url $url) {
$this->name = $name;
$this->url = $url;
}
/**
* @return string
*/
public function getName() {
return $this->name;
}
/**
* @return Url
*/
public function getUrl() {
return $this->url;
}
}

View File

@ -0,0 +1,138 @@
<?php
/*
* This file is part of PharIo\Manifest.
*
* (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PharIo\Manifest;
use PharIo\Version\Version;
class Manifest {
/**
* @var ApplicationName
*/
private $name;
/**
* @var Version
*/
private $version;
/**
* @var Type
*/
private $type;
/**
* @var CopyrightInformation
*/
private $copyrightInformation;
/**
* @var RequirementCollection
*/
private $requirements;
/**
* @var BundledComponentCollection
*/
private $bundledComponents;
public function __construct(ApplicationName $name, Version $version, Type $type, CopyrightInformation $copyrightInformation, RequirementCollection $requirements, BundledComponentCollection $bundledComponents) {
$this->name = $name;
$this->version = $version;
$this->type = $type;
$this->copyrightInformation = $copyrightInformation;
$this->requirements = $requirements;
$this->bundledComponents = $bundledComponents;
}
/**
* @return ApplicationName
*/
public function getName() {
return $this->name;
}
/**
* @return Version
*/
public function getVersion() {
return $this->version;
}
/**
* @return Type
*/
public function getType() {
return $this->type;
}
/**
* @return CopyrightInformation
*/
public function getCopyrightInformation() {
return $this->copyrightInformation;
}
/**
* @return RequirementCollection
*/
public function getRequirements() {
return $this->requirements;
}
/**
* @return BundledComponentCollection
*/
public function getBundledComponents() {
return $this->bundledComponents;
}
/**
* @return bool
*/
public function isApplication() {
return $this->type->isApplication();
}
/**
* @return bool
*/
public function isLibrary() {
return $this->type->isLibrary();
}
/**
* @return bool
*/
public function isExtension() {
return $this->type->isExtension();
}
/**
* @param ApplicationName $application
* @param Version|null $version
*
* @return bool
*/
public function isExtensionFor(ApplicationName $application, Version $version = null) {
if (!$this->isExtension()) {
return false;
}
/** @var Extension $type */
$type = $this->type;
if ($version !== null) {
return $type->isCompatibleWith($application, $version);
}
return $type->isExtensionFor($application);
}
}

View File

@ -0,0 +1,32 @@
<?php
/*
* This file is part of PharIo\Manifest.
*
* (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PharIo\Manifest;
class PhpExtensionRequirement implements Requirement {
/**
* @var string
*/
private $extension;
/**
* @param string $extension
*/
public function __construct($extension) {
$this->extension = $extension;
}
/**
* @return string
*/
public function __toString() {
return $this->extension;
}
}

View File

@ -0,0 +1,31 @@
<?php
/*
* This file is part of PharIo\Manifest.
*
* (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PharIo\Manifest;
use PharIo\Version\VersionConstraint;
class PhpVersionRequirement implements Requirement {
/**
* @var VersionConstraint
*/
private $versionConstraint;
public function __construct(VersionConstraint $versionConstraint) {
$this->versionConstraint = $versionConstraint;
}
/**
* @return VersionConstraint
*/
public function getVersionConstraint() {
return $this->versionConstraint;
}
}

View File

@ -0,0 +1,14 @@
<?php
/*
* This file is part of PharIo\Manifest.
*
* (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PharIo\Manifest;
interface Requirement {
}

View File

@ -0,0 +1,43 @@
<?php
/*
* This file is part of PharIo\Manifest.
*
* (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PharIo\Manifest;
class RequirementCollection implements \Countable, \IteratorAggregate {
/**
* @var Requirement[]
*/
private $requirements = [];
public function add(Requirement $requirement) {
$this->requirements[] = $requirement;
}
/**
* @return Requirement[]
*/
public function getRequirements() {
return $this->requirements;
}
/**
* @return int
*/
public function count() {
return count($this->requirements);
}
/**
* @return RequirementCollectionIterator
*/
public function getIterator() {
return new RequirementCollectionIterator($this);
}
}

View File

@ -0,0 +1,56 @@
<?php
/*
* This file is part of PharIo\Manifest.
*
* (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PharIo\Manifest;
class RequirementCollectionIterator implements \Iterator {
/**
* @var Requirement[]
*/
private $requirements = [];
/**
* @var int
*/
private $position;
public function __construct(RequirementCollection $requirements) {
$this->requirements = $requirements->getRequirements();
}
public function rewind() {
$this->position = 0;
}
/**
* @return bool
*/
public function valid() {
return $this->position < count($this->requirements);
}
/**
* @return int
*/
public function key() {
return $this->position;
}
/**
* @return Requirement
*/
public function current() {
return $this->requirements[$this->position];
}
public function next() {
$this->position++;
}
}

View File

@ -0,0 +1,60 @@
<?php
/*
* This file is part of PharIo\Manifest.
*
* (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PharIo\Manifest;
use PharIo\Version\VersionConstraint;
abstract class Type {
/**
* @return Application
*/
public static function application() {
return new Application;
}
/**
* @return Library
*/
public static function library() {
return new Library;
}
/**
* @param ApplicationName $application
* @param VersionConstraint $versionConstraint
*
* @return Extension
*/
public static function extension(ApplicationName $application, VersionConstraint $versionConstraint) {
return new Extension($application, $versionConstraint);
}
/**
* @return bool
*/
public function isApplication() {
return false;
}
/**
* @return bool
*/
public function isLibrary() {
return false;
}
/**
* @return bool
*/
public function isExtension() {
return false;
}
}

View File

@ -0,0 +1,47 @@
<?php
/*
* This file is part of PharIo\Manifest.
*
* (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PharIo\Manifest;
class Url {
/**
* @var string
*/
private $url;
/**
* @param string $url
*
* @throws InvalidUrlException
*/
public function __construct($url) {
$this->ensureUrlIsValid($url);
$this->url = $url;
}
/**
* @return string
*/
public function __toString() {
return $this->url;
}
/**
* @param string $url
*
* @throws InvalidUrlException
*/
private function ensureUrlIsValid($url) {
if (filter_var($url, \FILTER_VALIDATE_URL) === false) {
throw new InvalidUrlException;
}
}
}

View File

@ -0,0 +1,21 @@
<?php
/*
* This file is part of PharIo\Manifest.
*
* (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PharIo\Manifest;
class AuthorElement extends ManifestElement {
public function getName() {
return $this->getAttributeValue('name');
}
public function getEmail() {
return $this->getAttributeValue('email');
}
}

View File

@ -0,0 +1,19 @@
<?php
/*
* This file is part of PharIo\Manifest.
*
* (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PharIo\Manifest;
class AuthorElementCollection extends ElementCollection {
public function current() {
return new AuthorElement(
$this->getCurrentElement()
);
}
}

View File

@ -0,0 +1,19 @@
<?php
/*
* This file is part of PharIo\Manifest.
*
* (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PharIo\Manifest;
class BundlesElement extends ManifestElement {
public function getComponentElements() {
return new ComponentElementCollection(
$this->getChildrenByName('component')
);
}
}

View File

@ -0,0 +1,21 @@
<?php
/*
* This file is part of PharIo\Manifest.
*
* (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PharIo\Manifest;
class ComponentElement extends ManifestElement {
public function getName() {
return $this->getAttributeValue('name');
}
public function getVersion() {
return $this->getAttributeValue('version');
}
}

View File

@ -0,0 +1,19 @@
<?php
/*
* This file is part of PharIo\Manifest.
*
* (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PharIo\Manifest;
class ComponentElementCollection extends ElementCollection {
public function current() {
return new ComponentElement(
$this->getCurrentElement()
);
}
}

View File

@ -0,0 +1,31 @@
<?php
/*
* This file is part of PharIo\Manifest.
*
* (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PharIo\Manifest;
class ContainsElement extends ManifestElement {
public function getName() {
return $this->getAttributeValue('name');
}
public function getVersion() {
return $this->getAttributeValue('version');
}
public function getType() {
return $this->getAttributeValue('type');
}
public function getExtensionElement() {
return new ExtensionElement(
$this->getChildByName('extension')
);
}
}

View File

@ -0,0 +1,25 @@
<?php
/*
* This file is part of PharIo\Manifest.
*
* (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PharIo\Manifest;
class CopyrightElement extends ManifestElement {
public function getAuthorElements() {
return new AuthorElementCollection(
$this->getChildrenByName('author')
);
}
public function getLicenseElement() {
return new LicenseElement(
$this->getChildByName('license')
);
}
}

View File

@ -0,0 +1,58 @@
<?php
/*
* This file is part of PharIo\Manifest.
*
* (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PharIo\Manifest;
use DOMElement;
use DOMNodeList;
abstract class ElementCollection implements \Iterator {
/**
* @var DOMNodeList
*/
private $nodeList;
private $position;
/**
* ElementCollection constructor.
*
* @param DOMNodeList $nodeList
*/
public function __construct(DOMNodeList $nodeList) {
$this->nodeList = $nodeList;
$this->position = 0;
}
abstract public function current();
/**
* @return DOMElement
*/
protected function getCurrentElement() {
return $this->nodeList->item($this->position);
}
public function next() {
$this->position++;
}
public function key() {
return $this->position;
}
public function valid() {
return $this->position < $this->nodeList->length;
}
public function rewind() {
$this->position = 0;
}
}

View File

@ -0,0 +1,17 @@
<?php
/*
* This file is part of PharIo\Manifest.
*
* (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PharIo\Manifest;
class ExtElement extends ManifestElement {
public function getName() {
return $this->getAttributeValue('name');
}
}

View File

@ -0,0 +1,20 @@
<?php
/*
* This file is part of PharIo\Manifest.
*
* (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PharIo\Manifest;
class ExtElementCollection extends ElementCollection {
public function current() {
return new ExtElement(
$this->getCurrentElement()
);
}
}

View File

@ -0,0 +1,21 @@
<?php
/*
* This file is part of PharIo\Manifest.
*
* (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PharIo\Manifest;
class ExtensionElement extends ManifestElement {
public function getFor() {
return $this->getAttributeValue('for');
}
public function getCompatible() {
return $this->getAttributeValue('compatible');
}
}

View File

@ -0,0 +1,21 @@
<?php
/*
* This file is part of PharIo\Manifest.
*
* (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PharIo\Manifest;
class LicenseElement extends ManifestElement {
public function getType() {
return $this->getAttributeValue('type');
}
public function getUrl() {
return $this->getAttributeValue('url');
}
}

View File

@ -0,0 +1,118 @@
<?php
/*
* This file is part of PharIo\Manifest.
*
* (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PharIo\Manifest;
use DOMDocument;
use DOMElement;
class ManifestDocument {
const XMLNS = 'https://phar.io/xml/manifest/1.0';
/**
* @var DOMDocument
*/
private $dom;
/**
* ManifestDocument constructor.
*
* @param DOMDocument $dom
*/
private function __construct(DOMDocument $dom) {
$this->ensureCorrectDocumentType($dom);
$this->dom = $dom;
}
public static function fromFile($filename) {
if (!file_exists($filename)) {
throw new ManifestDocumentException(
sprintf('File "%s" not found', $filename)
);
}
return self::fromString(
file_get_contents($filename)
);
}
public static function fromString($xmlString) {
$prev = libxml_use_internal_errors(true);
libxml_clear_errors();
$dom = new DOMDocument();
$dom->loadXML($xmlString);
$errors = libxml_get_errors();
libxml_use_internal_errors($prev);
if (count($errors) !== 0) {
throw new ManifestDocumentLoadingException($errors);
}
return new self($dom);
}
public function getContainsElement() {
return new ContainsElement(
$this->fetchElementByName('contains')
);
}
public function getCopyrightElement() {
return new CopyrightElement(
$this->fetchElementByName('copyright')
);
}
public function getRequiresElement() {
return new RequiresElement(
$this->fetchElementByName('requires')
);
}
public function hasBundlesElement() {
return $this->dom->getElementsByTagNameNS(self::XMLNS, 'bundles')->length === 1;
}
public function getBundlesElement() {
return new BundlesElement(
$this->fetchElementByName('bundles')
);
}
private function ensureCorrectDocumentType(DOMDocument $dom) {
$root = $dom->documentElement;
if ($root->localName !== 'phar' || $root->namespaceURI !== self::XMLNS) {
throw new ManifestDocumentException('Not a phar.io manifest document');
}
}
/**
* @param $elementName
*
* @return DOMElement
*
* @throws ManifestDocumentException
*/
private function fetchElementByName($elementName) {
$element = $this->dom->getElementsByTagNameNS(self::XMLNS, $elementName)->item(0);
if (!$element instanceof DOMElement) {
throw new ManifestDocumentException(
sprintf('Element %s missing', $elementName)
);
}
return $element;
}
}

View File

@ -0,0 +1,48 @@
<?php
/*
* This file is part of PharIo\Manifest.
*
* (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PharIo\Manifest;
use LibXMLError;
class ManifestDocumentLoadingException extends \Exception implements Exception {
/**
* @var LibXMLError[]
*/
private $libxmlErrors;
/**
* ManifestDocumentLoadingException constructor.
*
* @param LibXMLError[] $libxmlErrors
*/
public function __construct(array $libxmlErrors) {
$this->libxmlErrors = $libxmlErrors;
$first = $this->libxmlErrors[0];
parent::__construct(
sprintf(
'%s (Line: %d / Column: %d / File: %s)',
$first->message,
$first->line,
$first->column,
$first->file
),
$first->code
);
}
/**
* @return LibXMLError[]
*/
public function getLibxmlErrors() {
return $this->libxmlErrors;
}
}

View File

@ -0,0 +1,100 @@
<?php
/*
* This file is part of PharIo\Manifest.
*
* (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PharIo\Manifest;
use DOMElement;
use DOMNodeList;
class ManifestElement {
const XMLNS = 'https://phar.io/xml/manifest/1.0';
/**
* @var DOMElement
*/
private $element;
/**
* ContainsElement constructor.
*
* @param DOMElement $element
*/
public function __construct(DOMElement $element) {
$this->element = $element;
}
/**
* @param string $name
*
* @return string
*
* @throws ManifestElementException
*/
protected function getAttributeValue($name) {
if (!$this->element->hasAttribute($name)) {
throw new ManifestElementException(
sprintf(
'Attribute %s not set on element %s',
$name,
$this->element->localName
)
);
}
return $this->element->getAttribute($name);
}
/**
* @param $elementName
*
* @return DOMElement
*
* @throws ManifestElementException
*/
protected function getChildByName($elementName) {
$element = $this->element->getElementsByTagNameNS(self::XMLNS, $elementName)->item(0);
if (!$element instanceof DOMElement) {
throw new ManifestElementException(
sprintf('Element %s missing', $elementName)
);
}
return $element;
}
/**
* @param $elementName
*
* @return DOMNodeList
*
* @throws ManifestElementException
*/
protected function getChildrenByName($elementName) {
$elementList = $this->element->getElementsByTagNameNS(self::XMLNS, $elementName);
if ($elementList->length === 0) {
throw new ManifestElementException(
sprintf('Element(s) %s missing', $elementName)
);
}
return $elementList;
}
/**
* @param string $elementName
*
* @return bool
*/
protected function hasChild($elementName) {
return $this->element->getElementsByTagNameNS(self::XMLNS, $elementName)->length !== 0;
}
}

View File

@ -0,0 +1,27 @@
<?php
/*
* This file is part of PharIo\Manifest.
*
* (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PharIo\Manifest;
class PhpElement extends ManifestElement {
public function getVersion() {
return $this->getAttributeValue('version');
}
public function hasExtElements() {
return $this->hasChild('ext');
}
public function getExtElements() {
return new ExtElementCollection(
$this->getChildrenByName('ext')
);
}
}

View File

@ -0,0 +1,19 @@
<?php
/*
* This file is part of PharIo\Manifest.
*
* (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PharIo\Manifest;
class RequiresElement extends ManifestElement {
public function getPHPElement() {
return new PhpElement(
$this->getChildByName('php')
);
}
}

View File

@ -0,0 +1,110 @@
<?php
namespace PharIo\Manifest;
/**
* @covers \PharIo\Manifest\ManifestDocumentMapper
*
* @uses \PharIo\Manifest\ApplicationName
* @uses \PharIo\Manifest\Author
* @uses \PharIo\Manifest\AuthorCollection
* @uses \PharIo\Manifest\AuthorCollectionIterator
* @uses \PharIo\Manifest\AuthorElement
* @uses \PharIo\Manifest\AuthorElementCollection
* @uses \PharIo\Manifest\BundledComponent
* @uses \PharIo\Manifest\BundledComponentCollection
* @uses \PharIo\Manifest\BundledComponentCollectionIterator
* @uses \PharIo\Manifest\BundlesElement
* @uses \PharIo\Manifest\ComponentElement
* @uses \PharIo\Manifest\ComponentElementCollection
* @uses \PharIo\Manifest\ContainsElement
* @uses \PharIo\Manifest\CopyrightElement
* @uses \PharIo\Manifest\CopyrightInformation
* @uses \PharIo\Manifest\ElementCollection
* @uses \PharIo\Manifest\Email
* @uses \PharIo\Manifest\ExtElement
* @uses \PharIo\Manifest\ExtElementCollection
* @uses \PharIo\Manifest\License
* @uses \PharIo\Manifest\LicenseElement
* @uses \PharIo\Manifest\Manifest
* @uses \PharIo\Manifest\ManifestDocument
* @uses \PharIo\Manifest\ManifestDocumentMapper
* @uses \PharIo\Manifest\ManifestElement
* @uses \PharIo\Manifest\ManifestLoader
* @uses \PharIo\Manifest\PhpElement
* @uses \PharIo\Manifest\PhpExtensionRequirement
* @uses \PharIo\Manifest\PhpVersionRequirement
* @uses \PharIo\Manifest\RequirementCollection
* @uses \PharIo\Manifest\RequirementCollectionIterator
* @uses \PharIo\Manifest\RequiresElement
* @uses \PharIo\Manifest\Type
* @uses \PharIo\Manifest\Url
* @uses \PharIo\Version\Version
* @uses \PharIo\Version\VersionConstraint
*/
class ManifestDocumentMapperTest extends \PHPUnit_Framework_TestCase {
/**
* @dataProvider dataProvider
*
* @param $expected
*
* @uses \PharIo\Manifest\Application
* @uses \PharIo\Manifest\ApplicationName
* @uses \PharIo\Manifest\Library
* @uses \PharIo\Manifest\Extension
* @uses \PharIo\Manifest\ExtensionElement
*/
public function testCanSerializeToString($expected) {
$manifestDocument = ManifestDocument::fromFile($expected);
$mapper = new ManifestDocumentMapper();
$this->assertInstanceOf(
Manifest::class,
$mapper->map($manifestDocument)
);
}
public function dataProvider() {
return [
'application' => [__DIR__ . '/_fixture/phpunit-5.6.5.xml'],
'library' => [__DIR__ . '/_fixture/library.xml'],
'extension' => [__DIR__ . '/_fixture/extension.xml']
];
}
public function testThrowsExceptionOnUnsupportedType() {
$manifestDocument = ManifestDocument::fromFile(__DIR__ . '/_fixture/custom.xml');
$mapper = new ManifestDocumentMapper();
$this->expectException(ManifestDocumentMapperException::class);
$mapper->map($manifestDocument);
}
public function testInvalidVersionInformationThrowsException() {
$manifestDocument = ManifestDocument::fromFile(__DIR__ . '/_fixture/invalidversion.xml');
$mapper = new ManifestDocumentMapper();
$this->expectException(ManifestDocumentMapperException::class);
$mapper->map($manifestDocument);
}
public function testInvalidVersionConstraintThrowsException() {
$manifestDocument = ManifestDocument::fromFile(__DIR__ . '/_fixture/invalidversionconstraint.xml');
$mapper = new ManifestDocumentMapper();
$this->expectException(ManifestDocumentMapperException::class);
$mapper->map($manifestDocument);
}
/**
* @uses \PharIo\Manifest\ExtensionElement
*/
public function testInvalidCompatibleConstraintThrowsException() {
$manifestDocument = ManifestDocument::fromFile(__DIR__ . '/_fixture/extension-invalidcompatible.xml');
$mapper = new ManifestDocumentMapper();
$this->expectException(ManifestDocumentMapperException::class);
$mapper->map($manifestDocument);
}
}

View File

@ -0,0 +1,83 @@
<?php
namespace PharIo\Manifest;
/**
* @covers \PharIo\Manifest\ManifestLoader
*
* @uses \PharIo\Manifest\Author
* @uses \PharIo\Manifest\AuthorCollection
* @uses \PharIo\Manifest\AuthorCollectionIterator
* @uses \PharIo\Manifest\AuthorElement
* @uses \PharIo\Manifest\AuthorElementCollection
* @uses \PharIo\Manifest\ApplicationName
* @uses \PharIo\Manifest\BundledComponent
* @uses \PharIo\Manifest\BundledComponentCollection
* @uses \PharIo\Manifest\BundledComponentCollectionIterator
* @uses \PharIo\Manifest\BundlesElement
* @uses \PharIo\Manifest\ComponentElement
* @uses \PharIo\Manifest\ComponentElementCollection
* @uses \PharIo\Manifest\ContainsElement
* @uses \PharIo\Manifest\CopyrightElement
* @uses \PharIo\Manifest\CopyrightInformation
* @uses \PharIo\Manifest\ElementCollection
* @uses \PharIo\Manifest\Email
* @uses \PharIo\Manifest\ExtElement
* @uses \PharIo\Manifest\ExtElementCollection
* @uses \PharIo\Manifest\License
* @uses \PharIo\Manifest\LicenseElement
* @uses \PharIo\Manifest\Manifest
* @uses \PharIo\Manifest\ManifestDocument
* @uses \PharIo\Manifest\ManifestDocumentMapper
* @uses \PharIo\Manifest\ManifestElement
* @uses \PharIo\Manifest\ManifestLoader
* @uses \PharIo\Manifest\PhpElement
* @uses \PharIo\Manifest\PhpExtensionRequirement
* @uses \PharIo\Manifest\PhpVersionRequirement
* @uses \PharIo\Manifest\RequirementCollection
* @uses \PharIo\Manifest\RequirementCollectionIterator
* @uses \PharIo\Manifest\RequiresElement
* @uses \PharIo\Manifest\Type
* @uses \PharIo\Manifest\Url
* @uses \PharIo\Version\Version
* @uses \PharIo\Version\VersionConstraint
*/
class ManifestLoaderTest extends \PHPUnit_Framework_TestCase {
public function testCanBeLoadedFromFile() {
$this->assertInstanceOf(
Manifest::class,
ManifestLoader::fromFile(__DIR__ . '/_fixture/library.xml')
);
}
public function testCanBeLoadedFromString() {
$this->assertInstanceOf(
Manifest::class,
ManifestLoader::fromString(
file_get_contents(__DIR__ . '/_fixture/library.xml')
)
);
}
public function testCanBeLoadedFromPhar() {
$this->assertInstanceOf(
Manifest::class,
ManifestLoader::fromPhar(__DIR__ . '/_fixture/test.phar')
);
}
public function testLoadingNonExistingFileThrowsException() {
$this->expectException(ManifestLoaderException::class);
ManifestLoader::fromFile('/not/existing');
}
/**
* @uses \PharIo\Manifest\ManifestDocumentLoadingException
*/
public function testLoadingInvalidXmlThrowsException() {
$this->expectException(ManifestLoaderException::class);
ManifestLoader::fromString('<?xml version="1.0" ?><broken>');
}
}

View File

@ -0,0 +1,114 @@
<?php
namespace PharIo\Manifest;
use PharIo\Version\Version;
/**
* @covers \PharIo\Manifest\ManifestSerializer
*
* @uses \PharIo\Manifest\ApplicationName
* @uses \PharIo\Manifest\Author
* @uses \PharIo\Manifest\AuthorCollection
* @uses \PharIo\Manifest\AuthorCollectionIterator
* @uses \PharIo\Manifest\AuthorElement
* @uses \PharIo\Manifest\AuthorElementCollection
* @uses \PharIo\Manifest\BundledComponent
* @uses \PharIo\Manifest\BundledComponentCollection
* @uses \PharIo\Manifest\BundledComponentCollectionIterator
* @uses \PharIo\Manifest\BundlesElement
* @uses \PharIo\Manifest\ComponentElement
* @uses \PharIo\Manifest\ComponentElementCollection
* @uses \PharIo\Manifest\ContainsElement
* @uses \PharIo\Manifest\CopyrightElement
* @uses \PharIo\Manifest\CopyrightInformation
* @uses \PharIo\Manifest\ElementCollection
* @uses \PharIo\Manifest\Email
* @uses \PharIo\Manifest\ExtElement
* @uses \PharIo\Manifest\ExtElementCollection
* @uses \PharIo\Manifest\License
* @uses \PharIo\Manifest\LicenseElement
* @uses \PharIo\Manifest\Manifest
* @uses \PharIo\Manifest\ManifestDocument
* @uses \PharIo\Manifest\ManifestDocumentMapper
* @uses \PharIo\Manifest\ManifestElement
* @uses \PharIo\Manifest\ManifestLoader
* @uses \PharIo\Manifest\PhpElement
* @uses \PharIo\Manifest\PhpExtensionRequirement
* @uses \PharIo\Manifest\PhpVersionRequirement
* @uses \PharIo\Manifest\RequirementCollection
* @uses \PharIo\Manifest\RequirementCollectionIterator
* @uses \PharIo\Manifest\RequiresElement
* @uses \PharIo\Manifest\Type
* @uses \PharIo\Manifest\Url
* @uses \PharIo\Version\Version
* @uses \PharIo\Version\VersionConstraint
*/
class ManifestSerializerTest extends \PHPUnit_Framework_TestCase {
/**
* @dataProvider dataProvider
*
* @param $expected
*
* @uses \PharIo\Manifest\Application
* @uses \PharIo\Manifest\Library
* @uses \PharIo\Manifest\Extension
* @uses \PharIo\Manifest\ExtensionElement
*/
public function testCanSerializeToString($expected) {
$manifest = ManifestLoader::fromString($expected);
$serializer = new ManifestSerializer();
$this->assertXmlStringEqualsXmlString(
$expected,
$serializer->serializeToString($manifest)
);
}
public function dataProvider() {
return [
'application' => [file_get_contents(__DIR__ . '/_fixture/phpunit-5.6.5.xml')],
'library' => [file_get_contents(__DIR__ . '/_fixture/library.xml')],
'extension' => [file_get_contents(__DIR__ . '/_fixture/extension.xml')]
];
}
/**
* @uses \PharIo\Manifest\Library
* @uses \PharIo\Manifest\ApplicationName
*/
public function testCanSerializeToFile() {
$src = __DIR__ . '/_fixture/library.xml';
$dest = '/tmp/' . uniqid('serializer', true);
$manifest = ManifestLoader::fromFile($src);
$serializer = new ManifestSerializer();
$serializer->serializeToFile($manifest, $dest);
$this->assertXmlFileEqualsXmlFile($src, $dest);
unlink($dest);
}
/**
* @uses \PharIo\Manifest\ApplicationName
*/
public function testCanHandleUnknownType() {
$type = $this->getMockForAbstractClass(Type::class);
$manifest = new Manifest(
new ApplicationName('testvendor/testname'),
new Version('1.0.0'),
$type,
new CopyrightInformation(
new AuthorCollection(),
new License('bsd-3', new Url('https://some/uri'))
),
new RequirementCollection(),
new BundledComponentCollection()
);
$serializer = new ManifestSerializer();
$this->assertXmlStringEqualsXmlFile(
__DIR__ . '/_fixture/custom.xml',
$serializer->serializeToString($manifest)
);
}
}

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<phar xmlns="https://phar.io/xml/manifest/1.0">
<contains name="testvendor/testname" version="1.0.0" type="custom"/>
<copyright>
<license type="bsd-3" url="https://some/uri"/>
</copyright>
<requires>
<php version="*"/>
</requires>
</phar>

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<phar xmlns="https://phar.io/xml/manifest/1.0">
<contains name="phpunit/phpunit-example-extension" version="1.0.0" type="extension">
<extension for="phpunit/phpunit" compatible="invalid"/>
</contains>
<copyright>
<author name="Sebastian Bergmann" email="sebastian@phpunit.de"/>
<license type="BSD-3-Clause" url="https://github.com/sebastianbergmann/phpunit-example-extension/blob/master/LICENSE"/>
</copyright>
<requires>
<php version="^7.0"/>
</requires>
</phar>

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<phar xmlns="https://phar.io/xml/manifest/1.0">
<contains name="phpunit/phpunit-example-extension" version="1.0.0" type="extension">
<extension for="phpunit/phpunit" compatible="^5.7"/>
</contains>
<copyright>
<author name="Sebastian Bergmann" email="sebastian@phpunit.de"/>
<license type="BSD-3-Clause" url="https://github.com/sebastianbergmann/phpunit-example-extension/blob/master/LICENSE"/>
</copyright>
<requires>
<php version="^7.0"/>
</requires>
</phar>

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<phar xmlns="https://phar.io/xml/manifest/1.0">
<contains name="some/library" version="abc" type="library" />
<copyright>
<author name="Reiner Zufall" email="reiner@zufall.de"/>
<license type="BSD-3-Clause" url="https://domain.tld/LICENSE"/>
</copyright>
<requires>
<php version="7.0"/>
</requires>
</phar>

Some files were not shown because too many files have changed in this diff Show More