From 2f67b70363ca6ff16f1c86f443f23b6c21b5b456 Mon Sep 17 00:00:00 2001 From: Denis Golubovskiy Date: Sat, 16 Dec 2017 18:16:26 +0200 Subject: [PATCH 1/5] Add dependencies and first test --- .php_cs | 46 + .travis.yml | 30 + Command/RequestAPICommand.php | 65 +- .../AtlassianConnectExtension.php | 4 +- Model/JWTRequest.php | 8 +- Resources/config/services.yml | 35 +- Security/JWTAuthenticator.php | 5 +- Security/JWTUserProvider.php | 7 +- .../AtlassianConnectExtensionTest.php | 62 + composer.json | 35 +- composer.lock | 3942 ++++++++++++++++- phpunit.xml.dist | 25 + ruleset.xml | 70 + 13 files changed, 4214 insertions(+), 120 deletions(-) create mode 100644 .php_cs create mode 100644 .travis.yml create mode 100644 Tests/DependencyInjection/AtlassianConnectExtensionTest.php create mode 100644 phpunit.xml.dist create mode 100644 ruleset.xml diff --git a/.php_cs b/.php_cs new file mode 100644 index 0000000..636ec78 --- /dev/null +++ b/.php_cs @@ -0,0 +1,46 @@ +exclude('vendor') + ->in(__DIR__) +; + +return PhpCsFixer\Config::create() + ->setRiskyAllowed(true) + ->setRules([ + '@PSR1' => true, + '@PSR2' => true, + '@Symfony' => true, + '@Symfony:risky' => true, + '@PHP70Migration' => true, + '@PHP70Migration:risky' => true, + '@PHP71Migration' => true, + 'phpdoc_summary' => false, + 'yoda_style' => false, + 'self_accessor' => false, + 'combine_consecutive_unsets' => true, + 'blank_line_after_opening_tag' => false, + 'phpdoc_to_comment' => false, + 'phpdoc_no_empty_return' => false, + 'strict_param' => true, + 'doctrine_annotation_indentation' => true, + 'mb_str_functions' => true, + 'native_function_invocation' => true, + 'no_short_echo_tag' => true, + 'no_unreachable_default_argument_value' => true, + 'no_useless_else' => true, + 'no_useless_return' => true, + 'ordered_class_elements' => true, + 'phpdoc_add_missing_param_annotation' => true, + 'phpdoc_order' => true, + 'simplified_null_return' => false, + 'strict_comparison' => true, + 'ordered_imports' => ['sortAlgorithm' => 'alpha'], + 'declare_equal_normalize' => ['space' => 'single'], + 'array_syntax' => ['syntax' => 'short'], + 'list_syntax' => ['syntax' => 'short'], + 'doctrine_annotation_braces' => ['syntax' => 'with_braces'], + 'general_phpdoc_annotation_remove' => ['annotations' => ['author', 'created', 'version', 'package', 'copyright', 'license', 'throws']], + ]) + ->setFinder($finder) +; diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..d7d5b8a --- /dev/null +++ b/.travis.yml @@ -0,0 +1,30 @@ +language: php +sudo: false + +php: + - 7.1 + +env: + - SYMFONY_VERSION="3.3.*" + - SYMFONY_VERSION="4.0.*" + +before_script: + - composer self-update + - sed -i -e 's/^3.3|^4.0/${SYMFONY_VERSION}/g' composer.json; + - composer install --dev --prefer-dist --no-interaction -o + +script: + - ./vendor/bin/phpcs -p --standard=./ruleset.xml + - ./vendor/bin/phpunit -c phpunit.xml.dist --coverage-clover=coverage.xml + +after_success: + - bash <(curl -s https://codecov.io/bash) + +cache: + directories: + - $COMPOSER_CACHE_DIR + +notifications: + email: + - vitaliy.zurian@gmail.com + - bukashk0zzz@gmail.com diff --git a/Command/RequestAPICommand.php b/Command/RequestAPICommand.php index 75899ef..b5a7eb1 100644 --- a/Command/RequestAPICommand.php +++ b/Command/RequestAPICommand.php @@ -2,38 +2,73 @@ namespace AtlassianConnectBundle\Command; use AtlassianConnectBundle\Model\JWTRequest; -use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; +use Doctrine\Common\Persistence\ManagerRegistry; +use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -class RequestAPICommand extends ContainerAwareCommand +class RequestAPICommand extends Command { - protected function configure() + /** + * @var bool + */ + protected $shouldNotRun; + + /** + * @var \Doctrine\ORM\EntityManager + */ + private $em; + + /** + * @var string + */ + private $tenantClass; + + /** + * @param ManagerRegistry $registry + * @param string $tenantClass + */ + public function __construct(ManagerRegistry $registry, string $tenantClass) + { + $this->em = $registry->getManager(); + $this->tenantClass = $tenantClass; + + parent::__construct(); + } + + /** + * @return void + */ + protected function configure(): void { $this ->setName('ac:request-api') - ->addArgument('rest-url', InputArgument::REQUIRED, "REST api endpoint, like /rest/api/2/issue/{issueIdOrKey}") - ->addOption('client-key', "c", InputOption::VALUE_REQUIRED, "Client-key from tenant") - ->addOption('tenant-id', "t", InputOption::VALUE_REQUIRED, "Tenant-id") + ->addArgument('rest-url', InputArgument::REQUIRED, 'REST api endpoint, like /rest/api/2/issue/{issueIdOrKey}') + ->addOption('client-key', 'c', InputOption::VALUE_REQUIRED, 'Client-key from tenant') + ->addOption('tenant-id', 't', InputOption::VALUE_REQUIRED, 'Tenant-id') ->setDescription('Request REST end-points. Documentation available on https://docs.atlassian.com/jira/REST/cloud/'); } - protected function execute(InputInterface $input, OutputInterface $output) + /** + * @param InputInterface $input + * @param OutputInterface $output + * + * @return void + */ + protected function execute(InputInterface $input, OutputInterface $output): void { $restUrl = $input->getArgument('rest-url'); - $em = $this->getContainer()->get('doctrine')->getManager(); - $tenantClass = $this->getContainer()->getParameter("atlassian_connect_tenant_entity_class"); - if($input->getOption("tenant-id")) { - $tenant = $em->getRepository($tenantClass) - ->find($input->getOption("tenant-id")); - } elseif($input->getOption("client-key")) { - $tenant = $em->getRepository($tenantClass) + if($input->getOption('tenant-id')) { + $tenant = $this->em->getRepository($this->tenantClass) + ->find($input->getOption('tenant-id')); + } elseif($input->getOption('client-key')) { + $tenant = $this->em->getRepository($this->tenantClass) ->findOneByClientKey($input->getOption('client-key')); } else { - throw new \Exception("Please provide client-key or tenant-id"); + throw new \RuntimeException('Please provide client-key or tenant-id'); } $request = new JWTRequest($tenant); diff --git a/DependencyInjection/AtlassianConnectExtension.php b/DependencyInjection/AtlassianConnectExtension.php index 3a80321..aa53fc0 100644 --- a/DependencyInjection/AtlassianConnectExtension.php +++ b/DependencyInjection/AtlassianConnectExtension.php @@ -28,8 +28,8 @@ public function load(array $configs, ContainerBuilder $container) $config['dev'] = array_merge($prod, $dev); $container->setParameter('atlassian_connect', $config); - $container->setParameter('atlassian_connect_token_lifetime', $config["token_lifetime"]); - $container->setParameter('atlassian_connect_dev_tenant', $config["dev_tenant"]); + $container->setParameter('atlassian_connect_token_lifetime', $config['token_lifetime']); + $container->setParameter('atlassian_connect_dev_tenant', $config['dev_tenant']); $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); diff --git a/Model/JWTRequest.php b/Model/JWTRequest.php index 3cd04a1..db0359c 100644 --- a/Model/JWTRequest.php +++ b/Model/JWTRequest.php @@ -31,7 +31,7 @@ public function sendFile(UploadedFile $file, $restUrl) $savedFile = $file->move('/tmp/', $file->getClientOriginalName()); $options['body'] = [ - 'file' => fopen($savedFile->getRealPath(), 'r') + 'file' => fopen($savedFile->getRealPath(), 'rb') ]; unlink($savedFile->getRealPath()); @@ -51,7 +51,7 @@ public function put($restUrl, $json) return $response->json(); } - + public function post($restUrl, $json) { $url = $this->buildURL($restUrl); @@ -93,8 +93,8 @@ private function buildAuthHeader($method, $restUrl) private function buildURL($restUrl) { - // Jira return absolute self links, so its more easy to work with get with absolute urls in such cases - if((substr($restUrl,0,7) != 'http://') && (substr($restUrl,0,8) != 'https://')) { + // Jira return absolute self links, so its more easy to work with get with absolute urls in such cases + if((substr($restUrl,0,7) !== 'http://') && (substr($restUrl,0,8) !== 'https://')) { return $this->tenant->getBaseUrl().$restUrl; } else { return $restUrl; diff --git a/Resources/config/services.yml b/Resources/config/services.yml index ab26ca4..7202330 100644 --- a/Resources/config/services.yml +++ b/Resources/config/services.yml @@ -5,16 +5,37 @@ parameters: atlassian_connect_tenant_entity_class: AtlassianConnectBundle:Tenant services: + _defaults: + public: true + autowire: false + autoconfigure: true + + AtlassianConnectBundle\Command\RequestAPICommand: + public: false + arguments: + $registry: '@Doctrine\Common\Persistence\ManagerRegistry' + $tenantClass: '%atlassian_connect_tenant_entity_class%' + + kernel.listener.license_listener: - class: "%atlassian_connect_license_listener_class%" - arguments: ['@router', '@kernel', '@security.token_storage'] - tags: - - { name: kernel.event_listener, event: kernel.request, method: onKernelRequest } + class: '%atlassian_connect_license_listener_class%' + arguments: + $router: '@Symfony\Component\Routing\RouterInterface' + $kernel: '@Symfony\Component\HttpKernel\KernelInterface' + $tokenStorage: '@Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage' jwt_user_provider: - class: "%atlassian_connect_jwt_user_provider_class%" - arguments: ['@doctrine.orm.entity_manager','%atlassian_connect_token_lifetime%',"%atlassian_connect_tenant_entity_class%"] + class: '%atlassian_connect_jwt_user_provider_class%' + arguments: + $registry: '@Doctrine\Common\Persistence\ManagerRegistry' + $tokenLifetime: '%atlassian_connect_token_lifetime%' + $tenantClass: '%atlassian_connect_tenant_entity_class%' jwt_authenticator: class: "%atlassian_connect_jwt_authenticator_class%" - arguments: ['@jwt_user_provider', '@kernel', '@doctrine.orm.entity_manager', "%atlassian_connect_tenant_entity_class%", "%atlassian_connect_dev_tenant%"] \ No newline at end of file + arguments: + $userProvider: '@jwt_user_provider' + $kernel: '@Symfony\Component\HttpKernel\KernelInterface' + $registry: '@Doctrine\Common\Persistence\ManagerRegistry' + $tenantEntityClass: '%atlassian_connect_tenant_entity_class%' + $devTenant: '%atlassian_connect_dev_tenant%' diff --git a/Security/JWTAuthenticator.php b/Security/JWTAuthenticator.php index ca51a0a..49f4ce6 100644 --- a/Security/JWTAuthenticator.php +++ b/Security/JWTAuthenticator.php @@ -4,11 +4,12 @@ use AtlassianConnectBundle\Entity\Tenant; use AtlassianConnectBundle\Model\QSH; +use Doctrine\Common\Persistence\ManagerRegistry; use Doctrine\ORM\EntityManager; use AtlassianConnectBundle\JWT\Authentication\JWT; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\KernelInterface; -use Symfony\Component\Security\Core\Authentication\SimplePreAuthenticatorInterface; +use Symfony\Component\Security\Http\Authentication\SimplePreAuthenticatorInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken; @@ -32,7 +33,7 @@ class JWTAuthenticator implements SimplePreAuthenticatorInterface, Authenticatio protected $tenantEntityClass; protected $devTenant; - public function __construct(JWTUserProvider $userProvider, KernelInterface $kernel, EntityManager $em, $tenantEntityClass, $devTenant) + public function __construct(JWTUserProvider $userProvider, KernelInterface $kernel, ManagerRegistry $registry, $tenantEntityClass, $devTenant) { $this->userProvider = $userProvider; $this->kernel = $kernel; diff --git a/Security/JWTUserProvider.php b/Security/JWTUserProvider.php index 6fb8452..559c133 100644 --- a/Security/JWTUserProvider.php +++ b/Security/JWTUserProvider.php @@ -2,6 +2,7 @@ namespace AtlassianConnectBundle\Security; +use Doctrine\Common\Persistence\ManagerRegistry; use Doctrine\ORM\EntityManager; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; @@ -21,9 +22,9 @@ class JWTUserProvider implements UserProviderInterface protected $tokenLifetime; protected $tenantClass; - public function __construct(EntityManager $em, $tokenLifetime, $tenantClass) + public function __construct(ManagerRegistry $registry, $tokenLifetime, $tenantClass) { - $this->em = $em; + $this->em = $registry->getManager(); $this->tokenLifetime = $tokenLifetime; $this->tenantClass = $tenantClass; } @@ -77,4 +78,4 @@ protected function findTenant($clientKey) ->getRepository($this->tenantClass) ->findOneByClientKey($clientKey); } -} \ No newline at end of file +} diff --git a/Tests/DependencyInjection/AtlassianConnectExtensionTest.php b/Tests/DependencyInjection/AtlassianConnectExtensionTest.php new file mode 100644 index 0000000..e0284d7 --- /dev/null +++ b/Tests/DependencyInjection/AtlassianConnectExtensionTest.php @@ -0,0 +1,62 @@ +extension = new AtlassianConnectExtension(); + $this->container = new ContainerBuilder(); + $this->container->registerExtension($this->extension); + + } + + /** + * Test load extension + */ + public function testLoadExtension(): void + { + $this->container->set(RouterInterface::class, new \stdClass()); + $this->container->set(KernelInterface::class, new \stdClass()); + $this->container->set(TokenStorage::class, new \stdClass()); + $this->container->set(ManagerRegistry::class, new \stdClass()); + + $this->container->prependExtensionConfig($this->extension->getAlias(), [ + 'token_lifetime' => 86400, + 'dev_tenant' => 1, + 'prod' => [], + 'dev' => [], + ]); + $this->container->loadFromExtension($this->extension->getAlias()); + $this->container->compile(); + + // Check that services have been loaded + static::assertTrue($this->container->has('jwt_user_provider')); + static::assertTrue($this->container->has('jwt_authenticator')); + } +} diff --git a/composer.json b/composer.json index 7406d59..3da6f27 100644 --- a/composer.json +++ b/composer.json @@ -1,16 +1,43 @@ { "name": "thecatontheflat/atlassian-connect-bundle", - "description": "Atlassian Connect Symfony2 Bundle", - "license": "MIT", + "description": "Atlassian Connect Symfony Bundle", + "keywords": ["bundle", "symfony", "atlassian", "connect", "jira", "atlassian-connect"], + "homepage": "https://github.com/thecatontheflat/atlassian-connect-bundle", + "type": "symfony-bundle", + "license": "GPL-2.0", "require": { - "guzzlehttp/guzzle": "~5.0" + "php": "^7.1", + "symfony/dependency-injection": "^3.3|^4.0", + "symfony/http-kernel": "^3.3|^4.0", + "symfony/config": "^3.3|^4.0", + "symfony/yaml": "^3.3|^4.0", + "symfony/security": "^3.3|^4.0", + "symfony/routing": "^3.3|^4.0", + "symfony/console": "^3.3|^4.0", + "doctrine/orm": "^2.5", + "guzzlehttp/guzzle": "^6.0" + }, + "require-dev": { + "escapestudios/symfony2-coding-standard": "^3.0", + "friendsofphp/php-cs-fixer": "^2.3", + "slevomat/coding-standard": "^4.0", + "phpunit/phpunit": "^6.3" }, "authors": [ { "name": "Vitaliy Zurian", - "email": "vitaliy.zurian@gmail.com" + "email": "vitaliy.zurian@gmail.com", + "role": "Creator" + }, + { + "name": "Denis Golubovskiy", + "email": "bukashk0zzz@gmail.com" } ], + "support": { + "email": "vitaliy.zurian@gmail.com", + "issues": "https://github.com/thecatontheflat/atlassian-connect-bundle/issues" + }, "autoload": { "psr-4": {"AtlassianConnectBundle\\": ""} } diff --git a/composer.lock b/composer.lock index 05b13c2..0eee815 100644 --- a/composer.lock +++ b/composer.lock @@ -1,43 +1,42 @@ { "_readme": [ "This file locks the dependencies of your project to a known state", - "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "92207eef770cf8f1d656087dc7ecb8bd", + "content-hash": "31b47ee368b8ec00e3523e8cfaf22097", "packages": [ { - "name": "guzzlehttp/guzzle", - "version": "5.3.0", + "name": "doctrine/annotations", + "version": "v1.6.0", "source": { "type": "git", - "url": "https://github.com/guzzle/guzzle.git", - "reference": "f3c8c22471cb55475105c14769644a49c3262b93" + "url": "https://github.com/doctrine/annotations.git", + "reference": "c7f2050c68a9ab0bdb0f98567ec08d80ea7d24d5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/f3c8c22471cb55475105c14769644a49c3262b93", - "reference": "f3c8c22471cb55475105c14769644a49c3262b93", + "url": "https://api.github.com/repos/doctrine/annotations/zipball/c7f2050c68a9ab0bdb0f98567ec08d80ea7d24d5", + "reference": "c7f2050c68a9ab0bdb0f98567ec08d80ea7d24d5", "shasum": "" }, "require": { - "guzzlehttp/ringphp": "^1.1", - "php": ">=5.4.0" + "doctrine/lexer": "1.*", + "php": "^7.1" }, "require-dev": { - "ext-curl": "*", - "phpunit/phpunit": "^4.0", - "psr/log": "^1.0" + "doctrine/cache": "1.*", + "phpunit/phpunit": "^6.4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0-dev" + "dev-master": "1.6.x-dev" } }, "autoload": { "psr-4": { - "GuzzleHttp\\": "src/" + "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" } }, "notification-url": "https://packagist.org/downloads/", @@ -46,59 +45,73 @@ ], "authors": [ { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" } ], - "description": "Guzzle is a PHP HTTP client library and framework for building RESTful web service clients", - "homepage": "http://guzzlephp.org/", + "description": "Docblock Annotations Parser", + "homepage": "http://www.doctrine-project.org", "keywords": [ - "client", - "curl", - "framework", - "http", - "http client", - "rest", - "web service" + "annotations", + "docblock", + "parser" ], - "time": "2015-05-20 03:47:55" + "time": "2017-12-06T07:11:42+00:00" }, { - "name": "guzzlehttp/ringphp", - "version": "1.1.0", + "name": "doctrine/cache", + "version": "v1.7.1", "source": { "type": "git", - "url": "https://github.com/guzzle/RingPHP.git", - "reference": "dbbb91d7f6c191e5e405e900e3102ac7f261bc0b" + "url": "https://github.com/doctrine/cache.git", + "reference": "b3217d58609e9c8e661cd41357a54d926c4a2a1a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/RingPHP/zipball/dbbb91d7f6c191e5e405e900e3102ac7f261bc0b", - "reference": "dbbb91d7f6c191e5e405e900e3102ac7f261bc0b", + "url": "https://api.github.com/repos/doctrine/cache/zipball/b3217d58609e9c8e661cd41357a54d926c4a2a1a", + "reference": "b3217d58609e9c8e661cd41357a54d926c4a2a1a", "shasum": "" }, "require": { - "guzzlehttp/streams": "~3.0", - "php": ">=5.4.0", - "react/promise": "~2.0" + "php": "~7.1" + }, + "conflict": { + "doctrine/common": ">2.2,<2.4" }, "require-dev": { - "ext-curl": "*", - "phpunit/phpunit": "~4.0" + "alcaeus/mongo-php-adapter": "^1.1", + "mongodb/mongodb": "^1.1", + "phpunit/phpunit": "^5.7", + "predis/predis": "~1.0" }, "suggest": { - "ext-curl": "Guzzle will use specific adapters if cURL is present" + "alcaeus/mongo-php-adapter": "Required to use legacy MongoDB driver" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1-dev" + "dev-master": "1.7.x-dev" } }, "autoload": { "psr-4": { - "GuzzleHttp\\Ring\\": "src/" + "Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache" } }, "notification-url": "https://packagist.org/downloads/", @@ -107,43 +120,135 @@ ], "authors": [ { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" } ], - "description": "Provides a simple API and specification that abstracts away the details of HTTP into a single PHP function.", - "time": "2015-05-20 03:37:09" + "description": "Caching library offering an object-oriented API for many cache backends", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "cache", + "caching" + ], + "time": "2017-08-25T07:02:50+00:00" }, { - "name": "guzzlehttp/streams", - "version": "3.0.0", + "name": "doctrine/collections", + "version": "v1.5.0", "source": { "type": "git", - "url": "https://github.com/guzzle/streams.git", - "reference": "47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5" + "url": "https://github.com/doctrine/collections.git", + "reference": "a01ee38fcd999f34d9bfbcee59dbda5105449cbf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/streams/zipball/47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5", - "reference": "47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5", + "url": "https://api.github.com/repos/doctrine/collections/zipball/a01ee38fcd999f34d9bfbcee59dbda5105449cbf", + "reference": "a01ee38fcd999f34d9bfbcee59dbda5105449cbf", "shasum": "" }, "require": { - "php": ">=5.4.0" + "php": "^7.1" }, "require-dev": { - "phpunit/phpunit": "~4.0" + "doctrine/coding-standard": "~0.1@dev", + "phpunit/phpunit": "^5.7" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "1.3.x-dev" + } + }, + "autoload": { + "psr-0": { + "Doctrine\\Common\\Collections\\": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Collections Abstraction library", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "array", + "collections", + "iterator" + ], + "time": "2017-07-22T10:37:32+00:00" + }, + { + "name": "doctrine/common", + "version": "v2.8.1", + "source": { + "type": "git", + "url": "https://github.com/doctrine/common.git", + "reference": "f68c297ce6455e8fd794aa8ffaf9fa458f6ade66" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/common/zipball/f68c297ce6455e8fd794aa8ffaf9fa458f6ade66", + "reference": "f68c297ce6455e8fd794aa8ffaf9fa458f6ade66", + "shasum": "" + }, + "require": { + "doctrine/annotations": "1.*", + "doctrine/cache": "1.*", + "doctrine/collections": "1.*", + "doctrine/inflector": "1.*", + "doctrine/lexer": "1.*", + "php": "~7.1" + }, + "require-dev": { + "phpunit/phpunit": "^5.7" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8.x-dev" } }, "autoload": { "psr-4": { - "GuzzleHttp\\Stream\\": "src/" + "Doctrine\\Common\\": "lib/Doctrine/Common" } }, "notification-url": "https://packagist.org/downloads/", @@ -152,49 +257,258 @@ ], "authors": [ { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" } ], - "description": "Provides a simple abstraction over streams of data", - "homepage": "http://guzzlephp.org/", + "description": "Common Library for Doctrine projects", + "homepage": "http://www.doctrine-project.org", "keywords": [ - "Guzzle", - "stream" + "annotations", + "collections", + "eventmanager", + "persistence", + "spl" ], - "time": "2014-10-12 19:18:40" + "time": "2017-08-31T08:43:38+00:00" }, { - "name": "react/promise", - "version": "v2.2.0", + "name": "doctrine/dbal", + "version": "v2.6.3", "source": { "type": "git", - "url": "https://github.com/reactphp/promise.git", - "reference": "365fcee430dfa4ace1fbc75737ca60ceea7eeeef" + "url": "https://github.com/doctrine/dbal.git", + "reference": "e3eed9b1facbb0ced3a0995244843a189e7d1b13" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/promise/zipball/365fcee430dfa4ace1fbc75737ca60ceea7eeeef", - "reference": "365fcee430dfa4ace1fbc75737ca60ceea7eeeef", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/e3eed9b1facbb0ced3a0995244843a189e7d1b13", + "reference": "e3eed9b1facbb0ced3a0995244843a189e7d1b13", "shasum": "" }, "require": { - "php": ">=5.4.0" + "doctrine/common": "^2.7.1", + "ext-pdo": "*", + "php": "^7.1" + }, + "require-dev": { + "phpunit/phpunit": "^5.4.6", + "phpunit/phpunit-mock-objects": "!=3.2.4,!=3.2.5", + "symfony/console": "2.*||^3.0" + }, + "suggest": { + "symfony/console": "For helpful console commands such as SQL execution and import of files." }, + "bin": [ + "bin/doctrine-dbal" + ], "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-master": "2.6.x-dev" + } + }, + "autoload": { + "psr-0": { + "Doctrine\\DBAL\\": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + } + ], + "description": "Database Abstraction Layer", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "database", + "dbal", + "persistence", + "queryobject" + ], + "time": "2017-11-19T13:38:54+00:00" + }, + { + "name": "doctrine/inflector", + "version": "v1.2.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/inflector.git", + "reference": "e11d84c6e018beedd929cff5220969a3c6d1d462" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/e11d84c6e018beedd929cff5220969a3c6d1d462", + "reference": "e11d84c6e018beedd929cff5220969a3c6d1d462", + "shasum": "" + }, + "require": { + "php": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" } }, "autoload": { "psr-4": { - "React\\Promise\\": "src/" + "Doctrine\\Common\\Inflector\\": "lib/Doctrine/Common/Inflector" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" }, - "files": [ - "src/functions_include.php" - ] + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Common String Manipulations with regard to casing and singular/plural rules.", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "inflection", + "pluralize", + "singularize", + "string" + ], + "time": "2017-07-22T12:18:28+00:00" + }, + { + "name": "doctrine/instantiator", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/instantiator.git", + "reference": "185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda", + "reference": "185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "require-dev": { + "athletic/athletic": "~0.1.8", + "ext-pdo": "*", + "ext-phar": "*", + "phpunit/phpunit": "^6.2.3", + "squizlabs/php_codesniffer": "^3.0.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "http://ocramius.github.com/" + } + ], + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://github.com/doctrine/instantiator", + "keywords": [ + "constructor", + "instantiate" + ], + "time": "2017-07-22T11:58:36+00:00" + }, + { + "name": "doctrine/lexer", + "version": "v1.0.1", + "source": { + "type": "git", + "url": "https://github.com/doctrine/lexer.git", + "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/83893c552fd2045dd78aef794c31e694c37c0b8c", + "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-0": { + "Doctrine\\Common\\Lexer\\": "lib/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -202,20 +516,3482 @@ ], "authors": [ { - "name": "Jan Sorgalla", - "email": "jsorgalla@googlemail.com" + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "lexer", + "parser" + ], + "time": "2014-09-09T13:34:57+00:00" + }, + { + "name": "doctrine/orm", + "version": "v2.5.13", + "source": { + "type": "git", + "url": "https://github.com/doctrine/doctrine2.git", + "reference": "93103f44a3e36e7b48165b6e6b736833f33b18ef" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/doctrine2/zipball/93103f44a3e36e7b48165b6e6b736833f33b18ef", + "reference": "93103f44a3e36e7b48165b6e6b736833f33b18ef", + "shasum": "" + }, + "require": { + "doctrine/cache": "~1.4", + "doctrine/collections": "~1.2", + "doctrine/common": ">=2.5-dev,<2.9-dev", + "doctrine/dbal": ">=2.5-dev,<2.7-dev", + "doctrine/instantiator": "^1.0.1", + "ext-pdo": "*", + "php": ">=5.4", + "symfony/console": "~2.5|~3.0|~4.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0", + "symfony/yaml": "~2.3|~3.0|~4.0" + }, + "suggest": { + "symfony/yaml": "If you want to use YAML Metadata Mapping Driver" + }, + "bin": [ + "bin/doctrine", + "bin/doctrine.php" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.6.x-dev" } + }, + "autoload": { + "psr-0": { + "Doctrine\\ORM\\": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + } + ], + "description": "Object-Relational-Mapper for PHP", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "database", + "orm" + ], + "time": "2017-11-27T23:25:55+00:00" + }, + { + "name": "guzzlehttp/guzzle", + "version": "6.3.0", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "f4db5a78a5ea468d4831de7f0bf9d9415e348699" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/f4db5a78a5ea468d4831de7f0bf9d9415e348699", + "reference": "f4db5a78a5ea468d4831de7f0bf9d9415e348699", + "shasum": "" + }, + "require": { + "guzzlehttp/promises": "^1.0", + "guzzlehttp/psr7": "^1.4", + "php": ">=5.5" + }, + "require-dev": { + "ext-curl": "*", + "phpunit/phpunit": "^4.0 || ^5.0", + "psr/log": "^1.0" + }, + "suggest": { + "psr/log": "Required for using the Log middleware" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "6.2-dev" + } + }, + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "GuzzleHttp\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle is a PHP HTTP client library", + "homepage": "http://guzzlephp.org/", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "rest", + "web service" + ], + "time": "2017-06-22T18:50:49+00:00" + }, + { + "name": "guzzlehttp/promises", + "version": "v1.3.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/promises.git", + "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646", + "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646", + "shasum": "" + }, + "require": { + "php": ">=5.5.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Promise\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle promises library", + "keywords": [ + "promise" + ], + "time": "2016-12-20T10:07:11+00:00" + }, + { + "name": "guzzlehttp/psr7", + "version": "1.4.2", + "source": { + "type": "git", + "url": "https://github.com/guzzle/psr7.git", + "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/f5b8a8512e2b58b0071a7280e39f14f72e05d87c", + "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c", + "shasum": "" + }, + "require": { + "php": ">=5.4.0", + "psr/http-message": "~1.0" + }, + "provide": { + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Psr7\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Schultze", + "homepage": "https://github.com/Tobion" + } + ], + "description": "PSR-7 message implementation that also provides common utility methods", + "keywords": [ + "http", + "message", + "request", + "response", + "stream", + "uri", + "url" + ], + "time": "2017-03-20T17:10:46+00:00" + }, + { + "name": "psr/container", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f", + "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "time": "2017-02-14T16:28:37+00:00" + }, + { + "name": "psr/http-message", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "time": "2016-08-06T14:39:51+00:00" + }, + { + "name": "psr/log", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", + "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "Psr/Log/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "time": "2016-10-10T12:19:37+00:00" + }, + { + "name": "symfony/config", + "version": "v4.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/config.git", + "reference": "0356e6d5298e9e72212c0bad65c2f1b49e42d622" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/config/zipball/0356e6d5298e9e72212c0bad65c2f1b49e42d622", + "reference": "0356e6d5298e9e72212c0bad65c2f1b49e42d622", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/filesystem": "~3.4|~4.0" + }, + "conflict": { + "symfony/finder": "<3.4" + }, + "require-dev": { + "symfony/finder": "~3.4|~4.0", + "symfony/yaml": "~3.4|~4.0" + }, + "suggest": { + "symfony/yaml": "To use the yaml reference dumper" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Config\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Config Component", + "homepage": "https://symfony.com", + "time": "2017-12-14T19:48:22+00:00" + }, + { + "name": "symfony/console", + "version": "v4.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "de8cf039eacdec59d83f7def67e3b8ff5ed46714" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/de8cf039eacdec59d83f7def67e3b8ff5ed46714", + "reference": "de8cf039eacdec59d83f7def67e3b8ff5ed46714", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/dependency-injection": "<3.4", + "symfony/process": "<3.3" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "~3.4|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/event-dispatcher": "~3.4|~4.0", + "symfony/lock": "~3.4|~4.0", + "symfony/process": "~3.4|~4.0" + }, + "suggest": { + "psr/log": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/lock": "", + "symfony/process": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Console Component", + "homepage": "https://symfony.com", + "time": "2017-12-14T19:48:22+00:00" + }, + { + "name": "symfony/debug", + "version": "v4.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/debug.git", + "reference": "8c3e709209ce3b952a31c0f4a31ac7703c3d0226" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/debug/zipball/8c3e709209ce3b952a31c0f4a31ac7703c3d0226", + "reference": "8c3e709209ce3b952a31c0f4a31ac7703c3d0226", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "psr/log": "~1.0" + }, + "conflict": { + "symfony/http-kernel": "<3.4" + }, + "require-dev": { + "symfony/http-kernel": "~3.4|~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Debug\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Debug Component", + "homepage": "https://symfony.com", + "time": "2017-12-12T08:41:51+00:00" + }, + { + "name": "symfony/dependency-injection", + "version": "v4.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/dependency-injection.git", + "reference": "d2fa088b5fd7d429974a36bf1a9846b912d9d124" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/d2fa088b5fd7d429974a36bf1a9846b912d9d124", + "reference": "d2fa088b5fd7d429974a36bf1a9846b912d9d124", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "psr/container": "^1.0" + }, + "conflict": { + "symfony/config": "<3.4", + "symfony/finder": "<3.4", + "symfony/proxy-manager-bridge": "<3.4", + "symfony/yaml": "<3.4" + }, + "provide": { + "psr/container-implementation": "1.0" + }, + "require-dev": { + "symfony/config": "~3.4|~4.0", + "symfony/expression-language": "~3.4|~4.0", + "symfony/yaml": "~3.4|~4.0" + }, + "suggest": { + "symfony/config": "", + "symfony/expression-language": "For using expressions in service container configuration", + "symfony/finder": "For using double-star glob patterns or when GLOB_BRACE portability is required", + "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them", + "symfony/yaml": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\DependencyInjection\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony DependencyInjection Component", + "homepage": "https://symfony.com", + "time": "2017-12-14T19:48:22+00:00" + }, + { + "name": "symfony/event-dispatcher", + "version": "v4.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "d4face19ed8002eec8280bc1c5ec18130472bf43" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/d4face19ed8002eec8280bc1c5ec18130472bf43", + "reference": "d4face19ed8002eec8280bc1c5ec18130472bf43", + "shasum": "" + }, + "require": { + "php": "^7.1.3" + }, + "conflict": { + "symfony/dependency-injection": "<3.4" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "~3.4|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/expression-language": "~3.4|~4.0", + "symfony/stopwatch": "~3.4|~4.0" + }, + "suggest": { + "symfony/dependency-injection": "", + "symfony/http-kernel": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\EventDispatcher\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony EventDispatcher Component", + "homepage": "https://symfony.com", + "time": "2017-12-14T19:48:22+00:00" + }, + { + "name": "symfony/filesystem", + "version": "v4.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/filesystem.git", + "reference": "8c2868641d0c4885eee9c12a89c2b695eb1985cd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/8c2868641d0c4885eee9c12a89c2b695eb1985cd", + "reference": "8c2868641d0c4885eee9c12a89c2b695eb1985cd", + "shasum": "" + }, + "require": { + "php": "^7.1.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Filesystem\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Filesystem Component", + "homepage": "https://symfony.com", + "time": "2017-12-14T19:48:22+00:00" + }, + { + "name": "symfony/http-foundation", + "version": "v4.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-foundation.git", + "reference": "aba96bd07be7796c81ca0ceafa7d48a6fef036c8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/aba96bd07be7796c81ca0ceafa7d48a6fef036c8", + "reference": "aba96bd07be7796c81ca0ceafa7d48a6fef036c8", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/polyfill-mbstring": "~1.1" + }, + "require-dev": { + "symfony/expression-language": "~3.4|~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpFoundation\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony HttpFoundation Component", + "homepage": "https://symfony.com", + "time": "2017-12-14T19:48:22+00:00" + }, + { + "name": "symfony/http-kernel", + "version": "v4.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-kernel.git", + "reference": "f2ea7461cdcad837b8bc6022b59d5eb8c9618aa5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/f2ea7461cdcad837b8bc6022b59d5eb8c9618aa5", + "reference": "f2ea7461cdcad837b8bc6022b59d5eb8c9618aa5", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "psr/log": "~1.0", + "symfony/debug": "~3.4|~4.0", + "symfony/event-dispatcher": "~3.4|~4.0", + "symfony/http-foundation": "~3.4|~4.0" + }, + "conflict": { + "symfony/config": "<3.4", + "symfony/dependency-injection": "<3.4", + "symfony/var-dumper": "<3.4", + "twig/twig": "<1.34|<2.4,>=2" + }, + "provide": { + "psr/log-implementation": "1.0" + }, + "require-dev": { + "psr/cache": "~1.0", + "symfony/browser-kit": "~3.4|~4.0", + "symfony/config": "~3.4|~4.0", + "symfony/console": "~3.4|~4.0", + "symfony/css-selector": "~3.4|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/dom-crawler": "~3.4|~4.0", + "symfony/expression-language": "~3.4|~4.0", + "symfony/finder": "~3.4|~4.0", + "symfony/process": "~3.4|~4.0", + "symfony/routing": "~3.4|~4.0", + "symfony/stopwatch": "~3.4|~4.0", + "symfony/templating": "~3.4|~4.0", + "symfony/translation": "~3.4|~4.0", + "symfony/var-dumper": "~3.4|~4.0" + }, + "suggest": { + "symfony/browser-kit": "", + "symfony/config": "", + "symfony/console": "", + "symfony/dependency-injection": "", + "symfony/var-dumper": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpKernel\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony HttpKernel Component", + "homepage": "https://symfony.com", + "time": "2017-12-15T03:06:17+00:00" + }, + { + "name": "symfony/inflector", + "version": "v4.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/inflector.git", + "reference": "8740990f67ec9f89bfa116d11bad2990dd510ece" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/inflector/zipball/8740990f67ec9f89bfa116d11bad2990dd510ece", + "reference": "8740990f67ec9f89bfa116d11bad2990dd510ece", + "shasum": "" + }, + "require": { + "php": "^7.1.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Inflector\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Inflector Component", + "homepage": "https://symfony.com", + "keywords": [ + "inflection", + "pluralize", + "singularize", + "string", + "symfony", + "words" + ], + "time": "2017-08-31T20:46:21+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.6.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "2ec8b39c38cb16674bbf3fea2b6ce5bf117e1296" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/2ec8b39c38cb16674bbf3fea2b6ce5bf117e1296", + "reference": "2ec8b39c38cb16674bbf3fea2b6ce5bf117e1296", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.6-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "time": "2017-10-11T12:05:26+00:00" + }, + { + "name": "symfony/property-access", + "version": "v4.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/property-access.git", + "reference": "8dc059852b7bdd8b871eb3ca95b8d70be3b39488" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/property-access/zipball/8dc059852b7bdd8b871eb3ca95b8d70be3b39488", + "reference": "8dc059852b7bdd8b871eb3ca95b8d70be3b39488", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/inflector": "~3.4|~4.0" + }, + "require-dev": { + "symfony/cache": "~3.4|~4.0" + }, + "suggest": { + "psr/cache-implementation": "To cache access methods." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\PropertyAccess\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony PropertyAccess Component", + "homepage": "https://symfony.com", + "keywords": [ + "access", + "array", + "extraction", + "index", + "injection", + "object", + "property", + "property path", + "reflection" + ], + "time": "2017-12-14T00:19:09+00:00" + }, + { + "name": "symfony/routing", + "version": "v4.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/routing.git", + "reference": "972810def5cae044d19195045f7eb418141bf37b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/routing/zipball/972810def5cae044d19195045f7eb418141bf37b", + "reference": "972810def5cae044d19195045f7eb418141bf37b", + "shasum": "" + }, + "require": { + "php": "^7.1.3" + }, + "conflict": { + "symfony/config": "<3.4", + "symfony/dependency-injection": "<3.4", + "symfony/yaml": "<3.4" + }, + "require-dev": { + "doctrine/annotations": "~1.0", + "doctrine/common": "~2.2", + "psr/log": "~1.0", + "symfony/config": "~3.4|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/expression-language": "~3.4|~4.0", + "symfony/http-foundation": "~3.4|~4.0", + "symfony/yaml": "~3.4|~4.0" + }, + "suggest": { + "doctrine/annotations": "For using the annotation loader", + "symfony/config": "For using the all-in-one router or any loader", + "symfony/dependency-injection": "For loading routes from a service", + "symfony/expression-language": "For using expression matching", + "symfony/http-foundation": "For using a Symfony Request object", + "symfony/yaml": "For using the YAML loader" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Routing\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Routing Component", + "homepage": "https://symfony.com", + "keywords": [ + "router", + "routing", + "uri", + "url" + ], + "time": "2017-12-14T22:39:22+00:00" + }, + { + "name": "symfony/security", + "version": "v4.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/security.git", + "reference": "6ff0f1e97f583583c10152e4050e8a4fac2cfd1e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/security/zipball/6ff0f1e97f583583c10152e4050e8a4fac2cfd1e", + "reference": "6ff0f1e97f583583c10152e4050e8a4fac2cfd1e", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/event-dispatcher": "~3.4|~4.0", + "symfony/http-foundation": "~3.4|~4.0", + "symfony/http-kernel": "~3.4|~4.0", + "symfony/property-access": "~3.4|~4.0" + }, + "replace": { + "symfony/security-core": "self.version", + "symfony/security-csrf": "self.version", + "symfony/security-guard": "self.version", + "symfony/security-http": "self.version" + }, + "require-dev": { + "psr/container": "^1.0", + "psr/log": "~1.0", + "symfony/expression-language": "~3.4|~4.0", + "symfony/finder": "~3.4|~4.0", + "symfony/ldap": "~3.4|~4.0", + "symfony/polyfill-intl-icu": "~1.0", + "symfony/routing": "~3.4|~4.0", + "symfony/validator": "~3.4|~4.0" + }, + "suggest": { + "psr/container": "To instantiate the Security class", + "symfony/expression-language": "For using the expression voter", + "symfony/form": "", + "symfony/ldap": "For using the LDAP user and authentication providers", + "symfony/routing": "For using the HttpUtils class to create sub-requests, redirect the user, and match URLs", + "symfony/validator": "For using the user password constraint" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Security\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Security Component", + "homepage": "https://symfony.com", + "time": "2017-12-14T19:48:22+00:00" + }, + { + "name": "symfony/yaml", + "version": "v4.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "a5ee52d155f06ad23b19eb63c31228ff56ad1116" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/a5ee52d155f06ad23b19eb63c31228ff56ad1116", + "reference": "a5ee52d155f06ad23b19eb63c31228ff56ad1116", + "shasum": "" + }, + "require": { + "php": "^7.1.3" + }, + "conflict": { + "symfony/console": "<3.4" + }, + "require-dev": { + "symfony/console": "~3.4|~4.0" + }, + "suggest": { + "symfony/console": "For validating YAML files using the lint command" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Yaml\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Yaml Component", + "homepage": "https://symfony.com", + "time": "2017-12-12T08:41:51+00:00" + } + ], + "packages-dev": [ + { + "name": "composer/semver", + "version": "1.4.2", + "source": { + "type": "git", + "url": "https://github.com/composer/semver.git", + "reference": "c7cb9a2095a074d131b65a8a0cd294479d785573" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/semver/zipball/c7cb9a2095a074d131b65a8a0cd294479d785573", + "reference": "c7cb9a2095a074d131b65a8a0cd294479d785573", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.5 || ^5.0.5", + "phpunit/phpunit-mock-objects": "2.3.0 || ^3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Semver\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nils Adermann", + "email": "naderman@naderman.de", + "homepage": "http://www.naderman.de" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + }, + { + "name": "Rob Bast", + "email": "rob.bast@gmail.com", + "homepage": "http://robbast.nl" + } + ], + "description": "Semver library that offers utilities, version constraint parsing and validation.", + "keywords": [ + "semantic", + "semver", + "validation", + "versioning" + ], + "time": "2016-08-30T16:08:34+00:00" + }, + { + "name": "escapestudios/symfony2-coding-standard", + "version": "3.0.1", + "source": { + "type": "git", + "url": "https://github.com/djoos/Symfony-coding-standard.git", + "reference": "b6209fe525a8119b5923ee94023cb26a71953038" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/djoos/Symfony-coding-standard/zipball/b6209fe525a8119b5923ee94023cb26a71953038", + "reference": "b6209fe525a8119b5923ee94023cb26a71953038", + "shasum": "" + }, + "require": { + "squizlabs/php_codesniffer": "3.*" + }, + "type": "phpcodesniffer-standard", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "David Joos", + "email": "iam@davidjoos.com" + }, + { + "name": "Community contributors", + "homepage": "https://github.com/djoos/Symfony-coding-standard/graphs/contributors" + } + ], + "description": "CodeSniffer ruleset for the Symfony 2+ coding standard", + "homepage": "https://github.com/djoos/Symfony2-coding-standard", + "keywords": [ + "Coding Standard", + "Symfony2", + "phpcs", + "symfony" + ], + "time": "2017-11-09T12:15:48+00:00" + }, + { + "name": "friendsofphp/php-cs-fixer", + "version": "v2.9.0", + "source": { + "type": "git", + "url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git", + "reference": "454ddbe65da6a9297446f442bad244e8a99a9a38" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/454ddbe65da6a9297446f442bad244e8a99a9a38", + "reference": "454ddbe65da6a9297446f442bad244e8a99a9a38", + "shasum": "" + }, + "require": { + "composer/semver": "^1.4", + "doctrine/annotations": "^1.2", + "ext-json": "*", + "ext-tokenizer": "*", + "gecko-packages/gecko-php-unit": "^2.0 || ^3.0", + "php": "^5.6 || >=7.0 <7.3", + "php-cs-fixer/diff": "^1.2", + "symfony/console": "^3.2 || ^4.0", + "symfony/event-dispatcher": "^3.0 || ^4.0", + "symfony/filesystem": "^3.0 || ^4.0", + "symfony/finder": "^3.0 || ^4.0", + "symfony/options-resolver": "^3.0 || ^4.0", + "symfony/polyfill-php70": "^1.0", + "symfony/polyfill-php72": "^1.4", + "symfony/process": "^3.0 || ^4.0", + "symfony/stopwatch": "^3.0 || ^4.0" + }, + "conflict": { + "hhvm": "*" + }, + "require-dev": { + "johnkary/phpunit-speedtrap": "^1.1 || ^2.0@dev", + "justinrainbow/json-schema": "^5.0", + "mikey179/vfsstream": "^1.6", + "php-coveralls/php-coveralls": "^2.0", + "php-cs-fixer/accessible-object": "^1.0", + "phpunit/phpunit": "^5.7.23 || ^6.4.3", + "symfony/phpunit-bridge": "^3.2.2 || ^4.0" + }, + "suggest": { + "ext-mbstring": "For handling non-UTF8 characters in cache signature.", + "symfony/polyfill-mbstring": "When enabling `ext-mbstring` is not possible." + }, + "bin": [ + "php-cs-fixer" + ], + "type": "application", + "autoload": { + "psr-4": { + "PhpCsFixer\\": "src/" + }, + "classmap": [ + "tests/Test/Assert/AssertTokensTrait.php", + "tests/Test/AbstractFixerTestCase.php", + "tests/Test/AbstractIntegrationTestCase.php", + "tests/Test/IntegrationCase.php", + "tests/Test/IntegrationCaseFactory.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Dariusz Rumiński", + "email": "dariusz.ruminski@gmail.com" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "A tool to automatically fix PHP code style", + "time": "2017-12-08T16:36:20+00:00" + }, + { + "name": "gecko-packages/gecko-php-unit", + "version": "v3.0", + "source": { + "type": "git", + "url": "https://github.com/GeckoPackages/GeckoPHPUnit.git", + "reference": "6a866551dffc2154c1b091bae3a7877d39c25ca3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/GeckoPackages/GeckoPHPUnit/zipball/6a866551dffc2154c1b091bae3a7877d39c25ca3", + "reference": "6a866551dffc2154c1b091bae3a7877d39c25ca3", + "shasum": "" + }, + "require": { + "php": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "suggest": { + "ext-dom": "When testing with xml.", + "ext-libxml": "When testing with xml.", + "phpunit/phpunit": "This is an extension for it so make sure you have it some way." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "psr-4": { + "GeckoPackages\\PHPUnit\\": "src/PHPUnit" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Additional PHPUnit asserts and constraints.", + "homepage": "https://github.com/GeckoPackages", + "keywords": [ + "extension", + "filesystem", + "phpunit" + ], + "time": "2017-08-23T07:46:41+00:00" + }, + { + "name": "myclabs/deep-copy", + "version": "1.7.0", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", + "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0" + }, + "require-dev": { + "doctrine/collections": "^1.0", + "doctrine/common": "^2.6", + "phpunit/phpunit": "^4.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + }, + "files": [ + "src/DeepCopy/deep_copy.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "time": "2017-10-19T19:58:43+00:00" + }, + { + "name": "paragonie/random_compat", + "version": "v2.0.11", + "source": { + "type": "git", + "url": "https://github.com/paragonie/random_compat.git", + "reference": "5da4d3c796c275c55f057af5a643ae297d96b4d8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paragonie/random_compat/zipball/5da4d3c796c275c55f057af5a643ae297d96b4d8", + "reference": "5da4d3c796c275c55f057af5a643ae297d96b4d8", + "shasum": "" + }, + "require": { + "php": ">=5.2.0" + }, + "require-dev": { + "phpunit/phpunit": "4.*|5.*" + }, + "suggest": { + "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." + }, + "type": "library", + "autoload": { + "files": [ + "lib/random.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Paragon Initiative Enterprises", + "email": "security@paragonie.com", + "homepage": "https://paragonie.com" + } + ], + "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", + "keywords": [ + "csprng", + "pseudorandom", + "random" + ], + "time": "2017-09-27T21:40:39+00:00" + }, + { + "name": "phar-io/manifest", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/manifest.git", + "reference": "2df402786ab5368a0169091f61a7c1e0eb6852d0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/2df402786ab5368a0169091f61a7c1e0eb6852d0", + "reference": "2df402786ab5368a0169091f61a7c1e0eb6852d0", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-phar": "*", + "phar-io/version": "^1.0.1", + "php": "^5.6 || ^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "time": "2017-03-05T18:14:27+00:00" + }, + { + "name": "phar-io/version", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/version.git", + "reference": "a70c0ced4be299a63d32fa96d9281d03e94041df" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/version/zipball/a70c0ced4be299a63d32fa96d9281d03e94041df", + "reference": "a70c0ced4be299a63d32fa96d9281d03e94041df", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "time": "2017-03-05T17:38:23+00:00" + }, + { + "name": "php-cs-fixer/diff", + "version": "v1.2.0", + "source": { + "type": "git", + "url": "https://github.com/PHP-CS-Fixer/diff.git", + "reference": "f0ef6133d674137e902fdf8a6f2e8e97e14a087b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHP-CS-Fixer/diff/zipball/f0ef6133d674137e902fdf8a6f2e8e97e14a087b", + "reference": "f0ef6133d674137e902fdf8a6f2e8e97e14a087b", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.4.3", + "symfony/process": "^3.3" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "authors": [ + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "SpacePossum" + } + ], + "description": "sebastian/diff v2 backport support for PHP5.6", + "homepage": "https://github.com/PHP-CS-Fixer", + "keywords": [ + "diff" + ], + "time": "2017-10-19T09:58:18+00:00" + }, + { + "name": "phpdocumentor/reflection-common", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionCommon.git", + "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", + "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", + "shasum": "" + }, + "require": { + "php": ">=5.5" + }, + "require-dev": { + "phpunit/phpunit": "^4.6" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "Common reflection classes used by phpdocumentor to reflect the code structure", + "homepage": "http://www.phpdoc.org", + "keywords": [ + "FQSEN", + "phpDocumentor", + "phpdoc", + "reflection", + "static analysis" + ], + "time": "2017-09-11T18:02:19+00:00" + }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "4.2.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "66465776cfc249844bde6d117abff1d22e06c2da" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/66465776cfc249844bde6d117abff1d22e06c2da", + "reference": "66465776cfc249844bde6d117abff1d22e06c2da", + "shasum": "" + }, + "require": { + "php": "^7.0", + "phpdocumentor/reflection-common": "^1.0.0", + "phpdocumentor/type-resolver": "^0.4.0", + "webmozart/assert": "^1.0" + }, + "require-dev": { + "doctrine/instantiator": "~1.0.5", + "mockery/mockery": "^1.0", + "phpunit/phpunit": "^6.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "time": "2017-11-27T17:38:31+00:00" + }, + { + "name": "phpdocumentor/type-resolver", + "version": "0.4.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7", + "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7", + "shasum": "" + }, + "require": { + "php": "^5.5 || ^7.0", + "phpdocumentor/reflection-common": "^1.0" + }, + "require-dev": { + "mockery/mockery": "^0.9.4", + "phpunit/phpunit": "^5.2||^4.8.24" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "time": "2017-07-14T14:27:02+00:00" + }, + { + "name": "phpspec/prophecy", + "version": "1.7.3", + "source": { + "type": "git", + "url": "https://github.com/phpspec/prophecy.git", + "reference": "e4ed002c67da8eceb0eb8ddb8b3847bb53c5c2bf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/e4ed002c67da8eceb0eb8ddb8b3847bb53c5c2bf", + "reference": "e4ed002c67da8eceb0eb8ddb8b3847bb53c5c2bf", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.0.2", + "php": "^5.3|^7.0", + "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0", + "sebastian/comparator": "^1.1|^2.0", + "sebastian/recursion-context": "^1.0|^2.0|^3.0" + }, + "require-dev": { + "phpspec/phpspec": "^2.5|^3.2", + "phpunit/phpunit": "^4.8.35 || ^5.7" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.7.x-dev" + } + }, + "autoload": { + "psr-0": { + "Prophecy\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + }, + { + "name": "Marcello Duarte", + "email": "marcello.duarte@gmail.com" + } + ], + "description": "Highly opinionated mocking framework for PHP 5.3+", + "homepage": "https://github.com/phpspec/prophecy", + "keywords": [ + "Double", + "Dummy", + "fake", + "mock", + "spy", + "stub" + ], + "time": "2017-11-24T13:59:53+00:00" + }, + { + "name": "phpunit/php-code-coverage", + "version": "5.3.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "661f34d0bd3f1a7225ef491a70a020ad23a057a1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/661f34d0bd3f1a7225ef491a70a020ad23a057a1", + "reference": "661f34d0bd3f1a7225ef491a70a020ad23a057a1", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-xmlwriter": "*", + "php": "^7.0", + "phpunit/php-file-iterator": "^1.4.2", + "phpunit/php-text-template": "^1.2.1", + "phpunit/php-token-stream": "^2.0.1", + "sebastian/code-unit-reverse-lookup": "^1.0.1", + "sebastian/environment": "^3.0", + "sebastian/version": "^2.0.1", + "theseer/tokenizer": "^1.1" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "suggest": { + "ext-xdebug": "^2.5.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.3.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "time": "2017-12-06T09:29:45+00:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "1.4.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/730b01bc3e867237eaac355e06a36b85dd93a8b4", + "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "time": "2017-11-27T13:52:08+00:00" + }, + { + "name": "phpunit/php-text-template", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "time": "2015-06-21T13:50:34+00:00" + }, + { + "name": "phpunit/php-timer", + "version": "1.0.9", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", + "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", + "shasum": "" + }, + "require": { + "php": "^5.3.3 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "time": "2017-02-26T11:10:40+00:00" + }, + { + "name": "phpunit/php-token-stream", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-token-stream.git", + "reference": "791198a2c6254db10131eecfe8c06670700904db" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/791198a2c6254db10131eecfe8c06670700904db", + "reference": "791198a2c6254db10131eecfe8c06670700904db", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.2.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Wrapper around PHP's tokenizer extension.", + "homepage": "https://github.com/sebastianbergmann/php-token-stream/", + "keywords": [ + "tokenizer" + ], + "time": "2017-11-27T05:48:46+00:00" + }, + { + "name": "phpunit/phpunit", + "version": "6.5.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "1b2f933d5775f9237369deaa2d2bfbf9d652be4c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/1b2f933d5775f9237369deaa2d2bfbf9d652be4c", + "reference": "1b2f933d5775f9237369deaa2d2bfbf9d652be4c", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "myclabs/deep-copy": "^1.6.1", + "phar-io/manifest": "^1.0.1", + "phar-io/version": "^1.0", + "php": "^7.0", + "phpspec/prophecy": "^1.7", + "phpunit/php-code-coverage": "^5.3", + "phpunit/php-file-iterator": "^1.4.3", + "phpunit/php-text-template": "^1.2.1", + "phpunit/php-timer": "^1.0.9", + "phpunit/phpunit-mock-objects": "^5.0.5", + "sebastian/comparator": "^2.1", + "sebastian/diff": "^2.0", + "sebastian/environment": "^3.1", + "sebastian/exporter": "^3.1", + "sebastian/global-state": "^2.0", + "sebastian/object-enumerator": "^3.0.3", + "sebastian/resource-operations": "^1.0", + "sebastian/version": "^2.0.1" + }, + "conflict": { + "phpdocumentor/reflection-docblock": "3.0.2", + "phpunit/dbunit": "<3.0" + }, + "require-dev": { + "ext-pdo": "*" + }, + "suggest": { + "ext-xdebug": "*", + "phpunit/php-invoker": "^1.1" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "6.5.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "time": "2017-12-10T08:06:19+00:00" + }, + { + "name": "phpunit/phpunit-mock-objects", + "version": "5.0.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", + "reference": "283b9f4f670e3a6fd6c4ff95c51a952eb5c75933" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/283b9f4f670e3a6fd6c4ff95c51a952eb5c75933", + "reference": "283b9f4f670e3a6fd6c4ff95c51a952eb5c75933", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.0.5", + "php": "^7.0", + "phpunit/php-text-template": "^1.2.1", + "sebastian/exporter": "^3.1" + }, + "conflict": { + "phpunit/phpunit": "<6.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.5" + }, + "suggest": { + "ext-soap": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Mock Object library for PHPUnit", + "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", + "keywords": [ + "mock", + "xunit" + ], + "time": "2017-12-10T08:01:53+00:00" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", + "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^5.7 || ^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "time": "2017-03-04T06:30:41+00:00" + }, + { + "name": "sebastian/comparator", + "version": "2.1.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "1174d9018191e93cb9d719edec01257fc05f8158" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/1174d9018191e93cb9d719edec01257fc05f8158", + "reference": "1174d9018191e93cb9d719edec01257fc05f8158", + "shasum": "" + }, + "require": { + "php": "^7.0", + "sebastian/diff": "^2.0", + "sebastian/exporter": "^3.1" + }, + "require-dev": { + "phpunit/phpunit": "^6.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.1.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "time": "2017-11-03T07:16:52+00:00" + }, + { + "name": "sebastian/diff", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "347c1d8b49c5c3ee30c7040ea6fc446790e6bddd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/347c1d8b49c5c3ee30c7040ea6fc446790e6bddd", + "reference": "347c1d8b49c5c3ee30c7040ea6fc446790e6bddd", + "shasum": "" + }, + "require": { + "php": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff" + ], + "time": "2017-08-03T08:09:46+00:00" + }, + { + "name": "sebastian/environment", + "version": "3.1.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "cd0871b3975fb7fc44d11314fd1ee20925fce4f5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/cd0871b3975fb7fc44d11314fd1ee20925fce4f5", + "reference": "cd0871b3975fb7fc44d11314fd1ee20925fce4f5", + "shasum": "" + }, + "require": { + "php": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "http://www.github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "time": "2017-07-01T08:51:00+00:00" + }, + { + "name": "sebastian/exporter", + "version": "3.1.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "234199f4528de6d12aaa58b612e98f7d36adb937" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/234199f4528de6d12aaa58b612e98f7d36adb937", + "reference": "234199f4528de6d12aaa58b612e98f7d36adb937", + "shasum": "" + }, + "require": { + "php": "^7.0", + "sebastian/recursion-context": "^3.0" + }, + "require-dev": { + "ext-mbstring": "*", + "phpunit/phpunit": "^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "http://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "time": "2017-04-03T13:19:02+00:00" + }, + { + "name": "sebastian/global-state", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", + "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", + "shasum": "" + }, + "require": { + "php": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "suggest": { + "ext-uopz": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "time": "2017-04-27T15:39:26+00:00" + }, + { + "name": "sebastian/object-enumerator", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/7cfd9e65d11ffb5af41198476395774d4c8a84c5", + "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5", + "shasum": "" + }, + "require": { + "php": "^7.0", + "sebastian/object-reflector": "^1.1.1", + "sebastian/recursion-context": "^3.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "time": "2017-08-03T12:35:26+00:00" + }, + { + "name": "sebastian/object-reflector", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "773f97c67f28de00d397be301821b06708fca0be" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/773f97c67f28de00d397be301821b06708fca0be", + "reference": "773f97c67f28de00d397be301821b06708fca0be", + "shasum": "" + }, + "require": { + "php": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "time": "2017-03-29T09:07:27+00:00" + }, + { + "name": "sebastian/recursion-context", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", + "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", + "shasum": "" + }, + "require": { + "php": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "http://www.github.com/sebastianbergmann/recursion-context", + "time": "2017-03-03T06:23:57+00:00" + }, + { + "name": "sebastian/resource-operations", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/resource-operations.git", + "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", + "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", + "shasum": "" + }, + "require": { + "php": ">=5.6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides a list of PHP built-in functions that operate on resources", + "homepage": "https://www.github.com/sebastianbergmann/resource-operations", + "time": "2015-07-28T20:34:47+00:00" + }, + { + "name": "sebastian/version", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", + "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "time": "2016-10-03T07:35:21+00:00" + }, + { + "name": "slevomat/coding-standard", + "version": "4.0.0", + "source": { + "type": "git", + "url": "https://github.com/slevomat/coding-standard.git", + "reference": "bab653d0f7f2e3ed13796f7803067d252f00a25a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/bab653d0f7f2e3ed13796f7803067d252f00a25a", + "reference": "bab653d0f7f2e3ed13796f7803067d252f00a25a", + "shasum": "" + }, + "require": { + "php": "^7.0", + "squizlabs/php_codesniffer": "^3.0.1" + }, + "require-dev": { + "jakub-onderka/php-parallel-lint": "0.9.2", + "phing/phing": "2.16", + "phpstan/phpstan": "0.8.4", + "phpunit/phpunit": "6.3.0" + }, + "type": "phpcodesniffer-standard", + "autoload": { + "psr-4": { + "SlevomatCodingStandard\\": "SlevomatCodingStandard" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Slevomat Coding Standard for PHP_CodeSniffer complements Consistence Coding Standard by providing sniffs with additional checks.", + "time": "2017-09-15T17:47:36+00:00" + }, + { + "name": "squizlabs/php_codesniffer", + "version": "3.2.0", + "source": { + "type": "git", + "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", + "reference": "ba816f2e1bacc16278792c78b67c730dfff064a6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/ba816f2e1bacc16278792c78b67c730dfff064a6", + "reference": "ba816f2e1bacc16278792c78b67c730dfff064a6", + "shasum": "" + }, + "require": { + "ext-simplexml": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0" + }, + "bin": [ + "bin/phpcs", + "bin/phpcbf" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Greg Sherwood", + "role": "lead" + } + ], + "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", + "homepage": "http://www.squizlabs.com/php-codesniffer", + "keywords": [ + "phpcs", + "standards" + ], + "time": "2017-12-12T21:36:10+00:00" + }, + { + "name": "symfony/finder", + "version": "v4.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "c9cdda4dc4a3182d8d6daeebce4a25fef078ea4c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/c9cdda4dc4a3182d8d6daeebce4a25fef078ea4c", + "reference": "c9cdda4dc4a3182d8d6daeebce4a25fef078ea4c", + "shasum": "" + }, + "require": { + "php": "^7.1.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Finder Component", + "homepage": "https://symfony.com", + "time": "2017-11-07T14:45:01+00:00" + }, + { + "name": "symfony/options-resolver", + "version": "v4.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/options-resolver.git", + "reference": "75fdda335eb0adbd464089e8a0184c61097808e0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/75fdda335eb0adbd464089e8a0184c61097808e0", + "reference": "75fdda335eb0adbd464089e8a0184c61097808e0", + "shasum": "" + }, + "require": { + "php": "^7.1.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\OptionsResolver\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony OptionsResolver Component", + "homepage": "https://symfony.com", + "keywords": [ + "config", + "configuration", + "options" + ], + "time": "2017-12-14T19:48:22+00:00" + }, + { + "name": "symfony/polyfill-php70", + "version": "v1.6.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php70.git", + "reference": "0442b9c0596610bd24ae7b5f0a6cdbbc16d9fcff" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/0442b9c0596610bd24ae7b5f0a6cdbbc16d9fcff", + "reference": "0442b9c0596610bd24ae7b5f0a6cdbbc16d9fcff", + "shasum": "" + }, + "require": { + "paragonie/random_compat": "~1.0|~2.0", + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.6-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php70\\": "" + }, + "files": [ + "bootstrap.php" + ], + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 7.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "time": "2017-10-11T12:05:26+00:00" + }, + { + "name": "symfony/polyfill-php72", + "version": "v1.6.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php72.git", + "reference": "6de4f4884b97abbbed9f0a84a95ff2ff77254254" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/6de4f4884b97abbbed9f0a84a95ff2ff77254254", + "reference": "6de4f4884b97abbbed9f0a84a95ff2ff77254254", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.6-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php72\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "time": "2017-10-11T12:05:26+00:00" + }, + { + "name": "symfony/process", + "version": "v4.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/process.git", + "reference": "18d1953068e72262830bad593f0366fa62c93fb7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/process/zipball/18d1953068e72262830bad593f0366fa62c93fb7", + "reference": "18d1953068e72262830bad593f0366fa62c93fb7", + "shasum": "" + }, + "require": { + "php": "^7.1.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Process\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Process Component", + "homepage": "https://symfony.com", + "time": "2017-12-14T19:48:22+00:00" + }, + { + "name": "symfony/stopwatch", + "version": "v4.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/stopwatch.git", + "reference": "ac0e49150555c703fef6b696d8eaba1db7a3ca03" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/ac0e49150555c703fef6b696d8eaba1db7a3ca03", + "reference": "ac0e49150555c703fef6b696d8eaba1db7a3ca03", + "shasum": "" + }, + "require": { + "php": "^7.1.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Stopwatch\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Stopwatch Component", + "homepage": "https://symfony.com", + "time": "2017-11-09T12:45:29+00:00" + }, + { + "name": "theseer/tokenizer", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/theseer/tokenizer.git", + "reference": "cb2f008f3f05af2893a87208fe6a6c4985483f8b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/cb2f008f3f05af2893a87208fe6a6c4985483f8b", + "reference": "cb2f008f3f05af2893a87208fe6a6c4985483f8b", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + } + ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "time": "2017-04-07T12:08:54+00:00" + }, + { + "name": "webmozart/assert", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/webmozart/assert.git", + "reference": "2db61e59ff05fe5126d152bd0655c9ea113e550f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozart/assert/zipball/2db61e59ff05fe5126d152bd0655c9ea113e550f", + "reference": "2db61e59ff05fe5126d152bd0655c9ea113e550f", + "shasum": "" + }, + "require": { + "php": "^5.3.3 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.6", + "sebastian/version": "^1.0.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" ], - "description": "A lightweight implementation of CommonJS Promises/A for PHP", - "time": "2014-12-30 13:32:42" + "time": "2016-11-23T20:04:58+00:00" } ], - "packages-dev": [], "aliases": [], "minimum-stability": "stable", "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, - "platform": [], + "platform": { + "php": "^7.1" + }, "platform-dev": [] } diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 0000000..43679d9 --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,25 @@ + + + + + + + ./Tests + + + + + + ./ + + ./Resources + ./Tests + ./vendor + + + + diff --git a/ruleset.xml b/ruleset.xml new file mode 100644 index 0000000..3ad8093 --- /dev/null +++ b/ruleset.xml @@ -0,0 +1,70 @@ + + + Coding standard. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + 0 + + + + + + + vendor/ + + ./ + From cf29ff19793a009c40e8f867ab5aa2d86eb7e380 Mon Sep 17 00:00:00 2001 From: Denis Golubovskiy Date: Sat, 16 Dec 2017 18:19:05 +0200 Subject: [PATCH 2/5] Fix code style --- .gitignore | 1 + AtlassianConnectBundle.php | 5 +- Command/RequestAPICommand.php | 12 +- Controller/DescriptorController.php | 40 ++++- Controller/HandshakeController.php | 70 ++++++-- Controller/UnlicensedController.php | 29 ++- .../AtlassianConnectExtension.php | 16 +- DependencyInjection/Configuration.php | 12 +- Entity/Tenant.php | 6 +- Entity/TenantTrait.php | 167 +++++++++++------- JWT/Authentication/JWT.php | 147 ++++++++------- JWT/Exceptions/BeforeValidException.php | 6 +- JWT/Exceptions/ExpiredException.php | 6 +- JWT/Exceptions/SignatureInvalidException.php | 6 +- Listener/LicenseListener.php | 32 ++-- Model/JWTRequest.php | 103 ++++++++--- Model/QSH.php | 38 ++-- Resources/config/services.yml | 20 +++ Security/JWTAuthenticator.php | 100 ++++++++--- Security/JWTUserProvider.php | 69 ++++++-- .../AtlassianConnectExtensionTest.php | 10 +- composer.json | 4 +- composer.lock | 126 ++++++++++++- 23 files changed, 737 insertions(+), 288 deletions(-) diff --git a/.gitignore b/.gitignore index ccb47ac..6fb9c71 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .idea/* /vendor/ +.php_cs.cache diff --git a/AtlassianConnectBundle.php b/AtlassianConnectBundle.php index 8b0d467..a40491e 100644 --- a/AtlassianConnectBundle.php +++ b/AtlassianConnectBundle.php @@ -1,9 +1,12 @@ -getArgument('rest-url'); - if($input->getOption('tenant-id')) { + if ($input->getOption('tenant-id')) { $tenant = $this->em->getRepository($this->tenantClass) ->find($input->getOption('tenant-id')); - } elseif($input->getOption('client-key')) { + } elseif ($input->getOption('client-key')) { $tenant = $this->em->getRepository($this->tenantClass) ->findOneByClientKey($input->getOption('client-key')); } else { @@ -75,7 +79,7 @@ protected function execute(InputInterface $input, OutputInterface $output): void $json = $request->get($restUrl); $output->writeln(''); - print json_encode($json, JSON_PRETTY_PRINT); + echo \json_encode($json, \JSON_PRETTY_PRINT); $output->writeln(''); } } diff --git a/Controller/DescriptorController.php b/Controller/DescriptorController.php index cb97b3d..97c2c4e 100644 --- a/Controller/DescriptorController.php +++ b/Controller/DescriptorController.php @@ -1,18 +1,42 @@ -kernel = $kernel; + $this->config = $config; + } + + /** + * @return Response + */ + public function indexAction(): Response { - $kernel = $this->container->get('kernel'); - $config = $this->getParameter('atlassian_connect'); - $envConfig = $config[$kernel->getEnvironment()]; - $descriptor = json_encode($envConfig); + $envConfig = $this->config[$this->kernel->getEnvironment()]; + $descriptor = \json_encode($envConfig); $response = new Response(); $response->setContent($descriptor); diff --git a/Controller/HandshakeController.php b/Controller/HandshakeController.php index c2489d6..c343c4e 100644 --- a/Controller/HandshakeController.php +++ b/Controller/HandshakeController.php @@ -1,38 +1,74 @@ -getContent(); - $content = json_decode($content, true); + $this->em = $registry->getManager(); + $this->logger = $logger; + $this->tenantClass = $tenantClass; + } - $tenantClass = $this->getParameter("atlassian_connect_tenant_entity_class"); - $tenant = $this->getDoctrine()->getRepository($tenantClass) - ->findOneByClientKey($content['clientKey']); + /** + * @param Request $request + * + * @return Response + */ + public function registerAction(Request $request): Response + { + $content = $request->getContent(); + $content = \json_decode($content, true); - if ($tenant) { + /** @var Tenant $tenant */ + $tenant = $this->em->getRepository($this->tenantClass)->findOneByClientKey($content['clientKey']); + if ($tenant !== null) { try { - $authorizationHeaderArray = explode(' ', $request->headers->get('authorization')); - if (count($authorizationHeaderArray) > 1) { + $authorizationHeaderArray = \explode(' ', $request->headers->get('authorization')); + if (\count($authorizationHeaderArray) > 1) { $jwt = $authorizationHeaderArray[1]; JWT::decode($jwt, $tenant->getSharedSecret(), ['HS256']); } else { throw new \InvalidArgumentException('Bad authorization header'); } - } catch (\Exception $e) { - $this->get('logger')->error($e->getMessage(), ['exception' => $e]); + } catch (\Throwable $e) { + $this->logger->error($e->getMessage(), ['exception' => $e]); + return new Response('Unauthorized', 401); } } else { + $tenantClass = $this->tenantClass; $tenant = new $tenantClass(); } @@ -48,8 +84,8 @@ public function registerAction(Request $request) ->setDescription($content['description']) ->setEventType($content['eventType']); - $this->getDoctrine()->getManager()->persist($tenant); - $this->getDoctrine()->getManager()->flush(); + $this->em->persist($tenant); + $this->em->flush(); return new Response('OK', 200); } diff --git a/Controller/UnlicensedController.php b/Controller/UnlicensedController.php index 2fae462..96e97dc 100644 --- a/Controller/UnlicensedController.php +++ b/Controller/UnlicensedController.php @@ -1,13 +1,30 @@ -twig = $twig; + } + + /** + * @return string + */ + public function unlicensedAction(): string { - return $this->render('@AtlassianConnect/unlicensed.html.twig'); + return $this->twig->render('@AtlassianConnect/unlicensed.html.twig'); } } diff --git a/DependencyInjection/AtlassianConnectExtension.php b/DependencyInjection/AtlassianConnectExtension.php index aa53fc0..ffb21ec 100644 --- a/DependencyInjection/AtlassianConnectExtension.php +++ b/DependencyInjection/AtlassianConnectExtension.php @@ -1,11 +1,11 @@ -processConfiguration($configuration, $configs); @@ -25,13 +28,12 @@ public function load(array $configs, ContainerBuilder $container) $prod = $config['prod']; $dev = $config['dev']; - $config['dev'] = array_merge($prod, $dev); + $config['dev'] = \array_merge($prod, $dev); $container->setParameter('atlassian_connect', $config); $container->setParameter('atlassian_connect_token_lifetime', $config['token_lifetime']); $container->setParameter('atlassian_connect_dev_tenant', $config['dev_tenant']); - $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); $loader->load('services.yml'); } diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index 97593f7..d1a5bd2 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -1,4 +1,4 @@ -root('atlassian_connect'); @@ -28,10 +26,6 @@ public function getConfigTreeBuilder() ->end() ; - // Here you should define the parameters that are allowed to - // configure your bundle. See the documentation linked above for - // more information on that topic. - return $treeBuilder; } } diff --git a/Entity/Tenant.php b/Entity/Tenant.php index a81bb10..fca09bd 100644 --- a/Entity/Tenant.php +++ b/Entity/Tenant.php @@ -1,10 +1,8 @@ -createdAt = new \DateTime(); $this->updatedAt = new \DateTime(); @@ -122,15 +135,17 @@ public function setCreatedAt() /** * @return \DateTime */ - public function getCreatedAt() + public function getCreatedAt(): \DateTime { return $this->createdAt; } /** - * @ORM\PreUpdate + * @ORM\PreUpdate() + * + * @return void */ - public function setUpdatedAt() + public function setUpdatedAt(): void { $this->updatedAt = new \DateTime(); } @@ -138,18 +153,17 @@ public function setUpdatedAt() /** * @return \DateTime */ - public function getUpdatedAt() + public function getUpdatedAt(): \DateTime { return $this->updatedAt; } - /** * Get id * - * @return integer + * @return int|null */ - public function getId() + public function getId(): ?int { return $this->id; } @@ -158,9 +172,10 @@ public function getId() * Set addonKey * * @param string $addonKey + * * @return self */ - public function setAddonKey($addonKey) + public function setAddonKey(string $addonKey): self { $this->addonKey = $addonKey; @@ -170,9 +185,9 @@ public function setAddonKey($addonKey) /** * Get addonKey * - * @return string + * @return string|null */ - public function getAddonKey() + public function getAddonKey(): ?string { return $this->addonKey; } @@ -181,9 +196,10 @@ public function getAddonKey() * Set clientKey * * @param string $clientKey + * * @return self */ - public function setClientKey($clientKey) + public function setClientKey(string $clientKey): self { $this->clientKey = $clientKey; @@ -193,9 +209,9 @@ public function setClientKey($clientKey) /** * Get clientKey * - * @return string + * @return string|null */ - public function getClientKey() + public function getClientKey(): ?string { return $this->clientKey; } @@ -204,9 +220,10 @@ public function getClientKey() * Set publicKey * * @param string $publicKey + * * @return self */ - public function setPublicKey($publicKey) + public function setPublicKey(string $publicKey): self { $this->publicKey = $publicKey; @@ -216,9 +233,9 @@ public function setPublicKey($publicKey) /** * Get publicKey * - * @return string + * @return string|null */ - public function getPublicKey() + public function getPublicKey(): ?string { return $this->publicKey; } @@ -227,9 +244,10 @@ public function getPublicKey() * Set sharedSecret * * @param string $sharedSecret + * * @return self */ - public function setSharedSecret($sharedSecret) + public function setSharedSecret(string $sharedSecret): self { $this->sharedSecret = $sharedSecret; @@ -239,9 +257,9 @@ public function setSharedSecret($sharedSecret) /** * Get sharedSecret * - * @return string + * @return string|null */ - public function getSharedSecret() + public function getSharedSecret(): ?string { return $this->sharedSecret; } @@ -250,9 +268,10 @@ public function getSharedSecret() * Set serverVersion * * @param string $serverVersion + * * @return self */ - public function setServerVersion($serverVersion) + public function setServerVersion(string $serverVersion): self { $this->serverVersion = $serverVersion; @@ -262,9 +281,9 @@ public function setServerVersion($serverVersion) /** * Get serverVersion * - * @return string + * @return string|null */ - public function getServerVersion() + public function getServerVersion(): ?string { return $this->serverVersion; } @@ -273,9 +292,10 @@ public function getServerVersion() * Set pluginsVersion * * @param string $pluginsVersion + * * @return self */ - public function setPluginsVersion($pluginsVersion) + public function setPluginsVersion(string $pluginsVersion): self { $this->pluginsVersion = $pluginsVersion; @@ -285,9 +305,9 @@ public function setPluginsVersion($pluginsVersion) /** * Get pluginsVersion * - * @return string + * @return string|null */ - public function getPluginsVersion() + public function getPluginsVersion(): ?string { return $this->pluginsVersion; } @@ -296,9 +316,10 @@ public function getPluginsVersion() * Set baseUrl * * @param string $baseUrl + * * @return self */ - public function setBaseUrl($baseUrl) + public function setBaseUrl(string $baseUrl): self { $this->baseUrl = $baseUrl; @@ -308,9 +329,9 @@ public function setBaseUrl($baseUrl) /** * Get baseUrl * - * @return string + * @return string|null */ - public function getBaseUrl() + public function getBaseUrl(): ?string { return $this->baseUrl; } @@ -319,9 +340,10 @@ public function getBaseUrl() * Set productType * * @param string $productType + * * @return self */ - public function setProductType($productType) + public function setProductType(string $productType): self { $this->productType = $productType; @@ -331,9 +353,9 @@ public function setProductType($productType) /** * Get productType * - * @return string + * @return string|null */ - public function getProductType() + public function getProductType(): ?string { return $this->productType; } @@ -342,9 +364,10 @@ public function getProductType() * Set description * * @param string $description + * * @return self */ - public function setDescription($description) + public function setDescription(string $description): self { $this->description = $description; @@ -354,9 +377,9 @@ public function setDescription($description) /** * Get description * - * @return string + * @return string|null */ - public function getDescription() + public function getDescription(): ?string { return $this->description; } @@ -365,9 +388,10 @@ public function getDescription() * Set eventType * * @param string $eventType + * * @return self */ - public function setEventType($eventType) + public function setEventType(string $eventType): self { $this->eventType = $eventType; @@ -377,90 +401,113 @@ public function setEventType($eventType) /** * Get eventType * - * @return string + * @return string|null */ - public function getEventType() + public function getEventType(): ?string { return $this->eventType; } /** - * * Implementing UserInterface * + * @return string[] */ - public function getRoles() + public function getRoles(): array { return ['ROLE_USER']; } - public function getPassword() + /** + * @return string + */ + public function getPassword(): string { return ''; } - - public function getSalt() + /** + * @return string + */ + public function getSalt(): string { return ''; } - public function getUsername() + /** + * @return null|string + */ + public function getUsername(): ?string { return $this->username; } - public function setUsername($name) + /** + * @param string $name + * + * @return self + */ + public function setUsername(string $name): self { $this->username = $name; + + return $this; } - public function eraseCredentials() + /** + * @return void + */ + public function eraseCredentials(): void { } /** - * @return boolean + * @return bool */ - public function getIsWhiteListed() + public function getIsWhiteListed(): bool { return $this->isWhiteListed; } /** - * @param boolean $isWhiteListed + * @param bool $isWhiteListed + * * @return self */ - public function setIsWhiteListed($isWhiteListed) + public function setIsWhiteListed(bool $isWhiteListed): self { $this->isWhiteListed = $isWhiteListed; + return $this; } /** * @return null|\DateTime */ - public function getWhiteListedUntil() + public function getWhiteListedUntil(): ?\DateTime { return $this->whiteListedUntil; } /** * @param \DateTime $whiteListedUntil + * * @return self */ - public function setWhiteListedUntil($whiteListedUntil) + public function setWhiteListedUntil(\DateTime $whiteListedUntil): self { $this->whiteListedUntil = $whiteListedUntil; + return $this; } /** - * @return boolean + * @return bool */ - public function isWhiteListed() + public function isWhiteListed(): bool { $now = new \DateTime(); - return $this->getIsWhiteListed() && (is_null($this->getWhiteListedUntil()) || ($now < $this->getWhiteListedUntil())); + + return $this->getIsWhiteListed() && ($this->getWhiteListedUntil() === null || ($now < $this->getWhiteListedUntil())); } -} \ No newline at end of file +} diff --git a/JWT/Authentication/JWT.php b/JWT/Authentication/JWT.php index 1f5e2b9..1a2264f 100644 --- a/JWT/Authentication/JWT.php +++ b/JWT/Authentication/JWT.php @@ -1,4 +1,4 @@ - array('hash_hmac', 'SHA256'), - 'HS512' => array('hash_hmac', 'SHA512'), - 'HS384' => array('hash_hmac', 'SHA384'), - 'RS256' => array('openssl', 'SHA256'), - ); - - public static function decode($jwt, $key = null, $allowedAlgs = array(), $extraSeconds = 0) + /** + * @var mixed[] + */ + public static $supportedAlgs = [ + 'HS256' => ['hash_hmac', 'SHA256'], + 'HS512' => ['hash_hmac', 'SHA512'], + 'HS384' => ['hash_hmac', 'SHA384'], + 'RS256' => ['openssl', 'SHA256'], + ]; + + public static function decode(string $jwt, $key = null, array $allowedAlgs = [], int $extraSeconds = 0) { - $tks = explode('.', $jwt); - if (count($tks) != 3) { + $tks = \explode('.', $jwt); + if (\count($tks) !== 3) { throw new \UnexpectedValueException('Wrong number of segments'); } - list($headb64, $bodyb64, $cryptob64) = $tks; - if (null === ($header = json_decode(JWT::urlsafeB64Decode($headb64)))) { + [$headb64, $bodyb64, $cryptob64] = $tks; + if (($header = \json_decode(JWT::urlsafeB64Decode($headb64))) === null) { throw new \UnexpectedValueException('Invalid header encoding'); } - if (null === $payload = json_decode(JWT::urlsafeB64Decode($bodyb64))) { + $payload = \json_decode(JWT::urlsafeB64Decode($bodyb64)); + if ($payload === null) { throw new \UnexpectedValueException('Invalid claims encoding'); } $sig = JWT::urlsafeB64Decode($cryptob64); @@ -40,10 +47,10 @@ public static function decode($jwt, $key = null, $allowedAlgs = array(), $extraS if (empty(self::$supportedAlgs[$header->alg])) { throw new \DomainException('Algorithm not supported'); } - if (!is_array($allowedAlgs) || !in_array($header->alg, $allowedAlgs)) { + if (!\is_array($allowedAlgs) || !\in_array($header->alg, $allowedAlgs, true)) { throw new \DomainException('Algorithm not allowed'); } - if (is_array($key)) { + if (\is_array($key)) { if (isset($header->kid)) { $key = $key[$header->kid]; } else { @@ -57,23 +64,23 @@ public static function decode($jwt, $key = null, $allowedAlgs = array(), $extraS // Check if the nbf if it is defined. This is the time that the // token can actually be used. If it's not yet that time, abort. - if (isset($payload->nbf) && $payload->nbf > time()) { + if (isset($payload->nbf) && $payload->nbf > \time()) { throw new BeforeValidException( - 'Cannot handle token prior to '.date(\DateTime::ISO8601, $payload->nbf) + 'Cannot handle token prior to '.\date(\DateTime::ISO8601, $payload->nbf) ); } // Check that this token has been created before 'now'. This prevents // using tokens that have been created for later use (and haven't // correctly used the nbf claim). - if (isset($payload->iat) && $payload->iat > time()) { + if (isset($payload->iat) && $payload->iat > \time()) { throw new BeforeValidException( - 'Cannot handle token prior to '.date(\DateTime::ISO8601, $payload->iat) + 'Cannot handle token prior to '.\date(\DateTime::ISO8601, $payload->iat) ); } // Check if this token has expired. - if (isset($payload->exp) && time() >= ($payload->exp + $extraSeconds)) { + if (isset($payload->exp) && \time() >= ($payload->exp + $extraSeconds)) { throw new ExpiredException('Expired token'); } } @@ -83,19 +90,19 @@ public static function decode($jwt, $key = null, $allowedAlgs = array(), $extraS public static function encode($payload, $key, $alg = 'HS256', $keyId = null) { - $header = array('typ' => 'JWT', 'alg' => $alg); + $header = ['typ' => 'JWT', 'alg' => $alg]; if ($keyId !== null) { $header['kid'] = $keyId; } - $segments = array(); - $segments[] = JWT::urlsafeB64Encode(json_encode($header)); - $segments[] = JWT::urlsafeB64Encode(json_encode($payload)); - $signing_input = implode('.', $segments); + $segments = []; + $segments[] = JWT::urlsafeB64Encode(\json_encode($header)); + $segments[] = JWT::urlsafeB64Encode(\json_encode($payload)); + $signing_input = \implode('.', $segments); $signature = JWT::sign($signing_input, $key, $alg); $segments[] = JWT::urlsafeB64Encode($signature); - return implode('.', $segments); + return \implode('.', $segments); } public static function sign($msg, $key, $alg = 'HS256') @@ -103,19 +110,35 @@ public static function sign($msg, $key, $alg = 'HS256') if (empty(self::$supportedAlgs[$alg])) { throw new \DomainException('Algorithm not supported'); } - list($function, $algorithm) = self::$supportedAlgs[$alg]; + [$function, $algorithm] = self::$supportedAlgs[$alg]; switch ($function) { case 'hash_hmac': - return hash_hmac($algorithm, $msg, $key, true); + return \hash_hmac($algorithm, $msg, $key, true); case 'openssl': $signature = ''; - $success = openssl_sign($msg, $signature, $key, $algorithm); + $success = \openssl_sign($msg, $signature, $key, $algorithm); if (!$success) { - throw new \DomainException("OpenSSL unable to sign data"); - } else { - return $signature; + throw new \DomainException('OpenSSL unable to sign data'); } + + return $signature; + } + } + + public static function urlsafeB64Decode($input) + { + $remainder = \mb_strlen($input) % 4; + if ($remainder) { + $padlen = 4 - $remainder; + $input .= \str_repeat('=', $padlen); } + + return \base64_decode(\strtr($input, '-_', '+/'), true); + } + + public static function urlsafeB64Encode($input) + { + return \str_replace('=', '', \strtr(\base64_encode($input), '+/', '-_')); } private static function verify($msg, $signature, $key, $alg) @@ -124,55 +147,45 @@ private static function verify($msg, $signature, $key, $alg) throw new \DomainException('Algorithm not supported'); } - list($function, $algorithm) = self::$supportedAlgs[$alg]; + [$function, $algorithm] = self::$supportedAlgs[$alg]; switch ($function) { case 'openssl': - $success = openssl_verify($msg, $signature, $key, $algorithm); + $success = \openssl_verify($msg, $signature, $key, $algorithm); if (!$success) { - throw new \DomainException("OpenSSL unable to verify data: ".openssl_error_string()); - } else { - return $signature; + throw new \DomainException('OpenSSL unable to verify data: '.\openssl_error_string()); } + + return $signature; + case 'hash_hmac': default: - $hash = hash_hmac($algorithm, $msg, $key, true); - if (function_exists('hash_equals')) { - return hash_equals($signature, $hash); + $hash = \hash_hmac($algorithm, $msg, $key, true); + if (\function_exists('hash_equals')) { + return \hash_equals($signature, $hash); } - $len = min(self::safeStrlen($signature), self::safeStrlen($hash)); + $len = \min(self::safeStrlen($signature), self::safeStrlen($hash)); $status = 0; - for ($i = 0; $i < $len; $i++) { - $status |= (ord($signature[$i]) ^ ord($hash[$i])); + for ($i = 0; $i < $len; ++$i) { + $status |= (\ord($signature[$i]) ^ \ord($hash[$i])); } $status |= (self::safeStrlen($signature) ^ self::safeStrlen($hash)); - return ($status === 0); + return $status === 0; } } - public static function urlsafeB64Decode($input) - { - $remainder = strlen($input) % 4; - if ($remainder) { - $padlen = 4 - $remainder; - $input .= str_repeat('=', $padlen); - } - - return base64_decode(strtr($input, '-_', '+/')); - } - - public static function urlsafeB64Encode($input) - { - return str_replace('=', '', strtr(base64_encode($input), '+/', '-_')); - } - - private static function safeStrlen($str) + /** + * @param string $str + * + * @return int + */ + private static function safeStrlen(string $str): int { - if (function_exists('mb_strlen')) { - return mb_strlen($str, '8bit'); + if (\function_exists('mb_strlen')) { + return \mb_strlen($str, '8bit'); } - return strlen($str); + return \mb_strlen($str); } } diff --git a/JWT/Exceptions/BeforeValidException.php b/JWT/Exceptions/BeforeValidException.php index dbae540..247bf90 100644 --- a/JWT/Exceptions/BeforeValidException.php +++ b/JWT/Exceptions/BeforeValidException.php @@ -1,8 +1,10 @@ -tokenStorage = $tokenStorage; } - public function onKernelRequest(GetResponseEvent $event) + /** + * @param GetResponseEvent $event + * + * @return void + */ + public function onKernelRequest(GetResponseEvent $event): void { if (!$event->isMasterRequest()) { return; @@ -48,31 +55,30 @@ public function onKernelRequest(GetResponseEvent $event) $routes = $this->router->getRouteCollection(); $route = $routes->get($request->attributes->get('_route')); - if (!$route->getOption('requires_license')) { - + if ($route !== null && !$route->getOption('requires_license')) { return; } - - if ('active' != $request->get('lic') && $this->kernel->getEnvironment() == 'prod') { + if ($request->get('lic') !== 'active' && $this->kernel->getEnvironment() === 'prod') { // Checking for whitelisted users try { + /** @noinspection NullPointerExceptionInspection */ $user = $this->tokenStorage->getToken()->getUser(); if ($user instanceof Tenant) { - if($user->isWhiteListed()){ + if ($user->isWhiteListed()) { return; } - $today = date('Y-m-d'); + $today = \date('Y-m-d'); $whitelist = $this->kernel->getContainer()->getParameter('license_whitelist'); + /** @noinspection ForeachSourceInspection */ foreach ($whitelist as $allowed) { - if ($allowed['client_key'] == $user->getClientKey() && $today <= $allowed['valid_till']) { - + if ($today <= $allowed['valid_till'] && $allowed['client_key'] === $user->getClientKey()) { return; } } } - } catch (\Exception $e) { + } catch (\Throwable $e) { // Do nothing } diff --git a/Model/JWTRequest.php b/Model/JWTRequest.php index db0359c..d916f22 100644 --- a/Model/JWTRequest.php +++ b/Model/JWTRequest.php @@ -1,12 +1,15 @@ -tenant = $tenant; $this->client = new Client(); $this->qshHelper = new QSH(); } - public function sendFile(UploadedFile $file, $restUrl) + /** + * @param UploadedFile $file + * @param string $restUrl + */ + public function sendFile(UploadedFile $file, string $restUrl): void { $url = $this->buildURL($restUrl); $options = ['headers' => $this->buildAuthHeader('POST', $restUrl)]; @@ -31,15 +51,21 @@ public function sendFile(UploadedFile $file, $restUrl) $savedFile = $file->move('/tmp/', $file->getClientOriginalName()); $options['body'] = [ - 'file' => fopen($savedFile->getRealPath(), 'rb') + 'file' => \fopen($savedFile->getRealPath(), 'rb'), ]; - unlink($savedFile->getRealPath()); + \unlink($savedFile->getRealPath()); $this->client->post($url, $options); } - public function put($restUrl, $json) + /** + * @param string $restUrl + * @param mixed[] $json + * + * @return string + */ + public function put(string $restUrl, array $json): string { $url = $this->buildURL($restUrl); $options = ['headers' => $this->buildAuthHeader('PUT', $restUrl)]; @@ -49,10 +75,16 @@ public function put($restUrl, $json) $response = $this->client->put($url, $options); - return $response->json(); + return $response->getBody()->getContents(); } - public function post($restUrl, $json) + /** + * @param string $restUrl + * @param mixed[] $json + * + * @return string + */ + public function post(string $restUrl, array $json): string { $url = $this->buildURL($restUrl); $options = ['headers' => $this->buildAuthHeader('POST', $restUrl)]; @@ -62,20 +94,28 @@ public function post($restUrl, $json) $response = $this->client->post($url, $options); - return $response->json(); + return $response->getBody()->getContents(); } - public function get($restUrl) + /** + * @param string $restUrl + * + * @return string + */ + public function get(string $restUrl): string { $url = $this->buildURL($restUrl); $options = ['headers' => $this->buildAuthHeader('GET', $restUrl)]; $response = $this->client->get($url, $options); - return $response->json(); + return $response->getBody()->getContents(); } - public function delete($restUrl) + /** + * @param string $restUrl + */ + public function delete(string $restUrl): void { $url = $this->buildURL($restUrl); $options = ['headers' => $this->buildAuthHeader('DELETE', $restUrl)]; @@ -83,7 +123,13 @@ public function delete($restUrl) $this->client->delete($url, $options); } - private function buildAuthHeader($method, $restUrl) + /** + * @param string $method + * @param string $restUrl + * + * @return mixed[] + */ + private function buildAuthHeader(string $method, string $restUrl): array { $token = $this->buildPayload($method, $restUrl); $jwt = JWT::encode($token, $this->tenant->getSharedSecret()); @@ -91,25 +137,34 @@ private function buildAuthHeader($method, $restUrl) return ['Authorization' => 'JWT '.$jwt]; } - private function buildURL($restUrl) + /** + * @param string $restUrl + * + * @return string + */ + private function buildURL(string $restUrl): string { // Jira return absolute self links, so its more easy to work with get with absolute urls in such cases - if((substr($restUrl,0,7) !== 'http://') && (substr($restUrl,0,8) !== 'https://')) { + if ((\mb_strpos($restUrl, 'http://') !== 0) && (\mb_strpos($restUrl, 'https://') !== 0)) { return $this->tenant->getBaseUrl().$restUrl; - } else { - return $restUrl; } + + return $restUrl; } - private function buildPayload($method, $restUrl) + /** + * @param string $method + * @param string $restUrl + * + * @return mixed[] + */ + private function buildPayload(string $method, string $restUrl): array { - $qsh = $this->qshHelper->create($method, $restUrl); - return [ 'iss' => $this->tenant->getAddonKey(), - 'iat' => time(), - 'exp' => time() + 86400, - 'qsh' => $qsh, + 'iat' => \time(), + 'exp' => \strtotime('+1 day'), + 'qsh' => $this->qshHelper->create($method, $restUrl), ]; } } diff --git a/Model/QSH.php b/Model/QSH.php index 6470552..10cf87f 100644 --- a/Model/QSH.php +++ b/Model/QSH.php @@ -1,46 +1,54 @@ - $pieceOfQuery) { - $pieceOfQuery = implode(',', $pieceOfQuery); + $pieceOfQuery = \implode(',', $pieceOfQuery); $canonicalQuery .= $key.'='.$pieceOfQuery.'&'; } - $canonicalQuery = rtrim($canonicalQuery, '&'); + $canonicalQuery = \rtrim($canonicalQuery, '&'); } $qshString = $method.'&'.$path.'&'.$canonicalQuery; - $qsh = hash('sha256', $qshString); - return $qsh; + return \hash('sha256', $qshString); } } diff --git a/Resources/config/services.yml b/Resources/config/services.yml index 7202330..9cd42b3 100644 --- a/Resources/config/services.yml +++ b/Resources/config/services.yml @@ -10,6 +10,26 @@ services: autowire: false autoconfigure: true + AtlassianConnectBundle\Controller\: + resource: '../../Controller' + tags: ['controller.service_arguments'] + + + AtlassianConnectBundle\Controller\UnlicensedController: + arguments: + $twig: '@twig' + + AtlassianConnectBundle\Controller\HandshakeController: + arguments: + $registry: '@Doctrine\Common\Persistence\ManagerRegistry' + $logger: '@Psr\Log\LoggerInterface' + $tenantClass: '%atlassian_connect_tenant_entity_class%' + + AtlassianConnectBundle\Controller\DescriptorController: + arguments: + $kernel: '@Symfony\Component\HttpKernel\KernelInterface' + $config: '%atlassian_connect%' + AtlassianConnectBundle\Command\RequestAPICommand: public: false arguments: diff --git a/Security/JWTAuthenticator.php b/Security/JWTAuthenticator.php index 49f4ce6..193b4aa 100644 --- a/Security/JWTAuthenticator.php +++ b/Security/JWTAuthenticator.php @@ -1,60 +1,91 @@ -userProvider = $userProvider; $this->kernel = $kernel; - $this->em = $em; + $this->em = $registry->getManager(); $this->tenantEntityClass = $tenantEntityClass; $this->devTenant = $devTenant; } - public function createToken(Request $request, $providerKey) + /** + * @param Request $request + * @param mixed $providerKey + * + * @return PreAuthenticatedToken + */ + public function createToken(Request $request, $providerKey): PreAuthenticatedToken { $jwt = $request->query->get('jwt'); - if(!$jwt && $request->headers->has("authorization")) { - $authorizationHeaderArray = explode(" ",$request->headers->get("authorization")); - if(count($authorizationHeaderArray) > 1) { + if (!$jwt && $request->headers->has('authorization')) { + $authorizationHeaderArray = \explode(' ', $request->headers->get('authorization')); + if (\count($authorizationHeaderArray) > 1) { $jwt = $authorizationHeaderArray[1]; } } - if (!$jwt && ($this->kernel->getEnvironment() == 'dev') && ($this->devTenant)) { - if(!$tenant = $this->em->getRepository($this->tenantEntityClass)->find($this->devTenant)) { - throw new \Exception("Cant find tenant with id ".$this->devTenant." - please set atlassian_connect.dev_tenant to false to disable dedicated dev tenant OR add valid id"); + if (!$jwt && $this->devTenant && ($this->kernel->getEnvironment() === 'dev')) { + $tenant = $this->em->getRepository($this->tenantEntityClass)->find($this->devTenant); + if ($tenant === null) { + throw new \RuntimeException(\sprintf('Cant find tenant with id %s - please set atlassian_connect.dev_tenant to false to disable dedicated dev tenant OR add valid id', $this->devTenant)); } $clientKey = $tenant->getClientKey(); $sharedSecret = $tenant->getSharedSecret(); @@ -62,10 +93,10 @@ public function createToken(Request $request, $providerKey) $qsh = $qshHelper->create('GET', $request->getRequestUri()); $payload = [ 'iss' => $clientKey, - 'iat' => time(), - 'exp' => time() + 86400, + 'iat' => \time(), + 'exp' => \strtotime('+1 day'), 'qsh' => $qsh, - 'sub' => 'admin' + 'sub' => 'admin', ]; $jwt = JWT::encode($payload, $sharedSecret); @@ -78,7 +109,14 @@ public function createToken(Request $request, $providerKey) return new PreAuthenticatedToken('anon.', $jwt, $providerKey); } - public function authenticateToken(TokenInterface $token, UserProviderInterface $userProvider, $providerKey) + /** + * @param TokenInterface $token + * @param UserProviderInterface $userProvider + * @param mixed $providerKey + * + * @return PreAuthenticatedToken + */ + public function authenticateToken(TokenInterface $token, UserProviderInterface $userProvider, $providerKey): PreAuthenticatedToken { $jwt = $token->getCredentials(); $token = $this->userProvider->getDecodedToken($jwt); @@ -86,13 +124,13 @@ public function authenticateToken(TokenInterface $token, UserProviderInterface $ if (!$clientKey) { throw new AuthenticationException( - sprintf('API Key "%s" does not exist.', $jwt) + \sprintf('API Key "%s" does not exist.', $jwt) ); } - /** @var $user Tenant */ + /** @var Tenant $user */ $user = $this->userProvider->loadUserByUsername($clientKey); - if(property_exists($token,"sub")) { + if (\property_exists($token, 'sub')) { // for some reasons, when webhooks are called - field sub is undefined $user->setUsername($token->sub); } @@ -100,12 +138,24 @@ public function authenticateToken(TokenInterface $token, UserProviderInterface $ return new PreAuthenticatedToken($user, $jwt, $providerKey, $user->getRoles()); } - public function supportsToken(TokenInterface $token, $providerKey) + /** + * @param TokenInterface $token + * @param mixed $providerKey + * + * @return bool + */ + public function supportsToken(TokenInterface $token, $providerKey): bool { return $token instanceof PreAuthenticatedToken && $token->getProviderKey() === $providerKey; } - public function onAuthenticationFailure(Request $request, AuthenticationException $exception) + /** + * @param Request $request + * @param AuthenticationException $exception + * + * @return Response + */ + public function onAuthenticationFailure(Request $request, AuthenticationException $exception): Response { return new Response('Authentication Failed: '.$exception->getMessage(), 403); } diff --git a/Security/JWTUserProvider.php b/Security/JWTUserProvider.php index 559c133..9a2a28b 100644 --- a/Security/JWTUserProvider.php +++ b/Security/JWTUserProvider.php @@ -1,35 +1,57 @@ -em = $registry->getManager(); $this->tokenLifetime = $tokenLifetime; $this->tenantClass = $tenantClass; } - public function getDecodedToken($jwt) + /** + * @param string $jwt + * + * @return mixed + */ + public function getDecodedToken(string $jwt) { try { $decodedToken = JWT::decode($jwt); @@ -38,41 +60,50 @@ public function getDecodedToken($jwt) JWT::decode($jwt, $tenant->getSharedSecret(), ['HS256'], $this->tokenLifetime); return $decodedToken; - } catch (\Exception $e) { + } catch (\Throwable $e) { throw new AuthenticationException($e->getMessage()); } } /** - * @param string $clientKey - + * @param mixed $clientKey + * * @return Tenant */ - public function loadUserByUsername($clientKey) + public function loadUserByUsername($clientKey): Tenant { $tenant = $this->findTenant($clientKey); if (!$tenant) { - throw new UsernameNotFoundException(); + throw new UsernameNotFoundException('Can\'t find tenant with such username'); } return $this->findTenant($clientKey); } - public function refreshUser(UserInterface $user) + /** + * @param UserInterface $user + */ + public function refreshUser(UserInterface $user): void { - throw new UnsupportedUserException(); + throw new UnsupportedUserException('Refresh prohibited'); } - public function supportsClass($class) + /** + * @param string|mixed $class + * + * @return bool + */ + public function supportsClass($class): bool { - return ('AtlassianConnectBundle\Entity\Tenant' === $class) || is_subclass_of($class,'AtlassianConnectBundle\Entity\Tenant'); + return ($class === 'AtlassianConnectBundle\Entity\Tenant') || \is_subclass_of($class, Tenant::class); } /** - * @param $clientKey + * @param string $clientKey + * * @return Tenant|null */ - protected function findTenant($clientKey) + protected function findTenant(string $clientKey): ?Tenant { return $this->em ->getRepository($this->tenantClass) diff --git a/Tests/DependencyInjection/AtlassianConnectExtensionTest.php b/Tests/DependencyInjection/AtlassianConnectExtensionTest.php index e0284d7..7f281b3 100644 --- a/Tests/DependencyInjection/AtlassianConnectExtensionTest.php +++ b/Tests/DependencyInjection/AtlassianConnectExtensionTest.php @@ -2,9 +2,13 @@ namespace Bukashk0zzz\FilterBundle\Tests\DependencyInjection; +use AtlassianConnectBundle\Controller\DescriptorController; +use AtlassianConnectBundle\Controller\HandshakeController; +use AtlassianConnectBundle\Controller\UnlicensedController; use AtlassianConnectBundle\DependencyInjection\AtlassianConnectExtension; use Doctrine\Common\Persistence\ManagerRegistry; use PHPUnit\Framework\TestCase; +use Psr\Log\LoggerInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\HttpKernel\KernelInterface; use Symfony\Component\Routing\RouterInterface; @@ -33,7 +37,6 @@ protected function setUp() $this->extension = new AtlassianConnectExtension(); $this->container = new ContainerBuilder(); $this->container->registerExtension($this->extension); - } /** @@ -45,6 +48,8 @@ public function testLoadExtension(): void $this->container->set(KernelInterface::class, new \stdClass()); $this->container->set(TokenStorage::class, new \stdClass()); $this->container->set(ManagerRegistry::class, new \stdClass()); + $this->container->set(LoggerInterface::class, new \stdClass()); + $this->container->set('twig', new \stdClass()); $this->container->prependExtensionConfig($this->extension->getAlias(), [ 'token_lifetime' => 86400, @@ -58,5 +63,8 @@ public function testLoadExtension(): void // Check that services have been loaded static::assertTrue($this->container->has('jwt_user_provider')); static::assertTrue($this->container->has('jwt_authenticator')); + static::assertTrue($this->container->has(DescriptorController::class)); + static::assertTrue($this->container->has(UnlicensedController::class)); + static::assertTrue($this->container->has(HandshakeController::class)); } } diff --git a/composer.json b/composer.json index 3da6f27..144e0da 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,9 @@ "symfony/routing": "^3.3|^4.0", "symfony/console": "^3.3|^4.0", "doctrine/orm": "^2.5", - "guzzlehttp/guzzle": "^6.0" + "guzzlehttp/guzzle": "^6.0", + "twig/twig": "^2.4", + "lcobucci/jwt": "^3.2" }, "require-dev": { "escapestudios/symfony2-coding-standard": "^3.0", diff --git a/composer.lock b/composer.lock index 0eee815..2d93c84 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "31b47ee368b8ec00e3523e8cfaf22097", + "content-hash": "f44a7aac9fe7a92b27212853efcf584e", "packages": [ { "name": "doctrine/annotations", @@ -793,6 +793,64 @@ ], "time": "2017-03-20T17:10:46+00:00" }, + { + "name": "lcobucci/jwt", + "version": "3.2.2", + "source": { + "type": "git", + "url": "https://github.com/lcobucci/jwt.git", + "reference": "0b5930be73582369e10c4d4bb7a12bac927a203c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/lcobucci/jwt/zipball/0b5930be73582369e10c4d4bb7a12bac927a203c", + "reference": "0b5930be73582369e10c4d4bb7a12bac927a203c", + "shasum": "" + }, + "require": { + "ext-openssl": "*", + "php": ">=5.5" + }, + "require-dev": { + "mdanter/ecc": "~0.3.1", + "mikey179/vfsstream": "~1.5", + "phpmd/phpmd": "~2.2", + "phpunit/php-invoker": "~1.1", + "phpunit/phpunit": "~4.5", + "squizlabs/php_codesniffer": "~2.3" + }, + "suggest": { + "mdanter/ecc": "Required to use Elliptic Curves based algorithms." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "psr-4": { + "Lcobucci\\JWT\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Luís Otávio Cobucci Oblonczyk", + "email": "lcobucci@gmail.com", + "role": "Developer" + } + ], + "description": "A simple library to work with JSON Web Token and JSON Web Signature", + "keywords": [ + "JWS", + "jwt" + ], + "time": "2017-09-01T08:23:26+00:00" + }, { "name": "psr/container", "version": "1.0.0", @@ -1840,6 +1898,72 @@ "description": "Symfony Yaml Component", "homepage": "https://symfony.com", "time": "2017-12-12T08:41:51+00:00" + }, + { + "name": "twig/twig", + "version": "v2.4.4", + "source": { + "type": "git", + "url": "https://github.com/twigphp/Twig.git", + "reference": "eddb97148ad779f27e670e1e3f19fb323aedafeb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/eddb97148ad779f27e670e1e3f19fb323aedafeb", + "reference": "eddb97148ad779f27e670e1e3f19fb323aedafeb", + "shasum": "" + }, + "require": { + "php": "^7.0", + "symfony/polyfill-mbstring": "~1.0" + }, + "require-dev": { + "psr/container": "^1.0", + "symfony/debug": "~2.7", + "symfony/phpunit-bridge": "~3.3@dev" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.4-dev" + } + }, + "autoload": { + "psr-0": { + "Twig_": "lib/" + }, + "psr-4": { + "Twig\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com", + "homepage": "http://fabien.potencier.org", + "role": "Lead Developer" + }, + { + "name": "Armin Ronacher", + "email": "armin.ronacher@active-4.com", + "role": "Project Founder" + }, + { + "name": "Twig Team", + "homepage": "http://twig.sensiolabs.org/contributors", + "role": "Contributors" + } + ], + "description": "Twig, the flexible, fast, and secure template language for PHP", + "homepage": "http://twig.sensiolabs.org", + "keywords": [ + "templating" + ], + "time": "2017-09-27T18:10:31+00:00" } ], "packages-dev": [ From 3c2ab6c3c079cc0a144e1b9521d648493bfeb17a Mon Sep 17 00:00:00 2001 From: Denis Golubovskiy Date: Sat, 16 Dec 2017 21:00:28 +0200 Subject: [PATCH 3/5] Remove JWT --- Command/RequestAPICommand.php | 13 +- Controller/HandshakeController.php | 3 +- .../AtlassianConnectExtension.php | 2 - Entity/Tenant.php | 2 +- Entity/TenantInterface.php | 24 +++ JWT/Authentication/JWT.php | 191 ------------------ JWT/Exceptions/BeforeValidException.php | 10 - JWT/Exceptions/ExpiredException.php | 10 - JWT/Exceptions/SignatureInvalidException.php | 10 - Model/JWTRequest.php | 10 +- Resources/config/services.yml | 2 +- Security/JWTAuthenticator.php | 2 +- Security/JWTUserProvider.php | 11 +- composer.json | 2 +- composer.lock | 164 +++++++++------ 15 files changed, 155 insertions(+), 301 deletions(-) create mode 100644 Entity/TenantInterface.php delete mode 100644 JWT/Authentication/JWT.php delete mode 100644 JWT/Exceptions/BeforeValidException.php delete mode 100644 JWT/Exceptions/ExpiredException.php delete mode 100644 JWT/Exceptions/SignatureInvalidException.php diff --git a/Command/RequestAPICommand.php b/Command/RequestAPICommand.php index f956750..9653d49 100644 --- a/Command/RequestAPICommand.php +++ b/Command/RequestAPICommand.php @@ -2,6 +2,7 @@ namespace AtlassianConnectBundle\Command; +use AtlassianConnectBundle\Entity\TenantInterface; use AtlassianConnectBundle\Model\JWTRequest; use Doctrine\Common\Persistence\ManagerRegistry; use Symfony\Component\Console\Command\Command; @@ -52,8 +53,7 @@ protected function configure(): void ->addArgument('rest-url', InputArgument::REQUIRED, 'REST api endpoint, like /rest/api/2/issue/{issueIdOrKey}') ->addOption('client-key', 'c', InputOption::VALUE_REQUIRED, 'Client-key from tenant') ->addOption('tenant-id', 't', InputOption::VALUE_REQUIRED, 'Tenant-id') - ->setDescription('Request REST end-points. -Documentation available on https://docs.atlassian.com/jira/REST/cloud/'); + ->setDescription('Request REST end-points. Documentation available on https://docs.atlassian.com/jira/REST/cloud/'); } /** @@ -65,12 +65,13 @@ protected function configure(): void protected function execute(InputInterface $input, OutputInterface $output): void { $restUrl = $input->getArgument('rest-url'); + + /** @var TenantInterface $tenant */ if ($input->getOption('tenant-id')) { - $tenant = $this->em->getRepository($this->tenantClass) - ->find($input->getOption('tenant-id')); + $tenant = $this->em->getRepository($this->tenantClass)->find($input->getOption('tenant-id')); } elseif ($input->getOption('client-key')) { - $tenant = $this->em->getRepository($this->tenantClass) - ->findOneByClientKey($input->getOption('client-key')); + /** @noinspection PhpUndefinedMethodInspection */ + $tenant = $this->em->getRepository($this->tenantClass)->findOneByClientKey($input->getOption('client-key')); } else { throw new \RuntimeException('Please provide client-key or tenant-id'); } diff --git a/Controller/HandshakeController.php b/Controller/HandshakeController.php index c343c4e..d5ebe28 100644 --- a/Controller/HandshakeController.php +++ b/Controller/HandshakeController.php @@ -3,8 +3,8 @@ namespace AtlassianConnectBundle\Controller; use AtlassianConnectBundle\Entity\Tenant; -use AtlassianConnectBundle\JWT\Authentication\JWT; use Doctrine\Common\Persistence\ManagerRegistry; +use Firebase\JWT\JWT; use Psr\Log\LoggerInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -52,6 +52,7 @@ public function registerAction(Request $request): Response $content = \json_decode($content, true); /** @var Tenant $tenant */ + /** @noinspection PhpUndefinedMethodInspection */ $tenant = $this->em->getRepository($this->tenantClass)->findOneByClientKey($content['clientKey']); if ($tenant !== null) { try { diff --git a/DependencyInjection/AtlassianConnectExtension.php b/DependencyInjection/AtlassianConnectExtension.php index ffb21ec..f383bf4 100644 --- a/DependencyInjection/AtlassianConnectExtension.php +++ b/DependencyInjection/AtlassianConnectExtension.php @@ -9,8 +9,6 @@ /** * This is the class that loads and manages your bundle configuration - * - * To learn more see {@link http://symfony.com/doc/current/cookbook/bundles/extension.html} */ class AtlassianConnectExtension extends Extension { diff --git a/Entity/Tenant.php b/Entity/Tenant.php index fca09bd..4f79a10 100644 --- a/Entity/Tenant.php +++ b/Entity/Tenant.php @@ -12,7 +12,7 @@ * @ORM\HasLifecycleCallbacks() * @ORM\Entity() */ -class Tenant implements UserInterface +class Tenant implements UserInterface, TenantInterface { use TenantTrait; } diff --git a/Entity/TenantInterface.php b/Entity/TenantInterface.php new file mode 100644 index 0000000..e63244e --- /dev/null +++ b/Entity/TenantInterface.php @@ -0,0 +1,24 @@ + ['hash_hmac', 'SHA256'], - 'HS512' => ['hash_hmac', 'SHA512'], - 'HS384' => ['hash_hmac', 'SHA384'], - 'RS256' => ['openssl', 'SHA256'], - ]; - - public static function decode(string $jwt, $key = null, array $allowedAlgs = [], int $extraSeconds = 0) - { - $tks = \explode('.', $jwt); - if (\count($tks) !== 3) { - throw new \UnexpectedValueException('Wrong number of segments'); - } - [$headb64, $bodyb64, $cryptob64] = $tks; - if (($header = \json_decode(JWT::urlsafeB64Decode($headb64))) === null) { - throw new \UnexpectedValueException('Invalid header encoding'); - } - $payload = \json_decode(JWT::urlsafeB64Decode($bodyb64)); - if ($payload === null) { - throw new \UnexpectedValueException('Invalid claims encoding'); - } - $sig = JWT::urlsafeB64Decode($cryptob64); - if (isset($key)) { - if (empty($header->alg)) { - throw new \DomainException('Empty algorithm'); - } - if (empty(self::$supportedAlgs[$header->alg])) { - throw new \DomainException('Algorithm not supported'); - } - if (!\is_array($allowedAlgs) || !\in_array($header->alg, $allowedAlgs, true)) { - throw new \DomainException('Algorithm not allowed'); - } - if (\is_array($key)) { - if (isset($header->kid)) { - $key = $key[$header->kid]; - } else { - throw new \DomainException('"kid" empty, unable to lookup correct key'); - } - } - - if (!JWT::verify("$headb64.$bodyb64", $sig, $key, $header->alg)) { - throw new SignatureInvalidException('Signature verification failed'); - } - - // Check if the nbf if it is defined. This is the time that the - // token can actually be used. If it's not yet that time, abort. - if (isset($payload->nbf) && $payload->nbf > \time()) { - throw new BeforeValidException( - 'Cannot handle token prior to '.\date(\DateTime::ISO8601, $payload->nbf) - ); - } - - // Check that this token has been created before 'now'. This prevents - // using tokens that have been created for later use (and haven't - // correctly used the nbf claim). - if (isset($payload->iat) && $payload->iat > \time()) { - throw new BeforeValidException( - 'Cannot handle token prior to '.\date(\DateTime::ISO8601, $payload->iat) - ); - } - - // Check if this token has expired. - if (isset($payload->exp) && \time() >= ($payload->exp + $extraSeconds)) { - throw new ExpiredException('Expired token'); - } - } - - return $payload; - } - - public static function encode($payload, $key, $alg = 'HS256', $keyId = null) - { - $header = ['typ' => 'JWT', 'alg' => $alg]; - if ($keyId !== null) { - $header['kid'] = $keyId; - } - $segments = []; - $segments[] = JWT::urlsafeB64Encode(\json_encode($header)); - $segments[] = JWT::urlsafeB64Encode(\json_encode($payload)); - $signing_input = \implode('.', $segments); - - $signature = JWT::sign($signing_input, $key, $alg); - $segments[] = JWT::urlsafeB64Encode($signature); - - return \implode('.', $segments); - } - - public static function sign($msg, $key, $alg = 'HS256') - { - if (empty(self::$supportedAlgs[$alg])) { - throw new \DomainException('Algorithm not supported'); - } - [$function, $algorithm] = self::$supportedAlgs[$alg]; - switch ($function) { - case 'hash_hmac': - return \hash_hmac($algorithm, $msg, $key, true); - case 'openssl': - $signature = ''; - $success = \openssl_sign($msg, $signature, $key, $algorithm); - if (!$success) { - throw new \DomainException('OpenSSL unable to sign data'); - } - - return $signature; - } - } - - public static function urlsafeB64Decode($input) - { - $remainder = \mb_strlen($input) % 4; - if ($remainder) { - $padlen = 4 - $remainder; - $input .= \str_repeat('=', $padlen); - } - - return \base64_decode(\strtr($input, '-_', '+/'), true); - } - - public static function urlsafeB64Encode($input) - { - return \str_replace('=', '', \strtr(\base64_encode($input), '+/', '-_')); - } - - private static function verify($msg, $signature, $key, $alg) - { - if (empty(self::$supportedAlgs[$alg])) { - throw new \DomainException('Algorithm not supported'); - } - - [$function, $algorithm] = self::$supportedAlgs[$alg]; - switch ($function) { - case 'openssl': - $success = \openssl_verify($msg, $signature, $key, $algorithm); - if (!$success) { - throw new \DomainException('OpenSSL unable to verify data: '.\openssl_error_string()); - } - - return $signature; - - case 'hash_hmac': - default: - $hash = \hash_hmac($algorithm, $msg, $key, true); - if (\function_exists('hash_equals')) { - return \hash_equals($signature, $hash); - } - $len = \min(self::safeStrlen($signature), self::safeStrlen($hash)); - - $status = 0; - for ($i = 0; $i < $len; ++$i) { - $status |= (\ord($signature[$i]) ^ \ord($hash[$i])); - } - $status |= (self::safeStrlen($signature) ^ self::safeStrlen($hash)); - - return $status === 0; - } - } - - /** - * @param string $str - * - * @return int - */ - private static function safeStrlen(string $str): int - { - if (\function_exists('mb_strlen')) { - return \mb_strlen($str, '8bit'); - } - - return \mb_strlen($str); - } -} diff --git a/JWT/Exceptions/BeforeValidException.php b/JWT/Exceptions/BeforeValidException.php deleted file mode 100644 index 247bf90..0000000 --- a/JWT/Exceptions/BeforeValidException.php +++ /dev/null @@ -1,10 +0,0 @@ -tenant = $tenant; $this->client = new Client(); diff --git a/Resources/config/services.yml b/Resources/config/services.yml index 9cd42b3..9be55f2 100644 --- a/Resources/config/services.yml +++ b/Resources/config/services.yml @@ -2,7 +2,7 @@ parameters: atlassian_connect_license_listener_class: AtlassianConnectBundle\Listener\LicenseListener atlassian_connect_jwt_user_provider_class: AtlassianConnectBundle\Security\JWTUserProvider atlassian_connect_jwt_authenticator_class: AtlassianConnectBundle\Security\JWTAuthenticator - atlassian_connect_tenant_entity_class: AtlassianConnectBundle:Tenant + atlassian_connect_tenant_entity_class: AtlassianConnectBundle\Entity\Tenant services: _defaults: diff --git a/Security/JWTAuthenticator.php b/Security/JWTAuthenticator.php index 193b4aa..63858d8 100644 --- a/Security/JWTAuthenticator.php +++ b/Security/JWTAuthenticator.php @@ -3,10 +3,10 @@ namespace AtlassianConnectBundle\Security; use AtlassianConnectBundle\Entity\Tenant; -use AtlassianConnectBundle\JWT\Authentication\JWT; use AtlassianConnectBundle\Model\QSH; use Doctrine\Common\Persistence\ManagerRegistry; use Doctrine\ORM\EntityManager; +use Firebase\JWT\JWT; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\KernelInterface; diff --git a/Security/JWTUserProvider.php b/Security/JWTUserProvider.php index 9a2a28b..2337d05 100644 --- a/Security/JWTUserProvider.php +++ b/Security/JWTUserProvider.php @@ -3,9 +3,9 @@ namespace AtlassianConnectBundle\Security; use AtlassianConnectBundle\Entity\Tenant; -use AtlassianConnectBundle\JWT\Authentication\JWT; use Doctrine\Common\Persistence\ManagerRegistry; use Doctrine\ORM\EntityManager; +use Firebase\JWT\JWT; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\Exception\UnsupportedUserException; use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; @@ -54,10 +54,13 @@ public function __construct(ManagerRegistry $registry, int $tokenLifetime, strin public function getDecodedToken(string $jwt) { try { - $decodedToken = JWT::decode($jwt); + /** @noinspection PhpUnusedLocalVariableInspection */ + [$headb64, $bodyb64, $cryptob64] = \explode('.', $jwt); + $decodedToken = \json_decode(JWT::urlsafeB64Decode($bodyb64)); + $tenant = $this->findTenant($decodedToken->iss); - JWT::decode($jwt, $tenant->getSharedSecret(), ['HS256'], $this->tokenLifetime); + JWT::decode($jwt, $tenant->getSharedSecret(), ['HS256']); return $decodedToken; } catch (\Throwable $e) { @@ -105,6 +108,8 @@ public function supportsClass($class): bool */ protected function findTenant(string $clientKey): ?Tenant { + /** @noinspection PhpUndefinedMethodInspection */ + return $this->em ->getRepository($this->tenantClass) ->findOneByClientKey($clientKey); diff --git a/composer.json b/composer.json index 144e0da..f75f05e 100644 --- a/composer.json +++ b/composer.json @@ -17,7 +17,7 @@ "doctrine/orm": "^2.5", "guzzlehttp/guzzle": "^6.0", "twig/twig": "^2.4", - "lcobucci/jwt": "^3.2" + "firebase/php-jwt": "^5.0" }, "require-dev": { "escapestudios/symfony2-coding-standard": "^3.0", diff --git a/composer.lock b/composer.lock index 2d93c84..1652897 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "f44a7aac9fe7a92b27212853efcf584e", + "content-hash": "78663c95c2aad6681aa1d1f1d7e35bdb", "packages": [ { "name": "doctrine/annotations", @@ -612,6 +612,52 @@ ], "time": "2017-11-27T23:25:55+00:00" }, + { + "name": "firebase/php-jwt", + "version": "v5.0.0", + "source": { + "type": "git", + "url": "https://github.com/firebase/php-jwt.git", + "reference": "9984a4d3a32ae7673d6971ea00bae9d0a1abba0e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/firebase/php-jwt/zipball/9984a4d3a32ae7673d6971ea00bae9d0a1abba0e", + "reference": "9984a4d3a32ae7673d6971ea00bae9d0a1abba0e", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": " 4.8.35" + }, + "type": "library", + "autoload": { + "psr-4": { + "Firebase\\JWT\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Neuman Vong", + "email": "neuman+pear@twilio.com", + "role": "Developer" + }, + { + "name": "Anant Narayanan", + "email": "anant@php.net", + "role": "Developer" + } + ], + "description": "A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current spec.", + "homepage": "https://github.com/firebase/php-jwt", + "time": "2017-06-27T22:17:23+00:00" + }, { "name": "guzzlehttp/guzzle", "version": "6.3.0", @@ -793,64 +839,6 @@ ], "time": "2017-03-20T17:10:46+00:00" }, - { - "name": "lcobucci/jwt", - "version": "3.2.2", - "source": { - "type": "git", - "url": "https://github.com/lcobucci/jwt.git", - "reference": "0b5930be73582369e10c4d4bb7a12bac927a203c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/lcobucci/jwt/zipball/0b5930be73582369e10c4d4bb7a12bac927a203c", - "reference": "0b5930be73582369e10c4d4bb7a12bac927a203c", - "shasum": "" - }, - "require": { - "ext-openssl": "*", - "php": ">=5.5" - }, - "require-dev": { - "mdanter/ecc": "~0.3.1", - "mikey179/vfsstream": "~1.5", - "phpmd/phpmd": "~2.2", - "phpunit/php-invoker": "~1.1", - "phpunit/phpunit": "~4.5", - "squizlabs/php_codesniffer": "~2.3" - }, - "suggest": { - "mdanter/ecc": "Required to use Elliptic Curves based algorithms." - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.1-dev" - } - }, - "autoload": { - "psr-4": { - "Lcobucci\\JWT\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Luís Otávio Cobucci Oblonczyk", - "email": "lcobucci@gmail.com", - "role": "Developer" - } - ], - "description": "A simple library to work with JSON Web Token and JSON Web Signature", - "keywords": [ - "JWS", - "jwt" - ], - "time": "2017-09-01T08:23:26+00:00" - }, { "name": "psr/container", "version": "1.0.0", @@ -2206,6 +2194,64 @@ ], "time": "2017-08-23T07:46:41+00:00" }, + { + "name": "lcobucci/jwt", + "version": "3.2.2", + "source": { + "type": "git", + "url": "https://github.com/lcobucci/jwt.git", + "reference": "0b5930be73582369e10c4d4bb7a12bac927a203c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/lcobucci/jwt/zipball/0b5930be73582369e10c4d4bb7a12bac927a203c", + "reference": "0b5930be73582369e10c4d4bb7a12bac927a203c", + "shasum": "" + }, + "require": { + "ext-openssl": "*", + "php": ">=5.5" + }, + "require-dev": { + "mdanter/ecc": "~0.3.1", + "mikey179/vfsstream": "~1.5", + "phpmd/phpmd": "~2.2", + "phpunit/php-invoker": "~1.1", + "phpunit/phpunit": "~4.5", + "squizlabs/php_codesniffer": "~2.3" + }, + "suggest": { + "mdanter/ecc": "Required to use Elliptic Curves based algorithms." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "psr-4": { + "Lcobucci\\JWT\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Luís Otávio Cobucci Oblonczyk", + "email": "lcobucci@gmail.com", + "role": "Developer" + } + ], + "description": "A simple library to work with JSON Web Token and JSON Web Signature", + "keywords": [ + "JWS", + "jwt" + ], + "time": "2017-09-01T08:23:26+00:00" + }, { "name": "myclabs/deep-copy", "version": "1.7.0", From 8d809b1f9d6642d94f6cc37131cd26c70d05a913 Mon Sep 17 00:00:00 2001 From: Denis Golubovskiy Date: Sat, 16 Dec 2017 22:31:43 +0200 Subject: [PATCH 4/5] Bug fixes --- Resources/config/services.yml | 2 +- Tests/DependencyInjection/AtlassianConnectExtensionTest.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Resources/config/services.yml b/Resources/config/services.yml index 9be55f2..62c2f24 100644 --- a/Resources/config/services.yml +++ b/Resources/config/services.yml @@ -42,7 +42,7 @@ services: arguments: $router: '@Symfony\Component\Routing\RouterInterface' $kernel: '@Symfony\Component\HttpKernel\KernelInterface' - $tokenStorage: '@Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage' + $tokenStorage: '@Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface' jwt_user_provider: class: '%atlassian_connect_jwt_user_provider_class%' diff --git a/Tests/DependencyInjection/AtlassianConnectExtensionTest.php b/Tests/DependencyInjection/AtlassianConnectExtensionTest.php index 7f281b3..b2773d1 100644 --- a/Tests/DependencyInjection/AtlassianConnectExtensionTest.php +++ b/Tests/DependencyInjection/AtlassianConnectExtensionTest.php @@ -12,7 +12,7 @@ use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\HttpKernel\KernelInterface; use Symfony\Component\Routing\RouterInterface; -use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage; +use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; /** * AtlassianConnectExtensionTest @@ -46,7 +46,7 @@ public function testLoadExtension(): void { $this->container->set(RouterInterface::class, new \stdClass()); $this->container->set(KernelInterface::class, new \stdClass()); - $this->container->set(TokenStorage::class, new \stdClass()); + $this->container->set(TokenStorageInterface::class, new \stdClass()); $this->container->set(ManagerRegistry::class, new \stdClass()); $this->container->set(LoggerInterface::class, new \stdClass()); $this->container->set('twig', new \stdClass()); From a65981211402e949c4ff957d9bb315cdbb315796 Mon Sep 17 00:00:00 2001 From: Denis Golubovskiy Date: Sun, 17 Dec 2017 10:17:49 +0200 Subject: [PATCH 5/5] License update --- LICENSE | 360 +++----------------------------------------------- composer.json | 4 +- 2 files changed, 23 insertions(+), 341 deletions(-) diff --git a/LICENSE b/LICENSE index 8cdb845..10b0d95 100644 --- a/LICENSE +++ b/LICENSE @@ -1,340 +1,22 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - {description} - Copyright (C) {year} {fullname} - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - {signature of Ty Coon}, 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. +The MIT License (MIT) + +Copyright (c) 2017 Vitaliy Zurian, Denis Golubovskiy + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/composer.json b/composer.json index f75f05e..d239864 100644 --- a/composer.json +++ b/composer.json @@ -1,10 +1,10 @@ { "name": "thecatontheflat/atlassian-connect-bundle", "description": "Atlassian Connect Symfony Bundle", - "keywords": ["bundle", "symfony", "atlassian", "connect", "jira", "atlassian-connect"], + "keywords": ["bundle", "symfony", "atlassian", "connect", "jira", "confluence", "atlassian-connect"], "homepage": "https://github.com/thecatontheflat/atlassian-connect-bundle", "type": "symfony-bundle", - "license": "GPL-2.0", + "license": "MIT", "require": { "php": "^7.1", "symfony/dependency-injection": "^3.3|^4.0",