├── .gitignore ├── tests ├── di.xml ├── Stubs │ ├── install-config-mysql.stub │ └── Magento │ │ └── Framework │ │ └── ObjectManager │ │ └── Factory │ │ └── AbstractFactory.stub ├── Fakes │ └── CurrentWorkingDirectoryFake.php ├── FileSystem │ └── TemporaryFileTest.php ├── Service │ └── FileSystem │ │ └── CurrentWorkingDirectoryTest.php ├── Validate │ ├── Validators │ │ ├── TheConfigFileExistsTest.php │ │ ├── IsMagentoInstallationTest.php │ │ ├── PhpUnitFileExistsTest.php │ │ ├── RabbitMqCredentialsAreValidTest.php │ │ └── MysqlCredentialsAreValidTest.php │ └── ValidateSetupTest.php └── Magento │ └── ErrorOutputTest.php ├── src ├── Exceptions │ ├── FailingForUnknownReason.php │ ├── InstanceFailingException.php │ └── InvalidConfigurationException.php ├── Stubs │ ├── MagentoModule │ │ ├── etc │ │ │ ├── di.stub │ │ │ └── module.stub │ │ ├── registration.stub │ │ └── Test │ │ │ └── AlwaysSucceedingTest.stub │ ├── ReadConfig.stub │ └── ModuleFixer.stub ├── Validate │ ├── Validators │ │ ├── ValidatorContract.php │ │ ├── TheConfigFileExists.php │ │ ├── IsMagentoInstallation.php │ │ ├── PhpUnitFileExists.php │ │ ├── MysqlCredentialsAreValid.php │ │ └── AmpqCredentialsAreValid.php │ └── ValidateSetup.php ├── External │ ├── Amqp.php │ └── Mysql.php ├── FileSystem │ ├── TemporaryFile.php │ ├── CurrentWorkingDirectory.php │ ├── Folder.php │ └── ReadMysqlConfig.php ├── Revive.php ├── Application │ └── Configure.php ├── functions.php ├── Magento │ ├── FixModule.php │ ├── ModuleManager.php │ ├── ErrorOutput.php │ ├── IntegrationTests.php │ └── TestRunner.php └── Commands │ └── TestDebug.php ├── .travis.yml ├── phpunit.xml.dist ├── composer.json ├── README.md ├── CreatePhar.php └── composer.lock /.gitignore: -------------------------------------------------------------------------------- 1 | vendor/ 2 | -------------------------------------------------------------------------------- /tests/di.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/Exceptions/FailingForUnknownReason.php: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/Stubs/MagentoModule/registration.stub: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/Stubs/ReadConfig.stub: -------------------------------------------------------------------------------- 1 | 2 | 3 | 13 | 14 | 15 | tests 16 | 17 | 18 | 19 | 20 | src/ 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /tests/Stubs/install-config-mysql.stub: -------------------------------------------------------------------------------- 1 | 'localhost', 9 | 'db-user' => '{username}', 10 | 'db-password' => '{password}', 11 | 'db-name' => '{database}', 12 | 'db-prefix' => '', 13 | 'backend-frontname' => 'backend', 14 | 'admin-user' => \Magento\TestFramework\Bootstrap::ADMIN_NAME, 15 | 'admin-password' => \Magento\TestFramework\Bootstrap::ADMIN_PASSWORD, 16 | 'admin-email' => \Magento\TestFramework\Bootstrap::ADMIN_EMAIL, 17 | 'admin-firstname' => \Magento\TestFramework\Bootstrap::ADMIN_FIRSTNAME, 18 | 'admin-lastname' => \Magento\TestFramework\Bootstrap::ADMIN_LASTNAME, 19 | 'amqp-host' => 'localhost', 20 | 'amqp-port' => '5672', 21 | 'amqp-user' => 'guest', 22 | 'amqp-password' => 'guest', 23 | ]; 24 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "michielgerritsen/revive", 3 | "description": "Revive your project by adding integration tests to your Magento 2 store", 4 | "require": { 5 | "symfony/console": "^4.3", 6 | "illuminate/container": "^5.8", 7 | "symfony/process": "^4.3", 8 | "mikey179/vfsstream": "^1.6", 9 | "ext-json": "*" 10 | }, 11 | "require-dev": { 12 | "phpunit/phpunit": "^7.5" 13 | }, 14 | "authors": [ 15 | { 16 | "name": "Michiel Gerritsen", 17 | "email": "michiel@controlaltdelete.nl" 18 | } 19 | ], 20 | "autoload": { 21 | "psr-4": { 22 | "MichielGerritsen\\Revive\\": "src" 23 | }, 24 | "files": ["src/functions.php"] 25 | }, 26 | "autoload-dev": { 27 | "psr-4": { 28 | "MichielGerritsen\\Revive\\Test\\": "tests" 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Stubs/MagentoModule/Test/AlwaysSucceedingTest.stub: -------------------------------------------------------------------------------- 1 | assertTrue(true); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Exceptions/InstanceFailingException.php: -------------------------------------------------------------------------------- 1 | files[] = $path; 33 | 34 | return $path; 35 | } 36 | 37 | public function __destruct() 38 | { 39 | foreach ($this->files as $file) { 40 | unlink($file); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Revive.php: -------------------------------------------------------------------------------- 1 | singleton(CurrentWorkingDirectory::class); 27 | 28 | $application = new Application(); 29 | (new Configure())->options($application->getDefinition()); 30 | 31 | $application->add(container()->make(TestDebug::class)); 32 | 33 | $application->run(); 34 | -------------------------------------------------------------------------------- /src/External/Mysql.php: -------------------------------------------------------------------------------- 1 | addOption( 29 | new InputOption( 30 | '--root-dir', 31 | null, 32 | InputOption::VALUE_OPTIONAL, 33 | 'Where to find the Magento installation?' 34 | ) 35 | ); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Exceptions/InvalidConfigurationException.php: -------------------------------------------------------------------------------- 1 | getOption('root-dir')) { 33 | $this->directory = $input->getOption('root-dir'); 34 | return; 35 | } 36 | 37 | $this->directory = getcwd(); 38 | } 39 | 40 | public function get() 41 | { 42 | return $this->directory; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /tests/Fakes/CurrentWorkingDirectoryFake.php: -------------------------------------------------------------------------------- 1 | stream) { 34 | $this->stream = vfsStream::setup('magentoDirectory'); 35 | } 36 | 37 | return $this->stream; 38 | } 39 | 40 | public function get() 41 | { 42 | return $this->stream()->url(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Stubs/ModuleFixer.stub: -------------------------------------------------------------------------------- 1 | getConstructor()->getParameters(); 7 | 8 | $xml = simplexml_load_file('{$diPath}'); 9 | 10 | $child = $xml->addChild('type'); 11 | $child->addAttribute('name', '{$class}'); 12 | 13 | $argumentsNode = $child->addChild('arguments'); 14 | 15 | function getParameterClassName(ReflectionParameter $param) { 16 | preg_match('/(.*) \$/s', $param->__toString(), $matches); 17 | 18 | return isset($matches[1]) ? trim($matches[1]) : null; 19 | } 20 | 21 | /** @var \ReflectionParameter $param */ 22 | foreach($arguments as $param) { 23 | $className = getParameterClassName($param); 24 | if (!$className) { 25 | continue; 26 | } 27 | 28 | $argumentNode = $argumentsNode->addChild('argument', $className . '\Proxy'); 29 | $argumentNode->addAttribute('name', $param->name); 30 | $argumentNode->addAttribute('xsi:type', 'object', 'http://www.w3.org/2001/XMLSchema-instance'); 31 | } 32 | 33 | $arguments = ['directory' => 'path/to/directory', 'folder' => 'path/to/folder/class']; 34 | 35 | $dom = new \DOMDocument('1.0'); 36 | $dom->preserveWhiteSpace = false; 37 | $dom->formatOutput = true; 38 | $dom->loadXML($xml->asXML()); 39 | 40 | $dom->save('{$diPath}'); 41 | -------------------------------------------------------------------------------- /tests/FileSystem/TemporaryFileTest.php: -------------------------------------------------------------------------------- 1 | make(TemporaryFile::class); 30 | 31 | $path = $instance->generate(); 32 | 33 | $this->assertTrue(file_exists($path)); 34 | } 35 | 36 | public function testDeletesFilesOnDestruction() 37 | { 38 | /** @var TemporaryFile $instance */ 39 | $instance = container()->make(TemporaryFile::class); 40 | 41 | $path = $instance->generate(); 42 | 43 | $instance = null; 44 | 45 | $this->assertFalse(file_exists($path)); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Revive 2 | 3 | Got a Magento 2 store where the integration test always fails with some database errors? You can do an attempt to fix them manually by [following this blogpost](https://www.michiel-gerritsen.com/debugging-the-magento-2-integration-test-setup/), or use this tool. This tried to find the root cause of why your tests are failing and apply a fix for them. 4 | 5 | ![Revive in action](../images/revive-demo.gif?raw=true) 6 | 7 | (In this example the error was valid) 8 | 9 | ## What's in the name? 10 | 11 | We've been all in that place: A shiny new project. You can do everything right this time! But as times goes by and deadlines needs to get meet, testing may not be very high on you priority list. When you finally want to start writing tests it turns out that your test setup is broken. 12 | 13 | That's why it's called Revive: It helps you to revive this feeling at the start of the project: You ARE going to do this better this. Heck, you've already got this far that you are trying to run integration tests. 14 | 15 | ## Usage 16 | 17 | You have 2 options to use Revive: 18 | 19 | - Download `revive.phar` from the [release tab](https://github.com/michielgerritsen/revive/releases). 20 | - Clone this repository and run `composer install`. You can then use revive by using `php src/revive.php --root-dir=/path/to/your/magento/installation`. 21 | 22 | ## Testing 23 | 24 | You can run the tests using PHPUnit: 25 | 26 | `vendor/bin/phpunit` 27 | -------------------------------------------------------------------------------- /CreatePhar.php: -------------------------------------------------------------------------------- 1 | buildFromDirectory('./build'); 40 | 41 | // pointing main file which requires all classes 42 | $phar->setDefaultStub('src/Revive.php', 'src/Revive.php'); 43 | 44 | // plus - compressing it into gzip 45 | $phar->compress(Phar::GZ); 46 | $phar->compressFiles(Phar::GZ); 47 | 48 | echo $pharFile . ' successfully created' . PHP_EOL; 49 | 50 | if (file_exists($pharFile . '.gz')) { 51 | unlink($pharFile . '.gz'); 52 | } 53 | 54 | exec('rm -rf build'); 55 | -------------------------------------------------------------------------------- /tests/Service/FileSystem/CurrentWorkingDirectoryTest.php: -------------------------------------------------------------------------------- 1 | flush(); 32 | 33 | /** @var CurrentWorkingDirectory $instance */ 34 | $instance = container()->make(CurrentWorkingDirectory::class); 35 | 36 | $input = new StringInput('--root-dir=/test/directory/path'); 37 | $definition = new InputDefinition; 38 | container()->make(Configure::class)->options($definition); 39 | $input->bind($definition); 40 | 41 | $instance->setFromInput($input); 42 | 43 | $this->assertEquals('/test/directory/path', $instance->get()); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/functions.php: -------------------------------------------------------------------------------- 1 | bind(ValidateSetup::class, function () { 35 | return new ValidateSetup( 36 | container()->make(CurrentWorkingDirectory::class), 37 | [ 38 | container()->make(\MichielGerritsen\Revive\Validate\Validators\IsMagentoInstallation::class), 39 | container()->make(\MichielGerritsen\Revive\Validate\Validators\TheConfigFileExists::class), 40 | container()->make(\MichielGerritsen\Revive\Validate\Validators\PhpUnitFileExists::class), 41 | container()->make(\MichielGerritsen\Revive\Validate\Validators\MysqlCredentialsAreValid::class), 42 | container()->make(\MichielGerritsen\Revive\Validate\Validators\AmpqCredentialsAreValid::class), 43 | ] 44 | ); 45 | }); 46 | -------------------------------------------------------------------------------- /src/Validate/Validators/TheConfigFileExists.php: -------------------------------------------------------------------------------- 1 | directory = $directory; 34 | } 35 | 36 | public function shouldContinue(): bool 37 | { 38 | return false; 39 | } 40 | 41 | public function validate(): bool 42 | { 43 | return file_exists($this->directory->get() . '/dev/tests/integration/etc/install-config-mysql.php'); 44 | } 45 | 46 | public function getErrors(): array 47 | { 48 | return [ 49 | 'The `dev/tests/integration/etc/install-config-mysql.php` file is missing. See this page on how to prepare to run the ' . 50 | 'integration tests: https://devdocs.magento.com/guides/v2.3/test/integration/integration_test_execution.html' 51 | ]; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/FileSystem/Folder.php: -------------------------------------------------------------------------------- 1 | directory = $directory; 32 | } 33 | 34 | /** 35 | * @param string $directory 36 | */ 37 | public function emptyFolder($directory) 38 | { 39 | foreach (glob($directory . '/*') as $directory) { 40 | $this->deleteFolder($directory); 41 | } 42 | } 43 | 44 | /** 45 | * @param string $directory 46 | */ 47 | public function deleteFolder($directory) 48 | { 49 | $it = new \RecursiveDirectoryIterator($directory, \RecursiveDirectoryIterator::SKIP_DOTS); 50 | $files = new \RecursiveIteratorIterator($it, \RecursiveIteratorIterator::CHILD_FIRST); 51 | foreach ($files as $file) { 52 | if ($file->isDir()) { 53 | rmdir($file->getRealPath()); 54 | } else { 55 | unlink($file->getRealPath()); 56 | } 57 | } 58 | 59 | rmdir($directory); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/Validate/Validators/IsMagentoInstallation.php: -------------------------------------------------------------------------------- 1 | directory = $directory; 41 | } 42 | 43 | public function validate(): bool 44 | { 45 | foreach (static::REQUIRED_FILES as $file) { 46 | if (!file_exists($this->directory->get() . '/' . $file)) { 47 | return false; 48 | } 49 | } 50 | 51 | return true; 52 | } 53 | 54 | public function shouldContinue(): bool 55 | { 56 | return false; 57 | } 58 | 59 | public function getErrors(): array 60 | { 61 | return [ 62 | 'The current directory (' . $this->directory->get() . ') is not a Magento directory', 63 | ]; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/Validate/Validators/PhpUnitFileExists.php: -------------------------------------------------------------------------------- 1 | directory = $directory; 34 | } 35 | 36 | public function shouldContinue(): bool 37 | { 38 | return true; 39 | } 40 | 41 | public function validate(): bool 42 | { 43 | $paths = [ 44 | 'dev/tests/integration/phpunit.xml', 45 | 'dev/tests/quick-integration/phpunit.xml', 46 | ]; 47 | 48 | foreach ($paths as $path) { 49 | if (file_exists($this->directory->get() . '/' . $path)) { 50 | return true; 51 | } 52 | } 53 | 54 | return false; 55 | } 56 | 57 | public function getErrors(): array 58 | { 59 | return [ 60 | 'The `dev/tests/integration/phpunit.xml` file is missing. See this page on how to prepare to run the ' . 61 | 'integration tests: https://devdocs.magento.com/guides/v2.3/test/integration/integration_test_execution.html' 62 | ]; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/Validate/Validators/MysqlCredentialsAreValid.php: -------------------------------------------------------------------------------- 1 | config = $config; 41 | $this->mysql = $mysql; 42 | } 43 | 44 | public function validate(): bool 45 | { 46 | $config = $this->config->read(); 47 | 48 | if (empty($config['db-host']) || empty($config['db-name'])) { 49 | return false; 50 | } 51 | 52 | return $this->mysql->testConnection( 53 | $config['db-host'], 54 | $config['db-port'], 55 | $config['db-name'], 56 | $config['db-user'], 57 | $config['db-password'] 58 | ); 59 | } 60 | 61 | public function shouldContinue(): bool 62 | { 63 | return true; 64 | } 65 | 66 | public function getErrors(): array 67 | { 68 | return [ 69 | 'Please check your mysql settings in `dev/tests/integration/etc/install-config-mysql.php` ' . 70 | 'as these are invalid', 71 | ]; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/Validate/ValidateSetup.php: -------------------------------------------------------------------------------- 1 | directory = $directory; 48 | $this->validators = $validators; 49 | } 50 | 51 | public function validate() 52 | { 53 | $result = true; 54 | 55 | foreach ($this->validators as $validator) { 56 | if (!$validator->validate()) { 57 | $this->addErrors($validator->getErrors()); 58 | $result = false; 59 | 60 | if (!$validator->shouldContinue()) { 61 | break; 62 | } 63 | } 64 | } 65 | 66 | return $result; 67 | } 68 | 69 | public function getErrors() 70 | { 71 | return $this->errors; 72 | } 73 | 74 | private function addErrors(array $errors) 75 | { 76 | $this->errors = array_merge($this->errors, $errors); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /tests/Validate/Validators/TheConfigFileExistsTest.php: -------------------------------------------------------------------------------- 1 | singleton(CurrentWorkingDirectory::class, CurrentWorkingDirectoryFake::class); 31 | 32 | $directory = container()->make(CurrentWorkingDirectory::class)->get(); 33 | 34 | mkdir($directory . '/dev/tests/integration/etc', 0777, true); 35 | touch($directory . '/dev/tests/integration/etc/install-config-mysql.php'); 36 | 37 | /** @var TheConfigFileExists $instance */ 38 | $instance = container()->make(TheConfigFileExists::class); 39 | 40 | $this->assertTrue($instance->validate()); 41 | } 42 | 43 | public function testGetErrors() 44 | { 45 | /** @var TheConfigFileExists $instance */ 46 | $instance = container()->make(TheConfigFileExists::class); 47 | 48 | $errors = $instance->getErrors(); 49 | 50 | $this->assertContains( 51 | 'The `dev/tests/integration/etc/install-config-mysql.php` file is missing.', 52 | $errors[0] 53 | ); 54 | } 55 | 56 | public function testShouldContinue() 57 | { 58 | $this->assertFalse(container()->make(TheConfigFileExists::class)->shouldContinue()); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/Magento/FixModule.php: -------------------------------------------------------------------------------- 1 | directory = $directory; 35 | } 36 | 37 | public function proxyDependenciesFor($class) 38 | { 39 | $replacements = [ 40 | '{$autoloadPath}' => $this->directory->get() . '/vendor/autoload.php', 41 | '{$diPath}' => $this->directory->get() . '/app/code/MichielGerritsen/ReviveFixes/etc/di.xml', 42 | '{$class}' => $class, 43 | ]; 44 | 45 | $moduleFixerContent = str_replace( 46 | array_keys($replacements), 47 | array_values($replacements), 48 | file_get_contents(__DIR__ . '/../Stubs/ModuleFixer.stub') 49 | ); 50 | 51 | $path = tempnam(sys_get_temp_dir(), 'revive'); 52 | 53 | file_put_contents($path, $moduleFixerContent); 54 | file_put_contents($this->directory->get() . '/debugger.php', $moduleFixerContent); 55 | 56 | $process = new Process([PHP_BINARY, $path]); 57 | 58 | $process->run(function ($type, $buffer) { 59 | if (Process::ERR === $type) { 60 | echo 'ERR > ' . $buffer; 61 | } else { 62 | echo 'OUT > ' . $buffer; 63 | } 64 | }); 65 | 66 | unlink($path); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/Validate/Validators/AmpqCredentialsAreValid.php: -------------------------------------------------------------------------------- 1 | config = $config; 41 | $this->amqp = $amqp; 42 | } 43 | 44 | public function validate(): bool 45 | { 46 | $config = $this->config->read(); 47 | 48 | if (empty($config['amqp-host']) || 49 | empty($config['amqp-port']) || 50 | empty($config['amqp-user']) || 51 | empty($config['amqp-password']) 52 | ) { 53 | return true; 54 | } 55 | 56 | return $this->amqp->testConnection( 57 | $config['amqp-host'], 58 | $config['amqp-port'], 59 | $config['amqp-user'], 60 | $config['amqp-password'] 61 | ); 62 | } 63 | 64 | public function shouldContinue(): bool 65 | { 66 | return true; 67 | } 68 | 69 | public function getErrors(): array 70 | { 71 | return [ 72 | 'You have AMPQ variables in your `dev/tests/integration/etc/install-config-mysql.php` file, but these ' . 73 | 'are invalid. If you don\'t plan on using AMPQ just remove them.' 74 | ]; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/Magento/ModuleManager.php: -------------------------------------------------------------------------------- 1 | directory = $directory; 34 | } 35 | 36 | public function getPath() 37 | { 38 | return $this->directory->get() . '/app/code/MichielGerritsen/ReviveFixes/'; 39 | } 40 | 41 | public function createIntegrationTestModule() 42 | { 43 | // TODO: Check if the module exists. 44 | 45 | $modulePath = $this->getPath(); 46 | 47 | if (file_exists($modulePath)) { 48 | return; 49 | } 50 | 51 | mkdir($modulePath . 'etc/', 0777, true); 52 | mkdir($modulePath . 'Test/', 0777, true); 53 | 54 | $stubPath = __DIR__ . '/../Stubs/MagentoModule/'; 55 | $diXml = file_get_contents($stubPath . 'etc/di.stub'); 56 | $moduleXml = file_get_contents($stubPath . 'etc/module.stub'); 57 | $registrationPhp = file_get_contents($stubPath . 'registration.stub'); 58 | $testPhp = file_get_contents($stubPath . '/Test/AlwaysSucceedingTest.stub'); 59 | 60 | file_put_contents($modulePath . 'etc/di.xml', $diXml); 61 | file_put_contents($modulePath . 'etc/module.xml', $moduleXml); 62 | file_put_contents($modulePath . 'registration.php', $registrationPhp); 63 | file_put_contents($modulePath . 'Test/AlwaysSucceedingTest.php', $testPhp); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /tests/Validate/Validators/IsMagentoInstallationTest.php: -------------------------------------------------------------------------------- 1 | assertFalse(container()->make(IsMagentoInstallation::class)->shouldContinue()); 31 | } 32 | 33 | public function testGetErrors() 34 | { 35 | $this->assertCount(1, container()->make(IsMagentoInstallation::class)->getErrors()); 36 | } 37 | 38 | /** 39 | * @testWith [0] 40 | * [1] 41 | * [2] 42 | * [3] 43 | */ 44 | public function testTheConfigFileShouldExists($unexisting) 45 | { 46 | container()->singleton(CurrentWorkingDirectory::class, CurrentWorkingDirectoryFake::class); 47 | 48 | $directory = container()->make(CurrentWorkingDirectory::class); 49 | 50 | $files = IsMagentoInstallation::REQUIRED_FILES; 51 | unset($files[$unexisting]); 52 | 53 | foreach ($files as $file) { 54 | $path = $directory->get() . '/' . $file; 55 | mkdir(dirname($path), 0755, true); 56 | touch($path); 57 | } 58 | 59 | $this->assertFalse(container()->make(IsMagentoInstallation::class)->validate()); 60 | } 61 | 62 | public function testValidatesIfAllFilesExists() 63 | { 64 | container()->singleton(CurrentWorkingDirectory::class, CurrentWorkingDirectoryFake::class); 65 | 66 | $directory = container()->make(CurrentWorkingDirectory::class); 67 | 68 | foreach (IsMagentoInstallation::REQUIRED_FILES as $file) { 69 | $path = $directory->get() . '/' . $file; 70 | mkdir(dirname($path), 0755, true); 71 | touch($path); 72 | } 73 | 74 | $this->assertTrue(container()->make(IsMagentoInstallation::class)->validate()); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /tests/Validate/Validators/PhpUnitFileExistsTest.php: -------------------------------------------------------------------------------- 1 | singleton(CurrentWorkingDirectory::class, CurrentWorkingDirectoryFake::class); 31 | $directory = container()->make(CurrentWorkingDirectory::class)->get(); 32 | 33 | mkdir($directory . '/dev/tests/integration', 0777, true); 34 | touch($directory . '/dev/tests/integration/phpunit.xml'); 35 | 36 | /** @var PhpUnitFileExists $instance */ 37 | $instance = container()->make(PhpUnitFileExists::class); 38 | 39 | $this->assertTrue($instance->validate()); 40 | } 41 | 42 | public function testSupportsTheQuickIntegration() 43 | { 44 | container()->singleton(CurrentWorkingDirectory::class, CurrentWorkingDirectoryFake::class); 45 | $directory = container()->make(CurrentWorkingDirectory::class)->get(); 46 | 47 | mkdir($directory . '/dev/tests/quick-integration', 0777, true); 48 | touch($directory . '/dev/tests/quick-integration/phpunit.xml'); 49 | 50 | /** @var PhpUnitFileExists $instance */ 51 | $instance = container()->make(PhpUnitFileExists::class); 52 | 53 | $this->assertTrue($instance->validate()); 54 | } 55 | 56 | public function testGetErrors() 57 | { 58 | /** @var PhpUnitFileExists $instance */ 59 | $instance = container()->make(PhpUnitFileExists::class); 60 | 61 | $errors = $instance->getErrors(); 62 | 63 | $this->assertContains( 64 | 'The `dev/tests/integration/phpunit.xml` file is missing.', 65 | $errors[0] 66 | ); 67 | } 68 | 69 | public function testShouldContinue() 70 | { 71 | $this->assertTrue(container()->make(PhpUnitFileExists::class)->shouldContinue()); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/FileSystem/ReadMysqlConfig.php: -------------------------------------------------------------------------------- 1 | directory = $directory; 61 | $this->temporaryFile = $temporaryFile; 62 | } 63 | 64 | /** 65 | * @param string $contents 66 | * @return array 67 | * @throws \Exception 68 | */ 69 | public function read() 70 | { 71 | if ($this->contents) { 72 | return $this->contents; 73 | } 74 | 75 | $path = $this->temporaryFile->generate(); 76 | 77 | file_put_contents( 78 | $path, 79 | file_get_contents(__DIR__ . '/../Stubs/ReadConfig.stub') 80 | ); 81 | 82 | $process = new Process( 83 | [PHP_BINARY, $path], 84 | $this->directory->get() 85 | ); 86 | 87 | $process->run(); 88 | 89 | $output = $process->getOutput(); 90 | $contents = $this->fillBlanks(json_decode($output, JSON_OBJECT_AS_ARRAY)); 91 | 92 | if ($process->getExitCode()) { 93 | throw new \Exception('Unable to get mysql credentials: ' . PHP_EOL . $process->getOutput()); 94 | } 95 | 96 | $this->contents = $contents; 97 | return $contents; 98 | } 99 | 100 | private function fillBlanks($contents) 101 | { 102 | foreach (static::REQUIRED_KEYS as $key) { 103 | if (!array_key_exists($key, $contents)) { 104 | $contents[$key] = ''; 105 | } 106 | } 107 | 108 | return $contents; 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /tests/Validate/Validators/RabbitMqCredentialsAreValidTest.php: -------------------------------------------------------------------------------- 1 | createMock(ReadMysqlConfig::class); 33 | $readMysqlConfigMock->method('read')->willReturn([]); 34 | 35 | /** @var AmpqCredentialsAreValid $instance */ 36 | $instance = container()->make(AmpqCredentialsAreValid::class, [ 37 | 'config' => $readMysqlConfigMock, 38 | ]); 39 | 40 | $this->assertTrue($instance->validate()); 41 | } 42 | 43 | /** 44 | * @param $connectionSuccess 45 | * @param $expected 46 | * @throws \Illuminate\Contracts\Container\BindingResolutionException 47 | * 48 | * @testWith [true, true] 49 | * [false, false] 50 | */ 51 | public function testReturnsTheCorrectStatusDependingOnTheConnectionResult($connectionSuccess, $expected) 52 | { 53 | $readMysqlConfigMock = $this->createMock(ReadMysqlConfig::class); 54 | $readMysqlConfigMock->method('read')->willReturn([ 55 | 'amqp-host' => 'localhost', 56 | 'amqp-port' => '15672', 57 | 'amqp-user' => 'guest', 58 | 'amqp-password' => 'guest', 59 | ]); 60 | 61 | $amqpMock = $this->createMock(Amqp::class); 62 | $amqpMock->expects($this->once())->method('testConnection')->willReturn($connectionSuccess); 63 | 64 | /** @var AmpqCredentialsAreValid $instance */ 65 | $instance = container()->make(AmpqCredentialsAreValid::class, [ 66 | 'config' => $readMysqlConfigMock, 67 | 'amqp' => $amqpMock, 68 | ]); 69 | 70 | $this->assertSame($expected, $instance->validate()); 71 | } 72 | 73 | public function testGetErrors() 74 | { 75 | $this->assertCount(1, container()->make(AmpqCredentialsAreValid::class)->getErrors()); 76 | } 77 | 78 | public function testShouldContinue() 79 | { 80 | $this->assertTrue(container()->make(AmpqCredentialsAreValid::class)->shouldContinue()); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /tests/Validate/Validators/MysqlCredentialsAreValidTest.php: -------------------------------------------------------------------------------- 1 | assertTrue(container()->make(MysqlCredentialsAreValid::class)->shouldContinue()); 33 | } 34 | 35 | public function testGetErrors() 36 | { 37 | $this->assertNotEmpty(container()->make(MysqlCredentialsAreValid::class)->getErrors()[0]); 38 | } 39 | 40 | public function testFailsIfThereIsNoConnectionData() 41 | { 42 | $readMysqlConfigMock = $this->createMock(ReadMysqlConfig::class); 43 | $readMysqlConfigMock->method('read')->willReturn([ 44 | 'db-host' => '', 45 | 'db-port' => '', 46 | 'db-name' => '', 47 | 'db-user' => '', 48 | 'db-password' => '', 49 | ]); 50 | 51 | /** @var MysqlCredentialsAreValid $instance */ 52 | $instance = container()->make(MysqlCredentialsAreValid::class, [ 53 | 'config' => $readMysqlConfigMock, 54 | ]); 55 | 56 | $this->assertFalse($instance->validate()); 57 | } 58 | 59 | /** 60 | * @param $connectionResult 61 | * @param $expected 62 | * @throws \Illuminate\Contracts\Container\BindingResolutionException 63 | * 64 | * @testWith [false, false] 65 | * [true, true] 66 | */ 67 | public function testValidatesDependingOnTheStatus($connectionResult, $expected) 68 | { 69 | $mysqlMock = $this->createMock(Mysql::class); 70 | $mysqlMock->expects($this->once())->method('testConnection')->willReturn($connectionResult); 71 | 72 | $readMysqlConfigMock = $this->createMock(ReadMysqlConfig::class); 73 | $readMysqlConfigMock->method('read')->willReturn([ 74 | 'db-host' => 'localhost', 75 | 'db-port' => '', 76 | 'db-name' => 'database', 77 | 'db-user' => '', 78 | 'db-password' => '', 79 | ]); 80 | 81 | /** @var MysqlCredentialsAreValid $instance */ 82 | $instance = container()->make(MysqlCredentialsAreValid::class, [ 83 | 'mysql' => $mysqlMock, 84 | 'config' => $readMysqlConfigMock, 85 | ]); 86 | 87 | $this->assertSame($expected, $instance->validate()); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/Magento/ErrorOutput.php: -------------------------------------------------------------------------------- 1 | directory = $directory; 44 | } 45 | 46 | public function patch() 47 | { 48 | foreach ($this->paths as $path) { 49 | $this->patchFile($this->directory->get() . '/' . $path); 50 | } 51 | } 52 | 53 | private function patchFile($path) 54 | { 55 | if (!file_exists($path)) { 56 | return; 57 | } 58 | 59 | $contents = $this->originalContents = file_get_contents($path); 60 | 61 | if (strpos($contents, 'json_encode([\'instance\' => $item[\'instance\']])') !== false) { 62 | return; 63 | } 64 | 65 | $result = str_replace( 66 | '$array[$key] = $this->objectManager->get($item[\'instance\']);', 67 | 'try { 68 | $array[$key] = $this->objectManager->get($item[\'instance\']); 69 | } catch (\Exception $exception) { 70 | file_put_contents( 71 | getenv(\'DEBUG_TMPFILE\'), 72 | json_encode([\'instance\' => $item[\'instance\']]) 73 | ); 74 | 75 | throw new \Exception(\'Failing command: \' . $key . \' instance: \' . $item[\'instance\'] . \' JSON: \' . json_encode([\'instance\' => $item[\'instance\']])); 76 | }', 77 | $contents 78 | ); 79 | 80 | file_put_contents($path, $result); 81 | } 82 | 83 | public function undo() 84 | { 85 | if (!$this->originalContents) { 86 | return; 87 | } 88 | 89 | foreach ($this->paths as $path) { 90 | $fullPath = $this->directory->get() . '/' . $path; 91 | 92 | if (file_exists($fullPath)) { 93 | file_put_contents($fullPath, $this->originalContents); 94 | } 95 | } 96 | } 97 | 98 | public function __destruct() 99 | { 100 | $this->undo(); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/Magento/IntegrationTests.php: -------------------------------------------------------------------------------- 1 | directory = $directory; 65 | $this->temporaryFile = $temporaryFile; 66 | $this->folder = $folder; 67 | $this->moduleManager = $moduleManager; 68 | } 69 | 70 | private function createProcess() 71 | { 72 | $this->path = $this->temporaryFile->generate(); 73 | 74 | $this->folder->emptyFolder($this->directory->get() . '/dev/tests/integration/tmp/'); 75 | 76 | $this->process = new Process( 77 | [ 78 | '../../../vendor/bin/phpunit', 79 | $this->moduleManager->getPath() . '/Test/', 80 | ], 81 | $this->directory->get() . '/dev/tests/integration/', 82 | ['DEBUG_TMPFILE' => $this->path], 83 | null, 84 | null 85 | ); 86 | 87 | return $this->process; 88 | } 89 | 90 | public function run() 91 | { 92 | return $this->createProcess()->run(); 93 | } 94 | 95 | public function runVerbose(OutputInterface $output) 96 | { 97 | $this->createProcess()->run(function ($type, $buffer) use ($output) { 98 | if (Process::ERR === $type) { 99 | $output->writeln('' . $buffer . ''); 100 | } else { 101 | $output->writeln($buffer); 102 | } 103 | }); 104 | } 105 | 106 | public function wasRunSuccessful() 107 | { 108 | return !$this->process->getExitCode(); 109 | } 110 | 111 | public function getFailingInstance() 112 | { 113 | $json = json_decode(file_get_contents($this->path), JSON_OBJECT_AS_ARRAY); 114 | 115 | return $json['instance']; 116 | } 117 | 118 | public function getLogs() 119 | { 120 | return $this->process->getOutput(); 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /src/Magento/TestRunner.php: -------------------------------------------------------------------------------- 1 | integrationTests = $integrationTests; 42 | $this->fixModule = $fixModule; 43 | } 44 | 45 | public function execute(OutputInterface $output) 46 | { 47 | $run = 1; 48 | $failingInstance = null; 49 | $patchedInstances = []; 50 | while (true) { 51 | $start = microtime(true); 52 | $output->writeln(''); 53 | $output->writeln('Starting run #' . $run); 54 | 55 | if (!$output->isVeryVerbose()) { 56 | $this->integrationTests->run(); 57 | } else { 58 | $this->integrationTests->runVerbose($output); 59 | } 60 | 61 | if ($this->integrationTests->wasRunSuccessful()) { 62 | break; 63 | } 64 | 65 | $currentFailingInstance = $this->integrationTests->getFailingInstance(); 66 | 67 | if ($currentFailingInstance && $currentFailingInstance == $failingInstance) { 68 | $output->writeln($this->integrationTests->getLogs()); 69 | 70 | throw InstanceFailingException::withInstance($failingInstance); 71 | } 72 | 73 | $patchedInstances[] = $currentFailingInstance; 74 | if (!$currentFailingInstance) { 75 | $output->writeln($this->integrationTests->getLogs()); 76 | 77 | throw new FailingForUnknownReason( 78 | 'It looks like there are no instances that are failing (anymore), but the test command still ' . 79 | 'fails for unknown reasons. Usually this is caused by setup scripts that are failing' 80 | ); 81 | } 82 | 83 | $this->fixModule->proxyDependenciesFor($currentFailingInstance); 84 | $output->writeln('The class ' . $currentFailingInstance . ' is patched.'); 85 | 86 | $end = microtime(true); 87 | $execution_time = round(($end - $start) / 60, 2); 88 | 89 | $output->writeln('Completed run ' . $run . ' in ' . $execution_time . ' minutes'); 90 | $run++; 91 | 92 | if ($run == 50) { 93 | $output->writeln($this->integrationTests->getLogs()); 94 | 95 | $output->writeln( 96 | 'We tried to run the tests 50 times but without success. Please check the logs ' . 97 | 'to see what is going on. If they look good just try again.' 98 | ); 99 | break; 100 | } 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /tests/Validate/ValidateSetupTest.php: -------------------------------------------------------------------------------- 1 | createMock(ValidatorContract::class); 30 | $validator1->method('validate')->willReturn(true); 31 | 32 | $validator2 = $this->createMock(ValidatorContract::class); 33 | $validator2->method('validate')->willReturn(false); 34 | 35 | $validator3 = $this->createMock(ValidatorContract::class); 36 | $validator3->method('validate')->willReturn(true); 37 | 38 | container()->flush(); 39 | $instance = container()->make(ValidateSetup::class, [ 40 | 'validators' => [ 41 | $validator1, 42 | $validator2, 43 | $validator3, 44 | ] 45 | ]); 46 | 47 | $this->assertFalse($instance->validate()); 48 | } 49 | 50 | public function testSucceedsIfAllValidatorAreValid() 51 | { 52 | $validator = $this->createMock(ValidatorContract::class); 53 | $validator->method('validate')->willReturn(true); 54 | 55 | container()->flush(); 56 | $instance = container()->make(ValidateSetup::class, [ 57 | 'validators' => [$validator] 58 | ]); 59 | 60 | $this->assertTrue($instance->validate()); 61 | } 62 | 63 | public function testCollectsErrors() 64 | { 65 | $validator1 = $this->createMock(ValidatorContract::class); 66 | $validator1->method('validate')->willReturn(false); 67 | $validator1->method('getErrors')->willReturn(['error 1']); 68 | $validator1->method('shouldContinue')->willReturn(true); 69 | 70 | $validator2 = $this->createMock(ValidatorContract::class); 71 | $validator2->method('validate')->willReturn(false); 72 | $validator2->method('getErrors')->willReturn(['error 2']); 73 | $validator2->method('shouldContinue')->willReturn(true); 74 | 75 | container()->flush(); 76 | $instance = container()->make(ValidateSetup::class, [ 77 | 'validators' => [$validator1, $validator2] 78 | ]); 79 | 80 | $instance->validate(); 81 | 82 | $this->assertCount(2, $instance->getErrors()); 83 | $this->assertTrue(in_array('error 1', $instance->getErrors())); 84 | $this->assertTrue(in_array('error 2', $instance->getErrors())); 85 | } 86 | 87 | public function testSkipTheRestOfTheValidatorsIfNeeded() 88 | { 89 | $validator1 = $this->createMock(ValidatorContract::class); 90 | $validator1->expects($this->once())->method('validate')->willReturn(false); 91 | $validator1->method('shouldContinue')->willReturn(false); 92 | 93 | $validator2 = $this->createMock(ValidatorContract::class); 94 | $validator2->expects($this->never())->method('validate'); 95 | 96 | container()->flush(); 97 | $instance = container()->make(ValidateSetup::class, [ 98 | 'validators' => [$validator1, $validator2] 99 | ]); 100 | 101 | $instance->validate(); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/Commands/TestDebug.php: -------------------------------------------------------------------------------- 1 | directory = $directory; 71 | $this->moduleManager = $moduleManager; 72 | $this->errorOutput = $errorOutput; 73 | $this->validateSetup = $validateSetup; 74 | $this->testRunner = $testRunner; 75 | } 76 | 77 | protected function execute(InputInterface $input, OutputInterface $output) 78 | { 79 | $this->directory->setFromInput($input); 80 | 81 | $io = new SymfonyStyle($input, $output); 82 | 83 | // Validate installation. 84 | if (!$this->validateSetup->validate()) { 85 | $width = (new Terminal())->getWidth(); 86 | 87 | $message = 'There are some errors found, please fix these before continuing:'; 88 | 89 | $output->writeln(''); 90 | $output->writeln('' . str_repeat(' ', $width) . ''); 91 | $output->writeln(' ' . $message . str_repeat(' ', $width - strlen($message) - 2) . ''); 92 | $output->writeln('' . str_repeat(' ', $width) . ''); 93 | $io->listing($this->validateSetup->getErrors($output)); 94 | return 255; 95 | } 96 | 97 | // Place our code to read the exceptions. 98 | $output->writeln('Patching your Magento installation'); 99 | $this->errorOutput->patch(); 100 | 101 | // Create the module 102 | $this->moduleManager->createIntegrationTestModule(); 103 | 104 | // Run the installation. 105 | $output->writeln('You installation is verified. We are now starting the first run. This can take quite a while.'); 106 | 107 | try { 108 | $this->testRunner->execute($output); 109 | } finally { 110 | // Undo our manual fixes. 111 | $this->errorOutput->undo(); 112 | } 113 | 114 | $io->success( 115 | 'It looks like we succefully did a test run. We placed some fixes in the ' . 116 | '`app/code/MichielGerritsen/ReviveFixes` folder. Please review them and adjust where needed.' 117 | ); 118 | $io->success('Now go and build something awesome!'); 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /tests/Magento/ErrorOutputTest.php: -------------------------------------------------------------------------------- 1 | make(CurrentWorkingDirectory::class); 35 | 36 | $filePath = $directory->get() . '/vendor/magento/framework/ObjectManager/Factory/AbstractFactory.php'; 37 | $stub = file_get_contents(__DIR__ . '/../Stubs/Magento/Framework/ObjectManager/Factory/AbstractFactory.stub'); 38 | 39 | mkdir($directory->get() . '/vendor/magento/framework/ObjectManager/Factory/', 0777, true); 40 | file_put_contents($filePath, $stub); 41 | 42 | return $filePath; 43 | } 44 | 45 | public function testThatOurCodeIsPlaced() 46 | { 47 | container()->singleton(CurrentWorkingDirectory::class, CurrentWorkingDirectoryFake::class); 48 | 49 | $filePath = $this->prepareStubs(); 50 | 51 | /** @var ErrorOutput $instance */ 52 | $instance = container()->make(ErrorOutput::class); 53 | $instance->patch(); 54 | 55 | $this->assertContains( 56 | 'throw new \Exception(\'Failing command: \' . $key . \' instance: \' . $item[\'instance\'] . \' JSON: \' . json_encode([\'instance\' => $item[\'instance\']]));', 57 | file_get_contents($filePath) 58 | ); 59 | } 60 | 61 | public function testThePatchIsUndone() 62 | { 63 | container()->singleton(CurrentWorkingDirectory::class, CurrentWorkingDirectoryFake::class); 64 | 65 | $filePath = $this->prepareStubs(); 66 | 67 | /** @var ErrorOutput $instance */ 68 | $instance = container()->make(ErrorOutput::class); 69 | $instance->patch(); 70 | 71 | $this->assertContains( 72 | 'throw new \Exception(\'Failing command: \' . $key . \' instance: \' . $item[\'instance\'] . \' JSON: \' . json_encode([\'instance\' => $item[\'instance\']]));', 73 | file_get_contents($filePath) 74 | ); 75 | 76 | $instance->undo(); 77 | 78 | $this->assertNotContains( 79 | 'throw new \Exception(\'Failing command: \' . $key . \' instance: \' . $item[\'instance\'] . \' JSON: \' . json_encode([\'instance\' => $item[\'instance\']]));', 80 | file_get_contents($filePath) 81 | ); 82 | } 83 | 84 | public function testRestoresFilesOnDestruction() 85 | { 86 | container()->singleton(CurrentWorkingDirectory::class, CurrentWorkingDirectoryFake::class); 87 | 88 | $filePath = $this->prepareStubs(); 89 | 90 | /** @var ErrorOutput $instance */ 91 | $instance = container()->make(ErrorOutput::class); 92 | $instance->patch(); 93 | 94 | $this->assertContains( 95 | 'throw new \Exception(\'Failing command: \' . $key . \' instance: \' . $item[\'instance\'] . \' JSON: \' . json_encode([\'instance\' => $item[\'instance\']]));', 96 | file_get_contents($filePath) 97 | ); 98 | 99 | $instance = null; 100 | 101 | $this->assertNotContains( 102 | 'throw new \Exception(\'Failing command: \' . $key . \' instance: \' . $item[\'instance\'] . \' JSON: \' . json_encode([\'instance\' => $item[\'instance\']]));', 103 | file_get_contents($filePath) 104 | ); 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /tests/Stubs/Magento/Framework/ObjectManager/Factory/AbstractFactory.stub: -------------------------------------------------------------------------------- 1 | config = $config; 60 | $this->objectManager = $objectManager; 61 | $this->definitions = $definitions ?: $this->getDefinitions(); 62 | $this->globalArguments = $globalArguments; 63 | } 64 | 65 | /** 66 | * Set object manager 67 | * 68 | * @param ObjectManagerInterface $objectManager 69 | * 70 | * @return void 71 | */ 72 | public function setObjectManager(ObjectManagerInterface $objectManager) 73 | { 74 | $this->objectManager = $objectManager; 75 | } 76 | 77 | /** 78 | * Set global arguments 79 | * 80 | * @param array $arguments 81 | * 82 | * @return void 83 | */ 84 | public function setArguments($arguments) 85 | { 86 | $this->globalArguments = $arguments; 87 | } 88 | 89 | /** 90 | * @return \Magento\Framework\ObjectManager\DefinitionInterface 91 | */ 92 | public function getDefinitions() 93 | { 94 | if ($this->definitions === null) { 95 | $this->definitions = new \Magento\Framework\ObjectManager\Definition\Runtime(); 96 | } 97 | return $this->definitions; 98 | } 99 | 100 | /** 101 | * Create object 102 | * 103 | * @param string $type 104 | * @param array $args 105 | * 106 | * @return object 107 | * 108 | */ 109 | protected function createObject($type, $args) 110 | { 111 | return new $type(...array_values($args)); 112 | } 113 | 114 | /** 115 | * Resolve an argument 116 | * 117 | * @param array &$argument 118 | * @param string $paramType 119 | * @param mixed $paramDefault 120 | * @param string $paramName 121 | * @param string $requestedType 122 | * 123 | * @return void 124 | * 125 | * @SuppressWarnings(PHPMD.CyclomaticComplexity) 126 | */ 127 | protected function resolveArgument(&$argument, $paramType, $paramDefault, $paramName, $requestedType) 128 | { 129 | if ($paramType && $argument !== $paramDefault && !is_object($argument)) { 130 | $argumentType = $argument['instance']; 131 | if (!isset($argument['instance']) || $argument !== (array)$argument) { 132 | throw new \UnexpectedValueException( 133 | 'Invalid parameter configuration provided for $' . $paramName . ' argument of ' . $requestedType 134 | ); 135 | } 136 | 137 | if (isset($argument['shared'])) { 138 | $isShared = $argument['shared']; 139 | } else { 140 | $isShared = $this->config->isShared($argumentType); 141 | } 142 | 143 | if ($isShared) { 144 | $argument = $this->objectManager->get($argumentType); 145 | } else { 146 | $argument = $this->objectManager->create($argumentType); 147 | } 148 | } elseif ($argument === (array)$argument) { 149 | if (isset($argument['argument'])) { 150 | if (isset($this->globalArguments[$argument['argument']])) { 151 | $argument = $this->globalArguments[$argument['argument']]; 152 | } else { 153 | $argument = $paramDefault; 154 | } 155 | } elseif (!empty($argument)) { 156 | $this->parseArray($argument); 157 | } 158 | } 159 | } 160 | 161 | /** 162 | * Parse array argument 163 | * 164 | * @param array $array 165 | * 166 | * @return void 167 | */ 168 | protected function parseArray(&$array) 169 | { 170 | foreach ($array as $key => $item) { 171 | if ($item === (array)$item) { 172 | if (isset($item['instance'])) { 173 | if (isset($item['shared'])) { 174 | $isShared = $item['shared']; 175 | } else { 176 | $isShared = $this->config->isShared($item['instance']); 177 | } 178 | 179 | if ($isShared) { 180 | $array[$key] = $this->objectManager->get($item['instance']); 181 | } else { 182 | $array[$key] = $this->objectManager->create($item['instance']); 183 | } 184 | } elseif (isset($item['argument'])) { 185 | if (isset($this->globalArguments[$item['argument']])) { 186 | $array[$key] = $this->globalArguments[$item['argument']]; 187 | } else { 188 | $array[$key] = null; 189 | } 190 | } else { 191 | $this->parseArray($array[$key]); 192 | } 193 | } 194 | } 195 | } 196 | 197 | /** 198 | * Resolve constructor arguments 199 | * 200 | * @param string $requestedType 201 | * @param array $parameters 202 | * @param array $arguments 203 | * 204 | * @return array 205 | * 206 | * @throws \UnexpectedValueException 207 | * @throws \BadMethodCallException 208 | */ 209 | protected function resolveArgumentsInRuntime($requestedType, array $parameters, array $arguments = []) 210 | { 211 | $resolvedArguments = []; 212 | foreach ($parameters as $parameter) { 213 | list($paramName, $paramType, $paramRequired, $paramDefault) = $parameter; 214 | $argument = null; 215 | if (!empty($arguments) && (isset($arguments[$paramName]) || array_key_exists($paramName, $arguments))) { 216 | $argument = $arguments[$paramName]; 217 | } elseif ($paramRequired) { 218 | if ($paramType) { 219 | $argument = ['instance' => $paramType]; 220 | } else { 221 | $this->creationStack = []; 222 | throw new \BadMethodCallException( 223 | 'Missing required argument $' . $paramName . ' of ' . $requestedType . '.' 224 | ); 225 | } 226 | } else { 227 | $argument = $paramDefault; 228 | } 229 | 230 | $this->resolveArgument($argument, $paramType, $paramDefault, $paramName, $requestedType); 231 | 232 | $resolvedArguments[] = $argument; 233 | } 234 | return $resolvedArguments; 235 | } 236 | } 237 | -------------------------------------------------------------------------------- /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": "f9240ff4fac9a6798cac361425f2f938", 8 | "packages": [ 9 | { 10 | "name": "doctrine/inflector", 11 | "version": "v1.3.0", 12 | "source": { 13 | "type": "git", 14 | "url": "https://github.com/doctrine/inflector.git", 15 | "reference": "5527a48b7313d15261292c149e55e26eae771b0a" 16 | }, 17 | "dist": { 18 | "type": "zip", 19 | "url": "https://api.github.com/repos/doctrine/inflector/zipball/5527a48b7313d15261292c149e55e26eae771b0a", 20 | "reference": "5527a48b7313d15261292c149e55e26eae771b0a", 21 | "shasum": "" 22 | }, 23 | "require": { 24 | "php": "^7.1" 25 | }, 26 | "require-dev": { 27 | "phpunit/phpunit": "^6.2" 28 | }, 29 | "type": "library", 30 | "extra": { 31 | "branch-alias": { 32 | "dev-master": "1.3.x-dev" 33 | } 34 | }, 35 | "autoload": { 36 | "psr-4": { 37 | "Doctrine\\Common\\Inflector\\": "lib/Doctrine/Common/Inflector" 38 | } 39 | }, 40 | "notification-url": "https://packagist.org/downloads/", 41 | "license": [ 42 | "MIT" 43 | ], 44 | "authors": [ 45 | { 46 | "name": "Roman Borschel", 47 | "email": "roman@code-factory.org" 48 | }, 49 | { 50 | "name": "Benjamin Eberlei", 51 | "email": "kontakt@beberlei.de" 52 | }, 53 | { 54 | "name": "Guilherme Blanco", 55 | "email": "guilhermeblanco@gmail.com" 56 | }, 57 | { 58 | "name": "Jonathan Wage", 59 | "email": "jonwage@gmail.com" 60 | }, 61 | { 62 | "name": "Johannes Schmitt", 63 | "email": "schmittjoh@gmail.com" 64 | } 65 | ], 66 | "description": "Common String Manipulations with regard to casing and singular/plural rules.", 67 | "homepage": "http://www.doctrine-project.org", 68 | "keywords": [ 69 | "inflection", 70 | "pluralize", 71 | "singularize", 72 | "string" 73 | ], 74 | "time": "2018-01-09T20:05:19+00:00" 75 | }, 76 | { 77 | "name": "illuminate/container", 78 | "version": "v5.8.31", 79 | "source": { 80 | "type": "git", 81 | "url": "https://github.com/illuminate/container.git", 82 | "reference": "7afee1ef2cb53190a98d727ea77096b6a610c05e" 83 | }, 84 | "dist": { 85 | "type": "zip", 86 | "url": "https://api.github.com/repos/illuminate/container/zipball/7afee1ef2cb53190a98d727ea77096b6a610c05e", 87 | "reference": "7afee1ef2cb53190a98d727ea77096b6a610c05e", 88 | "shasum": "" 89 | }, 90 | "require": { 91 | "illuminate/contracts": "5.8.*", 92 | "illuminate/support": "5.8.*", 93 | "php": "^7.1.3", 94 | "psr/container": "^1.0" 95 | }, 96 | "type": "library", 97 | "extra": { 98 | "branch-alias": { 99 | "dev-master": "5.8-dev" 100 | } 101 | }, 102 | "autoload": { 103 | "psr-4": { 104 | "Illuminate\\Container\\": "" 105 | } 106 | }, 107 | "notification-url": "https://packagist.org/downloads/", 108 | "license": [ 109 | "MIT" 110 | ], 111 | "authors": [ 112 | { 113 | "name": "Taylor Otwell", 114 | "email": "taylor@laravel.com" 115 | } 116 | ], 117 | "description": "The Illuminate Container package.", 118 | "homepage": "https://laravel.com", 119 | "time": "2019-07-16T13:14:16+00:00" 120 | }, 121 | { 122 | "name": "illuminate/contracts", 123 | "version": "v5.8.31", 124 | "source": { 125 | "type": "git", 126 | "url": "https://github.com/illuminate/contracts.git", 127 | "reference": "00fc6afee788fa07c311b0650ad276585f8aef96" 128 | }, 129 | "dist": { 130 | "type": "zip", 131 | "url": "https://api.github.com/repos/illuminate/contracts/zipball/00fc6afee788fa07c311b0650ad276585f8aef96", 132 | "reference": "00fc6afee788fa07c311b0650ad276585f8aef96", 133 | "shasum": "" 134 | }, 135 | "require": { 136 | "php": "^7.1.3", 137 | "psr/container": "^1.0", 138 | "psr/simple-cache": "^1.0" 139 | }, 140 | "type": "library", 141 | "extra": { 142 | "branch-alias": { 143 | "dev-master": "5.8-dev" 144 | } 145 | }, 146 | "autoload": { 147 | "psr-4": { 148 | "Illuminate\\Contracts\\": "" 149 | } 150 | }, 151 | "notification-url": "https://packagist.org/downloads/", 152 | "license": [ 153 | "MIT" 154 | ], 155 | "authors": [ 156 | { 157 | "name": "Taylor Otwell", 158 | "email": "taylor@laravel.com" 159 | } 160 | ], 161 | "description": "The Illuminate Contracts package.", 162 | "homepage": "https://laravel.com", 163 | "time": "2019-07-30T13:57:21+00:00" 164 | }, 165 | { 166 | "name": "illuminate/support", 167 | "version": "v5.8.31", 168 | "source": { 169 | "type": "git", 170 | "url": "https://github.com/illuminate/support.git", 171 | "reference": "60fdf2cd0fe8092947f42add1681c34fa252af33" 172 | }, 173 | "dist": { 174 | "type": "zip", 175 | "url": "https://api.github.com/repos/illuminate/support/zipball/60fdf2cd0fe8092947f42add1681c34fa252af33", 176 | "reference": "60fdf2cd0fe8092947f42add1681c34fa252af33", 177 | "shasum": "" 178 | }, 179 | "require": { 180 | "doctrine/inflector": "^1.1", 181 | "ext-json": "*", 182 | "ext-mbstring": "*", 183 | "illuminate/contracts": "5.8.*", 184 | "nesbot/carbon": "^1.26.3 || ^2.0", 185 | "php": "^7.1.3" 186 | }, 187 | "conflict": { 188 | "tightenco/collect": "<5.5.33" 189 | }, 190 | "suggest": { 191 | "illuminate/filesystem": "Required to use the composer class (5.8.*).", 192 | "moontoast/math": "Required to use ordered UUIDs (^1.1).", 193 | "ramsey/uuid": "Required to use Str::uuid() (^3.7).", 194 | "symfony/process": "Required to use the composer class (^4.2).", 195 | "symfony/var-dumper": "Required to use the dd function (^4.2).", 196 | "vlucas/phpdotenv": "Required to use the env helper (^3.3)." 197 | }, 198 | "type": "library", 199 | "extra": { 200 | "branch-alias": { 201 | "dev-master": "5.8-dev" 202 | } 203 | }, 204 | "autoload": { 205 | "psr-4": { 206 | "Illuminate\\Support\\": "" 207 | }, 208 | "files": [ 209 | "helpers.php" 210 | ] 211 | }, 212 | "notification-url": "https://packagist.org/downloads/", 213 | "license": [ 214 | "MIT" 215 | ], 216 | "authors": [ 217 | { 218 | "name": "Taylor Otwell", 219 | "email": "taylor@laravel.com" 220 | } 221 | ], 222 | "description": "The Illuminate Support package.", 223 | "homepage": "https://laravel.com", 224 | "time": "2019-08-06T08:53:24+00:00" 225 | }, 226 | { 227 | "name": "mikey179/vfsstream", 228 | "version": "v1.6.7", 229 | "source": { 230 | "type": "git", 231 | "url": "https://github.com/bovigo/vfsStream.git", 232 | "reference": "2b544ac3a21bcc4dde5d90c4ae8d06f4319055fb" 233 | }, 234 | "dist": { 235 | "type": "zip", 236 | "url": "https://api.github.com/repos/bovigo/vfsStream/zipball/2b544ac3a21bcc4dde5d90c4ae8d06f4319055fb", 237 | "reference": "2b544ac3a21bcc4dde5d90c4ae8d06f4319055fb", 238 | "shasum": "" 239 | }, 240 | "require": { 241 | "php": ">=5.3.0" 242 | }, 243 | "require-dev": { 244 | "phpunit/phpunit": "^4.5|^5.0" 245 | }, 246 | "type": "library", 247 | "extra": { 248 | "branch-alias": { 249 | "dev-master": "1.6.x-dev" 250 | } 251 | }, 252 | "autoload": { 253 | "psr-0": { 254 | "org\\bovigo\\vfs\\": "src/main/php" 255 | } 256 | }, 257 | "notification-url": "https://packagist.org/downloads/", 258 | "license": [ 259 | "BSD-3-Clause" 260 | ], 261 | "authors": [ 262 | { 263 | "name": "Frank Kleine", 264 | "role": "Developer", 265 | "homepage": "http://frankkleine.de/" 266 | } 267 | ], 268 | "description": "Virtual file system to mock the real file system in unit tests.", 269 | "homepage": "http://vfs.bovigo.org/", 270 | "time": "2019-08-01T01:38:37+00:00" 271 | }, 272 | { 273 | "name": "nesbot/carbon", 274 | "version": "2.22.3", 275 | "source": { 276 | "type": "git", 277 | "url": "https://github.com/briannesbitt/Carbon.git", 278 | "reference": "738fbd8d80b2c5e158fda76c29c2de432fcc6f7e" 279 | }, 280 | "dist": { 281 | "type": "zip", 282 | "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/738fbd8d80b2c5e158fda76c29c2de432fcc6f7e", 283 | "reference": "738fbd8d80b2c5e158fda76c29c2de432fcc6f7e", 284 | "shasum": "" 285 | }, 286 | "require": { 287 | "ext-json": "*", 288 | "php": "^7.1.8 || ^8.0", 289 | "symfony/translation": "^3.4 || ^4.0" 290 | }, 291 | "require-dev": { 292 | "friendsofphp/php-cs-fixer": "^2.14 || ^3.0", 293 | "kylekatarnls/multi-tester": "^1.1", 294 | "phpmd/phpmd": "dev-php-7.1-compatibility", 295 | "phpstan/phpstan": "^0.11", 296 | "phpunit/phpunit": "^7.5 || ^8.0", 297 | "squizlabs/php_codesniffer": "^3.4" 298 | }, 299 | "bin": [ 300 | "bin/carbon" 301 | ], 302 | "type": "library", 303 | "extra": { 304 | "laravel": { 305 | "providers": [ 306 | "Carbon\\Laravel\\ServiceProvider" 307 | ] 308 | } 309 | }, 310 | "autoload": { 311 | "psr-4": { 312 | "Carbon\\": "src/Carbon/" 313 | } 314 | }, 315 | "notification-url": "https://packagist.org/downloads/", 316 | "license": [ 317 | "MIT" 318 | ], 319 | "authors": [ 320 | { 321 | "name": "Brian Nesbitt", 322 | "email": "brian@nesbot.com", 323 | "homepage": "http://nesbot.com" 324 | }, 325 | { 326 | "name": "kylekatarnls", 327 | "homepage": "http://github.com/kylekatarnls" 328 | } 329 | ], 330 | "description": "A simple API extension for DateTime.", 331 | "homepage": "http://carbon.nesbot.com", 332 | "keywords": [ 333 | "date", 334 | "datetime", 335 | "time" 336 | ], 337 | "time": "2019-08-07T12:36:44+00:00" 338 | }, 339 | { 340 | "name": "psr/container", 341 | "version": "1.0.0", 342 | "source": { 343 | "type": "git", 344 | "url": "https://github.com/php-fig/container.git", 345 | "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f" 346 | }, 347 | "dist": { 348 | "type": "zip", 349 | "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f", 350 | "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f", 351 | "shasum": "" 352 | }, 353 | "require": { 354 | "php": ">=5.3.0" 355 | }, 356 | "type": "library", 357 | "extra": { 358 | "branch-alias": { 359 | "dev-master": "1.0.x-dev" 360 | } 361 | }, 362 | "autoload": { 363 | "psr-4": { 364 | "Psr\\Container\\": "src/" 365 | } 366 | }, 367 | "notification-url": "https://packagist.org/downloads/", 368 | "license": [ 369 | "MIT" 370 | ], 371 | "authors": [ 372 | { 373 | "name": "PHP-FIG", 374 | "homepage": "http://www.php-fig.org/" 375 | } 376 | ], 377 | "description": "Common Container Interface (PHP FIG PSR-11)", 378 | "homepage": "https://github.com/php-fig/container", 379 | "keywords": [ 380 | "PSR-11", 381 | "container", 382 | "container-interface", 383 | "container-interop", 384 | "psr" 385 | ], 386 | "time": "2017-02-14T16:28:37+00:00" 387 | }, 388 | { 389 | "name": "psr/simple-cache", 390 | "version": "1.0.1", 391 | "source": { 392 | "type": "git", 393 | "url": "https://github.com/php-fig/simple-cache.git", 394 | "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b" 395 | }, 396 | "dist": { 397 | "type": "zip", 398 | "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", 399 | "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", 400 | "shasum": "" 401 | }, 402 | "require": { 403 | "php": ">=5.3.0" 404 | }, 405 | "type": "library", 406 | "extra": { 407 | "branch-alias": { 408 | "dev-master": "1.0.x-dev" 409 | } 410 | }, 411 | "autoload": { 412 | "psr-4": { 413 | "Psr\\SimpleCache\\": "src/" 414 | } 415 | }, 416 | "notification-url": "https://packagist.org/downloads/", 417 | "license": [ 418 | "MIT" 419 | ], 420 | "authors": [ 421 | { 422 | "name": "PHP-FIG", 423 | "homepage": "http://www.php-fig.org/" 424 | } 425 | ], 426 | "description": "Common interfaces for simple caching", 427 | "keywords": [ 428 | "cache", 429 | "caching", 430 | "psr", 431 | "psr-16", 432 | "simple-cache" 433 | ], 434 | "time": "2017-10-23T01:57:42+00:00" 435 | }, 436 | { 437 | "name": "symfony/console", 438 | "version": "v4.3.3", 439 | "source": { 440 | "type": "git", 441 | "url": "https://github.com/symfony/console.git", 442 | "reference": "8b0ae5742ce9aaa8b0075665862c1ca397d1c1d9" 443 | }, 444 | "dist": { 445 | "type": "zip", 446 | "url": "https://api.github.com/repos/symfony/console/zipball/8b0ae5742ce9aaa8b0075665862c1ca397d1c1d9", 447 | "reference": "8b0ae5742ce9aaa8b0075665862c1ca397d1c1d9", 448 | "shasum": "" 449 | }, 450 | "require": { 451 | "php": "^7.1.3", 452 | "symfony/polyfill-mbstring": "~1.0", 453 | "symfony/polyfill-php73": "^1.8", 454 | "symfony/service-contracts": "^1.1" 455 | }, 456 | "conflict": { 457 | "symfony/dependency-injection": "<3.4", 458 | "symfony/event-dispatcher": "<4.3", 459 | "symfony/process": "<3.3" 460 | }, 461 | "provide": { 462 | "psr/log-implementation": "1.0" 463 | }, 464 | "require-dev": { 465 | "psr/log": "~1.0", 466 | "symfony/config": "~3.4|~4.0", 467 | "symfony/dependency-injection": "~3.4|~4.0", 468 | "symfony/event-dispatcher": "^4.3", 469 | "symfony/lock": "~3.4|~4.0", 470 | "symfony/process": "~3.4|~4.0", 471 | "symfony/var-dumper": "^4.3" 472 | }, 473 | "suggest": { 474 | "psr/log": "For using the console logger", 475 | "symfony/event-dispatcher": "", 476 | "symfony/lock": "", 477 | "symfony/process": "" 478 | }, 479 | "type": "library", 480 | "extra": { 481 | "branch-alias": { 482 | "dev-master": "4.3-dev" 483 | } 484 | }, 485 | "autoload": { 486 | "psr-4": { 487 | "Symfony\\Component\\Console\\": "" 488 | }, 489 | "exclude-from-classmap": [ 490 | "/Tests/" 491 | ] 492 | }, 493 | "notification-url": "https://packagist.org/downloads/", 494 | "license": [ 495 | "MIT" 496 | ], 497 | "authors": [ 498 | { 499 | "name": "Fabien Potencier", 500 | "email": "fabien@symfony.com" 501 | }, 502 | { 503 | "name": "Symfony Community", 504 | "homepage": "https://symfony.com/contributors" 505 | } 506 | ], 507 | "description": "Symfony Console Component", 508 | "homepage": "https://symfony.com", 509 | "time": "2019-07-24T17:13:59+00:00" 510 | }, 511 | { 512 | "name": "symfony/polyfill-mbstring", 513 | "version": "v1.12.0", 514 | "source": { 515 | "type": "git", 516 | "url": "https://github.com/symfony/polyfill-mbstring.git", 517 | "reference": "b42a2f66e8f1b15ccf25652c3424265923eb4f17" 518 | }, 519 | "dist": { 520 | "type": "zip", 521 | "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/b42a2f66e8f1b15ccf25652c3424265923eb4f17", 522 | "reference": "b42a2f66e8f1b15ccf25652c3424265923eb4f17", 523 | "shasum": "" 524 | }, 525 | "require": { 526 | "php": ">=5.3.3" 527 | }, 528 | "suggest": { 529 | "ext-mbstring": "For best performance" 530 | }, 531 | "type": "library", 532 | "extra": { 533 | "branch-alias": { 534 | "dev-master": "1.12-dev" 535 | } 536 | }, 537 | "autoload": { 538 | "psr-4": { 539 | "Symfony\\Polyfill\\Mbstring\\": "" 540 | }, 541 | "files": [ 542 | "bootstrap.php" 543 | ] 544 | }, 545 | "notification-url": "https://packagist.org/downloads/", 546 | "license": [ 547 | "MIT" 548 | ], 549 | "authors": [ 550 | { 551 | "name": "Nicolas Grekas", 552 | "email": "p@tchwork.com" 553 | }, 554 | { 555 | "name": "Symfony Community", 556 | "homepage": "https://symfony.com/contributors" 557 | } 558 | ], 559 | "description": "Symfony polyfill for the Mbstring extension", 560 | "homepage": "https://symfony.com", 561 | "keywords": [ 562 | "compatibility", 563 | "mbstring", 564 | "polyfill", 565 | "portable", 566 | "shim" 567 | ], 568 | "time": "2019-08-06T08:03:45+00:00" 569 | }, 570 | { 571 | "name": "symfony/polyfill-php73", 572 | "version": "v1.12.0", 573 | "source": { 574 | "type": "git", 575 | "url": "https://github.com/symfony/polyfill-php73.git", 576 | "reference": "2ceb49eaccb9352bff54d22570276bb75ba4a188" 577 | }, 578 | "dist": { 579 | "type": "zip", 580 | "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/2ceb49eaccb9352bff54d22570276bb75ba4a188", 581 | "reference": "2ceb49eaccb9352bff54d22570276bb75ba4a188", 582 | "shasum": "" 583 | }, 584 | "require": { 585 | "php": ">=5.3.3" 586 | }, 587 | "type": "library", 588 | "extra": { 589 | "branch-alias": { 590 | "dev-master": "1.12-dev" 591 | } 592 | }, 593 | "autoload": { 594 | "psr-4": { 595 | "Symfony\\Polyfill\\Php73\\": "" 596 | }, 597 | "files": [ 598 | "bootstrap.php" 599 | ], 600 | "classmap": [ 601 | "Resources/stubs" 602 | ] 603 | }, 604 | "notification-url": "https://packagist.org/downloads/", 605 | "license": [ 606 | "MIT" 607 | ], 608 | "authors": [ 609 | { 610 | "name": "Nicolas Grekas", 611 | "email": "p@tchwork.com" 612 | }, 613 | { 614 | "name": "Symfony Community", 615 | "homepage": "https://symfony.com/contributors" 616 | } 617 | ], 618 | "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", 619 | "homepage": "https://symfony.com", 620 | "keywords": [ 621 | "compatibility", 622 | "polyfill", 623 | "portable", 624 | "shim" 625 | ], 626 | "time": "2019-08-06T08:03:45+00:00" 627 | }, 628 | { 629 | "name": "symfony/process", 630 | "version": "v4.3.3", 631 | "source": { 632 | "type": "git", 633 | "url": "https://github.com/symfony/process.git", 634 | "reference": "856d35814cf287480465bb7a6c413bb7f5f5e69c" 635 | }, 636 | "dist": { 637 | "type": "zip", 638 | "url": "https://api.github.com/repos/symfony/process/zipball/856d35814cf287480465bb7a6c413bb7f5f5e69c", 639 | "reference": "856d35814cf287480465bb7a6c413bb7f5f5e69c", 640 | "shasum": "" 641 | }, 642 | "require": { 643 | "php": "^7.1.3" 644 | }, 645 | "type": "library", 646 | "extra": { 647 | "branch-alias": { 648 | "dev-master": "4.3-dev" 649 | } 650 | }, 651 | "autoload": { 652 | "psr-4": { 653 | "Symfony\\Component\\Process\\": "" 654 | }, 655 | "exclude-from-classmap": [ 656 | "/Tests/" 657 | ] 658 | }, 659 | "notification-url": "https://packagist.org/downloads/", 660 | "license": [ 661 | "MIT" 662 | ], 663 | "authors": [ 664 | { 665 | "name": "Fabien Potencier", 666 | "email": "fabien@symfony.com" 667 | }, 668 | { 669 | "name": "Symfony Community", 670 | "homepage": "https://symfony.com/contributors" 671 | } 672 | ], 673 | "description": "Symfony Process Component", 674 | "homepage": "https://symfony.com", 675 | "time": "2019-05-30T16:10:05+00:00" 676 | }, 677 | { 678 | "name": "symfony/service-contracts", 679 | "version": "v1.1.5", 680 | "source": { 681 | "type": "git", 682 | "url": "https://github.com/symfony/service-contracts.git", 683 | "reference": "f391a00de78ec7ec8cf5cdcdae59ec7b883edb8d" 684 | }, 685 | "dist": { 686 | "type": "zip", 687 | "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f391a00de78ec7ec8cf5cdcdae59ec7b883edb8d", 688 | "reference": "f391a00de78ec7ec8cf5cdcdae59ec7b883edb8d", 689 | "shasum": "" 690 | }, 691 | "require": { 692 | "php": "^7.1.3", 693 | "psr/container": "^1.0" 694 | }, 695 | "suggest": { 696 | "symfony/service-implementation": "" 697 | }, 698 | "type": "library", 699 | "extra": { 700 | "branch-alias": { 701 | "dev-master": "1.1-dev" 702 | } 703 | }, 704 | "autoload": { 705 | "psr-4": { 706 | "Symfony\\Contracts\\Service\\": "" 707 | } 708 | }, 709 | "notification-url": "https://packagist.org/downloads/", 710 | "license": [ 711 | "MIT" 712 | ], 713 | "authors": [ 714 | { 715 | "name": "Nicolas Grekas", 716 | "email": "p@tchwork.com" 717 | }, 718 | { 719 | "name": "Symfony Community", 720 | "homepage": "https://symfony.com/contributors" 721 | } 722 | ], 723 | "description": "Generic abstractions related to writing services", 724 | "homepage": "https://symfony.com", 725 | "keywords": [ 726 | "abstractions", 727 | "contracts", 728 | "decoupling", 729 | "interfaces", 730 | "interoperability", 731 | "standards" 732 | ], 733 | "time": "2019-06-13T11:15:36+00:00" 734 | }, 735 | { 736 | "name": "symfony/translation", 737 | "version": "v4.3.3", 738 | "source": { 739 | "type": "git", 740 | "url": "https://github.com/symfony/translation.git", 741 | "reference": "4e3e39cc485304f807622bdc64938e4633396406" 742 | }, 743 | "dist": { 744 | "type": "zip", 745 | "url": "https://api.github.com/repos/symfony/translation/zipball/4e3e39cc485304f807622bdc64938e4633396406", 746 | "reference": "4e3e39cc485304f807622bdc64938e4633396406", 747 | "shasum": "" 748 | }, 749 | "require": { 750 | "php": "^7.1.3", 751 | "symfony/polyfill-mbstring": "~1.0", 752 | "symfony/translation-contracts": "^1.1.2" 753 | }, 754 | "conflict": { 755 | "symfony/config": "<3.4", 756 | "symfony/dependency-injection": "<3.4", 757 | "symfony/yaml": "<3.4" 758 | }, 759 | "provide": { 760 | "symfony/translation-implementation": "1.0" 761 | }, 762 | "require-dev": { 763 | "psr/log": "~1.0", 764 | "symfony/config": "~3.4|~4.0", 765 | "symfony/console": "~3.4|~4.0", 766 | "symfony/dependency-injection": "~3.4|~4.0", 767 | "symfony/finder": "~2.8|~3.0|~4.0", 768 | "symfony/http-kernel": "~3.4|~4.0", 769 | "symfony/intl": "~3.4|~4.0", 770 | "symfony/service-contracts": "^1.1.2", 771 | "symfony/var-dumper": "~3.4|~4.0", 772 | "symfony/yaml": "~3.4|~4.0" 773 | }, 774 | "suggest": { 775 | "psr/log-implementation": "To use logging capability in translator", 776 | "symfony/config": "", 777 | "symfony/yaml": "" 778 | }, 779 | "type": "library", 780 | "extra": { 781 | "branch-alias": { 782 | "dev-master": "4.3-dev" 783 | } 784 | }, 785 | "autoload": { 786 | "psr-4": { 787 | "Symfony\\Component\\Translation\\": "" 788 | }, 789 | "exclude-from-classmap": [ 790 | "/Tests/" 791 | ] 792 | }, 793 | "notification-url": "https://packagist.org/downloads/", 794 | "license": [ 795 | "MIT" 796 | ], 797 | "authors": [ 798 | { 799 | "name": "Fabien Potencier", 800 | "email": "fabien@symfony.com" 801 | }, 802 | { 803 | "name": "Symfony Community", 804 | "homepage": "https://symfony.com/contributors" 805 | } 806 | ], 807 | "description": "Symfony Translation Component", 808 | "homepage": "https://symfony.com", 809 | "time": "2019-07-18T10:34:59+00:00" 810 | }, 811 | { 812 | "name": "symfony/translation-contracts", 813 | "version": "v1.1.5", 814 | "source": { 815 | "type": "git", 816 | "url": "https://github.com/symfony/translation-contracts.git", 817 | "reference": "cb4b18ad7b92a26e83b65dde940fab78339e6f3c" 818 | }, 819 | "dist": { 820 | "type": "zip", 821 | "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/cb4b18ad7b92a26e83b65dde940fab78339e6f3c", 822 | "reference": "cb4b18ad7b92a26e83b65dde940fab78339e6f3c", 823 | "shasum": "" 824 | }, 825 | "require": { 826 | "php": "^7.1.3" 827 | }, 828 | "suggest": { 829 | "symfony/translation-implementation": "" 830 | }, 831 | "type": "library", 832 | "extra": { 833 | "branch-alias": { 834 | "dev-master": "1.1-dev" 835 | } 836 | }, 837 | "autoload": { 838 | "psr-4": { 839 | "Symfony\\Contracts\\Translation\\": "" 840 | } 841 | }, 842 | "notification-url": "https://packagist.org/downloads/", 843 | "license": [ 844 | "MIT" 845 | ], 846 | "authors": [ 847 | { 848 | "name": "Nicolas Grekas", 849 | "email": "p@tchwork.com" 850 | }, 851 | { 852 | "name": "Symfony Community", 853 | "homepage": "https://symfony.com/contributors" 854 | } 855 | ], 856 | "description": "Generic abstractions related to translation", 857 | "homepage": "https://symfony.com", 858 | "keywords": [ 859 | "abstractions", 860 | "contracts", 861 | "decoupling", 862 | "interfaces", 863 | "interoperability", 864 | "standards" 865 | ], 866 | "time": "2019-06-13T11:15:36+00:00" 867 | } 868 | ], 869 | "packages-dev": [ 870 | { 871 | "name": "doctrine/instantiator", 872 | "version": "1.2.0", 873 | "source": { 874 | "type": "git", 875 | "url": "https://github.com/doctrine/instantiator.git", 876 | "reference": "a2c590166b2133a4633738648b6b064edae0814a" 877 | }, 878 | "dist": { 879 | "type": "zip", 880 | "url": "https://api.github.com/repos/doctrine/instantiator/zipball/a2c590166b2133a4633738648b6b064edae0814a", 881 | "reference": "a2c590166b2133a4633738648b6b064edae0814a", 882 | "shasum": "" 883 | }, 884 | "require": { 885 | "php": "^7.1" 886 | }, 887 | "require-dev": { 888 | "doctrine/coding-standard": "^6.0", 889 | "ext-pdo": "*", 890 | "ext-phar": "*", 891 | "phpbench/phpbench": "^0.13", 892 | "phpstan/phpstan-phpunit": "^0.11", 893 | "phpstan/phpstan-shim": "^0.11", 894 | "phpunit/phpunit": "^7.0" 895 | }, 896 | "type": "library", 897 | "extra": { 898 | "branch-alias": { 899 | "dev-master": "1.2.x-dev" 900 | } 901 | }, 902 | "autoload": { 903 | "psr-4": { 904 | "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" 905 | } 906 | }, 907 | "notification-url": "https://packagist.org/downloads/", 908 | "license": [ 909 | "MIT" 910 | ], 911 | "authors": [ 912 | { 913 | "name": "Marco Pivetta", 914 | "email": "ocramius@gmail.com", 915 | "homepage": "http://ocramius.github.com/" 916 | } 917 | ], 918 | "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", 919 | "homepage": "https://www.doctrine-project.org/projects/instantiator.html", 920 | "keywords": [ 921 | "constructor", 922 | "instantiate" 923 | ], 924 | "time": "2019-03-17T17:37:11+00:00" 925 | }, 926 | { 927 | "name": "myclabs/deep-copy", 928 | "version": "1.9.1", 929 | "source": { 930 | "type": "git", 931 | "url": "https://github.com/myclabs/DeepCopy.git", 932 | "reference": "e6828efaba2c9b79f4499dae1d66ef8bfa7b2b72" 933 | }, 934 | "dist": { 935 | "type": "zip", 936 | "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/e6828efaba2c9b79f4499dae1d66ef8bfa7b2b72", 937 | "reference": "e6828efaba2c9b79f4499dae1d66ef8bfa7b2b72", 938 | "shasum": "" 939 | }, 940 | "require": { 941 | "php": "^7.1" 942 | }, 943 | "replace": { 944 | "myclabs/deep-copy": "self.version" 945 | }, 946 | "require-dev": { 947 | "doctrine/collections": "^1.0", 948 | "doctrine/common": "^2.6", 949 | "phpunit/phpunit": "^7.1" 950 | }, 951 | "type": "library", 952 | "autoload": { 953 | "psr-4": { 954 | "DeepCopy\\": "src/DeepCopy/" 955 | }, 956 | "files": [ 957 | "src/DeepCopy/deep_copy.php" 958 | ] 959 | }, 960 | "notification-url": "https://packagist.org/downloads/", 961 | "license": [ 962 | "MIT" 963 | ], 964 | "description": "Create deep copies (clones) of your objects", 965 | "keywords": [ 966 | "clone", 967 | "copy", 968 | "duplicate", 969 | "object", 970 | "object graph" 971 | ], 972 | "time": "2019-04-07T13:18:21+00:00" 973 | }, 974 | { 975 | "name": "phar-io/manifest", 976 | "version": "1.0.3", 977 | "source": { 978 | "type": "git", 979 | "url": "https://github.com/phar-io/manifest.git", 980 | "reference": "7761fcacf03b4d4f16e7ccb606d4879ca431fcf4" 981 | }, 982 | "dist": { 983 | "type": "zip", 984 | "url": "https://api.github.com/repos/phar-io/manifest/zipball/7761fcacf03b4d4f16e7ccb606d4879ca431fcf4", 985 | "reference": "7761fcacf03b4d4f16e7ccb606d4879ca431fcf4", 986 | "shasum": "" 987 | }, 988 | "require": { 989 | "ext-dom": "*", 990 | "ext-phar": "*", 991 | "phar-io/version": "^2.0", 992 | "php": "^5.6 || ^7.0" 993 | }, 994 | "type": "library", 995 | "extra": { 996 | "branch-alias": { 997 | "dev-master": "1.0.x-dev" 998 | } 999 | }, 1000 | "autoload": { 1001 | "classmap": [ 1002 | "src/" 1003 | ] 1004 | }, 1005 | "notification-url": "https://packagist.org/downloads/", 1006 | "license": [ 1007 | "BSD-3-Clause" 1008 | ], 1009 | "authors": [ 1010 | { 1011 | "name": "Arne Blankerts", 1012 | "role": "Developer", 1013 | "email": "arne@blankerts.de" 1014 | }, 1015 | { 1016 | "name": "Sebastian Heuer", 1017 | "role": "Developer", 1018 | "email": "sebastian@phpeople.de" 1019 | }, 1020 | { 1021 | "name": "Sebastian Bergmann", 1022 | "role": "Developer", 1023 | "email": "sebastian@phpunit.de" 1024 | } 1025 | ], 1026 | "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", 1027 | "time": "2018-07-08T19:23:20+00:00" 1028 | }, 1029 | { 1030 | "name": "phar-io/version", 1031 | "version": "2.0.1", 1032 | "source": { 1033 | "type": "git", 1034 | "url": "https://github.com/phar-io/version.git", 1035 | "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6" 1036 | }, 1037 | "dist": { 1038 | "type": "zip", 1039 | "url": "https://api.github.com/repos/phar-io/version/zipball/45a2ec53a73c70ce41d55cedef9063630abaf1b6", 1040 | "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6", 1041 | "shasum": "" 1042 | }, 1043 | "require": { 1044 | "php": "^5.6 || ^7.0" 1045 | }, 1046 | "type": "library", 1047 | "autoload": { 1048 | "classmap": [ 1049 | "src/" 1050 | ] 1051 | }, 1052 | "notification-url": "https://packagist.org/downloads/", 1053 | "license": [ 1054 | "BSD-3-Clause" 1055 | ], 1056 | "authors": [ 1057 | { 1058 | "name": "Arne Blankerts", 1059 | "role": "Developer", 1060 | "email": "arne@blankerts.de" 1061 | }, 1062 | { 1063 | "name": "Sebastian Heuer", 1064 | "role": "Developer", 1065 | "email": "sebastian@phpeople.de" 1066 | }, 1067 | { 1068 | "name": "Sebastian Bergmann", 1069 | "role": "Developer", 1070 | "email": "sebastian@phpunit.de" 1071 | } 1072 | ], 1073 | "description": "Library for handling version information and constraints", 1074 | "time": "2018-07-08T19:19:57+00:00" 1075 | }, 1076 | { 1077 | "name": "phpdocumentor/reflection-common", 1078 | "version": "1.0.1", 1079 | "source": { 1080 | "type": "git", 1081 | "url": "https://github.com/phpDocumentor/ReflectionCommon.git", 1082 | "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6" 1083 | }, 1084 | "dist": { 1085 | "type": "zip", 1086 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", 1087 | "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", 1088 | "shasum": "" 1089 | }, 1090 | "require": { 1091 | "php": ">=5.5" 1092 | }, 1093 | "require-dev": { 1094 | "phpunit/phpunit": "^4.6" 1095 | }, 1096 | "type": "library", 1097 | "extra": { 1098 | "branch-alias": { 1099 | "dev-master": "1.0.x-dev" 1100 | } 1101 | }, 1102 | "autoload": { 1103 | "psr-4": { 1104 | "phpDocumentor\\Reflection\\": [ 1105 | "src" 1106 | ] 1107 | } 1108 | }, 1109 | "notification-url": "https://packagist.org/downloads/", 1110 | "license": [ 1111 | "MIT" 1112 | ], 1113 | "authors": [ 1114 | { 1115 | "name": "Jaap van Otterdijk", 1116 | "email": "opensource@ijaap.nl" 1117 | } 1118 | ], 1119 | "description": "Common reflection classes used by phpdocumentor to reflect the code structure", 1120 | "homepage": "http://www.phpdoc.org", 1121 | "keywords": [ 1122 | "FQSEN", 1123 | "phpDocumentor", 1124 | "phpdoc", 1125 | "reflection", 1126 | "static analysis" 1127 | ], 1128 | "time": "2017-09-11T18:02:19+00:00" 1129 | }, 1130 | { 1131 | "name": "phpdocumentor/reflection-docblock", 1132 | "version": "4.3.1", 1133 | "source": { 1134 | "type": "git", 1135 | "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", 1136 | "reference": "bdd9f737ebc2a01c06ea7ff4308ec6697db9b53c" 1137 | }, 1138 | "dist": { 1139 | "type": "zip", 1140 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/bdd9f737ebc2a01c06ea7ff4308ec6697db9b53c", 1141 | "reference": "bdd9f737ebc2a01c06ea7ff4308ec6697db9b53c", 1142 | "shasum": "" 1143 | }, 1144 | "require": { 1145 | "php": "^7.0", 1146 | "phpdocumentor/reflection-common": "^1.0.0", 1147 | "phpdocumentor/type-resolver": "^0.4.0", 1148 | "webmozart/assert": "^1.0" 1149 | }, 1150 | "require-dev": { 1151 | "doctrine/instantiator": "~1.0.5", 1152 | "mockery/mockery": "^1.0", 1153 | "phpunit/phpunit": "^6.4" 1154 | }, 1155 | "type": "library", 1156 | "extra": { 1157 | "branch-alias": { 1158 | "dev-master": "4.x-dev" 1159 | } 1160 | }, 1161 | "autoload": { 1162 | "psr-4": { 1163 | "phpDocumentor\\Reflection\\": [ 1164 | "src/" 1165 | ] 1166 | } 1167 | }, 1168 | "notification-url": "https://packagist.org/downloads/", 1169 | "license": [ 1170 | "MIT" 1171 | ], 1172 | "authors": [ 1173 | { 1174 | "name": "Mike van Riel", 1175 | "email": "me@mikevanriel.com" 1176 | } 1177 | ], 1178 | "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", 1179 | "time": "2019-04-30T17:48:53+00:00" 1180 | }, 1181 | { 1182 | "name": "phpdocumentor/type-resolver", 1183 | "version": "0.4.0", 1184 | "source": { 1185 | "type": "git", 1186 | "url": "https://github.com/phpDocumentor/TypeResolver.git", 1187 | "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7" 1188 | }, 1189 | "dist": { 1190 | "type": "zip", 1191 | "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7", 1192 | "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7", 1193 | "shasum": "" 1194 | }, 1195 | "require": { 1196 | "php": "^5.5 || ^7.0", 1197 | "phpdocumentor/reflection-common": "^1.0" 1198 | }, 1199 | "require-dev": { 1200 | "mockery/mockery": "^0.9.4", 1201 | "phpunit/phpunit": "^5.2||^4.8.24" 1202 | }, 1203 | "type": "library", 1204 | "extra": { 1205 | "branch-alias": { 1206 | "dev-master": "1.0.x-dev" 1207 | } 1208 | }, 1209 | "autoload": { 1210 | "psr-4": { 1211 | "phpDocumentor\\Reflection\\": [ 1212 | "src/" 1213 | ] 1214 | } 1215 | }, 1216 | "notification-url": "https://packagist.org/downloads/", 1217 | "license": [ 1218 | "MIT" 1219 | ], 1220 | "authors": [ 1221 | { 1222 | "name": "Mike van Riel", 1223 | "email": "me@mikevanriel.com" 1224 | } 1225 | ], 1226 | "time": "2017-07-14T14:27:02+00:00" 1227 | }, 1228 | { 1229 | "name": "phpspec/prophecy", 1230 | "version": "1.8.1", 1231 | "source": { 1232 | "type": "git", 1233 | "url": "https://github.com/phpspec/prophecy.git", 1234 | "reference": "1927e75f4ed19131ec9bcc3b002e07fb1173ee76" 1235 | }, 1236 | "dist": { 1237 | "type": "zip", 1238 | "url": "https://api.github.com/repos/phpspec/prophecy/zipball/1927e75f4ed19131ec9bcc3b002e07fb1173ee76", 1239 | "reference": "1927e75f4ed19131ec9bcc3b002e07fb1173ee76", 1240 | "shasum": "" 1241 | }, 1242 | "require": { 1243 | "doctrine/instantiator": "^1.0.2", 1244 | "php": "^5.3|^7.0", 1245 | "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0", 1246 | "sebastian/comparator": "^1.1|^2.0|^3.0", 1247 | "sebastian/recursion-context": "^1.0|^2.0|^3.0" 1248 | }, 1249 | "require-dev": { 1250 | "phpspec/phpspec": "^2.5|^3.2", 1251 | "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1" 1252 | }, 1253 | "type": "library", 1254 | "extra": { 1255 | "branch-alias": { 1256 | "dev-master": "1.8.x-dev" 1257 | } 1258 | }, 1259 | "autoload": { 1260 | "psr-4": { 1261 | "Prophecy\\": "src/Prophecy" 1262 | } 1263 | }, 1264 | "notification-url": "https://packagist.org/downloads/", 1265 | "license": [ 1266 | "MIT" 1267 | ], 1268 | "authors": [ 1269 | { 1270 | "name": "Konstantin Kudryashov", 1271 | "email": "ever.zet@gmail.com", 1272 | "homepage": "http://everzet.com" 1273 | }, 1274 | { 1275 | "name": "Marcello Duarte", 1276 | "email": "marcello.duarte@gmail.com" 1277 | } 1278 | ], 1279 | "description": "Highly opinionated mocking framework for PHP 5.3+", 1280 | "homepage": "https://github.com/phpspec/prophecy", 1281 | "keywords": [ 1282 | "Double", 1283 | "Dummy", 1284 | "fake", 1285 | "mock", 1286 | "spy", 1287 | "stub" 1288 | ], 1289 | "time": "2019-06-13T12:50:23+00:00" 1290 | }, 1291 | { 1292 | "name": "phpunit/php-code-coverage", 1293 | "version": "6.1.4", 1294 | "source": { 1295 | "type": "git", 1296 | "url": "https://github.com/sebastianbergmann/php-code-coverage.git", 1297 | "reference": "807e6013b00af69b6c5d9ceb4282d0393dbb9d8d" 1298 | }, 1299 | "dist": { 1300 | "type": "zip", 1301 | "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/807e6013b00af69b6c5d9ceb4282d0393dbb9d8d", 1302 | "reference": "807e6013b00af69b6c5d9ceb4282d0393dbb9d8d", 1303 | "shasum": "" 1304 | }, 1305 | "require": { 1306 | "ext-dom": "*", 1307 | "ext-xmlwriter": "*", 1308 | "php": "^7.1", 1309 | "phpunit/php-file-iterator": "^2.0", 1310 | "phpunit/php-text-template": "^1.2.1", 1311 | "phpunit/php-token-stream": "^3.0", 1312 | "sebastian/code-unit-reverse-lookup": "^1.0.1", 1313 | "sebastian/environment": "^3.1 || ^4.0", 1314 | "sebastian/version": "^2.0.1", 1315 | "theseer/tokenizer": "^1.1" 1316 | }, 1317 | "require-dev": { 1318 | "phpunit/phpunit": "^7.0" 1319 | }, 1320 | "suggest": { 1321 | "ext-xdebug": "^2.6.0" 1322 | }, 1323 | "type": "library", 1324 | "extra": { 1325 | "branch-alias": { 1326 | "dev-master": "6.1-dev" 1327 | } 1328 | }, 1329 | "autoload": { 1330 | "classmap": [ 1331 | "src/" 1332 | ] 1333 | }, 1334 | "notification-url": "https://packagist.org/downloads/", 1335 | "license": [ 1336 | "BSD-3-Clause" 1337 | ], 1338 | "authors": [ 1339 | { 1340 | "name": "Sebastian Bergmann", 1341 | "role": "lead", 1342 | "email": "sebastian@phpunit.de" 1343 | } 1344 | ], 1345 | "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", 1346 | "homepage": "https://github.com/sebastianbergmann/php-code-coverage", 1347 | "keywords": [ 1348 | "coverage", 1349 | "testing", 1350 | "xunit" 1351 | ], 1352 | "time": "2018-10-31T16:06:48+00:00" 1353 | }, 1354 | { 1355 | "name": "phpunit/php-file-iterator", 1356 | "version": "2.0.2", 1357 | "source": { 1358 | "type": "git", 1359 | "url": "https://github.com/sebastianbergmann/php-file-iterator.git", 1360 | "reference": "050bedf145a257b1ff02746c31894800e5122946" 1361 | }, 1362 | "dist": { 1363 | "type": "zip", 1364 | "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/050bedf145a257b1ff02746c31894800e5122946", 1365 | "reference": "050bedf145a257b1ff02746c31894800e5122946", 1366 | "shasum": "" 1367 | }, 1368 | "require": { 1369 | "php": "^7.1" 1370 | }, 1371 | "require-dev": { 1372 | "phpunit/phpunit": "^7.1" 1373 | }, 1374 | "type": "library", 1375 | "extra": { 1376 | "branch-alias": { 1377 | "dev-master": "2.0.x-dev" 1378 | } 1379 | }, 1380 | "autoload": { 1381 | "classmap": [ 1382 | "src/" 1383 | ] 1384 | }, 1385 | "notification-url": "https://packagist.org/downloads/", 1386 | "license": [ 1387 | "BSD-3-Clause" 1388 | ], 1389 | "authors": [ 1390 | { 1391 | "name": "Sebastian Bergmann", 1392 | "role": "lead", 1393 | "email": "sebastian@phpunit.de" 1394 | } 1395 | ], 1396 | "description": "FilterIterator implementation that filters files based on a list of suffixes.", 1397 | "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", 1398 | "keywords": [ 1399 | "filesystem", 1400 | "iterator" 1401 | ], 1402 | "time": "2018-09-13T20:33:42+00:00" 1403 | }, 1404 | { 1405 | "name": "phpunit/php-text-template", 1406 | "version": "1.2.1", 1407 | "source": { 1408 | "type": "git", 1409 | "url": "https://github.com/sebastianbergmann/php-text-template.git", 1410 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" 1411 | }, 1412 | "dist": { 1413 | "type": "zip", 1414 | "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", 1415 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", 1416 | "shasum": "" 1417 | }, 1418 | "require": { 1419 | "php": ">=5.3.3" 1420 | }, 1421 | "type": "library", 1422 | "autoload": { 1423 | "classmap": [ 1424 | "src/" 1425 | ] 1426 | }, 1427 | "notification-url": "https://packagist.org/downloads/", 1428 | "license": [ 1429 | "BSD-3-Clause" 1430 | ], 1431 | "authors": [ 1432 | { 1433 | "name": "Sebastian Bergmann", 1434 | "role": "lead", 1435 | "email": "sebastian@phpunit.de" 1436 | } 1437 | ], 1438 | "description": "Simple template engine.", 1439 | "homepage": "https://github.com/sebastianbergmann/php-text-template/", 1440 | "keywords": [ 1441 | "template" 1442 | ], 1443 | "time": "2015-06-21T13:50:34+00:00" 1444 | }, 1445 | { 1446 | "name": "phpunit/php-timer", 1447 | "version": "2.1.2", 1448 | "source": { 1449 | "type": "git", 1450 | "url": "https://github.com/sebastianbergmann/php-timer.git", 1451 | "reference": "1038454804406b0b5f5f520358e78c1c2f71501e" 1452 | }, 1453 | "dist": { 1454 | "type": "zip", 1455 | "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/1038454804406b0b5f5f520358e78c1c2f71501e", 1456 | "reference": "1038454804406b0b5f5f520358e78c1c2f71501e", 1457 | "shasum": "" 1458 | }, 1459 | "require": { 1460 | "php": "^7.1" 1461 | }, 1462 | "require-dev": { 1463 | "phpunit/phpunit": "^7.0" 1464 | }, 1465 | "type": "library", 1466 | "extra": { 1467 | "branch-alias": { 1468 | "dev-master": "2.1-dev" 1469 | } 1470 | }, 1471 | "autoload": { 1472 | "classmap": [ 1473 | "src/" 1474 | ] 1475 | }, 1476 | "notification-url": "https://packagist.org/downloads/", 1477 | "license": [ 1478 | "BSD-3-Clause" 1479 | ], 1480 | "authors": [ 1481 | { 1482 | "name": "Sebastian Bergmann", 1483 | "role": "lead", 1484 | "email": "sebastian@phpunit.de" 1485 | } 1486 | ], 1487 | "description": "Utility class for timing", 1488 | "homepage": "https://github.com/sebastianbergmann/php-timer/", 1489 | "keywords": [ 1490 | "timer" 1491 | ], 1492 | "time": "2019-06-07T04:22:29+00:00" 1493 | }, 1494 | { 1495 | "name": "phpunit/php-token-stream", 1496 | "version": "3.1.0", 1497 | "source": { 1498 | "type": "git", 1499 | "url": "https://github.com/sebastianbergmann/php-token-stream.git", 1500 | "reference": "e899757bb3df5ff6e95089132f32cd59aac2220a" 1501 | }, 1502 | "dist": { 1503 | "type": "zip", 1504 | "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/e899757bb3df5ff6e95089132f32cd59aac2220a", 1505 | "reference": "e899757bb3df5ff6e95089132f32cd59aac2220a", 1506 | "shasum": "" 1507 | }, 1508 | "require": { 1509 | "ext-tokenizer": "*", 1510 | "php": "^7.1" 1511 | }, 1512 | "require-dev": { 1513 | "phpunit/phpunit": "^7.0" 1514 | }, 1515 | "type": "library", 1516 | "extra": { 1517 | "branch-alias": { 1518 | "dev-master": "3.1-dev" 1519 | } 1520 | }, 1521 | "autoload": { 1522 | "classmap": [ 1523 | "src/" 1524 | ] 1525 | }, 1526 | "notification-url": "https://packagist.org/downloads/", 1527 | "license": [ 1528 | "BSD-3-Clause" 1529 | ], 1530 | "authors": [ 1531 | { 1532 | "name": "Sebastian Bergmann", 1533 | "email": "sebastian@phpunit.de" 1534 | } 1535 | ], 1536 | "description": "Wrapper around PHP's tokenizer extension.", 1537 | "homepage": "https://github.com/sebastianbergmann/php-token-stream/", 1538 | "keywords": [ 1539 | "tokenizer" 1540 | ], 1541 | "time": "2019-07-25T05:29:42+00:00" 1542 | }, 1543 | { 1544 | "name": "phpunit/phpunit", 1545 | "version": "7.5.14", 1546 | "source": { 1547 | "type": "git", 1548 | "url": "https://github.com/sebastianbergmann/phpunit.git", 1549 | "reference": "2834789aeb9ac182ad69bfdf9ae91856a59945ff" 1550 | }, 1551 | "dist": { 1552 | "type": "zip", 1553 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/2834789aeb9ac182ad69bfdf9ae91856a59945ff", 1554 | "reference": "2834789aeb9ac182ad69bfdf9ae91856a59945ff", 1555 | "shasum": "" 1556 | }, 1557 | "require": { 1558 | "doctrine/instantiator": "^1.1", 1559 | "ext-dom": "*", 1560 | "ext-json": "*", 1561 | "ext-libxml": "*", 1562 | "ext-mbstring": "*", 1563 | "ext-xml": "*", 1564 | "myclabs/deep-copy": "^1.7", 1565 | "phar-io/manifest": "^1.0.2", 1566 | "phar-io/version": "^2.0", 1567 | "php": "^7.1", 1568 | "phpspec/prophecy": "^1.7", 1569 | "phpunit/php-code-coverage": "^6.0.7", 1570 | "phpunit/php-file-iterator": "^2.0.1", 1571 | "phpunit/php-text-template": "^1.2.1", 1572 | "phpunit/php-timer": "^2.1", 1573 | "sebastian/comparator": "^3.0", 1574 | "sebastian/diff": "^3.0", 1575 | "sebastian/environment": "^4.0", 1576 | "sebastian/exporter": "^3.1", 1577 | "sebastian/global-state": "^2.0", 1578 | "sebastian/object-enumerator": "^3.0.3", 1579 | "sebastian/resource-operations": "^2.0", 1580 | "sebastian/version": "^2.0.1" 1581 | }, 1582 | "conflict": { 1583 | "phpunit/phpunit-mock-objects": "*" 1584 | }, 1585 | "require-dev": { 1586 | "ext-pdo": "*" 1587 | }, 1588 | "suggest": { 1589 | "ext-soap": "*", 1590 | "ext-xdebug": "*", 1591 | "phpunit/php-invoker": "^2.0" 1592 | }, 1593 | "bin": [ 1594 | "phpunit" 1595 | ], 1596 | "type": "library", 1597 | "extra": { 1598 | "branch-alias": { 1599 | "dev-master": "7.5-dev" 1600 | } 1601 | }, 1602 | "autoload": { 1603 | "classmap": [ 1604 | "src/" 1605 | ] 1606 | }, 1607 | "notification-url": "https://packagist.org/downloads/", 1608 | "license": [ 1609 | "BSD-3-Clause" 1610 | ], 1611 | "authors": [ 1612 | { 1613 | "name": "Sebastian Bergmann", 1614 | "role": "lead", 1615 | "email": "sebastian@phpunit.de" 1616 | } 1617 | ], 1618 | "description": "The PHP Unit Testing framework.", 1619 | "homepage": "https://phpunit.de/", 1620 | "keywords": [ 1621 | "phpunit", 1622 | "testing", 1623 | "xunit" 1624 | ], 1625 | "time": "2019-07-15T06:24:08+00:00" 1626 | }, 1627 | { 1628 | "name": "sebastian/code-unit-reverse-lookup", 1629 | "version": "1.0.1", 1630 | "source": { 1631 | "type": "git", 1632 | "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", 1633 | "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18" 1634 | }, 1635 | "dist": { 1636 | "type": "zip", 1637 | "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", 1638 | "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", 1639 | "shasum": "" 1640 | }, 1641 | "require": { 1642 | "php": "^5.6 || ^7.0" 1643 | }, 1644 | "require-dev": { 1645 | "phpunit/phpunit": "^5.7 || ^6.0" 1646 | }, 1647 | "type": "library", 1648 | "extra": { 1649 | "branch-alias": { 1650 | "dev-master": "1.0.x-dev" 1651 | } 1652 | }, 1653 | "autoload": { 1654 | "classmap": [ 1655 | "src/" 1656 | ] 1657 | }, 1658 | "notification-url": "https://packagist.org/downloads/", 1659 | "license": [ 1660 | "BSD-3-Clause" 1661 | ], 1662 | "authors": [ 1663 | { 1664 | "name": "Sebastian Bergmann", 1665 | "email": "sebastian@phpunit.de" 1666 | } 1667 | ], 1668 | "description": "Looks up which function or method a line of code belongs to", 1669 | "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", 1670 | "time": "2017-03-04T06:30:41+00:00" 1671 | }, 1672 | { 1673 | "name": "sebastian/comparator", 1674 | "version": "3.0.2", 1675 | "source": { 1676 | "type": "git", 1677 | "url": "https://github.com/sebastianbergmann/comparator.git", 1678 | "reference": "5de4fc177adf9bce8df98d8d141a7559d7ccf6da" 1679 | }, 1680 | "dist": { 1681 | "type": "zip", 1682 | "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/5de4fc177adf9bce8df98d8d141a7559d7ccf6da", 1683 | "reference": "5de4fc177adf9bce8df98d8d141a7559d7ccf6da", 1684 | "shasum": "" 1685 | }, 1686 | "require": { 1687 | "php": "^7.1", 1688 | "sebastian/diff": "^3.0", 1689 | "sebastian/exporter": "^3.1" 1690 | }, 1691 | "require-dev": { 1692 | "phpunit/phpunit": "^7.1" 1693 | }, 1694 | "type": "library", 1695 | "extra": { 1696 | "branch-alias": { 1697 | "dev-master": "3.0-dev" 1698 | } 1699 | }, 1700 | "autoload": { 1701 | "classmap": [ 1702 | "src/" 1703 | ] 1704 | }, 1705 | "notification-url": "https://packagist.org/downloads/", 1706 | "license": [ 1707 | "BSD-3-Clause" 1708 | ], 1709 | "authors": [ 1710 | { 1711 | "name": "Jeff Welch", 1712 | "email": "whatthejeff@gmail.com" 1713 | }, 1714 | { 1715 | "name": "Volker Dusch", 1716 | "email": "github@wallbash.com" 1717 | }, 1718 | { 1719 | "name": "Bernhard Schussek", 1720 | "email": "bschussek@2bepublished.at" 1721 | }, 1722 | { 1723 | "name": "Sebastian Bergmann", 1724 | "email": "sebastian@phpunit.de" 1725 | } 1726 | ], 1727 | "description": "Provides the functionality to compare PHP values for equality", 1728 | "homepage": "https://github.com/sebastianbergmann/comparator", 1729 | "keywords": [ 1730 | "comparator", 1731 | "compare", 1732 | "equality" 1733 | ], 1734 | "time": "2018-07-12T15:12:46+00:00" 1735 | }, 1736 | { 1737 | "name": "sebastian/diff", 1738 | "version": "3.0.2", 1739 | "source": { 1740 | "type": "git", 1741 | "url": "https://github.com/sebastianbergmann/diff.git", 1742 | "reference": "720fcc7e9b5cf384ea68d9d930d480907a0c1a29" 1743 | }, 1744 | "dist": { 1745 | "type": "zip", 1746 | "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/720fcc7e9b5cf384ea68d9d930d480907a0c1a29", 1747 | "reference": "720fcc7e9b5cf384ea68d9d930d480907a0c1a29", 1748 | "shasum": "" 1749 | }, 1750 | "require": { 1751 | "php": "^7.1" 1752 | }, 1753 | "require-dev": { 1754 | "phpunit/phpunit": "^7.5 || ^8.0", 1755 | "symfony/process": "^2 || ^3.3 || ^4" 1756 | }, 1757 | "type": "library", 1758 | "extra": { 1759 | "branch-alias": { 1760 | "dev-master": "3.0-dev" 1761 | } 1762 | }, 1763 | "autoload": { 1764 | "classmap": [ 1765 | "src/" 1766 | ] 1767 | }, 1768 | "notification-url": "https://packagist.org/downloads/", 1769 | "license": [ 1770 | "BSD-3-Clause" 1771 | ], 1772 | "authors": [ 1773 | { 1774 | "name": "Kore Nordmann", 1775 | "email": "mail@kore-nordmann.de" 1776 | }, 1777 | { 1778 | "name": "Sebastian Bergmann", 1779 | "email": "sebastian@phpunit.de" 1780 | } 1781 | ], 1782 | "description": "Diff implementation", 1783 | "homepage": "https://github.com/sebastianbergmann/diff", 1784 | "keywords": [ 1785 | "diff", 1786 | "udiff", 1787 | "unidiff", 1788 | "unified diff" 1789 | ], 1790 | "time": "2019-02-04T06:01:07+00:00" 1791 | }, 1792 | { 1793 | "name": "sebastian/environment", 1794 | "version": "4.2.2", 1795 | "source": { 1796 | "type": "git", 1797 | "url": "https://github.com/sebastianbergmann/environment.git", 1798 | "reference": "f2a2c8e1c97c11ace607a7a667d73d47c19fe404" 1799 | }, 1800 | "dist": { 1801 | "type": "zip", 1802 | "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/f2a2c8e1c97c11ace607a7a667d73d47c19fe404", 1803 | "reference": "f2a2c8e1c97c11ace607a7a667d73d47c19fe404", 1804 | "shasum": "" 1805 | }, 1806 | "require": { 1807 | "php": "^7.1" 1808 | }, 1809 | "require-dev": { 1810 | "phpunit/phpunit": "^7.5" 1811 | }, 1812 | "suggest": { 1813 | "ext-posix": "*" 1814 | }, 1815 | "type": "library", 1816 | "extra": { 1817 | "branch-alias": { 1818 | "dev-master": "4.2-dev" 1819 | } 1820 | }, 1821 | "autoload": { 1822 | "classmap": [ 1823 | "src/" 1824 | ] 1825 | }, 1826 | "notification-url": "https://packagist.org/downloads/", 1827 | "license": [ 1828 | "BSD-3-Clause" 1829 | ], 1830 | "authors": [ 1831 | { 1832 | "name": "Sebastian Bergmann", 1833 | "email": "sebastian@phpunit.de" 1834 | } 1835 | ], 1836 | "description": "Provides functionality to handle HHVM/PHP environments", 1837 | "homepage": "http://www.github.com/sebastianbergmann/environment", 1838 | "keywords": [ 1839 | "Xdebug", 1840 | "environment", 1841 | "hhvm" 1842 | ], 1843 | "time": "2019-05-05T09:05:15+00:00" 1844 | }, 1845 | { 1846 | "name": "sebastian/exporter", 1847 | "version": "3.1.0", 1848 | "source": { 1849 | "type": "git", 1850 | "url": "https://github.com/sebastianbergmann/exporter.git", 1851 | "reference": "234199f4528de6d12aaa58b612e98f7d36adb937" 1852 | }, 1853 | "dist": { 1854 | "type": "zip", 1855 | "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/234199f4528de6d12aaa58b612e98f7d36adb937", 1856 | "reference": "234199f4528de6d12aaa58b612e98f7d36adb937", 1857 | "shasum": "" 1858 | }, 1859 | "require": { 1860 | "php": "^7.0", 1861 | "sebastian/recursion-context": "^3.0" 1862 | }, 1863 | "require-dev": { 1864 | "ext-mbstring": "*", 1865 | "phpunit/phpunit": "^6.0" 1866 | }, 1867 | "type": "library", 1868 | "extra": { 1869 | "branch-alias": { 1870 | "dev-master": "3.1.x-dev" 1871 | } 1872 | }, 1873 | "autoload": { 1874 | "classmap": [ 1875 | "src/" 1876 | ] 1877 | }, 1878 | "notification-url": "https://packagist.org/downloads/", 1879 | "license": [ 1880 | "BSD-3-Clause" 1881 | ], 1882 | "authors": [ 1883 | { 1884 | "name": "Jeff Welch", 1885 | "email": "whatthejeff@gmail.com" 1886 | }, 1887 | { 1888 | "name": "Volker Dusch", 1889 | "email": "github@wallbash.com" 1890 | }, 1891 | { 1892 | "name": "Bernhard Schussek", 1893 | "email": "bschussek@2bepublished.at" 1894 | }, 1895 | { 1896 | "name": "Sebastian Bergmann", 1897 | "email": "sebastian@phpunit.de" 1898 | }, 1899 | { 1900 | "name": "Adam Harvey", 1901 | "email": "aharvey@php.net" 1902 | } 1903 | ], 1904 | "description": "Provides the functionality to export PHP variables for visualization", 1905 | "homepage": "http://www.github.com/sebastianbergmann/exporter", 1906 | "keywords": [ 1907 | "export", 1908 | "exporter" 1909 | ], 1910 | "time": "2017-04-03T13:19:02+00:00" 1911 | }, 1912 | { 1913 | "name": "sebastian/global-state", 1914 | "version": "2.0.0", 1915 | "source": { 1916 | "type": "git", 1917 | "url": "https://github.com/sebastianbergmann/global-state.git", 1918 | "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4" 1919 | }, 1920 | "dist": { 1921 | "type": "zip", 1922 | "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", 1923 | "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", 1924 | "shasum": "" 1925 | }, 1926 | "require": { 1927 | "php": "^7.0" 1928 | }, 1929 | "require-dev": { 1930 | "phpunit/phpunit": "^6.0" 1931 | }, 1932 | "suggest": { 1933 | "ext-uopz": "*" 1934 | }, 1935 | "type": "library", 1936 | "extra": { 1937 | "branch-alias": { 1938 | "dev-master": "2.0-dev" 1939 | } 1940 | }, 1941 | "autoload": { 1942 | "classmap": [ 1943 | "src/" 1944 | ] 1945 | }, 1946 | "notification-url": "https://packagist.org/downloads/", 1947 | "license": [ 1948 | "BSD-3-Clause" 1949 | ], 1950 | "authors": [ 1951 | { 1952 | "name": "Sebastian Bergmann", 1953 | "email": "sebastian@phpunit.de" 1954 | } 1955 | ], 1956 | "description": "Snapshotting of global state", 1957 | "homepage": "http://www.github.com/sebastianbergmann/global-state", 1958 | "keywords": [ 1959 | "global state" 1960 | ], 1961 | "time": "2017-04-27T15:39:26+00:00" 1962 | }, 1963 | { 1964 | "name": "sebastian/object-enumerator", 1965 | "version": "3.0.3", 1966 | "source": { 1967 | "type": "git", 1968 | "url": "https://github.com/sebastianbergmann/object-enumerator.git", 1969 | "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5" 1970 | }, 1971 | "dist": { 1972 | "type": "zip", 1973 | "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/7cfd9e65d11ffb5af41198476395774d4c8a84c5", 1974 | "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5", 1975 | "shasum": "" 1976 | }, 1977 | "require": { 1978 | "php": "^7.0", 1979 | "sebastian/object-reflector": "^1.1.1", 1980 | "sebastian/recursion-context": "^3.0" 1981 | }, 1982 | "require-dev": { 1983 | "phpunit/phpunit": "^6.0" 1984 | }, 1985 | "type": "library", 1986 | "extra": { 1987 | "branch-alias": { 1988 | "dev-master": "3.0.x-dev" 1989 | } 1990 | }, 1991 | "autoload": { 1992 | "classmap": [ 1993 | "src/" 1994 | ] 1995 | }, 1996 | "notification-url": "https://packagist.org/downloads/", 1997 | "license": [ 1998 | "BSD-3-Clause" 1999 | ], 2000 | "authors": [ 2001 | { 2002 | "name": "Sebastian Bergmann", 2003 | "email": "sebastian@phpunit.de" 2004 | } 2005 | ], 2006 | "description": "Traverses array structures and object graphs to enumerate all referenced objects", 2007 | "homepage": "https://github.com/sebastianbergmann/object-enumerator/", 2008 | "time": "2017-08-03T12:35:26+00:00" 2009 | }, 2010 | { 2011 | "name": "sebastian/object-reflector", 2012 | "version": "1.1.1", 2013 | "source": { 2014 | "type": "git", 2015 | "url": "https://github.com/sebastianbergmann/object-reflector.git", 2016 | "reference": "773f97c67f28de00d397be301821b06708fca0be" 2017 | }, 2018 | "dist": { 2019 | "type": "zip", 2020 | "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/773f97c67f28de00d397be301821b06708fca0be", 2021 | "reference": "773f97c67f28de00d397be301821b06708fca0be", 2022 | "shasum": "" 2023 | }, 2024 | "require": { 2025 | "php": "^7.0" 2026 | }, 2027 | "require-dev": { 2028 | "phpunit/phpunit": "^6.0" 2029 | }, 2030 | "type": "library", 2031 | "extra": { 2032 | "branch-alias": { 2033 | "dev-master": "1.1-dev" 2034 | } 2035 | }, 2036 | "autoload": { 2037 | "classmap": [ 2038 | "src/" 2039 | ] 2040 | }, 2041 | "notification-url": "https://packagist.org/downloads/", 2042 | "license": [ 2043 | "BSD-3-Clause" 2044 | ], 2045 | "authors": [ 2046 | { 2047 | "name": "Sebastian Bergmann", 2048 | "email": "sebastian@phpunit.de" 2049 | } 2050 | ], 2051 | "description": "Allows reflection of object attributes, including inherited and non-public ones", 2052 | "homepage": "https://github.com/sebastianbergmann/object-reflector/", 2053 | "time": "2017-03-29T09:07:27+00:00" 2054 | }, 2055 | { 2056 | "name": "sebastian/recursion-context", 2057 | "version": "3.0.0", 2058 | "source": { 2059 | "type": "git", 2060 | "url": "https://github.com/sebastianbergmann/recursion-context.git", 2061 | "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8" 2062 | }, 2063 | "dist": { 2064 | "type": "zip", 2065 | "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", 2066 | "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", 2067 | "shasum": "" 2068 | }, 2069 | "require": { 2070 | "php": "^7.0" 2071 | }, 2072 | "require-dev": { 2073 | "phpunit/phpunit": "^6.0" 2074 | }, 2075 | "type": "library", 2076 | "extra": { 2077 | "branch-alias": { 2078 | "dev-master": "3.0.x-dev" 2079 | } 2080 | }, 2081 | "autoload": { 2082 | "classmap": [ 2083 | "src/" 2084 | ] 2085 | }, 2086 | "notification-url": "https://packagist.org/downloads/", 2087 | "license": [ 2088 | "BSD-3-Clause" 2089 | ], 2090 | "authors": [ 2091 | { 2092 | "name": "Jeff Welch", 2093 | "email": "whatthejeff@gmail.com" 2094 | }, 2095 | { 2096 | "name": "Sebastian Bergmann", 2097 | "email": "sebastian@phpunit.de" 2098 | }, 2099 | { 2100 | "name": "Adam Harvey", 2101 | "email": "aharvey@php.net" 2102 | } 2103 | ], 2104 | "description": "Provides functionality to recursively process PHP variables", 2105 | "homepage": "http://www.github.com/sebastianbergmann/recursion-context", 2106 | "time": "2017-03-03T06:23:57+00:00" 2107 | }, 2108 | { 2109 | "name": "sebastian/resource-operations", 2110 | "version": "2.0.1", 2111 | "source": { 2112 | "type": "git", 2113 | "url": "https://github.com/sebastianbergmann/resource-operations.git", 2114 | "reference": "4d7a795d35b889bf80a0cc04e08d77cedfa917a9" 2115 | }, 2116 | "dist": { 2117 | "type": "zip", 2118 | "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/4d7a795d35b889bf80a0cc04e08d77cedfa917a9", 2119 | "reference": "4d7a795d35b889bf80a0cc04e08d77cedfa917a9", 2120 | "shasum": "" 2121 | }, 2122 | "require": { 2123 | "php": "^7.1" 2124 | }, 2125 | "type": "library", 2126 | "extra": { 2127 | "branch-alias": { 2128 | "dev-master": "2.0-dev" 2129 | } 2130 | }, 2131 | "autoload": { 2132 | "classmap": [ 2133 | "src/" 2134 | ] 2135 | }, 2136 | "notification-url": "https://packagist.org/downloads/", 2137 | "license": [ 2138 | "BSD-3-Clause" 2139 | ], 2140 | "authors": [ 2141 | { 2142 | "name": "Sebastian Bergmann", 2143 | "email": "sebastian@phpunit.de" 2144 | } 2145 | ], 2146 | "description": "Provides a list of PHP built-in functions that operate on resources", 2147 | "homepage": "https://www.github.com/sebastianbergmann/resource-operations", 2148 | "time": "2018-10-04T04:07:39+00:00" 2149 | }, 2150 | { 2151 | "name": "sebastian/version", 2152 | "version": "2.0.1", 2153 | "source": { 2154 | "type": "git", 2155 | "url": "https://github.com/sebastianbergmann/version.git", 2156 | "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" 2157 | }, 2158 | "dist": { 2159 | "type": "zip", 2160 | "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", 2161 | "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", 2162 | "shasum": "" 2163 | }, 2164 | "require": { 2165 | "php": ">=5.6" 2166 | }, 2167 | "type": "library", 2168 | "extra": { 2169 | "branch-alias": { 2170 | "dev-master": "2.0.x-dev" 2171 | } 2172 | }, 2173 | "autoload": { 2174 | "classmap": [ 2175 | "src/" 2176 | ] 2177 | }, 2178 | "notification-url": "https://packagist.org/downloads/", 2179 | "license": [ 2180 | "BSD-3-Clause" 2181 | ], 2182 | "authors": [ 2183 | { 2184 | "name": "Sebastian Bergmann", 2185 | "role": "lead", 2186 | "email": "sebastian@phpunit.de" 2187 | } 2188 | ], 2189 | "description": "Library that helps with managing the version number of Git-hosted PHP projects", 2190 | "homepage": "https://github.com/sebastianbergmann/version", 2191 | "time": "2016-10-03T07:35:21+00:00" 2192 | }, 2193 | { 2194 | "name": "symfony/polyfill-ctype", 2195 | "version": "v1.12.0", 2196 | "source": { 2197 | "type": "git", 2198 | "url": "https://github.com/symfony/polyfill-ctype.git", 2199 | "reference": "550ebaac289296ce228a706d0867afc34687e3f4" 2200 | }, 2201 | "dist": { 2202 | "type": "zip", 2203 | "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/550ebaac289296ce228a706d0867afc34687e3f4", 2204 | "reference": "550ebaac289296ce228a706d0867afc34687e3f4", 2205 | "shasum": "" 2206 | }, 2207 | "require": { 2208 | "php": ">=5.3.3" 2209 | }, 2210 | "suggest": { 2211 | "ext-ctype": "For best performance" 2212 | }, 2213 | "type": "library", 2214 | "extra": { 2215 | "branch-alias": { 2216 | "dev-master": "1.12-dev" 2217 | } 2218 | }, 2219 | "autoload": { 2220 | "psr-4": { 2221 | "Symfony\\Polyfill\\Ctype\\": "" 2222 | }, 2223 | "files": [ 2224 | "bootstrap.php" 2225 | ] 2226 | }, 2227 | "notification-url": "https://packagist.org/downloads/", 2228 | "license": [ 2229 | "MIT" 2230 | ], 2231 | "authors": [ 2232 | { 2233 | "name": "Gert de Pagter", 2234 | "email": "BackEndTea@gmail.com" 2235 | }, 2236 | { 2237 | "name": "Symfony Community", 2238 | "homepage": "https://symfony.com/contributors" 2239 | } 2240 | ], 2241 | "description": "Symfony polyfill for ctype functions", 2242 | "homepage": "https://symfony.com", 2243 | "keywords": [ 2244 | "compatibility", 2245 | "ctype", 2246 | "polyfill", 2247 | "portable" 2248 | ], 2249 | "time": "2019-08-06T08:03:45+00:00" 2250 | }, 2251 | { 2252 | "name": "theseer/tokenizer", 2253 | "version": "1.1.3", 2254 | "source": { 2255 | "type": "git", 2256 | "url": "https://github.com/theseer/tokenizer.git", 2257 | "reference": "11336f6f84e16a720dae9d8e6ed5019efa85a0f9" 2258 | }, 2259 | "dist": { 2260 | "type": "zip", 2261 | "url": "https://api.github.com/repos/theseer/tokenizer/zipball/11336f6f84e16a720dae9d8e6ed5019efa85a0f9", 2262 | "reference": "11336f6f84e16a720dae9d8e6ed5019efa85a0f9", 2263 | "shasum": "" 2264 | }, 2265 | "require": { 2266 | "ext-dom": "*", 2267 | "ext-tokenizer": "*", 2268 | "ext-xmlwriter": "*", 2269 | "php": "^7.0" 2270 | }, 2271 | "type": "library", 2272 | "autoload": { 2273 | "classmap": [ 2274 | "src/" 2275 | ] 2276 | }, 2277 | "notification-url": "https://packagist.org/downloads/", 2278 | "license": [ 2279 | "BSD-3-Clause" 2280 | ], 2281 | "authors": [ 2282 | { 2283 | "name": "Arne Blankerts", 2284 | "email": "arne@blankerts.de", 2285 | "role": "Developer" 2286 | } 2287 | ], 2288 | "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", 2289 | "time": "2019-06-13T22:48:21+00:00" 2290 | }, 2291 | { 2292 | "name": "webmozart/assert", 2293 | "version": "1.4.0", 2294 | "source": { 2295 | "type": "git", 2296 | "url": "https://github.com/webmozart/assert.git", 2297 | "reference": "83e253c8e0be5b0257b881e1827274667c5c17a9" 2298 | }, 2299 | "dist": { 2300 | "type": "zip", 2301 | "url": "https://api.github.com/repos/webmozart/assert/zipball/83e253c8e0be5b0257b881e1827274667c5c17a9", 2302 | "reference": "83e253c8e0be5b0257b881e1827274667c5c17a9", 2303 | "shasum": "" 2304 | }, 2305 | "require": { 2306 | "php": "^5.3.3 || ^7.0", 2307 | "symfony/polyfill-ctype": "^1.8" 2308 | }, 2309 | "require-dev": { 2310 | "phpunit/phpunit": "^4.6", 2311 | "sebastian/version": "^1.0.1" 2312 | }, 2313 | "type": "library", 2314 | "extra": { 2315 | "branch-alias": { 2316 | "dev-master": "1.3-dev" 2317 | } 2318 | }, 2319 | "autoload": { 2320 | "psr-4": { 2321 | "Webmozart\\Assert\\": "src/" 2322 | } 2323 | }, 2324 | "notification-url": "https://packagist.org/downloads/", 2325 | "license": [ 2326 | "MIT" 2327 | ], 2328 | "authors": [ 2329 | { 2330 | "name": "Bernhard Schussek", 2331 | "email": "bschussek@gmail.com" 2332 | } 2333 | ], 2334 | "description": "Assertions to validate method input/output with nice error messages.", 2335 | "keywords": [ 2336 | "assert", 2337 | "check", 2338 | "validate" 2339 | ], 2340 | "time": "2018-12-25T11:19:39+00:00" 2341 | } 2342 | ], 2343 | "aliases": [], 2344 | "minimum-stability": "stable", 2345 | "stability-flags": [], 2346 | "prefer-stable": false, 2347 | "prefer-lowest": false, 2348 | "platform": [], 2349 | "platform-dev": [] 2350 | } 2351 | --------------------------------------------------------------------------------