├── .gitignore ├── .php_cs ├── .travis.yml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── benchmark └── benchmark.php ├── composer.json ├── composer.lock ├── phpunit.xml ├── src ├── Detail │ ├── AbstractIsolator.php │ ├── Autoloader.php │ └── CodeGenerator.php ├── IsolatorTrait.php └── register-autoloader.php └── test ├── src ├── ClassA.php ├── ClassB.php ├── ClassC.php ├── ClassD.php ├── TraitUsage.php └── function.php └── suite ├── Detail ├── AutoloaderTest.php └── CodeGeneratorTest.php ├── IsolatorTest.php └── IsolatorTraitTest.php /.gitignore: -------------------------------------------------------------------------------- 1 | # archer start 2 | /artifacts/ 3 | /vendor/ 4 | # archer end 5 | -------------------------------------------------------------------------------- /.php_cs: -------------------------------------------------------------------------------- 1 | in(__DIR__) 5 | ->exclude([ 6 | 'artifacts', 7 | 'vendor', 8 | ]); 9 | 10 | return PhpCsFixer\Config::create() 11 | ->setFinder($finder) 12 | ->setCacheFile(__DIR__ . '/artifacts/.php_cs.cache') 13 | ->setRules([ 14 | '@PSR2' => true, 15 | 16 | 'array_syntax' => ['syntax' => 'short'], 17 | 'binary_operator_spaces' => false, 18 | 'blank_line_after_opening_tag' => true, 19 | 'blank_line_before_return' => true, 20 | 'braces' => false, 21 | 'cast_spaces' => true, 22 | 'class_definition' => ['singleLine' => false], 23 | 'concat_space' => ['spacing' => 'one'], 24 | 'declare_equal_normalize' => true, 25 | 'function_typehint_space' => true, 26 | 'hash_to_slash_comment' => true, 27 | 'heredoc_to_nowdoc' => true, 28 | 'include' => true, 29 | 'linebreak_after_opening_tag' => true, 30 | 'lowercase_cast' => true, 31 | 'method_separation' => true, 32 | 'native_function_casing' => true, 33 | 'new_with_braces' => true, 34 | 'no_blank_lines_after_class_opening' => true, 35 | 'no_blank_lines_after_phpdoc' => true, 36 | 'no_empty_comment' => true, 37 | 'no_empty_phpdoc' => true, 38 | 'no_empty_statement' => true, 39 | 'no_extra_consecutive_blank_lines' => true, 40 | 'no_leading_import_slash' => true, 41 | 'no_leading_namespace_whitespace' => true, 42 | 'no_mixed_echo_print' => true, 43 | 'no_multiline_whitespace_before_semicolons' => true, 44 | 'no_short_bool_cast' => true, 45 | 'no_singleline_whitespace_before_semicolons' => true, 46 | 'no_spaces_around_offset' => true, 47 | 'no_trailing_comma_in_singleline_array' => true, 48 | 'no_unneeded_control_parentheses' => true, 49 | 'no_unused_imports' => true, 50 | 'no_whitespace_before_comma_in_array' => true, 51 | 'no_whitespace_in_blank_line' => true, 52 | 'normalize_index_brace' => true, 53 | 'object_operator_without_whitespace' => true, 54 | 'ordered_imports' => true, 55 | 'phpdoc_align' => true, 56 | 'phpdoc_indent' => true, 57 | 'phpdoc_no_package' => true, 58 | 'phpdoc_scalar' => true, 59 | 'phpdoc_to_comment' => true, 60 | 'phpdoc_trim' => true, 61 | 'phpdoc_types' => true, 62 | 'pre_increment' => true, 63 | 'return_type_declaration' => true, 64 | 'self_accessor' => true, 65 | 'short_scalar_cast' => true, 66 | 'single_blank_line_before_namespace' => true, 67 | 'single_quote' => true, 68 | 'space_after_semicolon' => true, 69 | 'standardize_not_equals' => true, 70 | 'ternary_operator_spaces' => true, 71 | 'trailing_comma_in_multiline_array' => true, 72 | 'trim_array_spaces' => true, 73 | 'unary_operator_spaces' => true, 74 | 'whitespace_after_comma_in_array' => true, 75 | ]); 76 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: php 3 | php: 4 | - '7.1' 5 | - '7.2' 6 | - '7.3' 7 | - nightly 8 | matrix: 9 | fast_finish: true 10 | allow_failures: 11 | - php: nightly 12 | before_install: 13 | - phpenv config-rm xdebug.ini || true 14 | - "[[ $GITHUB_TOKEN ]] && composer config --global github-oauth.github.com $GITHUB_TOKEN" 15 | install: composer install --no-interaction 16 | script: phpdbg -qrr vendor/bin/phpunit 17 | after_script: bash <(curl -s https://codecov.io/bash) 18 | env: 19 | global: 20 | secure: RmDEsZS53wJfyMO/v7OgqZ2R4P2RqVMicAhvgXroeprSlsthqqxIDOS4ncPKdygHMaInbDEEMSPNomWKTLpDsjBUue9ypdYNLGAX23VrIQriyWiHpF0nEFh9ikU1deJ0ErpBNUYxJWBSofWT4+m0bVbf6gTh+/lSyjH5G+qtpFw= 21 | cache: 22 | directories: 23 | - "$HOME/.composer/cache/files" 24 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Isolator Changelog 2 | 3 | ### Next Release 4 | 5 | - **[BC]** Remove `PackageInfo` type 6 | 7 | ### 3.0.3 (2015-03-27) 8 | 9 | - **[FIXED]** Generated code file is now created with the correct mode 10 | 11 | ### 3.0.2 (2015-03-23) 12 | 13 | - **[FIXED]** Generated code directory is now created with the correct mode 14 | 15 | ### 3.0.1 (2014-10-21) 16 | 17 | - **[FIXED]** References are now preserved when calling functions with variable arguments 18 | 19 | ### 3.0.0 (2014-10-08) 20 | 21 | - **[BC]** Removed `Isolator::getIsolator()` and `resetIsolator()` 22 | - **[BC]** Removed `Isolator::className()` (the full class name is now always `Icecave\Isolator\Isolator`) 23 | - **[FIXED]** Calling functions with variable arguments now works correctly in PHP 5.6 24 | - **[NEW]** Added `Isolator::set()` 25 | - **[IMPROVED]** Code is now generated via a custom autoloader, and then cached, providing a massive performance improvement 26 | - **[IMRPOVED]** Several micro-optimisations to invocation of function-like language constructs 27 | 28 | While this release contains several backwards compatibility breaks, the `Isolator` class itself still behaves as per the 29 | examples given in the README file of v2.3.0. 30 | 31 | ### 2.3.0 (2014-08-12) 32 | 33 | - **[NEW]** Added support for isolation of the `new` operator 34 | 35 | ### 2.2.1 (2014-02-27) 36 | 37 | - **[IMPROVED]** Updated autoloader to [PSR-4](http://www.php-fig.org/psr/psr-4/) 38 | 39 | ### 2.2.0 (2013-06-04) 40 | 41 | - **[NEW]** Added `IsolatorTrait` to easily add an isolator dependency to a class 42 | - **[NEW]** Added `Isolator::className()` method to get the actual class name of the generated isolator 43 | - **[IMPROVED]** Several minor improvements to PSR compliance, documentation and test coverage 44 | 45 | ### 2.1.2 (2013-04-04) 46 | 47 | - **[FIXED]** Return values of isolated `include/require[_once]` calls are now propagated correctly 48 | - **[NEW]** Integrated `icecave/archer` (previously `icecave/testing`) 49 | 50 | ### 2.1.1 (2013-01-13) 51 | 52 | - **[NEW]** Integrated `icecave/testing` 53 | - **[IMPROVED]** Improved documentation 54 | - **[IMPROVED]** Improved PSR compliance 55 | 56 | ### 2.1.0 (2012-08-12) 57 | 58 | - **[NEW]** Added support for isolation of inclusion directives (`include/require[_once]`) 59 | 60 | ### 2.0.0 (2012-08-04) 61 | 62 | - **[BC]** Changed vendor namespace from `IcecaveStudios` to `Icecave` 63 | - **[BC]** Changed composer package name from `IcecaveStudios/isolator` to `icecave/isolator` 64 | 65 | ### 1.0.1 (2012-07-29) 66 | 67 | - **[IMPROVED]** Re-organised directory layout to be consistent with other Composer projects 68 | 69 | ### 1.0.0 (2012-07-09) 70 | 71 | * Initial release 72 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2012 James Harris, Erin Millard 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Isolator 2 | 3 | [![Build Status](http://img.shields.io/travis/icecave/isolator/master.svg?style=flat-square)](https://travis-ci.org/icecave/isolator) 4 | [![Code Coverage](https://img.shields.io/codecov/c/github/icecave/isolator/master.svg?style=flat-square)](https://codecov.io/github/icecave/isolator) 5 | [![Latest Version](http://img.shields.io/packagist/v/icecave/isolator.svg?style=flat-square&label=semver)](https://semver.org) 6 | 7 | **Isolator** simplifies testing of classes that make use of global functions by treating all global functions as methods 8 | on an "isolator" object. 9 | 10 | composer require icecave/isolator 11 | 12 | ## Rationale 13 | 14 | A large number of PHP extensions (and the PHP core) implement their functionality as global functions. Testing classes 15 | that use these functions quickly becomes difficult due to the inability to replace them with [test doubles](http://en.wikipedia.org/wiki/Test_double). 16 | 17 | **Isolator** endeavours to solve this problem by acting as a proxy between your class and global functions. An isolator 18 | instance is passed into your object as a [dependency](http://en.wikipedia.org/wiki/Dependency_injection) and used in 19 | place of any global function calls that you may want to replace when testing. 20 | 21 | ## Example 22 | 23 | The following class makes use of [file_get_contents()](http://php.net/manual/en/function.file-get-contents.php) to read 24 | the contents of a file. 25 | 26 | ```php 27 | class MyDocument 28 | { 29 | public function __construct($filename) 30 | { 31 | $this->filename = $filename; 32 | } 33 | 34 | public function getContents() 35 | { 36 | return file_get_contents($this->filename); 37 | } 38 | 39 | protected $filename; 40 | } 41 | ``` 42 | 43 | Despite the simplicity of the example, the class immediately becomes difficult to test due to it's reliance on the 44 | filesystem. In order to test this class you might be inclined to set up some static fixtures on disk, make a temporary 45 | directory when your test suite is set up or perhaps even use a [virtual filesystem wrapper](http://code.google.com/p/bovigo/wiki/vfsStream). 46 | 47 | **Isolator** provides a fourth alternative. Given below is the same example rewritten using an `Isolator` instance. 48 | 49 | ```php 50 | use Icecave\Isolator\Isolator; 51 | 52 | class MyDocument 53 | { 54 | public function __construct($filename, Isolator $isolator = null) 55 | { 56 | $this->filename = $filename; 57 | $this->isolator = Isolator::get($isolator); 58 | } 59 | 60 | public function getContents() 61 | { 62 | return $this->isolator->file_get_contents($this->filename); 63 | } 64 | 65 | protected $filename; 66 | protected $isolator; 67 | } 68 | ``` 69 | 70 | `MyDocument` now takes an instance of `Isolator` in it's constructor. It would be a pain - and unnecessary - to create a 71 | new `Isolator` instance every time you construct an object in your production code, so a shared instance is made 72 | accessible using the `Isolator::get()` method. If a non-null value is passed to `Isolator::get()` it is returned 73 | unchanged, allowing you to replace the isolator when necessary. 74 | 75 | `MyDocument::getContents()` is also updated to use the isolator instance rather than calling the global function 76 | directly. The behavior of `MyDocument` remains unchanged but testing the class is easy, as will be shown in the example 77 | test suite below. 78 | 79 | *Note: The test below is written for the [PHPUnit](http://www.phpunit.de) testing framework, using [Phake](https://github.com/mlively/Phake) 80 | for mocking. Phake provides a more flexible alternative to PHPUnit's built-in mock objects.* 81 | 82 | ```php 83 | class MyDocumentTest extends PHPUnit\Framework\TestCase 84 | { 85 | public function setUp() 86 | { 87 | // First a mocked isolator instance is created ... 88 | $this->isolator = Phake::mock('Icecave\Isolator\Isolator'); 89 | 90 | // That isolator instance is given to the MyDocument instance 91 | // that is to be tested ... 92 | $this->myDocument = new MyDocument('foo.txt', $this->isolator); 93 | } 94 | 95 | public function testGetContents() 96 | { 97 | // Phake is used to configure the mocked isolator to return a known 98 | // string when file_get_contents() is called with a parameter equal 99 | // to 'foo.txt' ... 100 | Phake::when($this->isolator) 101 | ->file_get_contents('foo.txt') 102 | ->thenReturn('This is the file contents.'); 103 | 104 | // MyDocument::getContents() is called, and it's result checked ... 105 | $contents = $this->myDocument->getContents(); 106 | $this->assertEquals($contents, 'This is the file contents.'); 107 | 108 | // Finally Phake is used to verify that a call to file_get_contents() 109 | // was made as expected ... 110 | Phake::verify($this->isolator) 111 | ->file_get_contents('foo.txt'); 112 | } 113 | } 114 | ``` 115 | 116 | The test verifies the behavior of the `MyDocument` class completely, without requiring any disk access. 117 | 118 | Using an isolator is most helpful when testing code that uses functions which maintain global state or utilize external 119 | resources such as databases, filesystems, etc. It is usually unnecessary to mock out deterministic functions such as 120 | `strlen()`, for example. 121 | 122 | ## Isolator Trait 123 | 124 | In PHP 5.4 and later, it is also possible to use `IsolatorTrait` to bring an isolator into your class. The isolator 125 | instance is accessed using `$this->isolator()` and can be set via `$this->setIsolator()`. 126 | 127 | ```php 128 | use Icecave\Isolator\IsolatorTrait; 129 | 130 | class MyDocument 131 | { 132 | use IsolatorTrait; 133 | 134 | public function __construct($filename) 135 | { 136 | $this->filename = $filename; 137 | } 138 | 139 | public function getContents() 140 | { 141 | return $this->isolator()->file_get_contents($this->filename); 142 | } 143 | 144 | protected $filename; 145 | } 146 | ``` 147 | 148 | ## Language Constructs 149 | 150 | **Isolator** can also be used to invoke the following function-like language constructs: 151 | 152 | * `include`, `include_once`, `require` and `require_once` 153 | * `exit` and `die` 154 | * `echo` 155 | * `eval` 156 | * `new` 157 | 158 | ## Peculiarities 159 | 160 | Several of PHP's core global functions have some peculiarities and inconsitencies in the way they are defined. 161 | **Isolator** attempts to accomodate such inconsistencies when possible, but may have issues with some native C functions 162 | for which parameter reflection information is non-standard or incorrect. These issues seem to be largely rectified as of 163 | PHP 5.6. 164 | -------------------------------------------------------------------------------- /benchmark/benchmark.php: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | getFilename() . PHP_EOL; 11 | 12 | class TestClass 13 | { 14 | public function __construct($param = null) 15 | { 16 | } 17 | } 18 | 19 | function runBenchmark($name, callable $work) 20 | { 21 | printf('-- %s --' . PHP_EOL, $name); 22 | 23 | $total = 0; 24 | 25 | ob_start(); 26 | 27 | for ($i = 0; $i < ITERATIONS; ++$i) { 28 | $start = microtime(true); 29 | $work(); 30 | $end = microtime(true); 31 | $total += $end - $start; 32 | } 33 | 34 | ob_end_clean(); 35 | 36 | printf('Iterations: %d' . PHP_EOL, ITERATIONS); 37 | printf('Elapsed Time: %.15f' . PHP_EOL, $total); 38 | printf('Average Time: %.15f' . PHP_EOL, $total / ITERATIONS); 39 | printf(PHP_EOL); 40 | } 41 | 42 | runBenchmark( 43 | 'fixed arguments', 44 | function () use ($isolator) { 45 | $isolator->strlen('foo'); 46 | } 47 | ); 48 | 49 | runBenchmark( 50 | 'variable arguments', 51 | function () use ($isolator) { 52 | $isolator->sprintf('%d %d %d %d %d', 1, 2, 3, 4, 5); 53 | } 54 | ); 55 | 56 | runBenchmark( 57 | 'reference parameter', 58 | function () use ($isolator) { 59 | $matches = array(); 60 | $isolator->preg_match('/./', 'a', $matches); 61 | } 62 | ); 63 | 64 | runBenchmark( 65 | 'echo', 66 | function () use ($isolator) { 67 | $isolator->echo('.'); 68 | } 69 | ); 70 | 71 | runBenchmark( 72 | 'new', 73 | function () use ($isolator) { 74 | $isolator->new('TestClass'); 75 | } 76 | ); 77 | 78 | runBenchmark( 79 | 'new with arguments', 80 | function () use ($isolator) { 81 | $isolator->new('TestClass', 'arg'); 82 | } 83 | ); 84 | 85 | runBenchmark( 86 | 'eval', 87 | function () use ($isolator) { 88 | $isolator->eval('return 1;'); 89 | } 90 | ); 91 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "icecave/isolator", 3 | "description": "Dependency injection for global functions.", 4 | "keywords": [ 5 | "test", 6 | "phpunit", 7 | "unit", 8 | "mock", 9 | "fake", 10 | "double", 11 | "stub" 12 | ], 13 | "homepage": "https://github.com/icecave/isolator", 14 | "license": "MIT", 15 | "authors": [ 16 | { 17 | "name": "James Harris", 18 | "email": "mailjamesharris@gmail.com", 19 | "homepage": "https://github.com/jmalloc" 20 | }, 21 | { 22 | "name": "Erin Millard", 23 | "email": "ezzatron@gmail.com", 24 | "homepage": "http://ezzatron.com/" 25 | } 26 | ], 27 | "require": { 28 | "php": "^7.1" 29 | }, 30 | "require-dev": { 31 | "friendsofphp/php-cs-fixer": "^2", 32 | "phake/phake": "^1", 33 | "phpunit/phpunit": "^7" 34 | }, 35 | "autoload": { 36 | "psr-4": { 37 | "Icecave\\Isolator\\": "src" 38 | }, 39 | "files": [ 40 | "src/register-autoloader.php" 41 | ] 42 | }, 43 | "autoload-dev": { "psr-4": { "Icecave\\Isolator\\": "test/src" } }, 44 | "config": { 45 | "sort-packages": true, 46 | "platform": { 47 | "php": "7.1" 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", 5 | "This file is @generated automatically" 6 | ], 7 | "content-hash": "b125c3d6758c12807b895dfe6cdd9204", 8 | "packages": [], 9 | "packages-dev": [ 10 | { 11 | "name": "composer/semver", 12 | "version": "1.5.0", 13 | "source": { 14 | "type": "git", 15 | "url": "https://github.com/composer/semver.git", 16 | "reference": "46d9139568ccb8d9e7cdd4539cab7347568a5e2e" 17 | }, 18 | "dist": { 19 | "type": "zip", 20 | "url": "https://api.github.com/repos/composer/semver/zipball/46d9139568ccb8d9e7cdd4539cab7347568a5e2e", 21 | "reference": "46d9139568ccb8d9e7cdd4539cab7347568a5e2e", 22 | "shasum": "" 23 | }, 24 | "require": { 25 | "php": "^5.3.2 || ^7.0" 26 | }, 27 | "require-dev": { 28 | "phpunit/phpunit": "^4.5 || ^5.0.5", 29 | "phpunit/phpunit-mock-objects": "2.3.0 || ^3.0" 30 | }, 31 | "type": "library", 32 | "extra": { 33 | "branch-alias": { 34 | "dev-master": "1.x-dev" 35 | } 36 | }, 37 | "autoload": { 38 | "psr-4": { 39 | "Composer\\Semver\\": "src" 40 | } 41 | }, 42 | "notification-url": "https://packagist.org/downloads/", 43 | "license": [ 44 | "MIT" 45 | ], 46 | "authors": [ 47 | { 48 | "name": "Nils Adermann", 49 | "email": "naderman@naderman.de", 50 | "homepage": "http://www.naderman.de" 51 | }, 52 | { 53 | "name": "Jordi Boggiano", 54 | "email": "j.boggiano@seld.be", 55 | "homepage": "http://seld.be" 56 | }, 57 | { 58 | "name": "Rob Bast", 59 | "email": "rob.bast@gmail.com", 60 | "homepage": "http://robbast.nl" 61 | } 62 | ], 63 | "description": "Semver library that offers utilities, version constraint parsing and validation.", 64 | "keywords": [ 65 | "semantic", 66 | "semver", 67 | "validation", 68 | "versioning" 69 | ], 70 | "time": "2019-03-19T17:25:45+00:00" 71 | }, 72 | { 73 | "name": "composer/xdebug-handler", 74 | "version": "1.3.3", 75 | "source": { 76 | "type": "git", 77 | "url": "https://github.com/composer/xdebug-handler.git", 78 | "reference": "46867cbf8ca9fb8d60c506895449eb799db1184f" 79 | }, 80 | "dist": { 81 | "type": "zip", 82 | "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/46867cbf8ca9fb8d60c506895449eb799db1184f", 83 | "reference": "46867cbf8ca9fb8d60c506895449eb799db1184f", 84 | "shasum": "" 85 | }, 86 | "require": { 87 | "php": "^5.3.2 || ^7.0", 88 | "psr/log": "^1.0" 89 | }, 90 | "require-dev": { 91 | "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5" 92 | }, 93 | "type": "library", 94 | "autoload": { 95 | "psr-4": { 96 | "Composer\\XdebugHandler\\": "src" 97 | } 98 | }, 99 | "notification-url": "https://packagist.org/downloads/", 100 | "license": [ 101 | "MIT" 102 | ], 103 | "authors": [ 104 | { 105 | "name": "John Stevenson", 106 | "email": "john-stevenson@blueyonder.co.uk" 107 | } 108 | ], 109 | "description": "Restarts a process without xdebug.", 110 | "keywords": [ 111 | "Xdebug", 112 | "performance" 113 | ], 114 | "time": "2019-05-27T17:52:04+00:00" 115 | }, 116 | { 117 | "name": "doctrine/annotations", 118 | "version": "v1.6.1", 119 | "source": { 120 | "type": "git", 121 | "url": "https://github.com/doctrine/annotations.git", 122 | "reference": "53120e0eb10355388d6ccbe462f1fea34ddadb24" 123 | }, 124 | "dist": { 125 | "type": "zip", 126 | "url": "https://api.github.com/repos/doctrine/annotations/zipball/53120e0eb10355388d6ccbe462f1fea34ddadb24", 127 | "reference": "53120e0eb10355388d6ccbe462f1fea34ddadb24", 128 | "shasum": "" 129 | }, 130 | "require": { 131 | "doctrine/lexer": "1.*", 132 | "php": "^7.1" 133 | }, 134 | "require-dev": { 135 | "doctrine/cache": "1.*", 136 | "phpunit/phpunit": "^6.4" 137 | }, 138 | "type": "library", 139 | "extra": { 140 | "branch-alias": { 141 | "dev-master": "1.6.x-dev" 142 | } 143 | }, 144 | "autoload": { 145 | "psr-4": { 146 | "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" 147 | } 148 | }, 149 | "notification-url": "https://packagist.org/downloads/", 150 | "license": [ 151 | "MIT" 152 | ], 153 | "authors": [ 154 | { 155 | "name": "Roman Borschel", 156 | "email": "roman@code-factory.org" 157 | }, 158 | { 159 | "name": "Benjamin Eberlei", 160 | "email": "kontakt@beberlei.de" 161 | }, 162 | { 163 | "name": "Guilherme Blanco", 164 | "email": "guilhermeblanco@gmail.com" 165 | }, 166 | { 167 | "name": "Jonathan Wage", 168 | "email": "jonwage@gmail.com" 169 | }, 170 | { 171 | "name": "Johannes Schmitt", 172 | "email": "schmittjoh@gmail.com" 173 | } 174 | ], 175 | "description": "Docblock Annotations Parser", 176 | "homepage": "http://www.doctrine-project.org", 177 | "keywords": [ 178 | "annotations", 179 | "docblock", 180 | "parser" 181 | ], 182 | "time": "2019-03-25T19:12:02+00:00" 183 | }, 184 | { 185 | "name": "doctrine/instantiator", 186 | "version": "1.2.0", 187 | "source": { 188 | "type": "git", 189 | "url": "https://github.com/doctrine/instantiator.git", 190 | "reference": "a2c590166b2133a4633738648b6b064edae0814a" 191 | }, 192 | "dist": { 193 | "type": "zip", 194 | "url": "https://api.github.com/repos/doctrine/instantiator/zipball/a2c590166b2133a4633738648b6b064edae0814a", 195 | "reference": "a2c590166b2133a4633738648b6b064edae0814a", 196 | "shasum": "" 197 | }, 198 | "require": { 199 | "php": "^7.1" 200 | }, 201 | "require-dev": { 202 | "doctrine/coding-standard": "^6.0", 203 | "ext-pdo": "*", 204 | "ext-phar": "*", 205 | "phpbench/phpbench": "^0.13", 206 | "phpstan/phpstan-phpunit": "^0.11", 207 | "phpstan/phpstan-shim": "^0.11", 208 | "phpunit/phpunit": "^7.0" 209 | }, 210 | "type": "library", 211 | "extra": { 212 | "branch-alias": { 213 | "dev-master": "1.2.x-dev" 214 | } 215 | }, 216 | "autoload": { 217 | "psr-4": { 218 | "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" 219 | } 220 | }, 221 | "notification-url": "https://packagist.org/downloads/", 222 | "license": [ 223 | "MIT" 224 | ], 225 | "authors": [ 226 | { 227 | "name": "Marco Pivetta", 228 | "email": "ocramius@gmail.com", 229 | "homepage": "http://ocramius.github.com/" 230 | } 231 | ], 232 | "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", 233 | "homepage": "https://www.doctrine-project.org/projects/instantiator.html", 234 | "keywords": [ 235 | "constructor", 236 | "instantiate" 237 | ], 238 | "time": "2019-03-17T17:37:11+00:00" 239 | }, 240 | { 241 | "name": "doctrine/lexer", 242 | "version": "v1.0.1", 243 | "source": { 244 | "type": "git", 245 | "url": "https://github.com/doctrine/lexer.git", 246 | "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c" 247 | }, 248 | "dist": { 249 | "type": "zip", 250 | "url": "https://api.github.com/repos/doctrine/lexer/zipball/83893c552fd2045dd78aef794c31e694c37c0b8c", 251 | "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c", 252 | "shasum": "" 253 | }, 254 | "require": { 255 | "php": ">=5.3.2" 256 | }, 257 | "type": "library", 258 | "extra": { 259 | "branch-alias": { 260 | "dev-master": "1.0.x-dev" 261 | } 262 | }, 263 | "autoload": { 264 | "psr-0": { 265 | "Doctrine\\Common\\Lexer\\": "lib/" 266 | } 267 | }, 268 | "notification-url": "https://packagist.org/downloads/", 269 | "license": [ 270 | "MIT" 271 | ], 272 | "authors": [ 273 | { 274 | "name": "Roman Borschel", 275 | "email": "roman@code-factory.org" 276 | }, 277 | { 278 | "name": "Guilherme Blanco", 279 | "email": "guilhermeblanco@gmail.com" 280 | }, 281 | { 282 | "name": "Johannes Schmitt", 283 | "email": "schmittjoh@gmail.com" 284 | } 285 | ], 286 | "description": "Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.", 287 | "homepage": "http://www.doctrine-project.org", 288 | "keywords": [ 289 | "lexer", 290 | "parser" 291 | ], 292 | "time": "2014-09-09T13:34:57+00:00" 293 | }, 294 | { 295 | "name": "friendsofphp/php-cs-fixer", 296 | "version": "v2.15.0", 297 | "source": { 298 | "type": "git", 299 | "url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git", 300 | "reference": "adfab51ae979ee8b0fcbc55aa231ec2786cb1f91" 301 | }, 302 | "dist": { 303 | "type": "zip", 304 | "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/adfab51ae979ee8b0fcbc55aa231ec2786cb1f91", 305 | "reference": "adfab51ae979ee8b0fcbc55aa231ec2786cb1f91", 306 | "shasum": "" 307 | }, 308 | "require": { 309 | "composer/semver": "^1.4", 310 | "composer/xdebug-handler": "^1.2", 311 | "doctrine/annotations": "^1.2", 312 | "ext-json": "*", 313 | "ext-tokenizer": "*", 314 | "php": "^5.6 || ^7.0", 315 | "php-cs-fixer/diff": "^1.3", 316 | "symfony/console": "^3.4.17 || ^4.1.6", 317 | "symfony/event-dispatcher": "^3.0 || ^4.0", 318 | "symfony/filesystem": "^3.0 || ^4.0", 319 | "symfony/finder": "^3.0 || ^4.0", 320 | "symfony/options-resolver": "^3.0 || ^4.0", 321 | "symfony/polyfill-php70": "^1.0", 322 | "symfony/polyfill-php72": "^1.4", 323 | "symfony/process": "^3.0 || ^4.0", 324 | "symfony/stopwatch": "^3.0 || ^4.0" 325 | }, 326 | "require-dev": { 327 | "johnkary/phpunit-speedtrap": "^1.1 || ^2.0 || ^3.0", 328 | "justinrainbow/json-schema": "^5.0", 329 | "keradus/cli-executor": "^1.2", 330 | "mikey179/vfsstream": "^1.6", 331 | "php-coveralls/php-coveralls": "^2.1", 332 | "php-cs-fixer/accessible-object": "^1.0", 333 | "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.1", 334 | "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.1", 335 | "phpunit/phpunit": "^5.7.27 || ^6.5.8 || ^7.1", 336 | "phpunitgoodpractices/traits": "^1.8", 337 | "symfony/phpunit-bridge": "^4.0" 338 | }, 339 | "suggest": { 340 | "ext-mbstring": "For handling non-UTF8 characters in cache signature.", 341 | "php-cs-fixer/phpunit-constraint-isidenticalstring": "For IsIdenticalString constraint.", 342 | "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "For XmlMatchesXsd constraint.", 343 | "symfony/polyfill-mbstring": "When enabling `ext-mbstring` is not possible." 344 | }, 345 | "bin": [ 346 | "php-cs-fixer" 347 | ], 348 | "type": "application", 349 | "extra": { 350 | "branch-alias": { 351 | "dev-master": "2.15-dev" 352 | } 353 | }, 354 | "autoload": { 355 | "psr-4": { 356 | "PhpCsFixer\\": "src/" 357 | }, 358 | "classmap": [ 359 | "tests/Test/AbstractFixerTestCase.php", 360 | "tests/Test/AbstractIntegrationCaseFactory.php", 361 | "tests/Test/AbstractIntegrationTestCase.php", 362 | "tests/Test/Assert/AssertTokensTrait.php", 363 | "tests/Test/IntegrationCase.php", 364 | "tests/Test/IntegrationCaseFactory.php", 365 | "tests/Test/IntegrationCaseFactoryInterface.php", 366 | "tests/Test/InternalIntegrationCaseFactory.php", 367 | "tests/TestCase.php" 368 | ] 369 | }, 370 | "notification-url": "https://packagist.org/downloads/", 371 | "license": [ 372 | "MIT" 373 | ], 374 | "authors": [ 375 | { 376 | "name": "Dariusz Rumiński", 377 | "email": "dariusz.ruminski@gmail.com" 378 | }, 379 | { 380 | "name": "Fabien Potencier", 381 | "email": "fabien@symfony.com" 382 | } 383 | ], 384 | "description": "A tool to automatically fix PHP code style", 385 | "time": "2019-05-06T07:13:51+00:00" 386 | }, 387 | { 388 | "name": "myclabs/deep-copy", 389 | "version": "1.9.1", 390 | "source": { 391 | "type": "git", 392 | "url": "https://github.com/myclabs/DeepCopy.git", 393 | "reference": "e6828efaba2c9b79f4499dae1d66ef8bfa7b2b72" 394 | }, 395 | "dist": { 396 | "type": "zip", 397 | "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/e6828efaba2c9b79f4499dae1d66ef8bfa7b2b72", 398 | "reference": "e6828efaba2c9b79f4499dae1d66ef8bfa7b2b72", 399 | "shasum": "" 400 | }, 401 | "require": { 402 | "php": "^7.1" 403 | }, 404 | "replace": { 405 | "myclabs/deep-copy": "self.version" 406 | }, 407 | "require-dev": { 408 | "doctrine/collections": "^1.0", 409 | "doctrine/common": "^2.6", 410 | "phpunit/phpunit": "^7.1" 411 | }, 412 | "type": "library", 413 | "autoload": { 414 | "psr-4": { 415 | "DeepCopy\\": "src/DeepCopy/" 416 | }, 417 | "files": [ 418 | "src/DeepCopy/deep_copy.php" 419 | ] 420 | }, 421 | "notification-url": "https://packagist.org/downloads/", 422 | "license": [ 423 | "MIT" 424 | ], 425 | "description": "Create deep copies (clones) of your objects", 426 | "keywords": [ 427 | "clone", 428 | "copy", 429 | "duplicate", 430 | "object", 431 | "object graph" 432 | ], 433 | "time": "2019-04-07T13:18:21+00:00" 434 | }, 435 | { 436 | "name": "paragonie/random_compat", 437 | "version": "v9.99.99", 438 | "source": { 439 | "type": "git", 440 | "url": "https://github.com/paragonie/random_compat.git", 441 | "reference": "84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95" 442 | }, 443 | "dist": { 444 | "type": "zip", 445 | "url": "https://api.github.com/repos/paragonie/random_compat/zipball/84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95", 446 | "reference": "84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95", 447 | "shasum": "" 448 | }, 449 | "require": { 450 | "php": "^7" 451 | }, 452 | "require-dev": { 453 | "phpunit/phpunit": "4.*|5.*", 454 | "vimeo/psalm": "^1" 455 | }, 456 | "suggest": { 457 | "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." 458 | }, 459 | "type": "library", 460 | "notification-url": "https://packagist.org/downloads/", 461 | "license": [ 462 | "MIT" 463 | ], 464 | "authors": [ 465 | { 466 | "name": "Paragon Initiative Enterprises", 467 | "email": "security@paragonie.com", 468 | "homepage": "https://paragonie.com" 469 | } 470 | ], 471 | "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", 472 | "keywords": [ 473 | "csprng", 474 | "polyfill", 475 | "pseudorandom", 476 | "random" 477 | ], 478 | "time": "2018-07-02T15:55:56+00:00" 479 | }, 480 | { 481 | "name": "phake/phake", 482 | "version": "v1.0.8", 483 | "source": { 484 | "type": "git", 485 | "url": "https://github.com/mlively/Phake.git", 486 | "reference": "c5a3d7a75fc7431e8a5e21a922f084af95456bc6" 487 | }, 488 | "dist": { 489 | "type": "zip", 490 | "url": "https://api.github.com/repos/mlively/Phake/zipball/c5a3d7a75fc7431e8a5e21a922f084af95456bc6", 491 | "reference": "c5a3d7a75fc7431e8a5e21a922f084af95456bc6", 492 | "shasum": "" 493 | }, 494 | "require": { 495 | "php": ">=5.2.0" 496 | }, 497 | "require-dev": { 498 | "doctrine/common": "2.3.*", 499 | "ext-soap": "*", 500 | "hamcrest/hamcrest-php": "1.1.0", 501 | "phpunit/phpunit": "3.7.*" 502 | }, 503 | "type": "library", 504 | "autoload": { 505 | "classmap": [ 506 | "src" 507 | ] 508 | }, 509 | "notification-url": "https://packagist.org/downloads/", 510 | "include-path": [ 511 | "src" 512 | ], 513 | "license": [ 514 | "BSD" 515 | ], 516 | "authors": [ 517 | { 518 | "name": "Mike Lively", 519 | "email": "m@digitalsandwich.com" 520 | } 521 | ], 522 | "description": "The Phake mock testing library", 523 | "homepage": "https://github.com/mlively/Phake", 524 | "keywords": [ 525 | "mock", 526 | "testing" 527 | ], 528 | "time": "2015-01-27T15:48:39+00:00" 529 | }, 530 | { 531 | "name": "phar-io/manifest", 532 | "version": "1.0.3", 533 | "source": { 534 | "type": "git", 535 | "url": "https://github.com/phar-io/manifest.git", 536 | "reference": "7761fcacf03b4d4f16e7ccb606d4879ca431fcf4" 537 | }, 538 | "dist": { 539 | "type": "zip", 540 | "url": "https://api.github.com/repos/phar-io/manifest/zipball/7761fcacf03b4d4f16e7ccb606d4879ca431fcf4", 541 | "reference": "7761fcacf03b4d4f16e7ccb606d4879ca431fcf4", 542 | "shasum": "" 543 | }, 544 | "require": { 545 | "ext-dom": "*", 546 | "ext-phar": "*", 547 | "phar-io/version": "^2.0", 548 | "php": "^5.6 || ^7.0" 549 | }, 550 | "type": "library", 551 | "extra": { 552 | "branch-alias": { 553 | "dev-master": "1.0.x-dev" 554 | } 555 | }, 556 | "autoload": { 557 | "classmap": [ 558 | "src/" 559 | ] 560 | }, 561 | "notification-url": "https://packagist.org/downloads/", 562 | "license": [ 563 | "BSD-3-Clause" 564 | ], 565 | "authors": [ 566 | { 567 | "name": "Arne Blankerts", 568 | "email": "arne@blankerts.de", 569 | "role": "Developer" 570 | }, 571 | { 572 | "name": "Sebastian Heuer", 573 | "email": "sebastian@phpeople.de", 574 | "role": "Developer" 575 | }, 576 | { 577 | "name": "Sebastian Bergmann", 578 | "email": "sebastian@phpunit.de", 579 | "role": "Developer" 580 | } 581 | ], 582 | "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", 583 | "time": "2018-07-08T19:23:20+00:00" 584 | }, 585 | { 586 | "name": "phar-io/version", 587 | "version": "2.0.1", 588 | "source": { 589 | "type": "git", 590 | "url": "https://github.com/phar-io/version.git", 591 | "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6" 592 | }, 593 | "dist": { 594 | "type": "zip", 595 | "url": "https://api.github.com/repos/phar-io/version/zipball/45a2ec53a73c70ce41d55cedef9063630abaf1b6", 596 | "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6", 597 | "shasum": "" 598 | }, 599 | "require": { 600 | "php": "^5.6 || ^7.0" 601 | }, 602 | "type": "library", 603 | "autoload": { 604 | "classmap": [ 605 | "src/" 606 | ] 607 | }, 608 | "notification-url": "https://packagist.org/downloads/", 609 | "license": [ 610 | "BSD-3-Clause" 611 | ], 612 | "authors": [ 613 | { 614 | "name": "Arne Blankerts", 615 | "email": "arne@blankerts.de", 616 | "role": "Developer" 617 | }, 618 | { 619 | "name": "Sebastian Heuer", 620 | "email": "sebastian@phpeople.de", 621 | "role": "Developer" 622 | }, 623 | { 624 | "name": "Sebastian Bergmann", 625 | "email": "sebastian@phpunit.de", 626 | "role": "Developer" 627 | } 628 | ], 629 | "description": "Library for handling version information and constraints", 630 | "time": "2018-07-08T19:19:57+00:00" 631 | }, 632 | { 633 | "name": "php-cs-fixer/diff", 634 | "version": "v1.3.0", 635 | "source": { 636 | "type": "git", 637 | "url": "https://github.com/PHP-CS-Fixer/diff.git", 638 | "reference": "78bb099e9c16361126c86ce82ec4405ebab8e756" 639 | }, 640 | "dist": { 641 | "type": "zip", 642 | "url": "https://api.github.com/repos/PHP-CS-Fixer/diff/zipball/78bb099e9c16361126c86ce82ec4405ebab8e756", 643 | "reference": "78bb099e9c16361126c86ce82ec4405ebab8e756", 644 | "shasum": "" 645 | }, 646 | "require": { 647 | "php": "^5.6 || ^7.0" 648 | }, 649 | "require-dev": { 650 | "phpunit/phpunit": "^5.7.23 || ^6.4.3", 651 | "symfony/process": "^3.3" 652 | }, 653 | "type": "library", 654 | "autoload": { 655 | "classmap": [ 656 | "src/" 657 | ] 658 | }, 659 | "notification-url": "https://packagist.org/downloads/", 660 | "license": [ 661 | "BSD-3-Clause" 662 | ], 663 | "authors": [ 664 | { 665 | "name": "Kore Nordmann", 666 | "email": "mail@kore-nordmann.de" 667 | }, 668 | { 669 | "name": "Sebastian Bergmann", 670 | "email": "sebastian@phpunit.de" 671 | }, 672 | { 673 | "name": "SpacePossum" 674 | } 675 | ], 676 | "description": "sebastian/diff v2 backport support for PHP5.6", 677 | "homepage": "https://github.com/PHP-CS-Fixer", 678 | "keywords": [ 679 | "diff" 680 | ], 681 | "time": "2018-02-15T16:58:55+00:00" 682 | }, 683 | { 684 | "name": "phpdocumentor/reflection-common", 685 | "version": "1.0.1", 686 | "source": { 687 | "type": "git", 688 | "url": "https://github.com/phpDocumentor/ReflectionCommon.git", 689 | "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6" 690 | }, 691 | "dist": { 692 | "type": "zip", 693 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", 694 | "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", 695 | "shasum": "" 696 | }, 697 | "require": { 698 | "php": ">=5.5" 699 | }, 700 | "require-dev": { 701 | "phpunit/phpunit": "^4.6" 702 | }, 703 | "type": "library", 704 | "extra": { 705 | "branch-alias": { 706 | "dev-master": "1.0.x-dev" 707 | } 708 | }, 709 | "autoload": { 710 | "psr-4": { 711 | "phpDocumentor\\Reflection\\": [ 712 | "src" 713 | ] 714 | } 715 | }, 716 | "notification-url": "https://packagist.org/downloads/", 717 | "license": [ 718 | "MIT" 719 | ], 720 | "authors": [ 721 | { 722 | "name": "Jaap van Otterdijk", 723 | "email": "opensource@ijaap.nl" 724 | } 725 | ], 726 | "description": "Common reflection classes used by phpdocumentor to reflect the code structure", 727 | "homepage": "http://www.phpdoc.org", 728 | "keywords": [ 729 | "FQSEN", 730 | "phpDocumentor", 731 | "phpdoc", 732 | "reflection", 733 | "static analysis" 734 | ], 735 | "time": "2017-09-11T18:02:19+00:00" 736 | }, 737 | { 738 | "name": "phpdocumentor/reflection-docblock", 739 | "version": "4.3.1", 740 | "source": { 741 | "type": "git", 742 | "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", 743 | "reference": "bdd9f737ebc2a01c06ea7ff4308ec6697db9b53c" 744 | }, 745 | "dist": { 746 | "type": "zip", 747 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/bdd9f737ebc2a01c06ea7ff4308ec6697db9b53c", 748 | "reference": "bdd9f737ebc2a01c06ea7ff4308ec6697db9b53c", 749 | "shasum": "" 750 | }, 751 | "require": { 752 | "php": "^7.0", 753 | "phpdocumentor/reflection-common": "^1.0.0", 754 | "phpdocumentor/type-resolver": "^0.4.0", 755 | "webmozart/assert": "^1.0" 756 | }, 757 | "require-dev": { 758 | "doctrine/instantiator": "~1.0.5", 759 | "mockery/mockery": "^1.0", 760 | "phpunit/phpunit": "^6.4" 761 | }, 762 | "type": "library", 763 | "extra": { 764 | "branch-alias": { 765 | "dev-master": "4.x-dev" 766 | } 767 | }, 768 | "autoload": { 769 | "psr-4": { 770 | "phpDocumentor\\Reflection\\": [ 771 | "src/" 772 | ] 773 | } 774 | }, 775 | "notification-url": "https://packagist.org/downloads/", 776 | "license": [ 777 | "MIT" 778 | ], 779 | "authors": [ 780 | { 781 | "name": "Mike van Riel", 782 | "email": "me@mikevanriel.com" 783 | } 784 | ], 785 | "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", 786 | "time": "2019-04-30T17:48:53+00:00" 787 | }, 788 | { 789 | "name": "phpdocumentor/type-resolver", 790 | "version": "0.4.0", 791 | "source": { 792 | "type": "git", 793 | "url": "https://github.com/phpDocumentor/TypeResolver.git", 794 | "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7" 795 | }, 796 | "dist": { 797 | "type": "zip", 798 | "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7", 799 | "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7", 800 | "shasum": "" 801 | }, 802 | "require": { 803 | "php": "^5.5 || ^7.0", 804 | "phpdocumentor/reflection-common": "^1.0" 805 | }, 806 | "require-dev": { 807 | "mockery/mockery": "^0.9.4", 808 | "phpunit/phpunit": "^5.2||^4.8.24" 809 | }, 810 | "type": "library", 811 | "extra": { 812 | "branch-alias": { 813 | "dev-master": "1.0.x-dev" 814 | } 815 | }, 816 | "autoload": { 817 | "psr-4": { 818 | "phpDocumentor\\Reflection\\": [ 819 | "src/" 820 | ] 821 | } 822 | }, 823 | "notification-url": "https://packagist.org/downloads/", 824 | "license": [ 825 | "MIT" 826 | ], 827 | "authors": [ 828 | { 829 | "name": "Mike van Riel", 830 | "email": "me@mikevanriel.com" 831 | } 832 | ], 833 | "time": "2017-07-14T14:27:02+00:00" 834 | }, 835 | { 836 | "name": "phpspec/prophecy", 837 | "version": "1.8.0", 838 | "source": { 839 | "type": "git", 840 | "url": "https://github.com/phpspec/prophecy.git", 841 | "reference": "4ba436b55987b4bf311cb7c6ba82aa528aac0a06" 842 | }, 843 | "dist": { 844 | "type": "zip", 845 | "url": "https://api.github.com/repos/phpspec/prophecy/zipball/4ba436b55987b4bf311cb7c6ba82aa528aac0a06", 846 | "reference": "4ba436b55987b4bf311cb7c6ba82aa528aac0a06", 847 | "shasum": "" 848 | }, 849 | "require": { 850 | "doctrine/instantiator": "^1.0.2", 851 | "php": "^5.3|^7.0", 852 | "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0", 853 | "sebastian/comparator": "^1.1|^2.0|^3.0", 854 | "sebastian/recursion-context": "^1.0|^2.0|^3.0" 855 | }, 856 | "require-dev": { 857 | "phpspec/phpspec": "^2.5|^3.2", 858 | "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1" 859 | }, 860 | "type": "library", 861 | "extra": { 862 | "branch-alias": { 863 | "dev-master": "1.8.x-dev" 864 | } 865 | }, 866 | "autoload": { 867 | "psr-0": { 868 | "Prophecy\\": "src/" 869 | } 870 | }, 871 | "notification-url": "https://packagist.org/downloads/", 872 | "license": [ 873 | "MIT" 874 | ], 875 | "authors": [ 876 | { 877 | "name": "Konstantin Kudryashov", 878 | "email": "ever.zet@gmail.com", 879 | "homepage": "http://everzet.com" 880 | }, 881 | { 882 | "name": "Marcello Duarte", 883 | "email": "marcello.duarte@gmail.com" 884 | } 885 | ], 886 | "description": "Highly opinionated mocking framework for PHP 5.3+", 887 | "homepage": "https://github.com/phpspec/prophecy", 888 | "keywords": [ 889 | "Double", 890 | "Dummy", 891 | "fake", 892 | "mock", 893 | "spy", 894 | "stub" 895 | ], 896 | "time": "2018-08-05T17:53:17+00:00" 897 | }, 898 | { 899 | "name": "phpunit/php-code-coverage", 900 | "version": "6.1.4", 901 | "source": { 902 | "type": "git", 903 | "url": "https://github.com/sebastianbergmann/php-code-coverage.git", 904 | "reference": "807e6013b00af69b6c5d9ceb4282d0393dbb9d8d" 905 | }, 906 | "dist": { 907 | "type": "zip", 908 | "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/807e6013b00af69b6c5d9ceb4282d0393dbb9d8d", 909 | "reference": "807e6013b00af69b6c5d9ceb4282d0393dbb9d8d", 910 | "shasum": "" 911 | }, 912 | "require": { 913 | "ext-dom": "*", 914 | "ext-xmlwriter": "*", 915 | "php": "^7.1", 916 | "phpunit/php-file-iterator": "^2.0", 917 | "phpunit/php-text-template": "^1.2.1", 918 | "phpunit/php-token-stream": "^3.0", 919 | "sebastian/code-unit-reverse-lookup": "^1.0.1", 920 | "sebastian/environment": "^3.1 || ^4.0", 921 | "sebastian/version": "^2.0.1", 922 | "theseer/tokenizer": "^1.1" 923 | }, 924 | "require-dev": { 925 | "phpunit/phpunit": "^7.0" 926 | }, 927 | "suggest": { 928 | "ext-xdebug": "^2.6.0" 929 | }, 930 | "type": "library", 931 | "extra": { 932 | "branch-alias": { 933 | "dev-master": "6.1-dev" 934 | } 935 | }, 936 | "autoload": { 937 | "classmap": [ 938 | "src/" 939 | ] 940 | }, 941 | "notification-url": "https://packagist.org/downloads/", 942 | "license": [ 943 | "BSD-3-Clause" 944 | ], 945 | "authors": [ 946 | { 947 | "name": "Sebastian Bergmann", 948 | "email": "sebastian@phpunit.de", 949 | "role": "lead" 950 | } 951 | ], 952 | "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", 953 | "homepage": "https://github.com/sebastianbergmann/php-code-coverage", 954 | "keywords": [ 955 | "coverage", 956 | "testing", 957 | "xunit" 958 | ], 959 | "time": "2018-10-31T16:06:48+00:00" 960 | }, 961 | { 962 | "name": "phpunit/php-file-iterator", 963 | "version": "2.0.2", 964 | "source": { 965 | "type": "git", 966 | "url": "https://github.com/sebastianbergmann/php-file-iterator.git", 967 | "reference": "050bedf145a257b1ff02746c31894800e5122946" 968 | }, 969 | "dist": { 970 | "type": "zip", 971 | "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/050bedf145a257b1ff02746c31894800e5122946", 972 | "reference": "050bedf145a257b1ff02746c31894800e5122946", 973 | "shasum": "" 974 | }, 975 | "require": { 976 | "php": "^7.1" 977 | }, 978 | "require-dev": { 979 | "phpunit/phpunit": "^7.1" 980 | }, 981 | "type": "library", 982 | "extra": { 983 | "branch-alias": { 984 | "dev-master": "2.0.x-dev" 985 | } 986 | }, 987 | "autoload": { 988 | "classmap": [ 989 | "src/" 990 | ] 991 | }, 992 | "notification-url": "https://packagist.org/downloads/", 993 | "license": [ 994 | "BSD-3-Clause" 995 | ], 996 | "authors": [ 997 | { 998 | "name": "Sebastian Bergmann", 999 | "email": "sebastian@phpunit.de", 1000 | "role": "lead" 1001 | } 1002 | ], 1003 | "description": "FilterIterator implementation that filters files based on a list of suffixes.", 1004 | "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", 1005 | "keywords": [ 1006 | "filesystem", 1007 | "iterator" 1008 | ], 1009 | "time": "2018-09-13T20:33:42+00:00" 1010 | }, 1011 | { 1012 | "name": "phpunit/php-text-template", 1013 | "version": "1.2.1", 1014 | "source": { 1015 | "type": "git", 1016 | "url": "https://github.com/sebastianbergmann/php-text-template.git", 1017 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" 1018 | }, 1019 | "dist": { 1020 | "type": "zip", 1021 | "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", 1022 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", 1023 | "shasum": "" 1024 | }, 1025 | "require": { 1026 | "php": ">=5.3.3" 1027 | }, 1028 | "type": "library", 1029 | "autoload": { 1030 | "classmap": [ 1031 | "src/" 1032 | ] 1033 | }, 1034 | "notification-url": "https://packagist.org/downloads/", 1035 | "license": [ 1036 | "BSD-3-Clause" 1037 | ], 1038 | "authors": [ 1039 | { 1040 | "name": "Sebastian Bergmann", 1041 | "email": "sebastian@phpunit.de", 1042 | "role": "lead" 1043 | } 1044 | ], 1045 | "description": "Simple template engine.", 1046 | "homepage": "https://github.com/sebastianbergmann/php-text-template/", 1047 | "keywords": [ 1048 | "template" 1049 | ], 1050 | "time": "2015-06-21T13:50:34+00:00" 1051 | }, 1052 | { 1053 | "name": "phpunit/php-timer", 1054 | "version": "2.1.1", 1055 | "source": { 1056 | "type": "git", 1057 | "url": "https://github.com/sebastianbergmann/php-timer.git", 1058 | "reference": "8b389aebe1b8b0578430bda0c7c95a829608e059" 1059 | }, 1060 | "dist": { 1061 | "type": "zip", 1062 | "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/8b389aebe1b8b0578430bda0c7c95a829608e059", 1063 | "reference": "8b389aebe1b8b0578430bda0c7c95a829608e059", 1064 | "shasum": "" 1065 | }, 1066 | "require": { 1067 | "php": "^7.1" 1068 | }, 1069 | "require-dev": { 1070 | "phpunit/phpunit": "^7.0" 1071 | }, 1072 | "type": "library", 1073 | "extra": { 1074 | "branch-alias": { 1075 | "dev-master": "2.1-dev" 1076 | } 1077 | }, 1078 | "autoload": { 1079 | "classmap": [ 1080 | "src/" 1081 | ] 1082 | }, 1083 | "notification-url": "https://packagist.org/downloads/", 1084 | "license": [ 1085 | "BSD-3-Clause" 1086 | ], 1087 | "authors": [ 1088 | { 1089 | "name": "Sebastian Bergmann", 1090 | "email": "sebastian@phpunit.de", 1091 | "role": "lead" 1092 | } 1093 | ], 1094 | "description": "Utility class for timing", 1095 | "homepage": "https://github.com/sebastianbergmann/php-timer/", 1096 | "keywords": [ 1097 | "timer" 1098 | ], 1099 | "time": "2019-02-20T10:12:59+00:00" 1100 | }, 1101 | { 1102 | "name": "phpunit/php-token-stream", 1103 | "version": "3.0.1", 1104 | "source": { 1105 | "type": "git", 1106 | "url": "https://github.com/sebastianbergmann/php-token-stream.git", 1107 | "reference": "c99e3be9d3e85f60646f152f9002d46ed7770d18" 1108 | }, 1109 | "dist": { 1110 | "type": "zip", 1111 | "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/c99e3be9d3e85f60646f152f9002d46ed7770d18", 1112 | "reference": "c99e3be9d3e85f60646f152f9002d46ed7770d18", 1113 | "shasum": "" 1114 | }, 1115 | "require": { 1116 | "ext-tokenizer": "*", 1117 | "php": "^7.1" 1118 | }, 1119 | "require-dev": { 1120 | "phpunit/phpunit": "^7.0" 1121 | }, 1122 | "type": "library", 1123 | "extra": { 1124 | "branch-alias": { 1125 | "dev-master": "3.0-dev" 1126 | } 1127 | }, 1128 | "autoload": { 1129 | "classmap": [ 1130 | "src/" 1131 | ] 1132 | }, 1133 | "notification-url": "https://packagist.org/downloads/", 1134 | "license": [ 1135 | "BSD-3-Clause" 1136 | ], 1137 | "authors": [ 1138 | { 1139 | "name": "Sebastian Bergmann", 1140 | "email": "sebastian@phpunit.de" 1141 | } 1142 | ], 1143 | "description": "Wrapper around PHP's tokenizer extension.", 1144 | "homepage": "https://github.com/sebastianbergmann/php-token-stream/", 1145 | "keywords": [ 1146 | "tokenizer" 1147 | ], 1148 | "time": "2018-10-30T05:52:18+00:00" 1149 | }, 1150 | { 1151 | "name": "phpunit/phpunit", 1152 | "version": "7.5.11", 1153 | "source": { 1154 | "type": "git", 1155 | "url": "https://github.com/sebastianbergmann/phpunit.git", 1156 | "reference": "64cb33f5b520da490a7b13149d39b43cf3c890c6" 1157 | }, 1158 | "dist": { 1159 | "type": "zip", 1160 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/64cb33f5b520da490a7b13149d39b43cf3c890c6", 1161 | "reference": "64cb33f5b520da490a7b13149d39b43cf3c890c6", 1162 | "shasum": "" 1163 | }, 1164 | "require": { 1165 | "doctrine/instantiator": "^1.1", 1166 | "ext-dom": "*", 1167 | "ext-json": "*", 1168 | "ext-libxml": "*", 1169 | "ext-mbstring": "*", 1170 | "ext-xml": "*", 1171 | "myclabs/deep-copy": "^1.7", 1172 | "phar-io/manifest": "^1.0.2", 1173 | "phar-io/version": "^2.0", 1174 | "php": "^7.1", 1175 | "phpspec/prophecy": "^1.7", 1176 | "phpunit/php-code-coverage": "^6.0.7", 1177 | "phpunit/php-file-iterator": "^2.0.1", 1178 | "phpunit/php-text-template": "^1.2.1", 1179 | "phpunit/php-timer": "^2.1", 1180 | "sebastian/comparator": "^3.0", 1181 | "sebastian/diff": "^3.0", 1182 | "sebastian/environment": "^4.0", 1183 | "sebastian/exporter": "^3.1", 1184 | "sebastian/global-state": "^2.0", 1185 | "sebastian/object-enumerator": "^3.0.3", 1186 | "sebastian/resource-operations": "^2.0", 1187 | "sebastian/version": "^2.0.1" 1188 | }, 1189 | "conflict": { 1190 | "phpunit/phpunit-mock-objects": "*" 1191 | }, 1192 | "require-dev": { 1193 | "ext-pdo": "*" 1194 | }, 1195 | "suggest": { 1196 | "ext-soap": "*", 1197 | "ext-xdebug": "*", 1198 | "phpunit/php-invoker": "^2.0" 1199 | }, 1200 | "bin": [ 1201 | "phpunit" 1202 | ], 1203 | "type": "library", 1204 | "extra": { 1205 | "branch-alias": { 1206 | "dev-master": "7.5-dev" 1207 | } 1208 | }, 1209 | "autoload": { 1210 | "classmap": [ 1211 | "src/" 1212 | ] 1213 | }, 1214 | "notification-url": "https://packagist.org/downloads/", 1215 | "license": [ 1216 | "BSD-3-Clause" 1217 | ], 1218 | "authors": [ 1219 | { 1220 | "name": "Sebastian Bergmann", 1221 | "email": "sebastian@phpunit.de", 1222 | "role": "lead" 1223 | } 1224 | ], 1225 | "description": "The PHP Unit Testing framework.", 1226 | "homepage": "https://phpunit.de/", 1227 | "keywords": [ 1228 | "phpunit", 1229 | "testing", 1230 | "xunit" 1231 | ], 1232 | "time": "2019-05-14T04:53:02+00:00" 1233 | }, 1234 | { 1235 | "name": "psr/log", 1236 | "version": "1.1.0", 1237 | "source": { 1238 | "type": "git", 1239 | "url": "https://github.com/php-fig/log.git", 1240 | "reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd" 1241 | }, 1242 | "dist": { 1243 | "type": "zip", 1244 | "url": "https://api.github.com/repos/php-fig/log/zipball/6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd", 1245 | "reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd", 1246 | "shasum": "" 1247 | }, 1248 | "require": { 1249 | "php": ">=5.3.0" 1250 | }, 1251 | "type": "library", 1252 | "extra": { 1253 | "branch-alias": { 1254 | "dev-master": "1.0.x-dev" 1255 | } 1256 | }, 1257 | "autoload": { 1258 | "psr-4": { 1259 | "Psr\\Log\\": "Psr/Log/" 1260 | } 1261 | }, 1262 | "notification-url": "https://packagist.org/downloads/", 1263 | "license": [ 1264 | "MIT" 1265 | ], 1266 | "authors": [ 1267 | { 1268 | "name": "PHP-FIG", 1269 | "homepage": "http://www.php-fig.org/" 1270 | } 1271 | ], 1272 | "description": "Common interface for logging libraries", 1273 | "homepage": "https://github.com/php-fig/log", 1274 | "keywords": [ 1275 | "log", 1276 | "psr", 1277 | "psr-3" 1278 | ], 1279 | "time": "2018-11-20T15:27:04+00:00" 1280 | }, 1281 | { 1282 | "name": "sebastian/code-unit-reverse-lookup", 1283 | "version": "1.0.1", 1284 | "source": { 1285 | "type": "git", 1286 | "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", 1287 | "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18" 1288 | }, 1289 | "dist": { 1290 | "type": "zip", 1291 | "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", 1292 | "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", 1293 | "shasum": "" 1294 | }, 1295 | "require": { 1296 | "php": "^5.6 || ^7.0" 1297 | }, 1298 | "require-dev": { 1299 | "phpunit/phpunit": "^5.7 || ^6.0" 1300 | }, 1301 | "type": "library", 1302 | "extra": { 1303 | "branch-alias": { 1304 | "dev-master": "1.0.x-dev" 1305 | } 1306 | }, 1307 | "autoload": { 1308 | "classmap": [ 1309 | "src/" 1310 | ] 1311 | }, 1312 | "notification-url": "https://packagist.org/downloads/", 1313 | "license": [ 1314 | "BSD-3-Clause" 1315 | ], 1316 | "authors": [ 1317 | { 1318 | "name": "Sebastian Bergmann", 1319 | "email": "sebastian@phpunit.de" 1320 | } 1321 | ], 1322 | "description": "Looks up which function or method a line of code belongs to", 1323 | "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", 1324 | "time": "2017-03-04T06:30:41+00:00" 1325 | }, 1326 | { 1327 | "name": "sebastian/comparator", 1328 | "version": "3.0.2", 1329 | "source": { 1330 | "type": "git", 1331 | "url": "https://github.com/sebastianbergmann/comparator.git", 1332 | "reference": "5de4fc177adf9bce8df98d8d141a7559d7ccf6da" 1333 | }, 1334 | "dist": { 1335 | "type": "zip", 1336 | "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/5de4fc177adf9bce8df98d8d141a7559d7ccf6da", 1337 | "reference": "5de4fc177adf9bce8df98d8d141a7559d7ccf6da", 1338 | "shasum": "" 1339 | }, 1340 | "require": { 1341 | "php": "^7.1", 1342 | "sebastian/diff": "^3.0", 1343 | "sebastian/exporter": "^3.1" 1344 | }, 1345 | "require-dev": { 1346 | "phpunit/phpunit": "^7.1" 1347 | }, 1348 | "type": "library", 1349 | "extra": { 1350 | "branch-alias": { 1351 | "dev-master": "3.0-dev" 1352 | } 1353 | }, 1354 | "autoload": { 1355 | "classmap": [ 1356 | "src/" 1357 | ] 1358 | }, 1359 | "notification-url": "https://packagist.org/downloads/", 1360 | "license": [ 1361 | "BSD-3-Clause" 1362 | ], 1363 | "authors": [ 1364 | { 1365 | "name": "Jeff Welch", 1366 | "email": "whatthejeff@gmail.com" 1367 | }, 1368 | { 1369 | "name": "Volker Dusch", 1370 | "email": "github@wallbash.com" 1371 | }, 1372 | { 1373 | "name": "Bernhard Schussek", 1374 | "email": "bschussek@2bepublished.at" 1375 | }, 1376 | { 1377 | "name": "Sebastian Bergmann", 1378 | "email": "sebastian@phpunit.de" 1379 | } 1380 | ], 1381 | "description": "Provides the functionality to compare PHP values for equality", 1382 | "homepage": "https://github.com/sebastianbergmann/comparator", 1383 | "keywords": [ 1384 | "comparator", 1385 | "compare", 1386 | "equality" 1387 | ], 1388 | "time": "2018-07-12T15:12:46+00:00" 1389 | }, 1390 | { 1391 | "name": "sebastian/diff", 1392 | "version": "3.0.2", 1393 | "source": { 1394 | "type": "git", 1395 | "url": "https://github.com/sebastianbergmann/diff.git", 1396 | "reference": "720fcc7e9b5cf384ea68d9d930d480907a0c1a29" 1397 | }, 1398 | "dist": { 1399 | "type": "zip", 1400 | "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/720fcc7e9b5cf384ea68d9d930d480907a0c1a29", 1401 | "reference": "720fcc7e9b5cf384ea68d9d930d480907a0c1a29", 1402 | "shasum": "" 1403 | }, 1404 | "require": { 1405 | "php": "^7.1" 1406 | }, 1407 | "require-dev": { 1408 | "phpunit/phpunit": "^7.5 || ^8.0", 1409 | "symfony/process": "^2 || ^3.3 || ^4" 1410 | }, 1411 | "type": "library", 1412 | "extra": { 1413 | "branch-alias": { 1414 | "dev-master": "3.0-dev" 1415 | } 1416 | }, 1417 | "autoload": { 1418 | "classmap": [ 1419 | "src/" 1420 | ] 1421 | }, 1422 | "notification-url": "https://packagist.org/downloads/", 1423 | "license": [ 1424 | "BSD-3-Clause" 1425 | ], 1426 | "authors": [ 1427 | { 1428 | "name": "Kore Nordmann", 1429 | "email": "mail@kore-nordmann.de" 1430 | }, 1431 | { 1432 | "name": "Sebastian Bergmann", 1433 | "email": "sebastian@phpunit.de" 1434 | } 1435 | ], 1436 | "description": "Diff implementation", 1437 | "homepage": "https://github.com/sebastianbergmann/diff", 1438 | "keywords": [ 1439 | "diff", 1440 | "udiff", 1441 | "unidiff", 1442 | "unified diff" 1443 | ], 1444 | "time": "2019-02-04T06:01:07+00:00" 1445 | }, 1446 | { 1447 | "name": "sebastian/environment", 1448 | "version": "4.2.2", 1449 | "source": { 1450 | "type": "git", 1451 | "url": "https://github.com/sebastianbergmann/environment.git", 1452 | "reference": "f2a2c8e1c97c11ace607a7a667d73d47c19fe404" 1453 | }, 1454 | "dist": { 1455 | "type": "zip", 1456 | "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/f2a2c8e1c97c11ace607a7a667d73d47c19fe404", 1457 | "reference": "f2a2c8e1c97c11ace607a7a667d73d47c19fe404", 1458 | "shasum": "" 1459 | }, 1460 | "require": { 1461 | "php": "^7.1" 1462 | }, 1463 | "require-dev": { 1464 | "phpunit/phpunit": "^7.5" 1465 | }, 1466 | "suggest": { 1467 | "ext-posix": "*" 1468 | }, 1469 | "type": "library", 1470 | "extra": { 1471 | "branch-alias": { 1472 | "dev-master": "4.2-dev" 1473 | } 1474 | }, 1475 | "autoload": { 1476 | "classmap": [ 1477 | "src/" 1478 | ] 1479 | }, 1480 | "notification-url": "https://packagist.org/downloads/", 1481 | "license": [ 1482 | "BSD-3-Clause" 1483 | ], 1484 | "authors": [ 1485 | { 1486 | "name": "Sebastian Bergmann", 1487 | "email": "sebastian@phpunit.de" 1488 | } 1489 | ], 1490 | "description": "Provides functionality to handle HHVM/PHP environments", 1491 | "homepage": "http://www.github.com/sebastianbergmann/environment", 1492 | "keywords": [ 1493 | "Xdebug", 1494 | "environment", 1495 | "hhvm" 1496 | ], 1497 | "time": "2019-05-05T09:05:15+00:00" 1498 | }, 1499 | { 1500 | "name": "sebastian/exporter", 1501 | "version": "3.1.0", 1502 | "source": { 1503 | "type": "git", 1504 | "url": "https://github.com/sebastianbergmann/exporter.git", 1505 | "reference": "234199f4528de6d12aaa58b612e98f7d36adb937" 1506 | }, 1507 | "dist": { 1508 | "type": "zip", 1509 | "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/234199f4528de6d12aaa58b612e98f7d36adb937", 1510 | "reference": "234199f4528de6d12aaa58b612e98f7d36adb937", 1511 | "shasum": "" 1512 | }, 1513 | "require": { 1514 | "php": "^7.0", 1515 | "sebastian/recursion-context": "^3.0" 1516 | }, 1517 | "require-dev": { 1518 | "ext-mbstring": "*", 1519 | "phpunit/phpunit": "^6.0" 1520 | }, 1521 | "type": "library", 1522 | "extra": { 1523 | "branch-alias": { 1524 | "dev-master": "3.1.x-dev" 1525 | } 1526 | }, 1527 | "autoload": { 1528 | "classmap": [ 1529 | "src/" 1530 | ] 1531 | }, 1532 | "notification-url": "https://packagist.org/downloads/", 1533 | "license": [ 1534 | "BSD-3-Clause" 1535 | ], 1536 | "authors": [ 1537 | { 1538 | "name": "Jeff Welch", 1539 | "email": "whatthejeff@gmail.com" 1540 | }, 1541 | { 1542 | "name": "Volker Dusch", 1543 | "email": "github@wallbash.com" 1544 | }, 1545 | { 1546 | "name": "Bernhard Schussek", 1547 | "email": "bschussek@2bepublished.at" 1548 | }, 1549 | { 1550 | "name": "Sebastian Bergmann", 1551 | "email": "sebastian@phpunit.de" 1552 | }, 1553 | { 1554 | "name": "Adam Harvey", 1555 | "email": "aharvey@php.net" 1556 | } 1557 | ], 1558 | "description": "Provides the functionality to export PHP variables for visualization", 1559 | "homepage": "http://www.github.com/sebastianbergmann/exporter", 1560 | "keywords": [ 1561 | "export", 1562 | "exporter" 1563 | ], 1564 | "time": "2017-04-03T13:19:02+00:00" 1565 | }, 1566 | { 1567 | "name": "sebastian/global-state", 1568 | "version": "2.0.0", 1569 | "source": { 1570 | "type": "git", 1571 | "url": "https://github.com/sebastianbergmann/global-state.git", 1572 | "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4" 1573 | }, 1574 | "dist": { 1575 | "type": "zip", 1576 | "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", 1577 | "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", 1578 | "shasum": "" 1579 | }, 1580 | "require": { 1581 | "php": "^7.0" 1582 | }, 1583 | "require-dev": { 1584 | "phpunit/phpunit": "^6.0" 1585 | }, 1586 | "suggest": { 1587 | "ext-uopz": "*" 1588 | }, 1589 | "type": "library", 1590 | "extra": { 1591 | "branch-alias": { 1592 | "dev-master": "2.0-dev" 1593 | } 1594 | }, 1595 | "autoload": { 1596 | "classmap": [ 1597 | "src/" 1598 | ] 1599 | }, 1600 | "notification-url": "https://packagist.org/downloads/", 1601 | "license": [ 1602 | "BSD-3-Clause" 1603 | ], 1604 | "authors": [ 1605 | { 1606 | "name": "Sebastian Bergmann", 1607 | "email": "sebastian@phpunit.de" 1608 | } 1609 | ], 1610 | "description": "Snapshotting of global state", 1611 | "homepage": "http://www.github.com/sebastianbergmann/global-state", 1612 | "keywords": [ 1613 | "global state" 1614 | ], 1615 | "time": "2017-04-27T15:39:26+00:00" 1616 | }, 1617 | { 1618 | "name": "sebastian/object-enumerator", 1619 | "version": "3.0.3", 1620 | "source": { 1621 | "type": "git", 1622 | "url": "https://github.com/sebastianbergmann/object-enumerator.git", 1623 | "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5" 1624 | }, 1625 | "dist": { 1626 | "type": "zip", 1627 | "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/7cfd9e65d11ffb5af41198476395774d4c8a84c5", 1628 | "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5", 1629 | "shasum": "" 1630 | }, 1631 | "require": { 1632 | "php": "^7.0", 1633 | "sebastian/object-reflector": "^1.1.1", 1634 | "sebastian/recursion-context": "^3.0" 1635 | }, 1636 | "require-dev": { 1637 | "phpunit/phpunit": "^6.0" 1638 | }, 1639 | "type": "library", 1640 | "extra": { 1641 | "branch-alias": { 1642 | "dev-master": "3.0.x-dev" 1643 | } 1644 | }, 1645 | "autoload": { 1646 | "classmap": [ 1647 | "src/" 1648 | ] 1649 | }, 1650 | "notification-url": "https://packagist.org/downloads/", 1651 | "license": [ 1652 | "BSD-3-Clause" 1653 | ], 1654 | "authors": [ 1655 | { 1656 | "name": "Sebastian Bergmann", 1657 | "email": "sebastian@phpunit.de" 1658 | } 1659 | ], 1660 | "description": "Traverses array structures and object graphs to enumerate all referenced objects", 1661 | "homepage": "https://github.com/sebastianbergmann/object-enumerator/", 1662 | "time": "2017-08-03T12:35:26+00:00" 1663 | }, 1664 | { 1665 | "name": "sebastian/object-reflector", 1666 | "version": "1.1.1", 1667 | "source": { 1668 | "type": "git", 1669 | "url": "https://github.com/sebastianbergmann/object-reflector.git", 1670 | "reference": "773f97c67f28de00d397be301821b06708fca0be" 1671 | }, 1672 | "dist": { 1673 | "type": "zip", 1674 | "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/773f97c67f28de00d397be301821b06708fca0be", 1675 | "reference": "773f97c67f28de00d397be301821b06708fca0be", 1676 | "shasum": "" 1677 | }, 1678 | "require": { 1679 | "php": "^7.0" 1680 | }, 1681 | "require-dev": { 1682 | "phpunit/phpunit": "^6.0" 1683 | }, 1684 | "type": "library", 1685 | "extra": { 1686 | "branch-alias": { 1687 | "dev-master": "1.1-dev" 1688 | } 1689 | }, 1690 | "autoload": { 1691 | "classmap": [ 1692 | "src/" 1693 | ] 1694 | }, 1695 | "notification-url": "https://packagist.org/downloads/", 1696 | "license": [ 1697 | "BSD-3-Clause" 1698 | ], 1699 | "authors": [ 1700 | { 1701 | "name": "Sebastian Bergmann", 1702 | "email": "sebastian@phpunit.de" 1703 | } 1704 | ], 1705 | "description": "Allows reflection of object attributes, including inherited and non-public ones", 1706 | "homepage": "https://github.com/sebastianbergmann/object-reflector/", 1707 | "time": "2017-03-29T09:07:27+00:00" 1708 | }, 1709 | { 1710 | "name": "sebastian/recursion-context", 1711 | "version": "3.0.0", 1712 | "source": { 1713 | "type": "git", 1714 | "url": "https://github.com/sebastianbergmann/recursion-context.git", 1715 | "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8" 1716 | }, 1717 | "dist": { 1718 | "type": "zip", 1719 | "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", 1720 | "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", 1721 | "shasum": "" 1722 | }, 1723 | "require": { 1724 | "php": "^7.0" 1725 | }, 1726 | "require-dev": { 1727 | "phpunit/phpunit": "^6.0" 1728 | }, 1729 | "type": "library", 1730 | "extra": { 1731 | "branch-alias": { 1732 | "dev-master": "3.0.x-dev" 1733 | } 1734 | }, 1735 | "autoload": { 1736 | "classmap": [ 1737 | "src/" 1738 | ] 1739 | }, 1740 | "notification-url": "https://packagist.org/downloads/", 1741 | "license": [ 1742 | "BSD-3-Clause" 1743 | ], 1744 | "authors": [ 1745 | { 1746 | "name": "Jeff Welch", 1747 | "email": "whatthejeff@gmail.com" 1748 | }, 1749 | { 1750 | "name": "Sebastian Bergmann", 1751 | "email": "sebastian@phpunit.de" 1752 | }, 1753 | { 1754 | "name": "Adam Harvey", 1755 | "email": "aharvey@php.net" 1756 | } 1757 | ], 1758 | "description": "Provides functionality to recursively process PHP variables", 1759 | "homepage": "http://www.github.com/sebastianbergmann/recursion-context", 1760 | "time": "2017-03-03T06:23:57+00:00" 1761 | }, 1762 | { 1763 | "name": "sebastian/resource-operations", 1764 | "version": "2.0.1", 1765 | "source": { 1766 | "type": "git", 1767 | "url": "https://github.com/sebastianbergmann/resource-operations.git", 1768 | "reference": "4d7a795d35b889bf80a0cc04e08d77cedfa917a9" 1769 | }, 1770 | "dist": { 1771 | "type": "zip", 1772 | "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/4d7a795d35b889bf80a0cc04e08d77cedfa917a9", 1773 | "reference": "4d7a795d35b889bf80a0cc04e08d77cedfa917a9", 1774 | "shasum": "" 1775 | }, 1776 | "require": { 1777 | "php": "^7.1" 1778 | }, 1779 | "type": "library", 1780 | "extra": { 1781 | "branch-alias": { 1782 | "dev-master": "2.0-dev" 1783 | } 1784 | }, 1785 | "autoload": { 1786 | "classmap": [ 1787 | "src/" 1788 | ] 1789 | }, 1790 | "notification-url": "https://packagist.org/downloads/", 1791 | "license": [ 1792 | "BSD-3-Clause" 1793 | ], 1794 | "authors": [ 1795 | { 1796 | "name": "Sebastian Bergmann", 1797 | "email": "sebastian@phpunit.de" 1798 | } 1799 | ], 1800 | "description": "Provides a list of PHP built-in functions that operate on resources", 1801 | "homepage": "https://www.github.com/sebastianbergmann/resource-operations", 1802 | "time": "2018-10-04T04:07:39+00:00" 1803 | }, 1804 | { 1805 | "name": "sebastian/version", 1806 | "version": "2.0.1", 1807 | "source": { 1808 | "type": "git", 1809 | "url": "https://github.com/sebastianbergmann/version.git", 1810 | "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" 1811 | }, 1812 | "dist": { 1813 | "type": "zip", 1814 | "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", 1815 | "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", 1816 | "shasum": "" 1817 | }, 1818 | "require": { 1819 | "php": ">=5.6" 1820 | }, 1821 | "type": "library", 1822 | "extra": { 1823 | "branch-alias": { 1824 | "dev-master": "2.0.x-dev" 1825 | } 1826 | }, 1827 | "autoload": { 1828 | "classmap": [ 1829 | "src/" 1830 | ] 1831 | }, 1832 | "notification-url": "https://packagist.org/downloads/", 1833 | "license": [ 1834 | "BSD-3-Clause" 1835 | ], 1836 | "authors": [ 1837 | { 1838 | "name": "Sebastian Bergmann", 1839 | "email": "sebastian@phpunit.de", 1840 | "role": "lead" 1841 | } 1842 | ], 1843 | "description": "Library that helps with managing the version number of Git-hosted PHP projects", 1844 | "homepage": "https://github.com/sebastianbergmann/version", 1845 | "time": "2016-10-03T07:35:21+00:00" 1846 | }, 1847 | { 1848 | "name": "symfony/console", 1849 | "version": "v3.4.27", 1850 | "source": { 1851 | "type": "git", 1852 | "url": "https://github.com/symfony/console.git", 1853 | "reference": "15a9104356436cb26e08adab97706654799d31d8" 1854 | }, 1855 | "dist": { 1856 | "type": "zip", 1857 | "url": "https://api.github.com/repos/symfony/console/zipball/15a9104356436cb26e08adab97706654799d31d8", 1858 | "reference": "15a9104356436cb26e08adab97706654799d31d8", 1859 | "shasum": "" 1860 | }, 1861 | "require": { 1862 | "php": "^5.5.9|>=7.0.8", 1863 | "symfony/debug": "~2.8|~3.0|~4.0", 1864 | "symfony/polyfill-mbstring": "~1.0" 1865 | }, 1866 | "conflict": { 1867 | "symfony/dependency-injection": "<3.4", 1868 | "symfony/process": "<3.3" 1869 | }, 1870 | "provide": { 1871 | "psr/log-implementation": "1.0" 1872 | }, 1873 | "require-dev": { 1874 | "psr/log": "~1.0", 1875 | "symfony/config": "~3.3|~4.0", 1876 | "symfony/dependency-injection": "~3.4|~4.0", 1877 | "symfony/event-dispatcher": "~2.8|~3.0|~4.0", 1878 | "symfony/lock": "~3.4|~4.0", 1879 | "symfony/process": "~3.3|~4.0" 1880 | }, 1881 | "suggest": { 1882 | "psr/log": "For using the console logger", 1883 | "symfony/event-dispatcher": "", 1884 | "symfony/lock": "", 1885 | "symfony/process": "" 1886 | }, 1887 | "type": "library", 1888 | "extra": { 1889 | "branch-alias": { 1890 | "dev-master": "3.4-dev" 1891 | } 1892 | }, 1893 | "autoload": { 1894 | "psr-4": { 1895 | "Symfony\\Component\\Console\\": "" 1896 | }, 1897 | "exclude-from-classmap": [ 1898 | "/Tests/" 1899 | ] 1900 | }, 1901 | "notification-url": "https://packagist.org/downloads/", 1902 | "license": [ 1903 | "MIT" 1904 | ], 1905 | "authors": [ 1906 | { 1907 | "name": "Fabien Potencier", 1908 | "email": "fabien@symfony.com" 1909 | }, 1910 | { 1911 | "name": "Symfony Community", 1912 | "homepage": "https://symfony.com/contributors" 1913 | } 1914 | ], 1915 | "description": "Symfony Console Component", 1916 | "homepage": "https://symfony.com", 1917 | "time": "2019-04-08T09:29:13+00:00" 1918 | }, 1919 | { 1920 | "name": "symfony/debug", 1921 | "version": "v3.4.27", 1922 | "source": { 1923 | "type": "git", 1924 | "url": "https://github.com/symfony/debug.git", 1925 | "reference": "681afbb26488903c5ac15e63734f1d8ac430c9b9" 1926 | }, 1927 | "dist": { 1928 | "type": "zip", 1929 | "url": "https://api.github.com/repos/symfony/debug/zipball/681afbb26488903c5ac15e63734f1d8ac430c9b9", 1930 | "reference": "681afbb26488903c5ac15e63734f1d8ac430c9b9", 1931 | "shasum": "" 1932 | }, 1933 | "require": { 1934 | "php": "^5.5.9|>=7.0.8", 1935 | "psr/log": "~1.0" 1936 | }, 1937 | "conflict": { 1938 | "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2" 1939 | }, 1940 | "require-dev": { 1941 | "symfony/http-kernel": "~2.8|~3.0|~4.0" 1942 | }, 1943 | "type": "library", 1944 | "extra": { 1945 | "branch-alias": { 1946 | "dev-master": "3.4-dev" 1947 | } 1948 | }, 1949 | "autoload": { 1950 | "psr-4": { 1951 | "Symfony\\Component\\Debug\\": "" 1952 | }, 1953 | "exclude-from-classmap": [ 1954 | "/Tests/" 1955 | ] 1956 | }, 1957 | "notification-url": "https://packagist.org/downloads/", 1958 | "license": [ 1959 | "MIT" 1960 | ], 1961 | "authors": [ 1962 | { 1963 | "name": "Fabien Potencier", 1964 | "email": "fabien@symfony.com" 1965 | }, 1966 | { 1967 | "name": "Symfony Community", 1968 | "homepage": "https://symfony.com/contributors" 1969 | } 1970 | ], 1971 | "description": "Symfony Debug Component", 1972 | "homepage": "https://symfony.com", 1973 | "time": "2019-04-11T09:48:14+00:00" 1974 | }, 1975 | { 1976 | "name": "symfony/event-dispatcher", 1977 | "version": "v3.4.27", 1978 | "source": { 1979 | "type": "git", 1980 | "url": "https://github.com/symfony/event-dispatcher.git", 1981 | "reference": "a088aafcefb4eef2520a290ed82e4374092a6dff" 1982 | }, 1983 | "dist": { 1984 | "type": "zip", 1985 | "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/a088aafcefb4eef2520a290ed82e4374092a6dff", 1986 | "reference": "a088aafcefb4eef2520a290ed82e4374092a6dff", 1987 | "shasum": "" 1988 | }, 1989 | "require": { 1990 | "php": "^5.5.9|>=7.0.8" 1991 | }, 1992 | "conflict": { 1993 | "symfony/dependency-injection": "<3.3" 1994 | }, 1995 | "require-dev": { 1996 | "psr/log": "~1.0", 1997 | "symfony/config": "~2.8|~3.0|~4.0", 1998 | "symfony/dependency-injection": "~3.3|~4.0", 1999 | "symfony/expression-language": "~2.8|~3.0|~4.0", 2000 | "symfony/stopwatch": "~2.8|~3.0|~4.0" 2001 | }, 2002 | "suggest": { 2003 | "symfony/dependency-injection": "", 2004 | "symfony/http-kernel": "" 2005 | }, 2006 | "type": "library", 2007 | "extra": { 2008 | "branch-alias": { 2009 | "dev-master": "3.4-dev" 2010 | } 2011 | }, 2012 | "autoload": { 2013 | "psr-4": { 2014 | "Symfony\\Component\\EventDispatcher\\": "" 2015 | }, 2016 | "exclude-from-classmap": [ 2017 | "/Tests/" 2018 | ] 2019 | }, 2020 | "notification-url": "https://packagist.org/downloads/", 2021 | "license": [ 2022 | "MIT" 2023 | ], 2024 | "authors": [ 2025 | { 2026 | "name": "Fabien Potencier", 2027 | "email": "fabien@symfony.com" 2028 | }, 2029 | { 2030 | "name": "Symfony Community", 2031 | "homepage": "https://symfony.com/contributors" 2032 | } 2033 | ], 2034 | "description": "Symfony EventDispatcher Component", 2035 | "homepage": "https://symfony.com", 2036 | "time": "2019-04-02T08:51:52+00:00" 2037 | }, 2038 | { 2039 | "name": "symfony/filesystem", 2040 | "version": "v3.4.27", 2041 | "source": { 2042 | "type": "git", 2043 | "url": "https://github.com/symfony/filesystem.git", 2044 | "reference": "acf99758b1df8e9295e6b85aa69f294565c9fedb" 2045 | }, 2046 | "dist": { 2047 | "type": "zip", 2048 | "url": "https://api.github.com/repos/symfony/filesystem/zipball/acf99758b1df8e9295e6b85aa69f294565c9fedb", 2049 | "reference": "acf99758b1df8e9295e6b85aa69f294565c9fedb", 2050 | "shasum": "" 2051 | }, 2052 | "require": { 2053 | "php": "^5.5.9|>=7.0.8", 2054 | "symfony/polyfill-ctype": "~1.8" 2055 | }, 2056 | "type": "library", 2057 | "extra": { 2058 | "branch-alias": { 2059 | "dev-master": "3.4-dev" 2060 | } 2061 | }, 2062 | "autoload": { 2063 | "psr-4": { 2064 | "Symfony\\Component\\Filesystem\\": "" 2065 | }, 2066 | "exclude-from-classmap": [ 2067 | "/Tests/" 2068 | ] 2069 | }, 2070 | "notification-url": "https://packagist.org/downloads/", 2071 | "license": [ 2072 | "MIT" 2073 | ], 2074 | "authors": [ 2075 | { 2076 | "name": "Fabien Potencier", 2077 | "email": "fabien@symfony.com" 2078 | }, 2079 | { 2080 | "name": "Symfony Community", 2081 | "homepage": "https://symfony.com/contributors" 2082 | } 2083 | ], 2084 | "description": "Symfony Filesystem Component", 2085 | "homepage": "https://symfony.com", 2086 | "time": "2019-02-04T21:34:32+00:00" 2087 | }, 2088 | { 2089 | "name": "symfony/finder", 2090 | "version": "v3.4.27", 2091 | "source": { 2092 | "type": "git", 2093 | "url": "https://github.com/symfony/finder.git", 2094 | "reference": "61af5ce0b34b942d414fe8f1b11950d0e9a90e98" 2095 | }, 2096 | "dist": { 2097 | "type": "zip", 2098 | "url": "https://api.github.com/repos/symfony/finder/zipball/61af5ce0b34b942d414fe8f1b11950d0e9a90e98", 2099 | "reference": "61af5ce0b34b942d414fe8f1b11950d0e9a90e98", 2100 | "shasum": "" 2101 | }, 2102 | "require": { 2103 | "php": "^5.5.9|>=7.0.8" 2104 | }, 2105 | "type": "library", 2106 | "extra": { 2107 | "branch-alias": { 2108 | "dev-master": "3.4-dev" 2109 | } 2110 | }, 2111 | "autoload": { 2112 | "psr-4": { 2113 | "Symfony\\Component\\Finder\\": "" 2114 | }, 2115 | "exclude-from-classmap": [ 2116 | "/Tests/" 2117 | ] 2118 | }, 2119 | "notification-url": "https://packagist.org/downloads/", 2120 | "license": [ 2121 | "MIT" 2122 | ], 2123 | "authors": [ 2124 | { 2125 | "name": "Fabien Potencier", 2126 | "email": "fabien@symfony.com" 2127 | }, 2128 | { 2129 | "name": "Symfony Community", 2130 | "homepage": "https://symfony.com/contributors" 2131 | } 2132 | ], 2133 | "description": "Symfony Finder Component", 2134 | "homepage": "https://symfony.com", 2135 | "time": "2019-04-02T19:54:57+00:00" 2136 | }, 2137 | { 2138 | "name": "symfony/options-resolver", 2139 | "version": "v3.4.27", 2140 | "source": { 2141 | "type": "git", 2142 | "url": "https://github.com/symfony/options-resolver.git", 2143 | "reference": "ed3b397f9c07c8ca388b2a1ef744403b4d4ecc44" 2144 | }, 2145 | "dist": { 2146 | "type": "zip", 2147 | "url": "https://api.github.com/repos/symfony/options-resolver/zipball/ed3b397f9c07c8ca388b2a1ef744403b4d4ecc44", 2148 | "reference": "ed3b397f9c07c8ca388b2a1ef744403b4d4ecc44", 2149 | "shasum": "" 2150 | }, 2151 | "require": { 2152 | "php": "^5.5.9|>=7.0.8" 2153 | }, 2154 | "type": "library", 2155 | "extra": { 2156 | "branch-alias": { 2157 | "dev-master": "3.4-dev" 2158 | } 2159 | }, 2160 | "autoload": { 2161 | "psr-4": { 2162 | "Symfony\\Component\\OptionsResolver\\": "" 2163 | }, 2164 | "exclude-from-classmap": [ 2165 | "/Tests/" 2166 | ] 2167 | }, 2168 | "notification-url": "https://packagist.org/downloads/", 2169 | "license": [ 2170 | "MIT" 2171 | ], 2172 | "authors": [ 2173 | { 2174 | "name": "Fabien Potencier", 2175 | "email": "fabien@symfony.com" 2176 | }, 2177 | { 2178 | "name": "Symfony Community", 2179 | "homepage": "https://symfony.com/contributors" 2180 | } 2181 | ], 2182 | "description": "Symfony OptionsResolver Component", 2183 | "homepage": "https://symfony.com", 2184 | "keywords": [ 2185 | "config", 2186 | "configuration", 2187 | "options" 2188 | ], 2189 | "time": "2019-04-10T16:00:48+00:00" 2190 | }, 2191 | { 2192 | "name": "symfony/polyfill-ctype", 2193 | "version": "v1.11.0", 2194 | "source": { 2195 | "type": "git", 2196 | "url": "https://github.com/symfony/polyfill-ctype.git", 2197 | "reference": "82ebae02209c21113908c229e9883c419720738a" 2198 | }, 2199 | "dist": { 2200 | "type": "zip", 2201 | "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/82ebae02209c21113908c229e9883c419720738a", 2202 | "reference": "82ebae02209c21113908c229e9883c419720738a", 2203 | "shasum": "" 2204 | }, 2205 | "require": { 2206 | "php": ">=5.3.3" 2207 | }, 2208 | "suggest": { 2209 | "ext-ctype": "For best performance" 2210 | }, 2211 | "type": "library", 2212 | "extra": { 2213 | "branch-alias": { 2214 | "dev-master": "1.11-dev" 2215 | } 2216 | }, 2217 | "autoload": { 2218 | "psr-4": { 2219 | "Symfony\\Polyfill\\Ctype\\": "" 2220 | }, 2221 | "files": [ 2222 | "bootstrap.php" 2223 | ] 2224 | }, 2225 | "notification-url": "https://packagist.org/downloads/", 2226 | "license": [ 2227 | "MIT" 2228 | ], 2229 | "authors": [ 2230 | { 2231 | "name": "Symfony Community", 2232 | "homepage": "https://symfony.com/contributors" 2233 | }, 2234 | { 2235 | "name": "Gert de Pagter", 2236 | "email": "BackEndTea@gmail.com" 2237 | } 2238 | ], 2239 | "description": "Symfony polyfill for ctype functions", 2240 | "homepage": "https://symfony.com", 2241 | "keywords": [ 2242 | "compatibility", 2243 | "ctype", 2244 | "polyfill", 2245 | "portable" 2246 | ], 2247 | "time": "2019-02-06T07:57:58+00:00" 2248 | }, 2249 | { 2250 | "name": "symfony/polyfill-mbstring", 2251 | "version": "v1.11.0", 2252 | "source": { 2253 | "type": "git", 2254 | "url": "https://github.com/symfony/polyfill-mbstring.git", 2255 | "reference": "fe5e94c604826c35a32fa832f35bd036b6799609" 2256 | }, 2257 | "dist": { 2258 | "type": "zip", 2259 | "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fe5e94c604826c35a32fa832f35bd036b6799609", 2260 | "reference": "fe5e94c604826c35a32fa832f35bd036b6799609", 2261 | "shasum": "" 2262 | }, 2263 | "require": { 2264 | "php": ">=5.3.3" 2265 | }, 2266 | "suggest": { 2267 | "ext-mbstring": "For best performance" 2268 | }, 2269 | "type": "library", 2270 | "extra": { 2271 | "branch-alias": { 2272 | "dev-master": "1.11-dev" 2273 | } 2274 | }, 2275 | "autoload": { 2276 | "psr-4": { 2277 | "Symfony\\Polyfill\\Mbstring\\": "" 2278 | }, 2279 | "files": [ 2280 | "bootstrap.php" 2281 | ] 2282 | }, 2283 | "notification-url": "https://packagist.org/downloads/", 2284 | "license": [ 2285 | "MIT" 2286 | ], 2287 | "authors": [ 2288 | { 2289 | "name": "Nicolas Grekas", 2290 | "email": "p@tchwork.com" 2291 | }, 2292 | { 2293 | "name": "Symfony Community", 2294 | "homepage": "https://symfony.com/contributors" 2295 | } 2296 | ], 2297 | "description": "Symfony polyfill for the Mbstring extension", 2298 | "homepage": "https://symfony.com", 2299 | "keywords": [ 2300 | "compatibility", 2301 | "mbstring", 2302 | "polyfill", 2303 | "portable", 2304 | "shim" 2305 | ], 2306 | "time": "2019-02-06T07:57:58+00:00" 2307 | }, 2308 | { 2309 | "name": "symfony/polyfill-php70", 2310 | "version": "v1.11.0", 2311 | "source": { 2312 | "type": "git", 2313 | "url": "https://github.com/symfony/polyfill-php70.git", 2314 | "reference": "bc4858fb611bda58719124ca079baff854149c89" 2315 | }, 2316 | "dist": { 2317 | "type": "zip", 2318 | "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/bc4858fb611bda58719124ca079baff854149c89", 2319 | "reference": "bc4858fb611bda58719124ca079baff854149c89", 2320 | "shasum": "" 2321 | }, 2322 | "require": { 2323 | "paragonie/random_compat": "~1.0|~2.0|~9.99", 2324 | "php": ">=5.3.3" 2325 | }, 2326 | "type": "library", 2327 | "extra": { 2328 | "branch-alias": { 2329 | "dev-master": "1.11-dev" 2330 | } 2331 | }, 2332 | "autoload": { 2333 | "psr-4": { 2334 | "Symfony\\Polyfill\\Php70\\": "" 2335 | }, 2336 | "files": [ 2337 | "bootstrap.php" 2338 | ], 2339 | "classmap": [ 2340 | "Resources/stubs" 2341 | ] 2342 | }, 2343 | "notification-url": "https://packagist.org/downloads/", 2344 | "license": [ 2345 | "MIT" 2346 | ], 2347 | "authors": [ 2348 | { 2349 | "name": "Nicolas Grekas", 2350 | "email": "p@tchwork.com" 2351 | }, 2352 | { 2353 | "name": "Symfony Community", 2354 | "homepage": "https://symfony.com/contributors" 2355 | } 2356 | ], 2357 | "description": "Symfony polyfill backporting some PHP 7.0+ features to lower PHP versions", 2358 | "homepage": "https://symfony.com", 2359 | "keywords": [ 2360 | "compatibility", 2361 | "polyfill", 2362 | "portable", 2363 | "shim" 2364 | ], 2365 | "time": "2019-02-06T07:57:58+00:00" 2366 | }, 2367 | { 2368 | "name": "symfony/polyfill-php72", 2369 | "version": "v1.11.0", 2370 | "source": { 2371 | "type": "git", 2372 | "url": "https://github.com/symfony/polyfill-php72.git", 2373 | "reference": "ab50dcf166d5f577978419edd37aa2bb8eabce0c" 2374 | }, 2375 | "dist": { 2376 | "type": "zip", 2377 | "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/ab50dcf166d5f577978419edd37aa2bb8eabce0c", 2378 | "reference": "ab50dcf166d5f577978419edd37aa2bb8eabce0c", 2379 | "shasum": "" 2380 | }, 2381 | "require": { 2382 | "php": ">=5.3.3" 2383 | }, 2384 | "type": "library", 2385 | "extra": { 2386 | "branch-alias": { 2387 | "dev-master": "1.11-dev" 2388 | } 2389 | }, 2390 | "autoload": { 2391 | "psr-4": { 2392 | "Symfony\\Polyfill\\Php72\\": "" 2393 | }, 2394 | "files": [ 2395 | "bootstrap.php" 2396 | ] 2397 | }, 2398 | "notification-url": "https://packagist.org/downloads/", 2399 | "license": [ 2400 | "MIT" 2401 | ], 2402 | "authors": [ 2403 | { 2404 | "name": "Nicolas Grekas", 2405 | "email": "p@tchwork.com" 2406 | }, 2407 | { 2408 | "name": "Symfony Community", 2409 | "homepage": "https://symfony.com/contributors" 2410 | } 2411 | ], 2412 | "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", 2413 | "homepage": "https://symfony.com", 2414 | "keywords": [ 2415 | "compatibility", 2416 | "polyfill", 2417 | "portable", 2418 | "shim" 2419 | ], 2420 | "time": "2019-02-06T07:57:58+00:00" 2421 | }, 2422 | { 2423 | "name": "symfony/process", 2424 | "version": "v3.4.27", 2425 | "source": { 2426 | "type": "git", 2427 | "url": "https://github.com/symfony/process.git", 2428 | "reference": "a9c4dfbf653023b668c282e4e02609d131f4057a" 2429 | }, 2430 | "dist": { 2431 | "type": "zip", 2432 | "url": "https://api.github.com/repos/symfony/process/zipball/a9c4dfbf653023b668c282e4e02609d131f4057a", 2433 | "reference": "a9c4dfbf653023b668c282e4e02609d131f4057a", 2434 | "shasum": "" 2435 | }, 2436 | "require": { 2437 | "php": "^5.5.9|>=7.0.8" 2438 | }, 2439 | "type": "library", 2440 | "extra": { 2441 | "branch-alias": { 2442 | "dev-master": "3.4-dev" 2443 | } 2444 | }, 2445 | "autoload": { 2446 | "psr-4": { 2447 | "Symfony\\Component\\Process\\": "" 2448 | }, 2449 | "exclude-from-classmap": [ 2450 | "/Tests/" 2451 | ] 2452 | }, 2453 | "notification-url": "https://packagist.org/downloads/", 2454 | "license": [ 2455 | "MIT" 2456 | ], 2457 | "authors": [ 2458 | { 2459 | "name": "Fabien Potencier", 2460 | "email": "fabien@symfony.com" 2461 | }, 2462 | { 2463 | "name": "Symfony Community", 2464 | "homepage": "https://symfony.com/contributors" 2465 | } 2466 | ], 2467 | "description": "Symfony Process Component", 2468 | "homepage": "https://symfony.com", 2469 | "time": "2019-04-08T16:15:54+00:00" 2470 | }, 2471 | { 2472 | "name": "symfony/stopwatch", 2473 | "version": "v3.4.27", 2474 | "source": { 2475 | "type": "git", 2476 | "url": "https://github.com/symfony/stopwatch.git", 2477 | "reference": "2a651c2645c10bbedd21170771f122d935e0dd58" 2478 | }, 2479 | "dist": { 2480 | "type": "zip", 2481 | "url": "https://api.github.com/repos/symfony/stopwatch/zipball/2a651c2645c10bbedd21170771f122d935e0dd58", 2482 | "reference": "2a651c2645c10bbedd21170771f122d935e0dd58", 2483 | "shasum": "" 2484 | }, 2485 | "require": { 2486 | "php": "^5.5.9|>=7.0.8" 2487 | }, 2488 | "type": "library", 2489 | "extra": { 2490 | "branch-alias": { 2491 | "dev-master": "3.4-dev" 2492 | } 2493 | }, 2494 | "autoload": { 2495 | "psr-4": { 2496 | "Symfony\\Component\\Stopwatch\\": "" 2497 | }, 2498 | "exclude-from-classmap": [ 2499 | "/Tests/" 2500 | ] 2501 | }, 2502 | "notification-url": "https://packagist.org/downloads/", 2503 | "license": [ 2504 | "MIT" 2505 | ], 2506 | "authors": [ 2507 | { 2508 | "name": "Fabien Potencier", 2509 | "email": "fabien@symfony.com" 2510 | }, 2511 | { 2512 | "name": "Symfony Community", 2513 | "homepage": "https://symfony.com/contributors" 2514 | } 2515 | ], 2516 | "description": "Symfony Stopwatch Component", 2517 | "homepage": "https://symfony.com", 2518 | "time": "2019-01-16T09:39:14+00:00" 2519 | }, 2520 | { 2521 | "name": "theseer/tokenizer", 2522 | "version": "1.1.2", 2523 | "source": { 2524 | "type": "git", 2525 | "url": "https://github.com/theseer/tokenizer.git", 2526 | "reference": "1c42705be2b6c1de5904f8afacef5895cab44bf8" 2527 | }, 2528 | "dist": { 2529 | "type": "zip", 2530 | "url": "https://api.github.com/repos/theseer/tokenizer/zipball/1c42705be2b6c1de5904f8afacef5895cab44bf8", 2531 | "reference": "1c42705be2b6c1de5904f8afacef5895cab44bf8", 2532 | "shasum": "" 2533 | }, 2534 | "require": { 2535 | "ext-dom": "*", 2536 | "ext-tokenizer": "*", 2537 | "ext-xmlwriter": "*", 2538 | "php": "^7.0" 2539 | }, 2540 | "type": "library", 2541 | "autoload": { 2542 | "classmap": [ 2543 | "src/" 2544 | ] 2545 | }, 2546 | "notification-url": "https://packagist.org/downloads/", 2547 | "license": [ 2548 | "BSD-3-Clause" 2549 | ], 2550 | "authors": [ 2551 | { 2552 | "name": "Arne Blankerts", 2553 | "email": "arne@blankerts.de", 2554 | "role": "Developer" 2555 | } 2556 | ], 2557 | "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", 2558 | "time": "2019-04-04T09:56:43+00:00" 2559 | }, 2560 | { 2561 | "name": "webmozart/assert", 2562 | "version": "1.4.0", 2563 | "source": { 2564 | "type": "git", 2565 | "url": "https://github.com/webmozart/assert.git", 2566 | "reference": "83e253c8e0be5b0257b881e1827274667c5c17a9" 2567 | }, 2568 | "dist": { 2569 | "type": "zip", 2570 | "url": "https://api.github.com/repos/webmozart/assert/zipball/83e253c8e0be5b0257b881e1827274667c5c17a9", 2571 | "reference": "83e253c8e0be5b0257b881e1827274667c5c17a9", 2572 | "shasum": "" 2573 | }, 2574 | "require": { 2575 | "php": "^5.3.3 || ^7.0", 2576 | "symfony/polyfill-ctype": "^1.8" 2577 | }, 2578 | "require-dev": { 2579 | "phpunit/phpunit": "^4.6", 2580 | "sebastian/version": "^1.0.1" 2581 | }, 2582 | "type": "library", 2583 | "extra": { 2584 | "branch-alias": { 2585 | "dev-master": "1.3-dev" 2586 | } 2587 | }, 2588 | "autoload": { 2589 | "psr-4": { 2590 | "Webmozart\\Assert\\": "src/" 2591 | } 2592 | }, 2593 | "notification-url": "https://packagist.org/downloads/", 2594 | "license": [ 2595 | "MIT" 2596 | ], 2597 | "authors": [ 2598 | { 2599 | "name": "Bernhard Schussek", 2600 | "email": "bschussek@gmail.com" 2601 | } 2602 | ], 2603 | "description": "Assertions to validate method input/output with nice error messages.", 2604 | "keywords": [ 2605 | "assert", 2606 | "check", 2607 | "validate" 2608 | ], 2609 | "time": "2018-12-25T11:19:39+00:00" 2610 | } 2611 | ], 2612 | "aliases": [], 2613 | "minimum-stability": "stable", 2614 | "stability-flags": [], 2615 | "prefer-stable": false, 2616 | "prefer-lowest": false, 2617 | "platform": { 2618 | "php": "^7.1" 2619 | }, 2620 | "platform-dev": [], 2621 | "platform-overrides": { 2622 | "php": "7.1" 2623 | } 2624 | } 2625 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | test/suite 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | src 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /src/Detail/AbstractIsolator.php: -------------------------------------------------------------------------------- 1 | newInstanceArgs($arguments); 63 | } 64 | 65 | if ($arguments) { 66 | return \call_user_func_array($name, $arguments); 67 | } 68 | 69 | return $name(); 70 | } 71 | 72 | /** 73 | * Fetch an isolator instance. 74 | * 75 | * This convenience method returns the global isolator instance, or $instance if provided. 76 | * 77 | * @param Isolator|null $isolator An existing isolator instance, if available. 78 | * 79 | * @return Isolator The global isolator instance, or $isolator if provided. 80 | */ 81 | public static function get(Isolator $isolator = null) 82 | { 83 | if (null !== $isolator) { 84 | return $isolator; 85 | } elseif (!self::$instance) { 86 | self::$instance = new Isolator(); 87 | } 88 | 89 | return self::$instance; 90 | } 91 | 92 | /** 93 | * Set the default isolator instance. 94 | * 95 | * @param Isolator $isolator The isolator instance. 96 | */ 97 | public static function set(Isolator $isolator = null) 98 | { 99 | self::$instance = $isolator; 100 | } 101 | 102 | private static $instance; 103 | } 104 | -------------------------------------------------------------------------------- /src/Detail/Autoloader.php: -------------------------------------------------------------------------------- 1 | path = $path; 20 | $this->codeGenerator = $codeGenerator; 21 | } 22 | 23 | /** 24 | * Load an isolator class with the given name. 25 | * 26 | * @param string $className The name to give to the isolator class. 27 | */ 28 | public function load($className) 29 | { 30 | $functions = get_defined_functions(); 31 | $functions = $functions['internal']; 32 | 33 | $hash = $this->computeHash($className, $functions); 34 | 35 | $fileName = $this->path . DIRECTORY_SEPARATOR . 'Isolator' . $hash . '.php'; 36 | 37 | if (!file_exists($fileName)) { 38 | $this->generateIsolatorClass( 39 | $fileName, 40 | $className, 41 | $functions 42 | ); 43 | } 44 | 45 | require_once $fileName; 46 | } 47 | 48 | /** 49 | * Compute a unique hash used to identify an isolator implementation that 50 | * proxies the given functions. 51 | * 52 | * @param string $className The name to give to the isolator class. 53 | * @param array $functions An array of global function names. 54 | * 55 | * @return string 56 | */ 57 | public function computeHash($className, array $functions) 58 | { 59 | $hash = hash_init('sha1'); 60 | 61 | hash_update($hash, $className); 62 | 63 | foreach ($functions as $function) { 64 | hash_update($hash, $function); 65 | } 66 | 67 | // Include the PHP version in the hash in case function signatures 68 | // change between versions. 69 | hash_update($hash, phpversion()); 70 | 71 | // Include the content of the code generator in case the implementation 72 | // changes between versions. 73 | hash_update_file($hash, __DIR__ . '/CodeGenerator.php'); 74 | 75 | return hash_final($hash); 76 | } 77 | 78 | /** 79 | * Generate and store an isolator implementation. 80 | * 81 | * @param string $className The name to give to the isolator class. 82 | * @param array $functions An array of global function names. 83 | */ 84 | public function generateIsolatorClass( 85 | $fileName, 86 | $className, 87 | array $functions 88 | ) { 89 | $dirName = dirname($fileName); 90 | $umask = umask(0); 91 | 92 | try { 93 | if (!file_exists($dirName)) { 94 | mkdir($dirName, 0777, true); 95 | } 96 | 97 | $code = $this 98 | ->codeGenerator 99 | ->generate( 100 | $className, 101 | $functions 102 | ); 103 | 104 | file_put_contents($fileName, $code); 105 | 106 | chmod($fileName, 0644); 107 | 108 | umask($umask); 109 | } catch (Exception $e) { 110 | umask($umask); 111 | 112 | throw $e; 113 | } 114 | } 115 | 116 | private $path; 117 | private $codeGenerator; 118 | } 119 | -------------------------------------------------------------------------------- /src/Detail/CodeGenerator.php: -------------------------------------------------------------------------------- 1 | ellipsisExpansion = $ellipsisExpansion; 16 | } 17 | 18 | /** 19 | * Generate an isolator implementation. 20 | */ 21 | public function generate($className, array $functions) 22 | { 23 | $pos = strrpos($className, '\\'); 24 | 25 | if ($pos) { 26 | $namespace = substr($className, 0, $pos); 27 | $shortName = substr($className, $pos + 1); 28 | } else { 29 | $namespace = null; 30 | $shortName = $className; 31 | } 32 | 33 | $code = 'generateMethod( 54 | new ReflectionFunction($function) 55 | ); 56 | } 57 | 58 | $code .= '}' . PHP_EOL; 59 | 60 | return $code; 61 | } 62 | 63 | private function generateMethod(ReflectionFunction $reflector) 64 | { 65 | $name = $reflector->getName(); 66 | 67 | list($minArity, $maxArity, $refIndices) = $this->inspectParameters($reflector); 68 | 69 | $signature = $this->generateSignature( 70 | $name, 71 | $reflector->returnsReference(), 72 | $minArity, 73 | $maxArity, 74 | $refIndices 75 | ); 76 | 77 | $code = ' ' . $signature . PHP_EOL; 78 | $code .= ' {' . PHP_EOL; 79 | $code .= $this->generateSwitch($name, $minArity, $maxArity); 80 | $code .= PHP_EOL; 81 | $code .= $this->generateFallbackReturn($name, $refIndices); 82 | $code .= ' }' . PHP_EOL; 83 | 84 | return $code; 85 | } 86 | 87 | /** 88 | * @param string $name The function name. 89 | * @param boolean $returnsReference True if the function returns a reference. 90 | * @param integer $minArity The minimum number of arguments. 91 | * @param integer $maxArity The maximum number of arguments present in the signature. 92 | * @param array $refIndices An array containing the indices of parameters that are references. 93 | */ 94 | private function generateSignature( 95 | $name, 96 | $returnsReference, 97 | $minArity, 98 | $maxArity, 99 | $refIndices 100 | ) { 101 | $parameters = array(); 102 | 103 | for ($index = 0; $index < $maxArity; ++$index) { 104 | $param = '$p' . $index; 105 | 106 | if ($refIndices[$index]) { 107 | $param = '&' . $param; 108 | } 109 | 110 | if ($index >= $minArity) { 111 | $param .= ' = null'; 112 | } 113 | 114 | $parameters[] = $param; 115 | } 116 | 117 | return sprintf( 118 | 'public function %s%s(%s)', 119 | $returnsReference ? '&' : '', 120 | str_replace('\\', '_', $name), 121 | implode(', ', $parameters) 122 | ); 123 | } 124 | 125 | private function generateSwitch($name, $minArity, $maxArity) 126 | { 127 | $code = ' switch (\func_num_args()) {' . PHP_EOL; 128 | 129 | for ($arity = $minArity; $arity <= $maxArity; ++$arity) { 130 | $code .= sprintf( 131 | ' case %d: %s', 132 | $arity, 133 | $this->generateReturn($name, $arity) 134 | ); 135 | } 136 | 137 | $code .= ' }' . PHP_EOL; 138 | 139 | return $code; 140 | } 141 | 142 | private function generateReturn($name, $arity) 143 | { 144 | $arguments = array(); 145 | for ($index = 0; $index < $arity; ++$index) { 146 | $arguments[] = '$p' . $index; 147 | } 148 | 149 | return sprintf( 150 | 'return \%s(%s);' . PHP_EOL, 151 | $name, 152 | implode(', ', $arguments) 153 | ); 154 | } 155 | 156 | public function generateFallbackReturn($name, $refIndices) 157 | { 158 | $code = ' $arguments = \func_get_args();' . PHP_EOL; 159 | 160 | foreach ($refIndices as $index => $isReference) { 161 | if ($isReference) { 162 | $code .= ' $arguments[' . $index . '] = &$p' . $index . ';' . PHP_EOL; 163 | } 164 | } 165 | 166 | $code .= PHP_EOL; 167 | $code .= ' return \call_user_func_array(' . var_export($name, true) . ', $arguments);' . PHP_EOL; 168 | 169 | return $code; 170 | } 171 | 172 | private function inspectParameters(ReflectionFunction $reflector) 173 | { 174 | $minArity = 0; 175 | $maxArity = 0; 176 | $refIndices = array(); 177 | 178 | foreach ($reflector->getParameters() as $parameter) { 179 | // PHP versions < 5.6 showed a parameter named '...' to indicate 180 | // that a function took an arbitrary number of arguments. 181 | // 182 | // @codeCoverageIgnoreStart 183 | if ($parameter->getName() === '...') { 184 | break; 185 | } 186 | // @codeCoverageIgnoreEnd 187 | 188 | $refIndices[$maxArity++] = $parameter->isPassedByReference(); 189 | 190 | if (!$parameter->isOptional()) { 191 | ++$minArity; 192 | } 193 | } 194 | 195 | return array($minArity, $maxArity, $refIndices); 196 | } 197 | 198 | private $ellipsisExpansion; 199 | } 200 | -------------------------------------------------------------------------------- /src/IsolatorTrait.php: -------------------------------------------------------------------------------- 1 | isolator) { 17 | return $this->isolator; 18 | } 19 | 20 | return Isolator::get(); 21 | } 22 | 23 | /** 24 | * Set the {@see Isolator} instance to be used by this object. 25 | * 26 | * @param Isolator|null $isolator The isolator instance to be used by this object, or null to use the global instance. 27 | */ 28 | public function setIsolator(Isolator $isolator = null) 29 | { 30 | $this->isolator = $isolator; 31 | } 32 | 33 | private $isolator; 34 | } 35 | -------------------------------------------------------------------------------- /src/register-autoloader.php: -------------------------------------------------------------------------------- 1 | load($className); 16 | } 17 | ); 18 | -------------------------------------------------------------------------------- /test/src/ClassA.php: -------------------------------------------------------------------------------- 1 | path = tempnam(sys_get_temp_dir(), 'isolator-'); 13 | $this->codeGenerator = Phake::mock(__NAMESPACE__ . '\CodeGenerator'); 14 | 15 | $this->autoloader = new Autoloader( 16 | $this->path, 17 | $this->codeGenerator 18 | ); 19 | 20 | unlink($this->path); 21 | 22 | Phake::when($this->codeGenerator) 23 | ->generate(Phake::anyParameters()) 24 | ->thenReturn('expectOutputString('Included!'); 30 | 31 | $this->autoloader->load('Foo'); 32 | 33 | $functions = get_defined_functions(); 34 | 35 | Phake::verify($this->codeGenerator)->generate( 36 | 'Foo', 37 | $functions['internal'] 38 | ); 39 | 40 | // Additional load should not produce additional output ... 41 | $this->autoloader->load('Foo'); 42 | 43 | Phake::verify($this->codeGenerator, Phake::times(1))->generate(Phake::anyParameters()); 44 | } 45 | 46 | public function testDirectoryIsCreatedWorldWritable() 47 | { 48 | $this->expectOutputString('Included!'); 49 | 50 | $this->autoloader->load('Foo'); 51 | 52 | $stat = stat($this->path); 53 | 54 | $this->assertEquals( 55 | 0777, 56 | $stat['mode'] & 0777, 57 | 'Isolator temporary directory must be world writable.' 58 | ); 59 | } 60 | 61 | public function testFileIsNotCreatedWorldWritable() 62 | { 63 | $this->expectOutputString('Included!'); 64 | 65 | $functions = get_defined_functions(); 66 | $hash = $this->autoloader->computeHash('Foo', $functions['internal']); 67 | $fileName = $this->path . '/Isolator' . $hash . '.php'; 68 | 69 | $this->autoloader->load('Foo'); 70 | 71 | $stat = stat($fileName); 72 | 73 | $this->assertEquals( 74 | 0444, 75 | $stat['mode'] & 0444, 76 | 'Isolator temporary file must be world readable.' 77 | ); 78 | 79 | $this->assertEquals( 80 | 0, 81 | $stat['mode'] & 02, 82 | 'Isolator temporary file not must be world writable.' 83 | ); 84 | } 85 | 86 | public function testUmaskIsReset() 87 | { 88 | $umask = umask(); 89 | 90 | $this->expectOutputString('Included!'); 91 | 92 | $this->autoloader->load('Foo'); 93 | 94 | $this->assertEquals( 95 | $umask, 96 | umask() 97 | ); 98 | } 99 | 100 | public function testUmaskIsResetAfterException() 101 | { 102 | $umask = umask(); 103 | $exception = new Exception('The exception!'); 104 | 105 | Phake::when($this->codeGenerator) 106 | ->generate(Phake::anyParameters()) 107 | ->thenThrow($exception); 108 | 109 | $this->expectException( 110 | 'Exception', 111 | 'The exception!' 112 | ); 113 | 114 | try { 115 | $this->autoloader->load('Foo'); 116 | } catch (Exception $e) { 117 | $this->assertEquals( 118 | $umask, 119 | umask() 120 | ); 121 | 122 | throw $e; 123 | } 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /test/suite/Detail/CodeGeneratorTest.php: -------------------------------------------------------------------------------- 1 | generator = new CodeGenerator(); 11 | } 12 | 13 | public function testGenerateClass() 14 | { 15 | $code = $this->generator->generate( 16 | 'Foo', 17 | array() 18 | ); 19 | 20 | $expectedCode = 'assertSame( 29 | $expectedCode, 30 | $code 31 | ); 32 | } 33 | 34 | public function testGenerateClassInNamespace() 35 | { 36 | $code = $this->generator->generate( 37 | 'Foo\Bar\Spam', 38 | array() 39 | ); 40 | 41 | $expectedCode = 'assertSame( 51 | $expectedCode, 52 | $code 53 | ); 54 | } 55 | 56 | public function testGenerateMethod() 57 | { 58 | $code = $this->generator->generate( 59 | 'Foo', 60 | array('strlen') 61 | ); 62 | 63 | $expectedCode = 'assertSame( 82 | $expectedCode, 83 | $code 84 | ); 85 | } 86 | 87 | public function testGenerateMethodWithReferenceParameter() 88 | { 89 | $code = $this->generator->generate( 90 | 'Foo', 91 | array('preg_match') 92 | ); 93 | 94 | $expectedCode = 'assertSame( 117 | $expectedCode, 118 | $code 119 | ); 120 | } 121 | 122 | public function testGenerateMethodWithVarArgs() 123 | { 124 | $code = $this->generator->generate( 125 | 'Foo', 126 | array('sprintf') 127 | ); 128 | 129 | $expectedCode = 'assertSame( 149 | $expectedCode, 150 | $code 151 | ); 152 | } 153 | 154 | public function testGenerateMultipleMethods() 155 | { 156 | $code = $this->generator->generate( 157 | 'Foo', 158 | array('strlen', 'phpversion') 159 | ); 160 | 161 | $expectedCode = 'assertSame( 192 | $expectedCode, 193 | $code 194 | ); 195 | } 196 | } 197 | -------------------------------------------------------------------------------- /test/suite/IsolatorTest.php: -------------------------------------------------------------------------------- 1 | isolator = new Isolator(); 17 | } 18 | 19 | public function tearDown() 20 | { 21 | Isolator::set(null); 22 | } 23 | 24 | public function testCall() 25 | { 26 | $this->assertSame( 27 | 3, 28 | $this->isolator->strlen('foo') 29 | ); 30 | } 31 | 32 | public function testCallWithReference() 33 | { 34 | $matches = array(); 35 | 36 | $this->isolator->preg_match( 37 | '/.*/', 38 | 'foo', 39 | $matches 40 | ); 41 | 42 | $this->assertSame( 43 | array('foo'), 44 | $matches 45 | ); 46 | } 47 | 48 | public function testCallWithVarArgs() 49 | { 50 | $this->assertSame( 51 | 'a b c', 52 | $this->isolator->sprintf( 53 | '%s %s %s', 54 | 'a', 55 | 'b', 56 | 'c' 57 | ) 58 | ); 59 | } 60 | 61 | public function testCallFunctionDefinedAfterIsolatorCreated() 62 | { 63 | if (function_exists('icecaveIsolatorPostGeneration')) { 64 | $this->markTestSkipped('This test can only be executed once.'); 65 | } 66 | 67 | require __DIR__ . '/../src/function.php'; 68 | 69 | $this->assertNull( 70 | $this->isolator->icecaveIsolatorPostGeneration() 71 | ); 72 | 73 | $this->assertSame( 74 | $this->isolator->icecaveIsolatorPostGeneration(123), 75 | 123 76 | ); 77 | } 78 | 79 | public function testEcho() 80 | { 81 | $this->expectOutputString('Echo works!'); 82 | 83 | $this->isolator->echo('Echo works!'); 84 | } 85 | 86 | public function testEval() 87 | { 88 | $this->assertSame( 89 | 3, 90 | $this->isolator->eval('return strlen("foo");') 91 | ); 92 | } 93 | 94 | public function testInclude() 95 | { 96 | $this->assertFalse( 97 | class_exists('Icecave\Isolator\ClassA', false) 98 | ); 99 | 100 | $this->assertSame( 101 | 'returnValueA', 102 | $this->isolator->include(__DIR__ . '/../src/ClassA.php') 103 | ); 104 | 105 | $this->assertTrue( 106 | class_exists('Icecave\Isolator\ClassA', false) 107 | ); 108 | } 109 | 110 | public function testIncludeOnce() 111 | { 112 | $this->assertFalse( 113 | class_exists('Icecave\Isolator\ClassB', false) 114 | ); 115 | 116 | $this->assertSame( 117 | 'returnValueB', 118 | $this->isolator->include_once(__DIR__ . '/../src/ClassB.php') 119 | ); 120 | 121 | $this->assertTrue( 122 | class_exists('Icecave\Isolator\ClassB', false) 123 | ); 124 | } 125 | 126 | public function testRequire() 127 | { 128 | $this->assertFalse( 129 | class_exists('Icecave\Isolator\ClassC', false) 130 | ); 131 | 132 | $this->assertSame( 133 | 'returnValueC', 134 | $this->isolator->require(__DIR__ . '/../src/ClassC.php') 135 | ); 136 | 137 | $this->assertTrue( 138 | class_exists('Icecave\Isolator\ClassC', false) 139 | ); 140 | } 141 | 142 | public function testRequireOnce() 143 | { 144 | $this->assertFalse( 145 | class_exists('Icecave\Isolator\ClassD', false) 146 | ); 147 | 148 | $this->assertSame( 149 | 'returnValueD', 150 | $this->isolator->require_once(__DIR__ . '/../src/ClassD.php') 151 | ); 152 | 153 | $this->assertTrue( 154 | class_exists('Icecave\Isolator\ClassD', false) 155 | ); 156 | } 157 | 158 | public function testNew() 159 | { 160 | $this->assertEquals( 161 | new SplObjectStorage(), 162 | $this->isolator->new('SplObjectStorage') 163 | ); 164 | } 165 | 166 | public function testNewWithConstructorArguments() 167 | { 168 | $this->assertEquals( 169 | new DateTime('2014-01-01 01:02:03 GMT'), 170 | $this->isolator->new('DateTime', '2014-01-01 01:02:03 GMT') 171 | ); 172 | } 173 | 174 | public function testGet() 175 | { 176 | $this->assertSame( 177 | $this->isolator, 178 | Isolator::get($this->isolator) 179 | ); 180 | 181 | $globalIsolator = Isolator::get(); 182 | 183 | $this->assertInstanceOf( 184 | 'Icecave\Isolator\Isolator', 185 | $globalIsolator 186 | ); 187 | 188 | $this->assertNotSame( 189 | $this->isolator, 190 | $globalIsolator 191 | ); 192 | 193 | $this->assertSame( 194 | $globalIsolator, 195 | Isolator::get() 196 | ); 197 | } 198 | 199 | /** 200 | * @group regression 201 | * @link https://github.com/icecave/isolator/issues/17 202 | */ 203 | public function testCallVarArgsWithReferences() 204 | { 205 | $array = array(); 206 | 207 | $this->isolator->array_push($array, 1, 2); 208 | 209 | $this->assertSame( 210 | array(1, 2), 211 | $array 212 | ); 213 | } 214 | } 215 | -------------------------------------------------------------------------------- /test/suite/IsolatorTraitTest.php: -------------------------------------------------------------------------------- 1 | assertSame($instance, $object->isolator()); 20 | 21 | $instance = Phake::mock(__NAMESPACE__ . '\Isolator'); 22 | 23 | $object->setIsolator($instance); 24 | 25 | $this->assertSame($instance, $object->isolator()); 26 | 27 | $object->setIsolator(null); 28 | 29 | $instance = Isolator::get(); 30 | 31 | $this->assertSame($instance, $object->isolator()); 32 | } 33 | } 34 | --------------------------------------------------------------------------------