├── var └── .gitkeep ├── .gitignore ├── app ├── bootstrap.php └── routes.php ├── db └── schema.sql ├── web └── index.php ├── .scrutinizer.yml ├── cli ├── deploy_test └── deploy_production ├── src ├── ReleaseRepository.php ├── ReleaseStateWriter.php ├── Deployer.php ├── PdoReleaseRepository.php └── TopLevelFactory.php ├── .travis.yml ├── tests ├── TestEnvironment.php ├── Integration │ ├── ReleaseFailureLoggingTest.php │ └── PdoReleaseRepositoryTest.php ├── EdgeToEdge │ ├── WebRouteTestCase.php │ └── DeploymentRouteTest.php ├── Unit │ └── DeployerTest.php └── files │ └── push-payload.json ├── phpunit.xml.dist ├── composer.json ├── README.md ├── phpcs.xml └── composer.lock /var/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | vendor/ 2 | var/ -------------------------------------------------------------------------------- /app/bootstrap.php: -------------------------------------------------------------------------------- 1 | run(); -------------------------------------------------------------------------------- /.scrutinizer.yml: -------------------------------------------------------------------------------- 1 | build: true 2 | inherit: true 3 | 4 | tools: 5 | external_code_coverage: true 6 | php_code_sniffer: true 7 | php_cpd: true 8 | php_cs_fixer: true 9 | php_loc: true 10 | php_mess_detector: true 11 | php_pdepend: true 12 | php_analyzer: true 13 | sensiolabs_security_checker: true 14 | 15 | filter: 16 | excluded_paths: 17 | - 'vendor/*' 18 | -------------------------------------------------------------------------------- /cli/deploy_test: -------------------------------------------------------------------------------- 1 | #!/bin/env php 2 | newDeployer( 'master' )->run( $command ); 16 | } ); 17 | -------------------------------------------------------------------------------- /cli/deploy_production: -------------------------------------------------------------------------------- 1 | #!/bin/env php 2 | newDeployer( 'production' )->run( $command ); 16 | } ); 17 | -------------------------------------------------------------------------------- /src/ReleaseRepository.php: -------------------------------------------------------------------------------- 1 | 8 | */ 9 | interface ReleaseRepository { 10 | 11 | public function hasUndeployedReleases(): bool; 12 | 13 | public function deploymentInProcess(): bool; 14 | 15 | public function getLatestReleaseId(): string; 16 | 17 | public function markDeploymentAsStarted( string $refId, string $now = '' ); 18 | 19 | public function markDeploymentAsFinished( string $refId, string $now = '' ); 20 | 21 | public function markDeploymentAsFailed( string $refId, string $now = '' ); 22 | } -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | matrix: 4 | include: 5 | - php: 7.1 6 | env: DB=sqlite 7 | fast_finish: true 8 | 9 | sudo: false 10 | 11 | install: travis_retry composer install 12 | 13 | script: composer ci 14 | 15 | after_success: 16 | - if [[ "`phpenv version-name`" != "7.1" ]]; then exit 0; fi 17 | - vendor/bin/phpunit --coverage-clover coverage.clover 18 | - wget https://scrutinizer-ci.com/ocular.phar 19 | - php ocular.phar code-coverage:upload --format=php-clover coverage.clover 20 | 21 | cache: 22 | directories: 23 | - "$HOME/.composer/cache" 24 | 25 | notifications: 26 | email: 27 | on_success: change 28 | on_failure: always 29 | -------------------------------------------------------------------------------- /src/ReleaseStateWriter.php: -------------------------------------------------------------------------------- 1 | 10 | */ 11 | class ReleaseStateWriter { 12 | 13 | private $db; 14 | 15 | public function __construct( \PDO $db ) { 16 | $this->db = $db; 17 | } 18 | 19 | public function addRelease( string $branchName, string $refId, $now = '' ) { 20 | $stmt = $this->db->prepare( 'INSERT INTO releases VALUES( :refId, :branchName, :timestampAdded, NULL, NULL, 0 )' ); 21 | $stmt->execute( [ 22 | 'branchName' => $branchName, 23 | 'refId' => $refId, 24 | 'timestampAdded' => $now ?: date( DATE_ISO8601 ) 25 | ] ); 26 | } 27 | 28 | } -------------------------------------------------------------------------------- /tests/TestEnvironment.php: -------------------------------------------------------------------------------- 1 | 10 | */ 11 | class TestEnvironment { 12 | 13 | public static function newInstance(): self { 14 | $instance = new self( 'sqlite::memory:' ); 15 | 16 | $instance->factory->getPdo()->exec( file_get_contents( __DIR__ .'/../db/schema.sql' ) ); 17 | 18 | return $instance; 19 | } 20 | 21 | private $factory; 22 | 23 | private function __construct( string $dbDsn ) { 24 | $this->factory = new TopLevelFactory( $dbDsn ); 25 | } 26 | 27 | public function getFactory(): TopLevelFactory { 28 | return $this->factory; 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 14 | 15 | 16 | tests 17 | 18 | 19 | 20 | 21 | src 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wmde/fundraising-github-webhook", 3 | "description": "Run actions for github webhooks", 4 | "license": "GPL-2.0+", 5 | "require": { 6 | "php": ">=7.1", 7 | "silex/silex": "~2.0", 8 | "symfony/process": "^3.1", 9 | "psr/log": "~1.0", 10 | "monolog/monolog": "~1.21" 11 | }, 12 | "require-dev": { 13 | "phpunit/phpunit": "^6.1", 14 | "wmde/psr-log-test-doubles": "^2.1", 15 | "symfony/browser-kit": "^3.1", 16 | 17 | "squizlabs/php_codesniffer": "~2.9", 18 | "mediawiki/mediawiki-codesniffer": "~0.8.0" 19 | }, 20 | "autoload": { 21 | "psr-4": { 22 | "WMDE\\Fundraising\\Deployment\\": "src/" 23 | } 24 | }, 25 | "autoload-dev": { 26 | "psr-4": { 27 | "WMDE\\Fundraising\\Deployment\\Tests\\": "tests/" 28 | } 29 | }, 30 | "scripts": { 31 | "ci": [ 32 | "@test", 33 | "@cs" 34 | ], 35 | "test": [ 36 | "composer validate --no-interaction", 37 | "vendor/bin/phpunit" 38 | ], 39 | "cs": [ 40 | "@phpcs" 41 | ], 42 | "phpcs": [ 43 | "vendor/bin/phpcs --standard=phpcs.xml" 44 | ] 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WMDE GitHub webhooks 2 | 3 | [![Build Status](https://secure.travis-ci.org/wmde/github-webhooks.png?branch=master)](http://travis-ci.org/wmde/github-webhooks) 4 | [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/wmde/github-webhooks/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/wmde/github-webhooks/?branch=master) 5 | [![Code Coverage](https://scrutinizer-ci.com/g/wmde/github-webhooks/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/wmde/github-webhooks/?branch=master) 6 | 7 | Continuous deployment for the WMDE fundraising projects. 8 | 9 | At present only the master and production branches of the FundraisingFrontend application are supported. 10 | 11 | ## High level workflow 12 | 13 | * The application exposes a `/deploy` endpoint which gets called by GitHub webhooks. 14 | * The `/deploy` endpoint saves the data it got, when relevant, into a database table. 15 | * Something (i.e. Cron) invokes one of the deployment scripts in `/cli` 16 | * The deployment script checks if there is something that needs deploying, 17 | and if so, executes an (Ansible) command that takes care of deployment. 18 | 19 | ## Running the tests 20 | 21 | For tests only 22 | 23 | composer test 24 | 25 | For style checks only 26 | 27 | composer cs 28 | 29 | For a full CI run 30 | 31 | composer ci -------------------------------------------------------------------------------- /tests/Integration/ReleaseFailureLoggingTest.php: -------------------------------------------------------------------------------- 1 | 15 | */ 16 | class ReleaseFailureLoggingTest extends TestCase { 17 | 18 | const BRANCH_NAME = 'master'; 19 | 20 | public function testWhenDeploymentFails_loggerGetsAlerted() { 21 | $loggerSpy = new LoggerSpy(); 22 | 23 | $factory = TestEnvironment::newInstance()->getFactory(); 24 | $factory->setLogger( $loggerSpy ); 25 | 26 | $this->insertRelease( $factory ); 27 | 28 | $command = new Process( 'cd plaintext-passwords/' ); 29 | 30 | $factory->newDeployer( self::BRANCH_NAME )->run( $command ); 31 | 32 | $this->assertNotEmpty( $loggerSpy->getLogCalls() ); 33 | $this->assertSame( LogLevel::ALERT, $loggerSpy->getLogCalls()->getFirstCall()->getLevel() ); 34 | } 35 | 36 | private function insertRelease( TopLevelFactory $factory ) { 37 | $factory->getReleaseStateWriter()->addRelease( self::BRANCH_NAME, 'deadbeef' ); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /app/routes.php: -------------------------------------------------------------------------------- 1 | post( '/deploy', function ( Request $request ) use ( $topLevelFactory ) { 12 | if ( !$request->headers->has( 'X-GitHub-Event' ) ) { 13 | return new Response( 'Bad request - X-GitHub-Event header missing', Response::HTTP_BAD_REQUEST ); 14 | } 15 | 16 | if ( $request->headers->get( 'X-GitHub-Event' ) !== 'push' ) { 17 | return new Response( 'Unsupported event.', Response::HTTP_NOT_IMPLEMENTED ); 18 | } 19 | 20 | $payload = json_decode( $request->getContent() ); 21 | 22 | if ( !$payload ) { 23 | return new Response( 'Bad request - Could not decode payload', Response::HTTP_BAD_REQUEST ); 24 | } 25 | 26 | if ( !empty( $payload->repository->full_name ) && 27 | !empty( $payload->ref ) && 28 | $payload->repository->full_name === 'wmde/FundraisingFrontend' && 29 | in_array( $payload->ref, [ 'refs/heads/master', 'refs/heads/production' ] ) ) { 30 | $branchName = str_replace( 'refs/heads/', '', $payload->ref ); 31 | 32 | $topLevelFactory->getReleaseStateWriter()->addRelease( $branchName, $payload->after ); 33 | } 34 | 35 | return new Response( 'Ok' ); 36 | } ); -------------------------------------------------------------------------------- /src/Deployer.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | class Deployer { 14 | 15 | private $releaseRepository; 16 | private $onDeploymentFailed; 17 | 18 | public function __construct( ReleaseRepository $releaseRepository, callable $onDeploymentFailed = null ) { 19 | $this->releaseRepository = $releaseRepository; 20 | $this->onDeploymentFailed = $onDeploymentFailed; 21 | } 22 | 23 | public function run( Process $deployCommand ) { 24 | if ( !$this->releaseRepository->hasUndeployedReleases() || $this->releaseRepository->deploymentInProcess() ) { 25 | return; 26 | } 27 | 28 | $latestReleaseId = $this->releaseRepository->getLatestReleaseId(); 29 | $this->releaseRepository->markDeploymentAsStarted( $latestReleaseId ); 30 | 31 | $deployCommand->run(); 32 | 33 | if ( $deployCommand->isSuccessful() ) { 34 | $this->releaseRepository->markDeploymentAsFinished( $latestReleaseId ); 35 | } else { 36 | $this->releaseRepository->markDeploymentAsFailed( $latestReleaseId ); 37 | 38 | if ( is_callable( $this->onDeploymentFailed ) ) { 39 | call_user_func( $this->onDeploymentFailed, $latestReleaseId, $deployCommand->getErrorOutput() ); 40 | } 41 | } 42 | 43 | } 44 | 45 | } -------------------------------------------------------------------------------- /tests/EdgeToEdge/WebRouteTestCase.php: -------------------------------------------------------------------------------- 1 | getFactory(); 30 | 31 | $app = $this->createApplication( $debug, $topLevelFactory ); 32 | 33 | if ( is_callable( $onAppCreated ) ) { 34 | call_user_func( $onAppCreated, $topLevelFactory, $app ); 35 | } 36 | 37 | return new Client( $app ); 38 | } 39 | 40 | private function createApplication( bool $debug, TopLevelFactory $topLevelFactory ) : Application { 41 | $app = require __DIR__ . ' /../../app/bootstrap.php'; 42 | 43 | require __DIR__ . ' /../../app/routes.php'; 44 | 45 | if ( $debug ) { 46 | $app['debug'] = true; 47 | unset( $app['exception_handler'] ); 48 | } 49 | 50 | return $app; 51 | } 52 | 53 | protected function assert404( Response $response ) { 54 | $this->assertSame( 404, $response->getStatusCode() ); 55 | } 56 | 57 | } -------------------------------------------------------------------------------- /tests/EdgeToEdge/DeploymentRouteTest.php: -------------------------------------------------------------------------------- 1 | createClient(); 13 | $client->request( 'POST', '/deploy' ); 14 | $this->assertSame( Response::HTTP_BAD_REQUEST, $client->getResponse()->getStatusCode() ); 15 | } 16 | 17 | public function testGivenWrongGithubEvent_requestIsRejected() { 18 | $client = $this->createClient(); 19 | $client->request( 'POST', '/deploy', [], [], [ 'HTTP_X-GitHub-Event' => 'dummy' ] ); 20 | $this->assertSame( Response::HTTP_NOT_IMPLEMENTED, $client->getResponse()->getStatusCode() ); 21 | } 22 | 23 | public function testGivenInvalidJsonContent_requestIsRejected() { 24 | $client = $this->createClient(); 25 | $client->request( 'POST', '/deploy', [], [], $this->getValidHeaders(), '~=[,,_,,]:3' ); 26 | $this->assertSame( Response::HTTP_BAD_REQUEST, $client->getResponse()->getStatusCode() ); 27 | } 28 | 29 | public function testGivenAValidPayload_aReleaseIsCreated() { 30 | $client = $this->createClient( function ( TopLevelFactory $factory ) { 31 | $releaseStateWriter = $this->getMockBuilder( ReleaseStateWriter::class )->disableOriginalConstructor()->getMock(); 32 | $releaseStateWriter->expects( $this->once() ) 33 | ->method( 'addRelease' ) 34 | ->with( 'master', '0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c' ); 35 | 36 | $factory->setReleaseStateWriter( $releaseStateWriter ); 37 | } ); 38 | 39 | $client->request( 'POST', '/deploy', [], [], $this->getValidHeaders(), $this->getValidPayload() ); 40 | $this->assertTrue( $client->getResponse()->isOk() ); 41 | } 42 | 43 | public function testGivenADifferentRepositoryName_noReleaseIsCreated() { 44 | $client = $this->createClient( function ( TopLevelFactory $factory ) { 45 | $releaseStateWriter = $this->getMockBuilder( ReleaseStateWriter::class )->disableOriginalConstructor()->getMock(); 46 | $releaseStateWriter->expects( $this->never() ) 47 | ->method( 'addRelease' ); 48 | 49 | $factory->setReleaseStateWriter( $releaseStateWriter ); 50 | } ); 51 | 52 | $client->request( 'POST', '/deploy', [], [], $this->getValidHeaders(), $this->getPayloadWithDifferentRepositoryName() ); 53 | $this->assertTrue( $client->getResponse()->isOk() ); 54 | } 55 | 56 | private function getValidHeaders() { 57 | return [ 'HTTP_X-GitHub-Event' => 'push' ]; 58 | } 59 | 60 | private function getValidPayload() { 61 | return file_get_contents( __DIR__ . '/../files/push-payload.json' ); 62 | } 63 | 64 | private function getPayloadWithDifferentRepositoryName() { 65 | return str_replace( 'wmde/FundraisingFrontend', 'wmde/FundraisingBackend', $this->getValidPayload() ); 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /src/PdoReleaseRepository.php: -------------------------------------------------------------------------------- 1 | 10 | */ 11 | class PdoReleaseRepository implements ReleaseRepository { 12 | 13 | private $db; 14 | private $branchName; 15 | 16 | public function __construct( \PDO $db, string $branchName ) { 17 | $this->db = $db; 18 | $this->branchName = $branchName; 19 | } 20 | 21 | public function hasUndeployedReleases(): bool { 22 | $stmt = $this->db->prepare( 'SELECT COUNT(*) FROM releases WHERE branch = :branchName AND ts_ended IS NULL AND ts_started IS NULL' ); 23 | $stmt->execute( [ 'branchName' => $this->branchName ] ); 24 | return $stmt->fetchColumn() > 0; 25 | } 26 | 27 | public function deploymentInProcess(): bool { 28 | $stmt = $this->db->prepare( 'SELECT COUNT(*) FROM releases WHERE branch = :branchName AND ts_ended IS NULL AND ts_started IS NOT NULL' ); 29 | $stmt->execute( [ 'branchName' => $this->branchName ] ); 30 | return $stmt->fetchColumn() > 0; 31 | } 32 | 33 | public function getLatestReleaseId(): string { 34 | $stmt = $this->db->prepare( 35 | 'SELECT refid FROM releases WHERE ts_ended IS NULL AND ts_started IS NULL AND branch = :branchName ORDER BY ts_added DESC LIMIT 1' 36 | ); 37 | $stmt->execute( [ 'branchName' => $this->branchName ] ); 38 | return $stmt->fetchColumn(); 39 | } 40 | 41 | public function markDeploymentAsStarted( string $refId, string $now = '' ) { 42 | $stmt = $this->db->prepare( 'UPDATE releases SET ts_started = :timestampStarted WHERE refid = :refId' ); 43 | $stmt->execute( [ 44 | 'refId' => $refId, 45 | 'timestampStarted' => $now ?: date( DATE_ISO8601 ) 46 | ] ); 47 | } 48 | 49 | public function markDeploymentAsFinished( string $refId, string $now = '' ) { 50 | $stmt = $this->db->prepare( 'UPDATE releases SET ts_ended = :timestampEnded WHERE refid = :refId' ); 51 | $stmt->execute( [ 52 | 'refId' => $refId, 53 | 'timestampEnded' => $now ?: date( DATE_ISO8601 ) 54 | ] ); 55 | $this->updateOlderReleases( $refId ); 56 | } 57 | 58 | public function markDeploymentAsFailed( string $refId, string $now = '' ) { 59 | $stmt = $this->db->prepare( 'UPDATE releases SET num_tries = num_tries + 1, ts_started = NULL, ts_ended = NULL WHERE refid = :refId' ); 60 | $stmt->execute( [ 61 | 'refId' => $refId, 62 | ] ); 63 | } 64 | 65 | private function updateOlderReleases( string $refId ) { 66 | $stmt = $this->db->prepare( 'SELECT * FROM releases WHERE refid = :refId' ); 67 | $stmt->execute( [ 'refId' => $refId ] ); 68 | $row = $stmt->fetch(); 69 | 70 | $stmt = $this->db->prepare( 71 | 'UPDATE releases SET ts_started = :timestampStarted, ts_ended = :timestampEnded ' . 72 | 'WHERE ts_started IS NULL AND ts_ended IS NULL AND branch = :branchName AND ts_added < :timestampAdded' 73 | ); 74 | $stmt->execute( [ 75 | 'branchName' => $row['branch'], 76 | 'timestampAdded' => $row['ts_added'], 77 | 'timestampStarted' => $row['ts_started'], 78 | 'timestampEnded' => $row['ts_ended'], 79 | ] ); 80 | } 81 | } -------------------------------------------------------------------------------- /src/TopLevelFactory.php: -------------------------------------------------------------------------------- 1 | 18 | */ 19 | class TopLevelFactory { 20 | 21 | public static function newFromConfig(): self { 22 | return new self( self::getVarPath() . '/releases.sqlite' ); 23 | } 24 | 25 | private $dbDsn; 26 | 27 | /** 28 | * @var LoggerInterface 29 | */ 30 | private $logger; 31 | 32 | /** 33 | * @var \PDO|null 34 | */ 35 | private $pdo = null; 36 | 37 | /** 38 | * @var ReleaseStateWriter|null 39 | */ 40 | private $releaseStateWriter = null; 41 | 42 | public function __construct( string $dbDsn ) { 43 | $this->dbDsn = $dbDsn; 44 | $this->logger = $this->newDefaultLogger(); 45 | } 46 | 47 | private function newDefaultLogger(): LoggerInterface { 48 | $logger = new Logger( 'Deployment logger' ); 49 | 50 | $streamHandler = new StreamHandler( 51 | $this->getLoggingPath() . '/error-debug.log' 52 | ); 53 | 54 | $fingersCrossedHandler = new FingersCrossedHandler( $streamHandler ); 55 | $streamHandler->setFormatter( new LineFormatter( LineFormatter::SIMPLE_FORMAT ) ); 56 | $logger->pushHandler( $fingersCrossedHandler ); 57 | 58 | $errorHandler = new StreamHandler( 59 | $this->getLoggingPath() . '/error.log', 60 | Logger::ERROR 61 | ); 62 | 63 | $errorHandler->setFormatter( new JsonFormatter() ); 64 | $logger->pushHandler( $errorHandler ); 65 | 66 | return $logger; 67 | } 68 | 69 | private function getLoggingPath(): string { 70 | return self::getVarPath() . '/log'; 71 | } 72 | 73 | private static function getVarPath(): string { 74 | return __DIR__ . '/../var'; 75 | } 76 | 77 | public function newDeployer( string $branchName ): Deployer { 78 | return new Deployer( 79 | $this->newReleaseRepository( $branchName ), 80 | function( string $releaseId, string $errorText ) { 81 | $this->logger->alert( 82 | 'Deployment failed', 83 | [ 84 | 'Release ID' => $releaseId, 85 | 'Command error output' => $errorText, 86 | ] 87 | ); 88 | } 89 | ); 90 | } 91 | 92 | private function newReleaseRepository( string $branchName ): ReleaseRepository { 93 | return new PdoReleaseRepository( $this->getPdo(), $branchName ); 94 | } 95 | 96 | public function getPdo(): \PDO { 97 | if ( $this->pdo === null ) { 98 | $this->pdo = new \PDO( $this->dbDsn ); 99 | } 100 | 101 | return $this->pdo; 102 | } 103 | 104 | public function getReleaseStateWriter(): ReleaseStateWriter { 105 | if ( $this->releaseStateWriter === null ) { 106 | $this->releaseStateWriter = new ReleaseStateWriter( $this->getPdo() ); 107 | } 108 | 109 | return $this->releaseStateWriter; 110 | } 111 | 112 | public function setReleaseStateWriter( ReleaseStateWriter $releaseStateWriter ) { 113 | $this->releaseStateWriter = $releaseStateWriter; 114 | } 115 | 116 | public function setLogger( LoggerInterface $logger ) { 117 | $this->logger = $logger; 118 | } 119 | 120 | } -------------------------------------------------------------------------------- /tests/Unit/DeployerTest.php: -------------------------------------------------------------------------------- 1 | createMock( ReleaseRepository::class ); 17 | $releaseState->method( 'hasUndeployedReleases' )->willReturn( false ); 18 | 19 | $process = $this->createMock( Process::class ); 20 | $process->expects( $this->never() ) 21 | ->method( 'run' ); 22 | 23 | $deployer = new Deployer( $releaseState ); 24 | $deployer->run( $process ); 25 | } 26 | 27 | public function testGivenReleaseForBranch_deployCommandIsExecuted() { 28 | $releaseState = $this->createDeployableReleaseState(); 29 | 30 | $process = $this->createMock( Process::class ); 31 | $process->expects( $this->once() ) 32 | ->method( 'run' ); 33 | 34 | $deployer = new Deployer( $releaseState ); 35 | $deployer->run( $process ); 36 | } 37 | 38 | public function testGivenReleaseInDeployment_deployCommandIsNotCalled() { 39 | $releaseState = $this->createMock( ReleaseRepository::class ); 40 | $releaseState->method( 'hasUndeployedReleases' )->willReturn( true ); 41 | $releaseState->method( 'deploymentInProcess' )->willReturn( true ); 42 | 43 | $process = $this->createMock( Process::class ); 44 | $process->expects( $this->never() ) 45 | ->method( 'run' ); 46 | 47 | $deployer = new Deployer( $releaseState ); 48 | $deployer->run( $process ); 49 | } 50 | 51 | public function testDeploymentWillBeStartedAndEnded() { 52 | $releaseState = $this->createDeployableReleaseState(); 53 | 54 | $releaseState->expects( $this->once() ) 55 | ->method( 'markDeploymentAsStarted' ) 56 | ->with( $this->equalTo( self::RELEASE_ID ) ); 57 | $releaseState->expects( $this->once() ) 58 | ->method( 'markDeploymentAsFinished' ) 59 | ->with( $this->equalTo( self::RELEASE_ID ) ); 60 | 61 | $deployer = new Deployer( $releaseState ); 62 | $deployer->run( $this->newSucceedingDeployProcess() ); 63 | } 64 | 65 | private function newSucceedingDeployProcess(): Process { 66 | $process = $this->createMock( Process::class ); 67 | $process->method( 'isSuccessful' )->willReturn( true ); 68 | return $process; 69 | } 70 | 71 | public function testWhenDeployProcessFails_releaseIsMarkedAsFailed() { 72 | $releaseState = $this->createDeployableReleaseState(); 73 | 74 | $releaseState->expects( $this->once() ) 75 | ->method( 'markDeploymentAsFailed' ) 76 | ->with( $this->equalTo( self::RELEASE_ID ) ); 77 | 78 | $deployer = new Deployer( $releaseState ); 79 | $deployer->run( $this->newFailingDeployProcess() ); 80 | } 81 | 82 | private function newFailingDeployProcess(): Process { 83 | $process = $this->createMock( Process::class ); 84 | 85 | $process->method( 'isSuccessful' )->willReturn( false ); 86 | $process->method( 'getErrorOutput' )->willReturn( self::PROCESS_ERROR_MESSAGE ); 87 | 88 | return $process; 89 | } 90 | 91 | /** 92 | * @return ReleaseRepository|\PHPUnit_Framework_MockObject_MockObject 93 | */ 94 | private function createDeployableReleaseState() { 95 | $releaseState = $this->createMock( ReleaseRepository::class ); 96 | $releaseState->method( 'hasUndeployedReleases' )->willReturn( true ); 97 | $releaseState->method( 'deploymentInProcess' )->willReturn( false ); 98 | $releaseState->method( 'getLatestReleaseId' )->willReturn( self::RELEASE_ID ); 99 | return $releaseState; 100 | } 101 | 102 | public function testWhenDeploymentFails_onDeploymentFailedCallbackGetsCalled() { 103 | $argumentsPassedToCallback = null; 104 | 105 | $onDeploymentFailedCallback = function() use ( &$argumentsPassedToCallback ) { 106 | $argumentsPassedToCallback = func_get_args(); 107 | }; 108 | 109 | $deployer = new Deployer( $this->createDeployableReleaseState(), $onDeploymentFailedCallback ); 110 | $deployer->run( $this->newFailingDeployProcess() ); 111 | 112 | $this->assertSame( 113 | [ self::RELEASE_ID, self::PROCESS_ERROR_MESSAGE ], 114 | $argumentsPassedToCallback 115 | ); 116 | } 117 | 118 | public function testWhenDeploymentSucceeds_onDeploymentFailedCallbackDoesNotGetCalled() { 119 | $deployer = new Deployer( 120 | $this->createDeployableReleaseState(), 121 | function() { 122 | $this->fail( 'Should not have been called' ); 123 | } 124 | ); 125 | 126 | $deployer->run( $this->newSucceedingDeployProcess() ); 127 | 128 | $this->assertTrue( (bool)'Sebastian does not like this' ); 129 | } 130 | 131 | } 132 | -------------------------------------------------------------------------------- /phpcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | app/ 8 | cli/ 9 | src/ 10 | tests/ 11 | web/ 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 0 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 0 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 0 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 0 116 | 117 | 118 | 119 | 120 | -------------------------------------------------------------------------------- /tests/Integration/PdoReleaseRepositoryTest.php: -------------------------------------------------------------------------------- 1 | getFactory(); 29 | $factory->getPdo()->setAttribute( \PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION ); 30 | 31 | $this->db = $factory->getPdo(); 32 | $this->releaseStateWriter = $factory->getReleaseStateWriter(); 33 | } 34 | 35 | public function testGivenNewRelaseState_itHasNoUndeployedReleases() { 36 | $releaseState = new PdoReleaseRepository( $this->db, self::BRANCH_NAME ); 37 | $this->assertFalse( $releaseState->hasUndeployedReleases() ); 38 | } 39 | 40 | public function testWhenAddingARelease_itIsUndeployed() { 41 | $releaseState = new PdoReleaseRepository( $this->db, self::BRANCH_NAME ); 42 | $this->insertFirstRelease(); 43 | 44 | $this->assertTrue( $releaseState->hasUndeployedReleases() ); 45 | } 46 | 47 | public function testWhenAddingARelease_deploymentInProcessReturnsFalse() { 48 | $releaseState = new PdoReleaseRepository( $this->db, self::BRANCH_NAME ); 49 | $this->insertFirstRelease(); 50 | 51 | $this->assertFalse( $releaseState->deploymentInProcess() ); 52 | } 53 | 54 | public function testGivenSeveralReleases_getLatestReleasesReturnsTheMostRecent() { 55 | $releaseState = new PdoReleaseRepository( $this->db, self::BRANCH_NAME ); 56 | $this->insertThreeReleases(); 57 | 58 | $this->assertEquals( self::THIRD_RELEASE, $releaseState->getLatestReleaseId() ); 59 | } 60 | 61 | public function testWhenAReleaseIsMarkedForDeployment_deploymentInProcessReturnsTrue() { 62 | $releaseState = new PdoReleaseRepository( $this->db, self::BRANCH_NAME ); 63 | $this->insertFirstRelease(); 64 | 65 | $releaseState->markDeploymentAsStarted( self::FIRST_RELEASE ); 66 | $this->assertTrue( $releaseState->deploymentInProcess() ); 67 | } 68 | 69 | public function testWhenAddingAndDeployingARelease_itIsNotUndeployed() { 70 | $releaseState = new PdoReleaseRepository( $this->db, self::BRANCH_NAME ); 71 | $this->insertFirstRelease(); 72 | $releaseState->markDeploymentAsStarted( self::FIRST_RELEASE ); 73 | 74 | $this->assertFalse( $releaseState->hasUndeployedReleases() ); 75 | } 76 | 77 | public function testWhenEndingADeployment_deploymentInProcessReturnsFalse() { 78 | $releaseState = new PdoReleaseRepository( $this->db, self::BRANCH_NAME ); 79 | $this->insertFirstRelease(); 80 | $releaseState->markDeploymentAsStarted( self::FIRST_RELEASE ); 81 | $releaseState->markDeploymentAsFinished( self::FIRST_RELEASE ); 82 | 83 | $this->assertFalse( $releaseState->deploymentInProcess() ); 84 | $this->assertFalse( $releaseState->hasUndeployedReleases() ); 85 | } 86 | 87 | public function testWhenEndingADeployment_previousUndeployedReleasesAreMarkedAsEnded() { 88 | $releaseState = new PdoReleaseRepository( $this->db, self::BRANCH_NAME ); 89 | $this->insertThreeReleases(); 90 | $releaseState->markDeploymentAsStarted( self::THIRD_RELEASE ); 91 | $releaseState->markDeploymentAsFinished( self::THIRD_RELEASE ); 92 | 93 | $this->assertFalse( $releaseState->deploymentInProcess() ); 94 | $this->assertFalse( $releaseState->hasUndeployedReleases() ); 95 | } 96 | 97 | public function testWhenEndingADeployment_subsequentReleasesAreNotTouched() { 98 | $releaseState = new PdoReleaseRepository( $this->db, self::BRANCH_NAME ); 99 | $this->insertThreeReleases(); 100 | $releaseState->markDeploymentAsStarted( self::SECOND_RELEASE ); 101 | $releaseState->markDeploymentAsFinished( self::SECOND_RELEASE ); 102 | 103 | $this->assertFalse( $releaseState->deploymentInProcess() ); 104 | $this->assertTrue( $releaseState->hasUndeployedReleases() ); 105 | $this->assertEquals( self::THIRD_RELEASE, $releaseState->getLatestReleaseId() ); 106 | } 107 | 108 | public function testWhenMarkingADeploymentAsFailed_ItCanBeDeployedAgain() { 109 | $releaseState = new PdoReleaseRepository( $this->db, self::BRANCH_NAME ); 110 | $this->insertFirstRelease(); 111 | $releaseState->markDeploymentAsStarted( self::FIRST_RELEASE ); 112 | $releaseState->markDeploymentAsFailed( self::FIRST_RELEASE ); 113 | 114 | $this->assertFalse( $releaseState->deploymentInProcess() ); 115 | $this->assertTrue( $releaseState->hasUndeployedReleases() ); 116 | } 117 | 118 | private function insertFirstRelease() { 119 | $this->releaseStateWriter->addRelease( self::BRANCH_NAME, self::FIRST_RELEASE ); 120 | } 121 | 122 | private function insertThreeReleases() { 123 | $this->releaseStateWriter->addRelease( self::BRANCH_NAME, self::FIRST_RELEASE, '2016-01-02 09:00:00' ); 124 | $this->releaseStateWriter->addRelease( self::BRANCH_NAME, self::SECOND_RELEASE, '2016-01-02 10:00:00' ); 125 | $this->releaseStateWriter->addRelease( self::BRANCH_NAME, self::THIRD_RELEASE, '2016-01-02 11:00:00' ); 126 | } 127 | 128 | } 129 | -------------------------------------------------------------------------------- /tests/files/push-payload.json: -------------------------------------------------------------------------------- 1 | { 2 | "ref": "refs/heads/master", 3 | "before": "9049f1265b7d61be4a8904a9a27120d2064dab3b", 4 | "after": "0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c", 5 | "created": false, 6 | "deleted": false, 7 | "forced": false, 8 | "base_ref": null, 9 | "compare": "https://github.com/wmde/FundraisingFrontend/compare/9049f1265b7d...0d1a26e67d8f", 10 | "commits": [ 11 | { 12 | "id": "0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c", 13 | "tree_id": "f9d2a07e9488b91af2641b26b9407fe22a451433", 14 | "distinct": true, 15 | "message": "Update README.md", 16 | "timestamp": "2015-05-05T19:40:15-04:00", 17 | "url": "https://github.com/wmde/FundraisingFrontend/commit/0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c", 18 | "author": { 19 | "name": "baxterthehacker", 20 | "email": "baxterthehacker@users.noreply.github.com", 21 | "username": "baxterthehacker" 22 | }, 23 | "committer": { 24 | "name": "baxterthehacker", 25 | "email": "baxterthehacker@users.noreply.github.com", 26 | "username": "baxterthehacker" 27 | }, 28 | "added": [ 29 | 30 | ], 31 | "removed": [ 32 | 33 | ], 34 | "modified": [ 35 | "README.md" 36 | ] 37 | } 38 | ], 39 | "head_commit": { 40 | "id": "0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c", 41 | "tree_id": "f9d2a07e9488b91af2641b26b9407fe22a451433", 42 | "distinct": true, 43 | "message": "Update README.md", 44 | "timestamp": "2015-05-05T19:40:15-04:00", 45 | "url": "https://github.com/wmde/FundraisingFrontend/commit/0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c", 46 | "author": { 47 | "name": "baxterthehacker", 48 | "email": "baxterthehacker@users.noreply.github.com", 49 | "username": "baxterthehacker" 50 | }, 51 | "committer": { 52 | "name": "baxterthehacker", 53 | "email": "baxterthehacker@users.noreply.github.com", 54 | "username": "baxterthehacker" 55 | }, 56 | "added": [ 57 | 58 | ], 59 | "removed": [ 60 | 61 | ], 62 | "modified": [ 63 | "README.md" 64 | ] 65 | }, 66 | "repository": { 67 | "id": 35129377, 68 | "name": "public-repo", 69 | "full_name": "wmde/FundraisingFrontend", 70 | "owner": { 71 | "name": "baxterthehacker", 72 | "email": "baxterthehacker@users.noreply.github.com" 73 | }, 74 | "private": false, 75 | "html_url": "https://github.com/wmde/FundraisingFrontend", 76 | "description": "", 77 | "fork": false, 78 | "url": "https://github.com/wmde/FundraisingFrontend", 79 | "forks_url": "https://api.github.com/repos/wmde/FundraisingFrontend/forks", 80 | "keys_url": "https://api.github.com/repos/wmde/FundraisingFrontend/keys{/key_id}", 81 | "collaborators_url": "https://api.github.com/repos/wmde/FundraisingFrontend/collaborators{/collaborator}", 82 | "teams_url": "https://api.github.com/repos/wmde/FundraisingFrontend/teams", 83 | "hooks_url": "https://api.github.com/repos/wmde/FundraisingFrontend/hooks", 84 | "issue_events_url": "https://api.github.com/repos/wmde/FundraisingFrontend/issues/events{/number}", 85 | "events_url": "https://api.github.com/repos/wmde/FundraisingFrontend/events", 86 | "assignees_url": "https://api.github.com/repos/wmde/FundraisingFrontend/assignees{/user}", 87 | "branches_url": "https://api.github.com/repos/wmde/FundraisingFrontend/branches{/branch}", 88 | "tags_url": "https://api.github.com/repos/wmde/FundraisingFrontend/tags", 89 | "blobs_url": "https://api.github.com/repos/wmde/FundraisingFrontend/git/blobs{/sha}", 90 | "git_tags_url": "https://api.github.com/repos/wmde/FundraisingFrontend/git/tags{/sha}", 91 | "git_refs_url": "https://api.github.com/repos/wmde/FundraisingFrontend/git/refs{/sha}", 92 | "trees_url": "https://api.github.com/repos/wmde/FundraisingFrontend/git/trees{/sha}", 93 | "statuses_url": "https://api.github.com/repos/wmde/FundraisingFrontend/statuses/{sha}", 94 | "languages_url": "https://api.github.com/repos/wmde/FundraisingFrontend/languages", 95 | "stargazers_url": "https://api.github.com/repos/wmde/FundraisingFrontend/stargazers", 96 | "contributors_url": "https://api.github.com/repos/wmde/FundraisingFrontend/contributors", 97 | "subscribers_url": "https://api.github.com/repos/wmde/FundraisingFrontend/subscribers", 98 | "subscription_url": "https://api.github.com/repos/wmde/FundraisingFrontend/subscription", 99 | "commits_url": "https://api.github.com/repos/wmde/FundraisingFrontend/commits{/sha}", 100 | "git_commits_url": "https://api.github.com/repos/wmde/FundraisingFrontend/git/commits{/sha}", 101 | "comments_url": "https://api.github.com/repos/wmde/FundraisingFrontend/comments{/number}", 102 | "issue_comment_url": "https://api.github.com/repos/wmde/FundraisingFrontend/issues/comments{/number}", 103 | "contents_url": "https://api.github.com/repos/wmde/FundraisingFrontend/contents/{+path}", 104 | "compare_url": "https://api.github.com/repos/wmde/FundraisingFrontend/compare/{base}...{head}", 105 | "merges_url": "https://api.github.com/repos/wmde/FundraisingFrontend/merges", 106 | "archive_url": "https://api.github.com/repos/wmde/FundraisingFrontend/{archive_format}{/ref}", 107 | "downloads_url": "https://api.github.com/repos/wmde/FundraisingFrontend/downloads", 108 | "issues_url": "https://api.github.com/repos/wmde/FundraisingFrontend/issues{/number}", 109 | "pulls_url": "https://api.github.com/repos/wmde/FundraisingFrontend/pulls{/number}", 110 | "milestones_url": "https://api.github.com/repos/wmde/FundraisingFrontend/milestones{/number}", 111 | "notifications_url": "https://api.github.com/repos/wmde/FundraisingFrontend/notifications{?since,all,participating}", 112 | "labels_url": "https://api.github.com/repos/wmde/FundraisingFrontend/labels{/name}", 113 | "releases_url": "https://api.github.com/repos/wmde/FundraisingFrontend/releases{/id}", 114 | "created_at": 1430869212, 115 | "updated_at": "2015-05-05T23:40:12Z", 116 | "pushed_at": 1430869217, 117 | "git_url": "git://github.com/wmde/FundraisingFrontend.git", 118 | "ssh_url": "git@github.com:wmde/FundraisingFrontend.git", 119 | "clone_url": "https://github.com/wmde/FundraisingFrontend.git", 120 | "svn_url": "https://github.com/wmde/FundraisingFrontend", 121 | "homepage": null, 122 | "size": 0, 123 | "stargazers_count": 0, 124 | "watchers_count": 0, 125 | "language": null, 126 | "has_issues": true, 127 | "has_downloads": true, 128 | "has_wiki": true, 129 | "has_pages": true, 130 | "forks_count": 0, 131 | "mirror_url": null, 132 | "open_issues_count": 0, 133 | "forks": 0, 134 | "open_issues": 0, 135 | "watchers": 0, 136 | "default_branch": "master", 137 | "stargazers": 0, 138 | "master_branch": "master" 139 | }, 140 | "pusher": { 141 | "name": "baxterthehacker", 142 | "email": "baxterthehacker@users.noreply.github.com" 143 | }, 144 | "sender": { 145 | "login": "baxterthehacker", 146 | "id": 6752317, 147 | "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", 148 | "gravatar_id": "", 149 | "url": "https://api.github.com/users/baxterthehacker", 150 | "html_url": "https://github.com/baxterthehacker", 151 | "followers_url": "https://api.github.com/users/baxterthehacker/followers", 152 | "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", 153 | "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", 154 | "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", 155 | "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", 156 | "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", 157 | "repos_url": "https://api.github.com/users/baxterthehacker/repos", 158 | "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", 159 | "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", 160 | "type": "User", 161 | "site_admin": false 162 | } 163 | } -------------------------------------------------------------------------------- /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#composer-lock-the-lock-file", 5 | "This file is @generated automatically" 6 | ], 7 | "content-hash": "5f37067ae2a887b246925109ee88b28f", 8 | "packages": [ 9 | { 10 | "name": "monolog/monolog", 11 | "version": "1.22.1", 12 | "source": { 13 | "type": "git", 14 | "url": "https://github.com/Seldaek/monolog.git", 15 | "reference": "1e044bc4b34e91743943479f1be7a1d5eb93add0" 16 | }, 17 | "dist": { 18 | "type": "zip", 19 | "url": "https://api.github.com/repos/Seldaek/monolog/zipball/1e044bc4b34e91743943479f1be7a1d5eb93add0", 20 | "reference": "1e044bc4b34e91743943479f1be7a1d5eb93add0", 21 | "shasum": "" 22 | }, 23 | "require": { 24 | "php": ">=5.3.0", 25 | "psr/log": "~1.0" 26 | }, 27 | "provide": { 28 | "psr/log-implementation": "1.0.0" 29 | }, 30 | "require-dev": { 31 | "aws/aws-sdk-php": "^2.4.9 || ^3.0", 32 | "doctrine/couchdb": "~1.0@dev", 33 | "graylog2/gelf-php": "~1.0", 34 | "jakub-onderka/php-parallel-lint": "0.9", 35 | "php-amqplib/php-amqplib": "~2.4", 36 | "php-console/php-console": "^3.1.3", 37 | "phpunit/phpunit": "~4.5", 38 | "phpunit/phpunit-mock-objects": "2.3.0", 39 | "ruflin/elastica": ">=0.90 <3.0", 40 | "sentry/sentry": "^0.13", 41 | "swiftmailer/swiftmailer": "~5.3" 42 | }, 43 | "suggest": { 44 | "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", 45 | "doctrine/couchdb": "Allow sending log messages to a CouchDB server", 46 | "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", 47 | "ext-mongo": "Allow sending log messages to a MongoDB server", 48 | "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", 49 | "mongodb/mongodb": "Allow sending log messages to a MongoDB server via PHP Driver", 50 | "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", 51 | "php-console/php-console": "Allow sending log messages to Google Chrome", 52 | "rollbar/rollbar": "Allow sending log messages to Rollbar", 53 | "ruflin/elastica": "Allow sending log messages to an Elastic Search server", 54 | "sentry/sentry": "Allow sending log messages to a Sentry server" 55 | }, 56 | "type": "library", 57 | "extra": { 58 | "branch-alias": { 59 | "dev-master": "2.0.x-dev" 60 | } 61 | }, 62 | "autoload": { 63 | "psr-4": { 64 | "Monolog\\": "src/Monolog" 65 | } 66 | }, 67 | "notification-url": "https://packagist.org/downloads/", 68 | "license": [ 69 | "MIT" 70 | ], 71 | "authors": [ 72 | { 73 | "name": "Jordi Boggiano", 74 | "email": "j.boggiano@seld.be", 75 | "homepage": "http://seld.be" 76 | } 77 | ], 78 | "description": "Sends your logs to files, sockets, inboxes, databases and various web services", 79 | "homepage": "http://github.com/Seldaek/monolog", 80 | "keywords": [ 81 | "log", 82 | "logging", 83 | "psr-3" 84 | ], 85 | "time": "2017-03-13T07:08:03+00:00" 86 | }, 87 | { 88 | "name": "pimple/pimple", 89 | "version": "v3.0.2", 90 | "source": { 91 | "type": "git", 92 | "url": "https://github.com/silexphp/Pimple.git", 93 | "reference": "a30f7d6e57565a2e1a316e1baf2a483f788b258a" 94 | }, 95 | "dist": { 96 | "type": "zip", 97 | "url": "https://api.github.com/repos/silexphp/Pimple/zipball/a30f7d6e57565a2e1a316e1baf2a483f788b258a", 98 | "reference": "a30f7d6e57565a2e1a316e1baf2a483f788b258a", 99 | "shasum": "" 100 | }, 101 | "require": { 102 | "php": ">=5.3.0" 103 | }, 104 | "type": "library", 105 | "extra": { 106 | "branch-alias": { 107 | "dev-master": "3.0.x-dev" 108 | } 109 | }, 110 | "autoload": { 111 | "psr-0": { 112 | "Pimple": "src/" 113 | } 114 | }, 115 | "notification-url": "https://packagist.org/downloads/", 116 | "license": [ 117 | "MIT" 118 | ], 119 | "authors": [ 120 | { 121 | "name": "Fabien Potencier", 122 | "email": "fabien@symfony.com" 123 | } 124 | ], 125 | "description": "Pimple, a simple Dependency Injection Container", 126 | "homepage": "http://pimple.sensiolabs.org", 127 | "keywords": [ 128 | "container", 129 | "dependency injection" 130 | ], 131 | "time": "2015-09-11T15:10:35+00:00" 132 | }, 133 | { 134 | "name": "psr/log", 135 | "version": "1.0.2", 136 | "source": { 137 | "type": "git", 138 | "url": "https://github.com/php-fig/log.git", 139 | "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d" 140 | }, 141 | "dist": { 142 | "type": "zip", 143 | "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", 144 | "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", 145 | "shasum": "" 146 | }, 147 | "require": { 148 | "php": ">=5.3.0" 149 | }, 150 | "type": "library", 151 | "extra": { 152 | "branch-alias": { 153 | "dev-master": "1.0.x-dev" 154 | } 155 | }, 156 | "autoload": { 157 | "psr-4": { 158 | "Psr\\Log\\": "Psr/Log/" 159 | } 160 | }, 161 | "notification-url": "https://packagist.org/downloads/", 162 | "license": [ 163 | "MIT" 164 | ], 165 | "authors": [ 166 | { 167 | "name": "PHP-FIG", 168 | "homepage": "http://www.php-fig.org/" 169 | } 170 | ], 171 | "description": "Common interface for logging libraries", 172 | "homepage": "https://github.com/php-fig/log", 173 | "keywords": [ 174 | "log", 175 | "psr", 176 | "psr-3" 177 | ], 178 | "time": "2016-10-10T12:19:37+00:00" 179 | }, 180 | { 181 | "name": "silex/silex", 182 | "version": "v2.1.0", 183 | "source": { 184 | "type": "git", 185 | "url": "https://github.com/silexphp/Silex.git", 186 | "reference": "d5a9d9af14a1424ddecc3da481769cf64e7d3b34" 187 | }, 188 | "dist": { 189 | "type": "zip", 190 | "url": "https://api.github.com/repos/silexphp/Silex/zipball/d5a9d9af14a1424ddecc3da481769cf64e7d3b34", 191 | "reference": "d5a9d9af14a1424ddecc3da481769cf64e7d3b34", 192 | "shasum": "" 193 | }, 194 | "require": { 195 | "php": ">=5.5.9", 196 | "pimple/pimple": "~3.0", 197 | "symfony/event-dispatcher": "~2.8|^3.0", 198 | "symfony/http-foundation": "~2.8|^3.0", 199 | "symfony/http-kernel": "~2.8|^3.0", 200 | "symfony/routing": "~2.8|^3.0" 201 | }, 202 | "replace": { 203 | "silex/api": "self.version", 204 | "silex/providers": "self.version" 205 | }, 206 | "require-dev": { 207 | "doctrine/dbal": "~2.2", 208 | "monolog/monolog": "^1.4.1", 209 | "swiftmailer/swiftmailer": "~5", 210 | "symfony/asset": "~2.8|^3.0", 211 | "symfony/browser-kit": "~2.8|^3.0", 212 | "symfony/config": "~2.8|^3.0", 213 | "symfony/css-selector": "~2.8|^3.0", 214 | "symfony/debug": "~2.8|^3.0", 215 | "symfony/doctrine-bridge": "~2.8|^3.0", 216 | "symfony/dom-crawler": "~2.8|^3.0", 217 | "symfony/expression-language": "~2.8|^3.0", 218 | "symfony/finder": "~2.8|^3.0", 219 | "symfony/form": "~2.8|^3.0", 220 | "symfony/intl": "~2.8|^3.0", 221 | "symfony/monolog-bridge": "~2.8|^3.0", 222 | "symfony/options-resolver": "~2.8|^3.0", 223 | "symfony/phpunit-bridge": "^3.2", 224 | "symfony/process": "~2.8|^3.0", 225 | "symfony/security": "~2.8|^3.0", 226 | "symfony/serializer": "~2.8|^3.0", 227 | "symfony/translation": "~2.8|^3.0", 228 | "symfony/twig-bridge": "~2.8|^3.0", 229 | "symfony/validator": "~2.8|^3.0", 230 | "symfony/var-dumper": "~2.8|^3.0", 231 | "symfony/web-link": "^3.3", 232 | "twig/twig": "~1.28|~2.0" 233 | }, 234 | "type": "library", 235 | "extra": { 236 | "branch-alias": { 237 | "dev-master": "2.1.x-dev" 238 | } 239 | }, 240 | "autoload": { 241 | "psr-4": { 242 | "Silex\\": "src/Silex" 243 | } 244 | }, 245 | "notification-url": "https://packagist.org/downloads/", 246 | "license": [ 247 | "MIT" 248 | ], 249 | "authors": [ 250 | { 251 | "name": "Fabien Potencier", 252 | "email": "fabien@symfony.com" 253 | }, 254 | { 255 | "name": "Igor Wiedler", 256 | "email": "igor@wiedler.ch" 257 | } 258 | ], 259 | "description": "The PHP micro-framework based on the Symfony Components", 260 | "homepage": "http://silex.sensiolabs.org", 261 | "keywords": [ 262 | "microframework" 263 | ], 264 | "time": "2017-05-03T15:21:42+00:00" 265 | }, 266 | { 267 | "name": "symfony/debug", 268 | "version": "v3.2.8", 269 | "source": { 270 | "type": "git", 271 | "url": "https://github.com/symfony/debug.git", 272 | "reference": "fd6eeee656a5a7b384d56f1072243fe1c0e81686" 273 | }, 274 | "dist": { 275 | "type": "zip", 276 | "url": "https://api.github.com/repos/symfony/debug/zipball/fd6eeee656a5a7b384d56f1072243fe1c0e81686", 277 | "reference": "fd6eeee656a5a7b384d56f1072243fe1c0e81686", 278 | "shasum": "" 279 | }, 280 | "require": { 281 | "php": ">=5.5.9", 282 | "psr/log": "~1.0" 283 | }, 284 | "conflict": { 285 | "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2" 286 | }, 287 | "require-dev": { 288 | "symfony/class-loader": "~2.8|~3.0", 289 | "symfony/http-kernel": "~2.8|~3.0" 290 | }, 291 | "type": "library", 292 | "extra": { 293 | "branch-alias": { 294 | "dev-master": "3.2-dev" 295 | } 296 | }, 297 | "autoload": { 298 | "psr-4": { 299 | "Symfony\\Component\\Debug\\": "" 300 | }, 301 | "exclude-from-classmap": [ 302 | "/Tests/" 303 | ] 304 | }, 305 | "notification-url": "https://packagist.org/downloads/", 306 | "license": [ 307 | "MIT" 308 | ], 309 | "authors": [ 310 | { 311 | "name": "Fabien Potencier", 312 | "email": "fabien@symfony.com" 313 | }, 314 | { 315 | "name": "Symfony Community", 316 | "homepage": "https://symfony.com/contributors" 317 | } 318 | ], 319 | "description": "Symfony Debug Component", 320 | "homepage": "https://symfony.com", 321 | "time": "2017-04-19T20:17:50+00:00" 322 | }, 323 | { 324 | "name": "symfony/event-dispatcher", 325 | "version": "v3.2.8", 326 | "source": { 327 | "type": "git", 328 | "url": "https://github.com/symfony/event-dispatcher.git", 329 | "reference": "b8a401f733b43251e1d088c589368b2a94155e40" 330 | }, 331 | "dist": { 332 | "type": "zip", 333 | "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/b8a401f733b43251e1d088c589368b2a94155e40", 334 | "reference": "b8a401f733b43251e1d088c589368b2a94155e40", 335 | "shasum": "" 336 | }, 337 | "require": { 338 | "php": ">=5.5.9" 339 | }, 340 | "require-dev": { 341 | "psr/log": "~1.0", 342 | "symfony/config": "~2.8|~3.0", 343 | "symfony/dependency-injection": "~2.8|~3.0", 344 | "symfony/expression-language": "~2.8|~3.0", 345 | "symfony/stopwatch": "~2.8|~3.0" 346 | }, 347 | "suggest": { 348 | "symfony/dependency-injection": "", 349 | "symfony/http-kernel": "" 350 | }, 351 | "type": "library", 352 | "extra": { 353 | "branch-alias": { 354 | "dev-master": "3.2-dev" 355 | } 356 | }, 357 | "autoload": { 358 | "psr-4": { 359 | "Symfony\\Component\\EventDispatcher\\": "" 360 | }, 361 | "exclude-from-classmap": [ 362 | "/Tests/" 363 | ] 364 | }, 365 | "notification-url": "https://packagist.org/downloads/", 366 | "license": [ 367 | "MIT" 368 | ], 369 | "authors": [ 370 | { 371 | "name": "Fabien Potencier", 372 | "email": "fabien@symfony.com" 373 | }, 374 | { 375 | "name": "Symfony Community", 376 | "homepage": "https://symfony.com/contributors" 377 | } 378 | ], 379 | "description": "Symfony EventDispatcher Component", 380 | "homepage": "https://symfony.com", 381 | "time": "2017-05-01T14:58:48+00:00" 382 | }, 383 | { 384 | "name": "symfony/http-foundation", 385 | "version": "v3.2.8", 386 | "source": { 387 | "type": "git", 388 | "url": "https://github.com/symfony/http-foundation.git", 389 | "reference": "9de6add7f731e5af7f5b2e9c0da365e43383ebef" 390 | }, 391 | "dist": { 392 | "type": "zip", 393 | "url": "https://api.github.com/repos/symfony/http-foundation/zipball/9de6add7f731e5af7f5b2e9c0da365e43383ebef", 394 | "reference": "9de6add7f731e5af7f5b2e9c0da365e43383ebef", 395 | "shasum": "" 396 | }, 397 | "require": { 398 | "php": ">=5.5.9", 399 | "symfony/polyfill-mbstring": "~1.1" 400 | }, 401 | "require-dev": { 402 | "symfony/expression-language": "~2.8|~3.0" 403 | }, 404 | "type": "library", 405 | "extra": { 406 | "branch-alias": { 407 | "dev-master": "3.2-dev" 408 | } 409 | }, 410 | "autoload": { 411 | "psr-4": { 412 | "Symfony\\Component\\HttpFoundation\\": "" 413 | }, 414 | "exclude-from-classmap": [ 415 | "/Tests/" 416 | ] 417 | }, 418 | "notification-url": "https://packagist.org/downloads/", 419 | "license": [ 420 | "MIT" 421 | ], 422 | "authors": [ 423 | { 424 | "name": "Fabien Potencier", 425 | "email": "fabien@symfony.com" 426 | }, 427 | { 428 | "name": "Symfony Community", 429 | "homepage": "https://symfony.com/contributors" 430 | } 431 | ], 432 | "description": "Symfony HttpFoundation Component", 433 | "homepage": "https://symfony.com", 434 | "time": "2017-05-01T14:55:58+00:00" 435 | }, 436 | { 437 | "name": "symfony/http-kernel", 438 | "version": "v3.2.8", 439 | "source": { 440 | "type": "git", 441 | "url": "https://github.com/symfony/http-kernel.git", 442 | "reference": "46e8b209abab55c072c47d72d5cd1d62c0585e05" 443 | }, 444 | "dist": { 445 | "type": "zip", 446 | "url": "https://api.github.com/repos/symfony/http-kernel/zipball/46e8b209abab55c072c47d72d5cd1d62c0585e05", 447 | "reference": "46e8b209abab55c072c47d72d5cd1d62c0585e05", 448 | "shasum": "" 449 | }, 450 | "require": { 451 | "php": ">=5.5.9", 452 | "psr/log": "~1.0", 453 | "symfony/debug": "~2.8|~3.0", 454 | "symfony/event-dispatcher": "~2.8|~3.0", 455 | "symfony/http-foundation": "~2.8.13|~3.1.6|~3.2" 456 | }, 457 | "conflict": { 458 | "symfony/config": "<2.8" 459 | }, 460 | "require-dev": { 461 | "symfony/browser-kit": "~2.8|~3.0", 462 | "symfony/class-loader": "~2.8|~3.0", 463 | "symfony/config": "~2.8|~3.0", 464 | "symfony/console": "~2.8|~3.0", 465 | "symfony/css-selector": "~2.8|~3.0", 466 | "symfony/dependency-injection": "~2.8|~3.0", 467 | "symfony/dom-crawler": "~2.8|~3.0", 468 | "symfony/expression-language": "~2.8|~3.0", 469 | "symfony/finder": "~2.8|~3.0", 470 | "symfony/process": "~2.8|~3.0", 471 | "symfony/routing": "~2.8|~3.0", 472 | "symfony/stopwatch": "~2.8|~3.0", 473 | "symfony/templating": "~2.8|~3.0", 474 | "symfony/translation": "~2.8|~3.0", 475 | "symfony/var-dumper": "~3.2" 476 | }, 477 | "suggest": { 478 | "symfony/browser-kit": "", 479 | "symfony/class-loader": "", 480 | "symfony/config": "", 481 | "symfony/console": "", 482 | "symfony/dependency-injection": "", 483 | "symfony/finder": "", 484 | "symfony/var-dumper": "" 485 | }, 486 | "type": "library", 487 | "extra": { 488 | "branch-alias": { 489 | "dev-master": "3.2-dev" 490 | } 491 | }, 492 | "autoload": { 493 | "psr-4": { 494 | "Symfony\\Component\\HttpKernel\\": "" 495 | }, 496 | "exclude-from-classmap": [ 497 | "/Tests/" 498 | ] 499 | }, 500 | "notification-url": "https://packagist.org/downloads/", 501 | "license": [ 502 | "MIT" 503 | ], 504 | "authors": [ 505 | { 506 | "name": "Fabien Potencier", 507 | "email": "fabien@symfony.com" 508 | }, 509 | { 510 | "name": "Symfony Community", 511 | "homepage": "https://symfony.com/contributors" 512 | } 513 | ], 514 | "description": "Symfony HttpKernel Component", 515 | "homepage": "https://symfony.com", 516 | "time": "2017-05-01T17:46:48+00:00" 517 | }, 518 | { 519 | "name": "symfony/polyfill-mbstring", 520 | "version": "v1.3.0", 521 | "source": { 522 | "type": "git", 523 | "url": "https://github.com/symfony/polyfill-mbstring.git", 524 | "reference": "e79d363049d1c2128f133a2667e4f4190904f7f4" 525 | }, 526 | "dist": { 527 | "type": "zip", 528 | "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/e79d363049d1c2128f133a2667e4f4190904f7f4", 529 | "reference": "e79d363049d1c2128f133a2667e4f4190904f7f4", 530 | "shasum": "" 531 | }, 532 | "require": { 533 | "php": ">=5.3.3" 534 | }, 535 | "suggest": { 536 | "ext-mbstring": "For best performance" 537 | }, 538 | "type": "library", 539 | "extra": { 540 | "branch-alias": { 541 | "dev-master": "1.3-dev" 542 | } 543 | }, 544 | "autoload": { 545 | "psr-4": { 546 | "Symfony\\Polyfill\\Mbstring\\": "" 547 | }, 548 | "files": [ 549 | "bootstrap.php" 550 | ] 551 | }, 552 | "notification-url": "https://packagist.org/downloads/", 553 | "license": [ 554 | "MIT" 555 | ], 556 | "authors": [ 557 | { 558 | "name": "Nicolas Grekas", 559 | "email": "p@tchwork.com" 560 | }, 561 | { 562 | "name": "Symfony Community", 563 | "homepage": "https://symfony.com/contributors" 564 | } 565 | ], 566 | "description": "Symfony polyfill for the Mbstring extension", 567 | "homepage": "https://symfony.com", 568 | "keywords": [ 569 | "compatibility", 570 | "mbstring", 571 | "polyfill", 572 | "portable", 573 | "shim" 574 | ], 575 | "time": "2016-11-14T01:06:16+00:00" 576 | }, 577 | { 578 | "name": "symfony/process", 579 | "version": "v3.2.8", 580 | "source": { 581 | "type": "git", 582 | "url": "https://github.com/symfony/process.git", 583 | "reference": "999c2cf5061e627e6cd551dc9ebf90dd1d11d9f0" 584 | }, 585 | "dist": { 586 | "type": "zip", 587 | "url": "https://api.github.com/repos/symfony/process/zipball/999c2cf5061e627e6cd551dc9ebf90dd1d11d9f0", 588 | "reference": "999c2cf5061e627e6cd551dc9ebf90dd1d11d9f0", 589 | "shasum": "" 590 | }, 591 | "require": { 592 | "php": ">=5.5.9" 593 | }, 594 | "type": "library", 595 | "extra": { 596 | "branch-alias": { 597 | "dev-master": "3.2-dev" 598 | } 599 | }, 600 | "autoload": { 601 | "psr-4": { 602 | "Symfony\\Component\\Process\\": "" 603 | }, 604 | "exclude-from-classmap": [ 605 | "/Tests/" 606 | ] 607 | }, 608 | "notification-url": "https://packagist.org/downloads/", 609 | "license": [ 610 | "MIT" 611 | ], 612 | "authors": [ 613 | { 614 | "name": "Fabien Potencier", 615 | "email": "fabien@symfony.com" 616 | }, 617 | { 618 | "name": "Symfony Community", 619 | "homepage": "https://symfony.com/contributors" 620 | } 621 | ], 622 | "description": "Symfony Process Component", 623 | "homepage": "https://symfony.com", 624 | "time": "2017-04-12T14:13:17+00:00" 625 | }, 626 | { 627 | "name": "symfony/routing", 628 | "version": "v3.2.8", 629 | "source": { 630 | "type": "git", 631 | "url": "https://github.com/symfony/routing.git", 632 | "reference": "5029745d6d463585e8b487dbc83d6333f408853a" 633 | }, 634 | "dist": { 635 | "type": "zip", 636 | "url": "https://api.github.com/repos/symfony/routing/zipball/5029745d6d463585e8b487dbc83d6333f408853a", 637 | "reference": "5029745d6d463585e8b487dbc83d6333f408853a", 638 | "shasum": "" 639 | }, 640 | "require": { 641 | "php": ">=5.5.9" 642 | }, 643 | "conflict": { 644 | "symfony/config": "<2.8" 645 | }, 646 | "require-dev": { 647 | "doctrine/annotations": "~1.0", 648 | "doctrine/common": "~2.2", 649 | "psr/log": "~1.0", 650 | "symfony/config": "~2.8|~3.0", 651 | "symfony/expression-language": "~2.8|~3.0", 652 | "symfony/http-foundation": "~2.8|~3.0", 653 | "symfony/yaml": "~2.8|~3.0" 654 | }, 655 | "suggest": { 656 | "doctrine/annotations": "For using the annotation loader", 657 | "symfony/config": "For using the all-in-one router or any loader", 658 | "symfony/dependency-injection": "For loading routes from a service", 659 | "symfony/expression-language": "For using expression matching", 660 | "symfony/http-foundation": "For using a Symfony Request object", 661 | "symfony/yaml": "For using the YAML loader" 662 | }, 663 | "type": "library", 664 | "extra": { 665 | "branch-alias": { 666 | "dev-master": "3.2-dev" 667 | } 668 | }, 669 | "autoload": { 670 | "psr-4": { 671 | "Symfony\\Component\\Routing\\": "" 672 | }, 673 | "exclude-from-classmap": [ 674 | "/Tests/" 675 | ] 676 | }, 677 | "notification-url": "https://packagist.org/downloads/", 678 | "license": [ 679 | "MIT" 680 | ], 681 | "authors": [ 682 | { 683 | "name": "Fabien Potencier", 684 | "email": "fabien@symfony.com" 685 | }, 686 | { 687 | "name": "Symfony Community", 688 | "homepage": "https://symfony.com/contributors" 689 | } 690 | ], 691 | "description": "Symfony Routing Component", 692 | "homepage": "https://symfony.com", 693 | "keywords": [ 694 | "router", 695 | "routing", 696 | "uri", 697 | "url" 698 | ], 699 | "time": "2017-04-12T14:13:17+00:00" 700 | } 701 | ], 702 | "packages-dev": [ 703 | { 704 | "name": "doctrine/instantiator", 705 | "version": "1.0.5", 706 | "source": { 707 | "type": "git", 708 | "url": "https://github.com/doctrine/instantiator.git", 709 | "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" 710 | }, 711 | "dist": { 712 | "type": "zip", 713 | "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", 714 | "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", 715 | "shasum": "" 716 | }, 717 | "require": { 718 | "php": ">=5.3,<8.0-DEV" 719 | }, 720 | "require-dev": { 721 | "athletic/athletic": "~0.1.8", 722 | "ext-pdo": "*", 723 | "ext-phar": "*", 724 | "phpunit/phpunit": "~4.0", 725 | "squizlabs/php_codesniffer": "~2.0" 726 | }, 727 | "type": "library", 728 | "extra": { 729 | "branch-alias": { 730 | "dev-master": "1.0.x-dev" 731 | } 732 | }, 733 | "autoload": { 734 | "psr-4": { 735 | "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" 736 | } 737 | }, 738 | "notification-url": "https://packagist.org/downloads/", 739 | "license": [ 740 | "MIT" 741 | ], 742 | "authors": [ 743 | { 744 | "name": "Marco Pivetta", 745 | "email": "ocramius@gmail.com", 746 | "homepage": "http://ocramius.github.com/" 747 | } 748 | ], 749 | "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", 750 | "homepage": "https://github.com/doctrine/instantiator", 751 | "keywords": [ 752 | "constructor", 753 | "instantiate" 754 | ], 755 | "time": "2015-06-14T21:17:01+00:00" 756 | }, 757 | { 758 | "name": "mediawiki/mediawiki-codesniffer", 759 | "version": "v0.8.0", 760 | "source": { 761 | "type": "git", 762 | "url": "https://github.com/wikimedia/mediawiki-tools-codesniffer.git", 763 | "reference": "439149cc2fe5ccc29aadfd49ce22c36122d51c4c" 764 | }, 765 | "dist": { 766 | "type": "zip", 767 | "url": "https://api.github.com/repos/wikimedia/mediawiki-tools-codesniffer/zipball/439149cc2fe5ccc29aadfd49ce22c36122d51c4c", 768 | "reference": "439149cc2fe5ccc29aadfd49ce22c36122d51c4c", 769 | "shasum": "" 770 | }, 771 | "require": { 772 | "php": ">= 5.5.9", 773 | "squizlabs/php_codesniffer": "2.9.0" 774 | }, 775 | "require-dev": { 776 | "jakub-onderka/php-parallel-lint": "0.9.*", 777 | "mikey179/vfsstream": "~1.6", 778 | "phpunit/phpunit": "~4.1" 779 | }, 780 | "type": "library", 781 | "notification-url": "https://packagist.org/downloads/", 782 | "license": [ 783 | "GPL-2.0+" 784 | ], 785 | "description": "MediaWiki CodeSniffer Standards", 786 | "homepage": "https://www.mediawiki.org/wiki/Manual:Coding_conventions/PHP", 787 | "keywords": [ 788 | "codesniffer", 789 | "mediawiki" 790 | ], 791 | "time": "2017-05-04T19:15:03+00:00" 792 | }, 793 | { 794 | "name": "myclabs/deep-copy", 795 | "version": "1.6.1", 796 | "source": { 797 | "type": "git", 798 | "url": "https://github.com/myclabs/DeepCopy.git", 799 | "reference": "8e6e04167378abf1ddb4d3522d8755c5fd90d102" 800 | }, 801 | "dist": { 802 | "type": "zip", 803 | "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/8e6e04167378abf1ddb4d3522d8755c5fd90d102", 804 | "reference": "8e6e04167378abf1ddb4d3522d8755c5fd90d102", 805 | "shasum": "" 806 | }, 807 | "require": { 808 | "php": ">=5.4.0" 809 | }, 810 | "require-dev": { 811 | "doctrine/collections": "1.*", 812 | "phpunit/phpunit": "~4.1" 813 | }, 814 | "type": "library", 815 | "autoload": { 816 | "psr-4": { 817 | "DeepCopy\\": "src/DeepCopy/" 818 | } 819 | }, 820 | "notification-url": "https://packagist.org/downloads/", 821 | "license": [ 822 | "MIT" 823 | ], 824 | "description": "Create deep copies (clones) of your objects", 825 | "homepage": "https://github.com/myclabs/DeepCopy", 826 | "keywords": [ 827 | "clone", 828 | "copy", 829 | "duplicate", 830 | "object", 831 | "object graph" 832 | ], 833 | "time": "2017-04-12T18:52:22+00:00" 834 | }, 835 | { 836 | "name": "phar-io/manifest", 837 | "version": "1.0.1", 838 | "source": { 839 | "type": "git", 840 | "url": "https://github.com/phar-io/manifest.git", 841 | "reference": "2df402786ab5368a0169091f61a7c1e0eb6852d0" 842 | }, 843 | "dist": { 844 | "type": "zip", 845 | "url": "https://api.github.com/repos/phar-io/manifest/zipball/2df402786ab5368a0169091f61a7c1e0eb6852d0", 846 | "reference": "2df402786ab5368a0169091f61a7c1e0eb6852d0", 847 | "shasum": "" 848 | }, 849 | "require": { 850 | "ext-dom": "*", 851 | "ext-phar": "*", 852 | "phar-io/version": "^1.0.1", 853 | "php": "^5.6 || ^7.0" 854 | }, 855 | "type": "library", 856 | "extra": { 857 | "branch-alias": { 858 | "dev-master": "1.0.x-dev" 859 | } 860 | }, 861 | "autoload": { 862 | "classmap": [ 863 | "src/" 864 | ] 865 | }, 866 | "notification-url": "https://packagist.org/downloads/", 867 | "license": [ 868 | "BSD-3-Clause" 869 | ], 870 | "authors": [ 871 | { 872 | "name": "Arne Blankerts", 873 | "email": "arne@blankerts.de", 874 | "role": "Developer" 875 | }, 876 | { 877 | "name": "Sebastian Heuer", 878 | "email": "sebastian@phpeople.de", 879 | "role": "Developer" 880 | }, 881 | { 882 | "name": "Sebastian Bergmann", 883 | "email": "sebastian@phpunit.de", 884 | "role": "Developer" 885 | } 886 | ], 887 | "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", 888 | "time": "2017-03-05T18:14:27+00:00" 889 | }, 890 | { 891 | "name": "phar-io/version", 892 | "version": "1.0.1", 893 | "source": { 894 | "type": "git", 895 | "url": "https://github.com/phar-io/version.git", 896 | "reference": "a70c0ced4be299a63d32fa96d9281d03e94041df" 897 | }, 898 | "dist": { 899 | "type": "zip", 900 | "url": "https://api.github.com/repos/phar-io/version/zipball/a70c0ced4be299a63d32fa96d9281d03e94041df", 901 | "reference": "a70c0ced4be299a63d32fa96d9281d03e94041df", 902 | "shasum": "" 903 | }, 904 | "require": { 905 | "php": "^5.6 || ^7.0" 906 | }, 907 | "type": "library", 908 | "autoload": { 909 | "classmap": [ 910 | "src/" 911 | ] 912 | }, 913 | "notification-url": "https://packagist.org/downloads/", 914 | "license": [ 915 | "BSD-3-Clause" 916 | ], 917 | "authors": [ 918 | { 919 | "name": "Arne Blankerts", 920 | "email": "arne@blankerts.de", 921 | "role": "Developer" 922 | }, 923 | { 924 | "name": "Sebastian Heuer", 925 | "email": "sebastian@phpeople.de", 926 | "role": "Developer" 927 | }, 928 | { 929 | "name": "Sebastian Bergmann", 930 | "email": "sebastian@phpunit.de", 931 | "role": "Developer" 932 | } 933 | ], 934 | "description": "Library for handling version information and constraints", 935 | "time": "2017-03-05T17:38:23+00:00" 936 | }, 937 | { 938 | "name": "phpdocumentor/reflection-common", 939 | "version": "1.0", 940 | "source": { 941 | "type": "git", 942 | "url": "https://github.com/phpDocumentor/ReflectionCommon.git", 943 | "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c" 944 | }, 945 | "dist": { 946 | "type": "zip", 947 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/144c307535e82c8fdcaacbcfc1d6d8eeb896687c", 948 | "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c", 949 | "shasum": "" 950 | }, 951 | "require": { 952 | "php": ">=5.5" 953 | }, 954 | "require-dev": { 955 | "phpunit/phpunit": "^4.6" 956 | }, 957 | "type": "library", 958 | "extra": { 959 | "branch-alias": { 960 | "dev-master": "1.0.x-dev" 961 | } 962 | }, 963 | "autoload": { 964 | "psr-4": { 965 | "phpDocumentor\\Reflection\\": [ 966 | "src" 967 | ] 968 | } 969 | }, 970 | "notification-url": "https://packagist.org/downloads/", 971 | "license": [ 972 | "MIT" 973 | ], 974 | "authors": [ 975 | { 976 | "name": "Jaap van Otterdijk", 977 | "email": "opensource@ijaap.nl" 978 | } 979 | ], 980 | "description": "Common reflection classes used by phpdocumentor to reflect the code structure", 981 | "homepage": "http://www.phpdoc.org", 982 | "keywords": [ 983 | "FQSEN", 984 | "phpDocumentor", 985 | "phpdoc", 986 | "reflection", 987 | "static analysis" 988 | ], 989 | "time": "2015-12-27T11:43:31+00:00" 990 | }, 991 | { 992 | "name": "phpdocumentor/reflection-docblock", 993 | "version": "3.1.1", 994 | "source": { 995 | "type": "git", 996 | "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", 997 | "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e" 998 | }, 999 | "dist": { 1000 | "type": "zip", 1001 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/8331b5efe816ae05461b7ca1e721c01b46bafb3e", 1002 | "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e", 1003 | "shasum": "" 1004 | }, 1005 | "require": { 1006 | "php": ">=5.5", 1007 | "phpdocumentor/reflection-common": "^1.0@dev", 1008 | "phpdocumentor/type-resolver": "^0.2.0", 1009 | "webmozart/assert": "^1.0" 1010 | }, 1011 | "require-dev": { 1012 | "mockery/mockery": "^0.9.4", 1013 | "phpunit/phpunit": "^4.4" 1014 | }, 1015 | "type": "library", 1016 | "autoload": { 1017 | "psr-4": { 1018 | "phpDocumentor\\Reflection\\": [ 1019 | "src/" 1020 | ] 1021 | } 1022 | }, 1023 | "notification-url": "https://packagist.org/downloads/", 1024 | "license": [ 1025 | "MIT" 1026 | ], 1027 | "authors": [ 1028 | { 1029 | "name": "Mike van Riel", 1030 | "email": "me@mikevanriel.com" 1031 | } 1032 | ], 1033 | "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", 1034 | "time": "2016-09-30T07:12:33+00:00" 1035 | }, 1036 | { 1037 | "name": "phpdocumentor/type-resolver", 1038 | "version": "0.2.1", 1039 | "source": { 1040 | "type": "git", 1041 | "url": "https://github.com/phpDocumentor/TypeResolver.git", 1042 | "reference": "e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb" 1043 | }, 1044 | "dist": { 1045 | "type": "zip", 1046 | "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb", 1047 | "reference": "e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb", 1048 | "shasum": "" 1049 | }, 1050 | "require": { 1051 | "php": ">=5.5", 1052 | "phpdocumentor/reflection-common": "^1.0" 1053 | }, 1054 | "require-dev": { 1055 | "mockery/mockery": "^0.9.4", 1056 | "phpunit/phpunit": "^5.2||^4.8.24" 1057 | }, 1058 | "type": "library", 1059 | "extra": { 1060 | "branch-alias": { 1061 | "dev-master": "1.0.x-dev" 1062 | } 1063 | }, 1064 | "autoload": { 1065 | "psr-4": { 1066 | "phpDocumentor\\Reflection\\": [ 1067 | "src/" 1068 | ] 1069 | } 1070 | }, 1071 | "notification-url": "https://packagist.org/downloads/", 1072 | "license": [ 1073 | "MIT" 1074 | ], 1075 | "authors": [ 1076 | { 1077 | "name": "Mike van Riel", 1078 | "email": "me@mikevanriel.com" 1079 | } 1080 | ], 1081 | "time": "2016-11-25T06:54:22+00:00" 1082 | }, 1083 | { 1084 | "name": "phpspec/prophecy", 1085 | "version": "v1.7.0", 1086 | "source": { 1087 | "type": "git", 1088 | "url": "https://github.com/phpspec/prophecy.git", 1089 | "reference": "93d39f1f7f9326d746203c7c056f300f7f126073" 1090 | }, 1091 | "dist": { 1092 | "type": "zip", 1093 | "url": "https://api.github.com/repos/phpspec/prophecy/zipball/93d39f1f7f9326d746203c7c056f300f7f126073", 1094 | "reference": "93d39f1f7f9326d746203c7c056f300f7f126073", 1095 | "shasum": "" 1096 | }, 1097 | "require": { 1098 | "doctrine/instantiator": "^1.0.2", 1099 | "php": "^5.3|^7.0", 1100 | "phpdocumentor/reflection-docblock": "^2.0|^3.0.2", 1101 | "sebastian/comparator": "^1.1|^2.0", 1102 | "sebastian/recursion-context": "^1.0|^2.0|^3.0" 1103 | }, 1104 | "require-dev": { 1105 | "phpspec/phpspec": "^2.5|^3.2", 1106 | "phpunit/phpunit": "^4.8 || ^5.6.5" 1107 | }, 1108 | "type": "library", 1109 | "extra": { 1110 | "branch-alias": { 1111 | "dev-master": "1.6.x-dev" 1112 | } 1113 | }, 1114 | "autoload": { 1115 | "psr-0": { 1116 | "Prophecy\\": "src/" 1117 | } 1118 | }, 1119 | "notification-url": "https://packagist.org/downloads/", 1120 | "license": [ 1121 | "MIT" 1122 | ], 1123 | "authors": [ 1124 | { 1125 | "name": "Konstantin Kudryashov", 1126 | "email": "ever.zet@gmail.com", 1127 | "homepage": "http://everzet.com" 1128 | }, 1129 | { 1130 | "name": "Marcello Duarte", 1131 | "email": "marcello.duarte@gmail.com" 1132 | } 1133 | ], 1134 | "description": "Highly opinionated mocking framework for PHP 5.3+", 1135 | "homepage": "https://github.com/phpspec/prophecy", 1136 | "keywords": [ 1137 | "Double", 1138 | "Dummy", 1139 | "fake", 1140 | "mock", 1141 | "spy", 1142 | "stub" 1143 | ], 1144 | "time": "2017-03-02T20:05:34+00:00" 1145 | }, 1146 | { 1147 | "name": "phpunit/php-code-coverage", 1148 | "version": "5.2.1", 1149 | "source": { 1150 | "type": "git", 1151 | "url": "https://github.com/sebastianbergmann/php-code-coverage.git", 1152 | "reference": "dc421f9ca5082a0c0cb04afb171c765f79add85b" 1153 | }, 1154 | "dist": { 1155 | "type": "zip", 1156 | "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/dc421f9ca5082a0c0cb04afb171c765f79add85b", 1157 | "reference": "dc421f9ca5082a0c0cb04afb171c765f79add85b", 1158 | "shasum": "" 1159 | }, 1160 | "require": { 1161 | "ext-dom": "*", 1162 | "ext-xmlwriter": "*", 1163 | "php": "^7.0", 1164 | "phpunit/php-file-iterator": "^1.3", 1165 | "phpunit/php-text-template": "^1.2", 1166 | "phpunit/php-token-stream": "^1.4.11 || ^2.0", 1167 | "sebastian/code-unit-reverse-lookup": "^1.0", 1168 | "sebastian/environment": "^3.0", 1169 | "sebastian/version": "^2.0", 1170 | "theseer/tokenizer": "^1.1" 1171 | }, 1172 | "require-dev": { 1173 | "ext-xdebug": "^2.5", 1174 | "phpunit/phpunit": "^6.0" 1175 | }, 1176 | "suggest": { 1177 | "ext-xdebug": "^2.5.3" 1178 | }, 1179 | "type": "library", 1180 | "extra": { 1181 | "branch-alias": { 1182 | "dev-master": "5.2.x-dev" 1183 | } 1184 | }, 1185 | "autoload": { 1186 | "classmap": [ 1187 | "src/" 1188 | ] 1189 | }, 1190 | "notification-url": "https://packagist.org/downloads/", 1191 | "license": [ 1192 | "BSD-3-Clause" 1193 | ], 1194 | "authors": [ 1195 | { 1196 | "name": "Sebastian Bergmann", 1197 | "email": "sb@sebastian-bergmann.de", 1198 | "role": "lead" 1199 | } 1200 | ], 1201 | "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", 1202 | "homepage": "https://github.com/sebastianbergmann/php-code-coverage", 1203 | "keywords": [ 1204 | "coverage", 1205 | "testing", 1206 | "xunit" 1207 | ], 1208 | "time": "2017-04-21T08:03:57+00:00" 1209 | }, 1210 | { 1211 | "name": "phpunit/php-file-iterator", 1212 | "version": "1.4.2", 1213 | "source": { 1214 | "type": "git", 1215 | "url": "https://github.com/sebastianbergmann/php-file-iterator.git", 1216 | "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5" 1217 | }, 1218 | "dist": { 1219 | "type": "zip", 1220 | "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/3cc8f69b3028d0f96a9078e6295d86e9bf019be5", 1221 | "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5", 1222 | "shasum": "" 1223 | }, 1224 | "require": { 1225 | "php": ">=5.3.3" 1226 | }, 1227 | "type": "library", 1228 | "extra": { 1229 | "branch-alias": { 1230 | "dev-master": "1.4.x-dev" 1231 | } 1232 | }, 1233 | "autoload": { 1234 | "classmap": [ 1235 | "src/" 1236 | ] 1237 | }, 1238 | "notification-url": "https://packagist.org/downloads/", 1239 | "license": [ 1240 | "BSD-3-Clause" 1241 | ], 1242 | "authors": [ 1243 | { 1244 | "name": "Sebastian Bergmann", 1245 | "email": "sb@sebastian-bergmann.de", 1246 | "role": "lead" 1247 | } 1248 | ], 1249 | "description": "FilterIterator implementation that filters files based on a list of suffixes.", 1250 | "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", 1251 | "keywords": [ 1252 | "filesystem", 1253 | "iterator" 1254 | ], 1255 | "time": "2016-10-03T07:40:28+00:00" 1256 | }, 1257 | { 1258 | "name": "phpunit/php-text-template", 1259 | "version": "1.2.1", 1260 | "source": { 1261 | "type": "git", 1262 | "url": "https://github.com/sebastianbergmann/php-text-template.git", 1263 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" 1264 | }, 1265 | "dist": { 1266 | "type": "zip", 1267 | "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", 1268 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", 1269 | "shasum": "" 1270 | }, 1271 | "require": { 1272 | "php": ">=5.3.3" 1273 | }, 1274 | "type": "library", 1275 | "autoload": { 1276 | "classmap": [ 1277 | "src/" 1278 | ] 1279 | }, 1280 | "notification-url": "https://packagist.org/downloads/", 1281 | "license": [ 1282 | "BSD-3-Clause" 1283 | ], 1284 | "authors": [ 1285 | { 1286 | "name": "Sebastian Bergmann", 1287 | "email": "sebastian@phpunit.de", 1288 | "role": "lead" 1289 | } 1290 | ], 1291 | "description": "Simple template engine.", 1292 | "homepage": "https://github.com/sebastianbergmann/php-text-template/", 1293 | "keywords": [ 1294 | "template" 1295 | ], 1296 | "time": "2015-06-21T13:50:34+00:00" 1297 | }, 1298 | { 1299 | "name": "phpunit/php-timer", 1300 | "version": "1.0.9", 1301 | "source": { 1302 | "type": "git", 1303 | "url": "https://github.com/sebastianbergmann/php-timer.git", 1304 | "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f" 1305 | }, 1306 | "dist": { 1307 | "type": "zip", 1308 | "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", 1309 | "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", 1310 | "shasum": "" 1311 | }, 1312 | "require": { 1313 | "php": "^5.3.3 || ^7.0" 1314 | }, 1315 | "require-dev": { 1316 | "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" 1317 | }, 1318 | "type": "library", 1319 | "extra": { 1320 | "branch-alias": { 1321 | "dev-master": "1.0-dev" 1322 | } 1323 | }, 1324 | "autoload": { 1325 | "classmap": [ 1326 | "src/" 1327 | ] 1328 | }, 1329 | "notification-url": "https://packagist.org/downloads/", 1330 | "license": [ 1331 | "BSD-3-Clause" 1332 | ], 1333 | "authors": [ 1334 | { 1335 | "name": "Sebastian Bergmann", 1336 | "email": "sb@sebastian-bergmann.de", 1337 | "role": "lead" 1338 | } 1339 | ], 1340 | "description": "Utility class for timing", 1341 | "homepage": "https://github.com/sebastianbergmann/php-timer/", 1342 | "keywords": [ 1343 | "timer" 1344 | ], 1345 | "time": "2017-02-26T11:10:40+00:00" 1346 | }, 1347 | { 1348 | "name": "phpunit/php-token-stream", 1349 | "version": "1.4.11", 1350 | "source": { 1351 | "type": "git", 1352 | "url": "https://github.com/sebastianbergmann/php-token-stream.git", 1353 | "reference": "e03f8f67534427a787e21a385a67ec3ca6978ea7" 1354 | }, 1355 | "dist": { 1356 | "type": "zip", 1357 | "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/e03f8f67534427a787e21a385a67ec3ca6978ea7", 1358 | "reference": "e03f8f67534427a787e21a385a67ec3ca6978ea7", 1359 | "shasum": "" 1360 | }, 1361 | "require": { 1362 | "ext-tokenizer": "*", 1363 | "php": ">=5.3.3" 1364 | }, 1365 | "require-dev": { 1366 | "phpunit/phpunit": "~4.2" 1367 | }, 1368 | "type": "library", 1369 | "extra": { 1370 | "branch-alias": { 1371 | "dev-master": "1.4-dev" 1372 | } 1373 | }, 1374 | "autoload": { 1375 | "classmap": [ 1376 | "src/" 1377 | ] 1378 | }, 1379 | "notification-url": "https://packagist.org/downloads/", 1380 | "license": [ 1381 | "BSD-3-Clause" 1382 | ], 1383 | "authors": [ 1384 | { 1385 | "name": "Sebastian Bergmann", 1386 | "email": "sebastian@phpunit.de" 1387 | } 1388 | ], 1389 | "description": "Wrapper around PHP's tokenizer extension.", 1390 | "homepage": "https://github.com/sebastianbergmann/php-token-stream/", 1391 | "keywords": [ 1392 | "tokenizer" 1393 | ], 1394 | "time": "2017-02-27T10:12:30+00:00" 1395 | }, 1396 | { 1397 | "name": "phpunit/phpunit", 1398 | "version": "6.1.4", 1399 | "source": { 1400 | "type": "git", 1401 | "url": "https://github.com/sebastianbergmann/phpunit.git", 1402 | "reference": "42b7f394a8e009516582331b1e03a1aba40175d1" 1403 | }, 1404 | "dist": { 1405 | "type": "zip", 1406 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/42b7f394a8e009516582331b1e03a1aba40175d1", 1407 | "reference": "42b7f394a8e009516582331b1e03a1aba40175d1", 1408 | "shasum": "" 1409 | }, 1410 | "require": { 1411 | "ext-dom": "*", 1412 | "ext-json": "*", 1413 | "ext-libxml": "*", 1414 | "ext-mbstring": "*", 1415 | "ext-xml": "*", 1416 | "myclabs/deep-copy": "^1.3", 1417 | "phar-io/manifest": "^1.0.1", 1418 | "phar-io/version": "^1.0", 1419 | "php": "^7.0", 1420 | "phpspec/prophecy": "^1.7", 1421 | "phpunit/php-code-coverage": "^5.2", 1422 | "phpunit/php-file-iterator": "^1.4", 1423 | "phpunit/php-text-template": "^1.2", 1424 | "phpunit/php-timer": "^1.0.6", 1425 | "phpunit/phpunit-mock-objects": "^4.0", 1426 | "sebastian/comparator": "^2.0", 1427 | "sebastian/diff": "^1.4.3 || ^2.0", 1428 | "sebastian/environment": "^3.0.2", 1429 | "sebastian/exporter": "^3.1", 1430 | "sebastian/global-state": "^1.1 || ^2.0", 1431 | "sebastian/object-enumerator": "^3.0.2", 1432 | "sebastian/resource-operations": "^1.0", 1433 | "sebastian/version": "^2.0" 1434 | }, 1435 | "conflict": { 1436 | "phpdocumentor/reflection-docblock": "3.0.2", 1437 | "phpunit/dbunit": "<3.0" 1438 | }, 1439 | "require-dev": { 1440 | "ext-pdo": "*" 1441 | }, 1442 | "suggest": { 1443 | "ext-xdebug": "*", 1444 | "phpunit/php-invoker": "^1.1" 1445 | }, 1446 | "bin": [ 1447 | "phpunit" 1448 | ], 1449 | "type": "library", 1450 | "extra": { 1451 | "branch-alias": { 1452 | "dev-master": "6.1.x-dev" 1453 | } 1454 | }, 1455 | "autoload": { 1456 | "classmap": [ 1457 | "src/" 1458 | ] 1459 | }, 1460 | "notification-url": "https://packagist.org/downloads/", 1461 | "license": [ 1462 | "BSD-3-Clause" 1463 | ], 1464 | "authors": [ 1465 | { 1466 | "name": "Sebastian Bergmann", 1467 | "email": "sebastian@phpunit.de", 1468 | "role": "lead" 1469 | } 1470 | ], 1471 | "description": "The PHP Unit Testing framework.", 1472 | "homepage": "https://phpunit.de/", 1473 | "keywords": [ 1474 | "phpunit", 1475 | "testing", 1476 | "xunit" 1477 | ], 1478 | "time": "2017-05-22T07:45:30+00:00" 1479 | }, 1480 | { 1481 | "name": "phpunit/phpunit-mock-objects", 1482 | "version": "4.0.1", 1483 | "source": { 1484 | "type": "git", 1485 | "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", 1486 | "reference": "eabce450df194817a7d7e27e19013569a903a2bf" 1487 | }, 1488 | "dist": { 1489 | "type": "zip", 1490 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/eabce450df194817a7d7e27e19013569a903a2bf", 1491 | "reference": "eabce450df194817a7d7e27e19013569a903a2bf", 1492 | "shasum": "" 1493 | }, 1494 | "require": { 1495 | "doctrine/instantiator": "^1.0.2", 1496 | "php": "^7.0", 1497 | "phpunit/php-text-template": "^1.2", 1498 | "sebastian/exporter": "^3.0" 1499 | }, 1500 | "conflict": { 1501 | "phpunit/phpunit": "<6.0" 1502 | }, 1503 | "require-dev": { 1504 | "phpunit/phpunit": "^6.0" 1505 | }, 1506 | "suggest": { 1507 | "ext-soap": "*" 1508 | }, 1509 | "type": "library", 1510 | "extra": { 1511 | "branch-alias": { 1512 | "dev-master": "4.0.x-dev" 1513 | } 1514 | }, 1515 | "autoload": { 1516 | "classmap": [ 1517 | "src/" 1518 | ] 1519 | }, 1520 | "notification-url": "https://packagist.org/downloads/", 1521 | "license": [ 1522 | "BSD-3-Clause" 1523 | ], 1524 | "authors": [ 1525 | { 1526 | "name": "Sebastian Bergmann", 1527 | "email": "sb@sebastian-bergmann.de", 1528 | "role": "lead" 1529 | } 1530 | ], 1531 | "description": "Mock Object library for PHPUnit", 1532 | "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", 1533 | "keywords": [ 1534 | "mock", 1535 | "xunit" 1536 | ], 1537 | "time": "2017-03-03T06:30:20+00:00" 1538 | }, 1539 | { 1540 | "name": "sebastian/code-unit-reverse-lookup", 1541 | "version": "1.0.1", 1542 | "source": { 1543 | "type": "git", 1544 | "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", 1545 | "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18" 1546 | }, 1547 | "dist": { 1548 | "type": "zip", 1549 | "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", 1550 | "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", 1551 | "shasum": "" 1552 | }, 1553 | "require": { 1554 | "php": "^5.6 || ^7.0" 1555 | }, 1556 | "require-dev": { 1557 | "phpunit/phpunit": "^5.7 || ^6.0" 1558 | }, 1559 | "type": "library", 1560 | "extra": { 1561 | "branch-alias": { 1562 | "dev-master": "1.0.x-dev" 1563 | } 1564 | }, 1565 | "autoload": { 1566 | "classmap": [ 1567 | "src/" 1568 | ] 1569 | }, 1570 | "notification-url": "https://packagist.org/downloads/", 1571 | "license": [ 1572 | "BSD-3-Clause" 1573 | ], 1574 | "authors": [ 1575 | { 1576 | "name": "Sebastian Bergmann", 1577 | "email": "sebastian@phpunit.de" 1578 | } 1579 | ], 1580 | "description": "Looks up which function or method a line of code belongs to", 1581 | "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", 1582 | "time": "2017-03-04T06:30:41+00:00" 1583 | }, 1584 | { 1585 | "name": "sebastian/comparator", 1586 | "version": "2.0.0", 1587 | "source": { 1588 | "type": "git", 1589 | "url": "https://github.com/sebastianbergmann/comparator.git", 1590 | "reference": "20f84f468cb67efee293246e6a09619b891f55f0" 1591 | }, 1592 | "dist": { 1593 | "type": "zip", 1594 | "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/20f84f468cb67efee293246e6a09619b891f55f0", 1595 | "reference": "20f84f468cb67efee293246e6a09619b891f55f0", 1596 | "shasum": "" 1597 | }, 1598 | "require": { 1599 | "php": "^7.0", 1600 | "sebastian/diff": "^1.2", 1601 | "sebastian/exporter": "^3.0" 1602 | }, 1603 | "require-dev": { 1604 | "phpunit/phpunit": "^6.0" 1605 | }, 1606 | "type": "library", 1607 | "extra": { 1608 | "branch-alias": { 1609 | "dev-master": "2.0.x-dev" 1610 | } 1611 | }, 1612 | "autoload": { 1613 | "classmap": [ 1614 | "src/" 1615 | ] 1616 | }, 1617 | "notification-url": "https://packagist.org/downloads/", 1618 | "license": [ 1619 | "BSD-3-Clause" 1620 | ], 1621 | "authors": [ 1622 | { 1623 | "name": "Jeff Welch", 1624 | "email": "whatthejeff@gmail.com" 1625 | }, 1626 | { 1627 | "name": "Volker Dusch", 1628 | "email": "github@wallbash.com" 1629 | }, 1630 | { 1631 | "name": "Bernhard Schussek", 1632 | "email": "bschussek@2bepublished.at" 1633 | }, 1634 | { 1635 | "name": "Sebastian Bergmann", 1636 | "email": "sebastian@phpunit.de" 1637 | } 1638 | ], 1639 | "description": "Provides the functionality to compare PHP values for equality", 1640 | "homepage": "http://www.github.com/sebastianbergmann/comparator", 1641 | "keywords": [ 1642 | "comparator", 1643 | "compare", 1644 | "equality" 1645 | ], 1646 | "time": "2017-03-03T06:26:08+00:00" 1647 | }, 1648 | { 1649 | "name": "sebastian/diff", 1650 | "version": "1.4.3", 1651 | "source": { 1652 | "type": "git", 1653 | "url": "https://github.com/sebastianbergmann/diff.git", 1654 | "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4" 1655 | }, 1656 | "dist": { 1657 | "type": "zip", 1658 | "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7f066a26a962dbe58ddea9f72a4e82874a3975a4", 1659 | "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4", 1660 | "shasum": "" 1661 | }, 1662 | "require": { 1663 | "php": "^5.3.3 || ^7.0" 1664 | }, 1665 | "require-dev": { 1666 | "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" 1667 | }, 1668 | "type": "library", 1669 | "extra": { 1670 | "branch-alias": { 1671 | "dev-master": "1.4-dev" 1672 | } 1673 | }, 1674 | "autoload": { 1675 | "classmap": [ 1676 | "src/" 1677 | ] 1678 | }, 1679 | "notification-url": "https://packagist.org/downloads/", 1680 | "license": [ 1681 | "BSD-3-Clause" 1682 | ], 1683 | "authors": [ 1684 | { 1685 | "name": "Kore Nordmann", 1686 | "email": "mail@kore-nordmann.de" 1687 | }, 1688 | { 1689 | "name": "Sebastian Bergmann", 1690 | "email": "sebastian@phpunit.de" 1691 | } 1692 | ], 1693 | "description": "Diff implementation", 1694 | "homepage": "https://github.com/sebastianbergmann/diff", 1695 | "keywords": [ 1696 | "diff" 1697 | ], 1698 | "time": "2017-05-22T07:24:03+00:00" 1699 | }, 1700 | { 1701 | "name": "sebastian/environment", 1702 | "version": "3.0.3", 1703 | "source": { 1704 | "type": "git", 1705 | "url": "https://github.com/sebastianbergmann/environment.git", 1706 | "reference": "02b6b2c7aefe2cdb1185b8dbf8718b0bcedf3ab3" 1707 | }, 1708 | "dist": { 1709 | "type": "zip", 1710 | "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/02b6b2c7aefe2cdb1185b8dbf8718b0bcedf3ab3", 1711 | "reference": "02b6b2c7aefe2cdb1185b8dbf8718b0bcedf3ab3", 1712 | "shasum": "" 1713 | }, 1714 | "require": { 1715 | "php": "^7.0" 1716 | }, 1717 | "require-dev": { 1718 | "phpunit/phpunit": "^6.1" 1719 | }, 1720 | "type": "library", 1721 | "extra": { 1722 | "branch-alias": { 1723 | "dev-master": "3.0.x-dev" 1724 | } 1725 | }, 1726 | "autoload": { 1727 | "classmap": [ 1728 | "src/" 1729 | ] 1730 | }, 1731 | "notification-url": "https://packagist.org/downloads/", 1732 | "license": [ 1733 | "BSD-3-Clause" 1734 | ], 1735 | "authors": [ 1736 | { 1737 | "name": "Sebastian Bergmann", 1738 | "email": "sebastian@phpunit.de" 1739 | } 1740 | ], 1741 | "description": "Provides functionality to handle HHVM/PHP environments", 1742 | "homepage": "http://www.github.com/sebastianbergmann/environment", 1743 | "keywords": [ 1744 | "Xdebug", 1745 | "environment", 1746 | "hhvm" 1747 | ], 1748 | "time": "2017-05-18T10:10:00+00:00" 1749 | }, 1750 | { 1751 | "name": "sebastian/exporter", 1752 | "version": "3.1.0", 1753 | "source": { 1754 | "type": "git", 1755 | "url": "https://github.com/sebastianbergmann/exporter.git", 1756 | "reference": "234199f4528de6d12aaa58b612e98f7d36adb937" 1757 | }, 1758 | "dist": { 1759 | "type": "zip", 1760 | "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/234199f4528de6d12aaa58b612e98f7d36adb937", 1761 | "reference": "234199f4528de6d12aaa58b612e98f7d36adb937", 1762 | "shasum": "" 1763 | }, 1764 | "require": { 1765 | "php": "^7.0", 1766 | "sebastian/recursion-context": "^3.0" 1767 | }, 1768 | "require-dev": { 1769 | "ext-mbstring": "*", 1770 | "phpunit/phpunit": "^6.0" 1771 | }, 1772 | "type": "library", 1773 | "extra": { 1774 | "branch-alias": { 1775 | "dev-master": "3.1.x-dev" 1776 | } 1777 | }, 1778 | "autoload": { 1779 | "classmap": [ 1780 | "src/" 1781 | ] 1782 | }, 1783 | "notification-url": "https://packagist.org/downloads/", 1784 | "license": [ 1785 | "BSD-3-Clause" 1786 | ], 1787 | "authors": [ 1788 | { 1789 | "name": "Jeff Welch", 1790 | "email": "whatthejeff@gmail.com" 1791 | }, 1792 | { 1793 | "name": "Volker Dusch", 1794 | "email": "github@wallbash.com" 1795 | }, 1796 | { 1797 | "name": "Bernhard Schussek", 1798 | "email": "bschussek@2bepublished.at" 1799 | }, 1800 | { 1801 | "name": "Sebastian Bergmann", 1802 | "email": "sebastian@phpunit.de" 1803 | }, 1804 | { 1805 | "name": "Adam Harvey", 1806 | "email": "aharvey@php.net" 1807 | } 1808 | ], 1809 | "description": "Provides the functionality to export PHP variables for visualization", 1810 | "homepage": "http://www.github.com/sebastianbergmann/exporter", 1811 | "keywords": [ 1812 | "export", 1813 | "exporter" 1814 | ], 1815 | "time": "2017-04-03T13:19:02+00:00" 1816 | }, 1817 | { 1818 | "name": "sebastian/global-state", 1819 | "version": "2.0.0", 1820 | "source": { 1821 | "type": "git", 1822 | "url": "https://github.com/sebastianbergmann/global-state.git", 1823 | "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4" 1824 | }, 1825 | "dist": { 1826 | "type": "zip", 1827 | "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", 1828 | "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", 1829 | "shasum": "" 1830 | }, 1831 | "require": { 1832 | "php": "^7.0" 1833 | }, 1834 | "require-dev": { 1835 | "phpunit/phpunit": "^6.0" 1836 | }, 1837 | "suggest": { 1838 | "ext-uopz": "*" 1839 | }, 1840 | "type": "library", 1841 | "extra": { 1842 | "branch-alias": { 1843 | "dev-master": "2.0-dev" 1844 | } 1845 | }, 1846 | "autoload": { 1847 | "classmap": [ 1848 | "src/" 1849 | ] 1850 | }, 1851 | "notification-url": "https://packagist.org/downloads/", 1852 | "license": [ 1853 | "BSD-3-Clause" 1854 | ], 1855 | "authors": [ 1856 | { 1857 | "name": "Sebastian Bergmann", 1858 | "email": "sebastian@phpunit.de" 1859 | } 1860 | ], 1861 | "description": "Snapshotting of global state", 1862 | "homepage": "http://www.github.com/sebastianbergmann/global-state", 1863 | "keywords": [ 1864 | "global state" 1865 | ], 1866 | "time": "2017-04-27T15:39:26+00:00" 1867 | }, 1868 | { 1869 | "name": "sebastian/object-enumerator", 1870 | "version": "3.0.2", 1871 | "source": { 1872 | "type": "git", 1873 | "url": "https://github.com/sebastianbergmann/object-enumerator.git", 1874 | "reference": "31dd3379d16446c5d86dec32ab1ad1f378581ad8" 1875 | }, 1876 | "dist": { 1877 | "type": "zip", 1878 | "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/31dd3379d16446c5d86dec32ab1ad1f378581ad8", 1879 | "reference": "31dd3379d16446c5d86dec32ab1ad1f378581ad8", 1880 | "shasum": "" 1881 | }, 1882 | "require": { 1883 | "php": "^7.0", 1884 | "sebastian/object-reflector": "^1.0", 1885 | "sebastian/recursion-context": "^3.0" 1886 | }, 1887 | "require-dev": { 1888 | "phpunit/phpunit": "^6.0" 1889 | }, 1890 | "type": "library", 1891 | "extra": { 1892 | "branch-alias": { 1893 | "dev-master": "3.0.x-dev" 1894 | } 1895 | }, 1896 | "autoload": { 1897 | "classmap": [ 1898 | "src/" 1899 | ] 1900 | }, 1901 | "notification-url": "https://packagist.org/downloads/", 1902 | "license": [ 1903 | "BSD-3-Clause" 1904 | ], 1905 | "authors": [ 1906 | { 1907 | "name": "Sebastian Bergmann", 1908 | "email": "sebastian@phpunit.de" 1909 | } 1910 | ], 1911 | "description": "Traverses array structures and object graphs to enumerate all referenced objects", 1912 | "homepage": "https://github.com/sebastianbergmann/object-enumerator/", 1913 | "time": "2017-03-12T15:17:29+00:00" 1914 | }, 1915 | { 1916 | "name": "sebastian/object-reflector", 1917 | "version": "1.1.1", 1918 | "source": { 1919 | "type": "git", 1920 | "url": "https://github.com/sebastianbergmann/object-reflector.git", 1921 | "reference": "773f97c67f28de00d397be301821b06708fca0be" 1922 | }, 1923 | "dist": { 1924 | "type": "zip", 1925 | "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/773f97c67f28de00d397be301821b06708fca0be", 1926 | "reference": "773f97c67f28de00d397be301821b06708fca0be", 1927 | "shasum": "" 1928 | }, 1929 | "require": { 1930 | "php": "^7.0" 1931 | }, 1932 | "require-dev": { 1933 | "phpunit/phpunit": "^6.0" 1934 | }, 1935 | "type": "library", 1936 | "extra": { 1937 | "branch-alias": { 1938 | "dev-master": "1.1-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": "Allows reflection of object attributes, including inherited and non-public ones", 1957 | "homepage": "https://github.com/sebastianbergmann/object-reflector/", 1958 | "time": "2017-03-29T09:07:27+00:00" 1959 | }, 1960 | { 1961 | "name": "sebastian/recursion-context", 1962 | "version": "3.0.0", 1963 | "source": { 1964 | "type": "git", 1965 | "url": "https://github.com/sebastianbergmann/recursion-context.git", 1966 | "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8" 1967 | }, 1968 | "dist": { 1969 | "type": "zip", 1970 | "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", 1971 | "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", 1972 | "shasum": "" 1973 | }, 1974 | "require": { 1975 | "php": "^7.0" 1976 | }, 1977 | "require-dev": { 1978 | "phpunit/phpunit": "^6.0" 1979 | }, 1980 | "type": "library", 1981 | "extra": { 1982 | "branch-alias": { 1983 | "dev-master": "3.0.x-dev" 1984 | } 1985 | }, 1986 | "autoload": { 1987 | "classmap": [ 1988 | "src/" 1989 | ] 1990 | }, 1991 | "notification-url": "https://packagist.org/downloads/", 1992 | "license": [ 1993 | "BSD-3-Clause" 1994 | ], 1995 | "authors": [ 1996 | { 1997 | "name": "Jeff Welch", 1998 | "email": "whatthejeff@gmail.com" 1999 | }, 2000 | { 2001 | "name": "Sebastian Bergmann", 2002 | "email": "sebastian@phpunit.de" 2003 | }, 2004 | { 2005 | "name": "Adam Harvey", 2006 | "email": "aharvey@php.net" 2007 | } 2008 | ], 2009 | "description": "Provides functionality to recursively process PHP variables", 2010 | "homepage": "http://www.github.com/sebastianbergmann/recursion-context", 2011 | "time": "2017-03-03T06:23:57+00:00" 2012 | }, 2013 | { 2014 | "name": "sebastian/resource-operations", 2015 | "version": "1.0.0", 2016 | "source": { 2017 | "type": "git", 2018 | "url": "https://github.com/sebastianbergmann/resource-operations.git", 2019 | "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52" 2020 | }, 2021 | "dist": { 2022 | "type": "zip", 2023 | "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", 2024 | "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", 2025 | "shasum": "" 2026 | }, 2027 | "require": { 2028 | "php": ">=5.6.0" 2029 | }, 2030 | "type": "library", 2031 | "extra": { 2032 | "branch-alias": { 2033 | "dev-master": "1.0.x-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": "Provides a list of PHP built-in functions that operate on resources", 2052 | "homepage": "https://www.github.com/sebastianbergmann/resource-operations", 2053 | "time": "2015-07-28T20:34:47+00:00" 2054 | }, 2055 | { 2056 | "name": "sebastian/version", 2057 | "version": "2.0.1", 2058 | "source": { 2059 | "type": "git", 2060 | "url": "https://github.com/sebastianbergmann/version.git", 2061 | "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" 2062 | }, 2063 | "dist": { 2064 | "type": "zip", 2065 | "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", 2066 | "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", 2067 | "shasum": "" 2068 | }, 2069 | "require": { 2070 | "php": ">=5.6" 2071 | }, 2072 | "type": "library", 2073 | "extra": { 2074 | "branch-alias": { 2075 | "dev-master": "2.0.x-dev" 2076 | } 2077 | }, 2078 | "autoload": { 2079 | "classmap": [ 2080 | "src/" 2081 | ] 2082 | }, 2083 | "notification-url": "https://packagist.org/downloads/", 2084 | "license": [ 2085 | "BSD-3-Clause" 2086 | ], 2087 | "authors": [ 2088 | { 2089 | "name": "Sebastian Bergmann", 2090 | "email": "sebastian@phpunit.de", 2091 | "role": "lead" 2092 | } 2093 | ], 2094 | "description": "Library that helps with managing the version number of Git-hosted PHP projects", 2095 | "homepage": "https://github.com/sebastianbergmann/version", 2096 | "time": "2016-10-03T07:35:21+00:00" 2097 | }, 2098 | { 2099 | "name": "squizlabs/php_codesniffer", 2100 | "version": "2.9.0", 2101 | "source": { 2102 | "type": "git", 2103 | "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", 2104 | "reference": "f7dfecbee89d68ab475a6c9e17d22bc9b69aed97" 2105 | }, 2106 | "dist": { 2107 | "type": "zip", 2108 | "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/f7dfecbee89d68ab475a6c9e17d22bc9b69aed97", 2109 | "reference": "f7dfecbee89d68ab475a6c9e17d22bc9b69aed97", 2110 | "shasum": "" 2111 | }, 2112 | "require": { 2113 | "ext-simplexml": "*", 2114 | "ext-tokenizer": "*", 2115 | "ext-xmlwriter": "*", 2116 | "php": ">=5.1.2" 2117 | }, 2118 | "require-dev": { 2119 | "phpunit/phpunit": "~4.0" 2120 | }, 2121 | "bin": [ 2122 | "scripts/phpcs", 2123 | "scripts/phpcbf" 2124 | ], 2125 | "type": "library", 2126 | "extra": { 2127 | "branch-alias": { 2128 | "dev-master": "2.x-dev" 2129 | } 2130 | }, 2131 | "autoload": { 2132 | "classmap": [ 2133 | "CodeSniffer.php", 2134 | "CodeSniffer/CLI.php", 2135 | "CodeSniffer/Exception.php", 2136 | "CodeSniffer/File.php", 2137 | "CodeSniffer/Fixer.php", 2138 | "CodeSniffer/Report.php", 2139 | "CodeSniffer/Reporting.php", 2140 | "CodeSniffer/Sniff.php", 2141 | "CodeSniffer/Tokens.php", 2142 | "CodeSniffer/Reports/", 2143 | "CodeSniffer/Tokenizers/", 2144 | "CodeSniffer/DocGenerators/", 2145 | "CodeSniffer/Standards/AbstractPatternSniff.php", 2146 | "CodeSniffer/Standards/AbstractScopeSniff.php", 2147 | "CodeSniffer/Standards/AbstractVariableSniff.php", 2148 | "CodeSniffer/Standards/IncorrectPatternException.php", 2149 | "CodeSniffer/Standards/Generic/Sniffs/", 2150 | "CodeSniffer/Standards/MySource/Sniffs/", 2151 | "CodeSniffer/Standards/PEAR/Sniffs/", 2152 | "CodeSniffer/Standards/PSR1/Sniffs/", 2153 | "CodeSniffer/Standards/PSR2/Sniffs/", 2154 | "CodeSniffer/Standards/Squiz/Sniffs/", 2155 | "CodeSniffer/Standards/Zend/Sniffs/" 2156 | ] 2157 | }, 2158 | "notification-url": "https://packagist.org/downloads/", 2159 | "license": [ 2160 | "BSD-3-Clause" 2161 | ], 2162 | "authors": [ 2163 | { 2164 | "name": "Greg Sherwood", 2165 | "role": "lead" 2166 | } 2167 | ], 2168 | "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", 2169 | "homepage": "http://www.squizlabs.com/php-codesniffer", 2170 | "keywords": [ 2171 | "phpcs", 2172 | "standards" 2173 | ], 2174 | "time": "2017-05-03T23:30:39+00:00" 2175 | }, 2176 | { 2177 | "name": "symfony/browser-kit", 2178 | "version": "v3.2.8", 2179 | "source": { 2180 | "type": "git", 2181 | "url": "https://github.com/symfony/browser-kit.git", 2182 | "reference": "9fab1ab6f77b77f3df5fc5250fc6956811699b57" 2183 | }, 2184 | "dist": { 2185 | "type": "zip", 2186 | "url": "https://api.github.com/repos/symfony/browser-kit/zipball/9fab1ab6f77b77f3df5fc5250fc6956811699b57", 2187 | "reference": "9fab1ab6f77b77f3df5fc5250fc6956811699b57", 2188 | "shasum": "" 2189 | }, 2190 | "require": { 2191 | "php": ">=5.5.9", 2192 | "symfony/dom-crawler": "~2.8|~3.0" 2193 | }, 2194 | "require-dev": { 2195 | "symfony/css-selector": "~2.8|~3.0", 2196 | "symfony/process": "~2.8|~3.0" 2197 | }, 2198 | "suggest": { 2199 | "symfony/process": "" 2200 | }, 2201 | "type": "library", 2202 | "extra": { 2203 | "branch-alias": { 2204 | "dev-master": "3.2-dev" 2205 | } 2206 | }, 2207 | "autoload": { 2208 | "psr-4": { 2209 | "Symfony\\Component\\BrowserKit\\": "" 2210 | }, 2211 | "exclude-from-classmap": [ 2212 | "/Tests/" 2213 | ] 2214 | }, 2215 | "notification-url": "https://packagist.org/downloads/", 2216 | "license": [ 2217 | "MIT" 2218 | ], 2219 | "authors": [ 2220 | { 2221 | "name": "Fabien Potencier", 2222 | "email": "fabien@symfony.com" 2223 | }, 2224 | { 2225 | "name": "Symfony Community", 2226 | "homepage": "https://symfony.com/contributors" 2227 | } 2228 | ], 2229 | "description": "Symfony BrowserKit Component", 2230 | "homepage": "https://symfony.com", 2231 | "time": "2017-04-12T14:13:17+00:00" 2232 | }, 2233 | { 2234 | "name": "symfony/dom-crawler", 2235 | "version": "v3.2.8", 2236 | "source": { 2237 | "type": "git", 2238 | "url": "https://github.com/symfony/dom-crawler.git", 2239 | "reference": "f1ad34e8af09ed17570e027cf0c58a12eddec286" 2240 | }, 2241 | "dist": { 2242 | "type": "zip", 2243 | "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/f1ad34e8af09ed17570e027cf0c58a12eddec286", 2244 | "reference": "f1ad34e8af09ed17570e027cf0c58a12eddec286", 2245 | "shasum": "" 2246 | }, 2247 | "require": { 2248 | "php": ">=5.5.9", 2249 | "symfony/polyfill-mbstring": "~1.0" 2250 | }, 2251 | "require-dev": { 2252 | "symfony/css-selector": "~2.8|~3.0" 2253 | }, 2254 | "suggest": { 2255 | "symfony/css-selector": "" 2256 | }, 2257 | "type": "library", 2258 | "extra": { 2259 | "branch-alias": { 2260 | "dev-master": "3.2-dev" 2261 | } 2262 | }, 2263 | "autoload": { 2264 | "psr-4": { 2265 | "Symfony\\Component\\DomCrawler\\": "" 2266 | }, 2267 | "exclude-from-classmap": [ 2268 | "/Tests/" 2269 | ] 2270 | }, 2271 | "notification-url": "https://packagist.org/downloads/", 2272 | "license": [ 2273 | "MIT" 2274 | ], 2275 | "authors": [ 2276 | { 2277 | "name": "Fabien Potencier", 2278 | "email": "fabien@symfony.com" 2279 | }, 2280 | { 2281 | "name": "Symfony Community", 2282 | "homepage": "https://symfony.com/contributors" 2283 | } 2284 | ], 2285 | "description": "Symfony DomCrawler Component", 2286 | "homepage": "https://symfony.com", 2287 | "time": "2017-04-12T14:13:17+00:00" 2288 | }, 2289 | { 2290 | "name": "theseer/tokenizer", 2291 | "version": "1.1.0", 2292 | "source": { 2293 | "type": "git", 2294 | "url": "https://github.com/theseer/tokenizer.git", 2295 | "reference": "cb2f008f3f05af2893a87208fe6a6c4985483f8b" 2296 | }, 2297 | "dist": { 2298 | "type": "zip", 2299 | "url": "https://api.github.com/repos/theseer/tokenizer/zipball/cb2f008f3f05af2893a87208fe6a6c4985483f8b", 2300 | "reference": "cb2f008f3f05af2893a87208fe6a6c4985483f8b", 2301 | "shasum": "" 2302 | }, 2303 | "require": { 2304 | "ext-dom": "*", 2305 | "ext-tokenizer": "*", 2306 | "ext-xmlwriter": "*", 2307 | "php": "^7.0" 2308 | }, 2309 | "type": "library", 2310 | "autoload": { 2311 | "classmap": [ 2312 | "src/" 2313 | ] 2314 | }, 2315 | "notification-url": "https://packagist.org/downloads/", 2316 | "license": [ 2317 | "BSD-3-Clause" 2318 | ], 2319 | "authors": [ 2320 | { 2321 | "name": "Arne Blankerts", 2322 | "email": "arne@blankerts.de", 2323 | "role": "Developer" 2324 | } 2325 | ], 2326 | "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", 2327 | "time": "2017-04-07T12:08:54+00:00" 2328 | }, 2329 | { 2330 | "name": "webmozart/assert", 2331 | "version": "1.2.0", 2332 | "source": { 2333 | "type": "git", 2334 | "url": "https://github.com/webmozart/assert.git", 2335 | "reference": "2db61e59ff05fe5126d152bd0655c9ea113e550f" 2336 | }, 2337 | "dist": { 2338 | "type": "zip", 2339 | "url": "https://api.github.com/repos/webmozart/assert/zipball/2db61e59ff05fe5126d152bd0655c9ea113e550f", 2340 | "reference": "2db61e59ff05fe5126d152bd0655c9ea113e550f", 2341 | "shasum": "" 2342 | }, 2343 | "require": { 2344 | "php": "^5.3.3 || ^7.0" 2345 | }, 2346 | "require-dev": { 2347 | "phpunit/phpunit": "^4.6", 2348 | "sebastian/version": "^1.0.1" 2349 | }, 2350 | "type": "library", 2351 | "extra": { 2352 | "branch-alias": { 2353 | "dev-master": "1.3-dev" 2354 | } 2355 | }, 2356 | "autoload": { 2357 | "psr-4": { 2358 | "Webmozart\\Assert\\": "src/" 2359 | } 2360 | }, 2361 | "notification-url": "https://packagist.org/downloads/", 2362 | "license": [ 2363 | "MIT" 2364 | ], 2365 | "authors": [ 2366 | { 2367 | "name": "Bernhard Schussek", 2368 | "email": "bschussek@gmail.com" 2369 | } 2370 | ], 2371 | "description": "Assertions to validate method input/output with nice error messages.", 2372 | "keywords": [ 2373 | "assert", 2374 | "check", 2375 | "validate" 2376 | ], 2377 | "time": "2016-11-23T20:04:58+00:00" 2378 | }, 2379 | { 2380 | "name": "wmde/psr-log-test-doubles", 2381 | "version": "2.1.0", 2382 | "source": { 2383 | "type": "git", 2384 | "url": "https://github.com/wmde/PsrLogTestDoubles.git", 2385 | "reference": "95e1e6bd06d18b11575eb0dd0108b08e6a742463" 2386 | }, 2387 | "dist": { 2388 | "type": "zip", 2389 | "url": "https://api.github.com/repos/wmde/PsrLogTestDoubles/zipball/95e1e6bd06d18b11575eb0dd0108b08e6a742463", 2390 | "reference": "95e1e6bd06d18b11575eb0dd0108b08e6a742463", 2391 | "shasum": "" 2392 | }, 2393 | "require": { 2394 | "php": ">=7.0", 2395 | "psr/log": "~1.0" 2396 | }, 2397 | "require-dev": { 2398 | "mediawiki/mediawiki-codesniffer": "~0.6.0", 2399 | "ockcyp/covers-validator": "~0.4", 2400 | "squizlabs/php_codesniffer": "~2.5" 2401 | }, 2402 | "type": "library", 2403 | "extra": { 2404 | "branch-alias": { 2405 | "dev-master": "2.1.x-dev" 2406 | } 2407 | }, 2408 | "autoload": { 2409 | "psr-4": { 2410 | "WMDE\\PsrLogTestDoubles\\": "src/" 2411 | } 2412 | }, 2413 | "notification-url": "https://packagist.org/downloads/", 2414 | "license": [ 2415 | "GPL-2.0+" 2416 | ], 2417 | "description": "Test Doubles for the PSR-3 Logger Interface", 2418 | "homepage": "https://github.com/wmde/PsrLogTestDoubles", 2419 | "keywords": [ 2420 | "Fixture", 2421 | "LoggerSpy", 2422 | "Test Doubles", 2423 | "fixtures", 2424 | "log", 2425 | "logger spy", 2426 | "mock", 2427 | "mocks", 2428 | "psr", 2429 | "psr-3", 2430 | "spies", 2431 | "spy", 2432 | "test", 2433 | "test double" 2434 | ], 2435 | "time": "2017-01-17T09:04:52+00:00" 2436 | } 2437 | ], 2438 | "aliases": [], 2439 | "minimum-stability": "stable", 2440 | "stability-flags": [], 2441 | "prefer-stable": false, 2442 | "prefer-lowest": false, 2443 | "platform": { 2444 | "php": ">=7.1" 2445 | }, 2446 | "platform-dev": [] 2447 | } 2448 | --------------------------------------------------------------------------------