commit 1143075e17ab4745e21bbacd89719cc1ba201fa3 Author: Dávid Danyi Date: Fri Apr 6 23:00:37 2018 +0200 * initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4da80f1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +.idea +composer.phar + +clover.xml +coveralls-upload.json +phpunit.xml +vendor/ diff --git a/bin/clear-config-cache.php b/bin/clear-config-cache.php new file mode 100644 index 0000000..60e92e1 --- /dev/null +++ b/bin/clear-config-cache.php @@ -0,0 +1,48 @@ +get('config')['console']['commands']; +foreach ($commands as $command) { + $application->add($container->get($command)); +} + +$application->run(); diff --git a/cli-config.php b/cli-config.php new file mode 100644 index 0000000..92a0dbd --- /dev/null +++ b/cli-config.php @@ -0,0 +1,9 @@ + new \Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper( + $container->get('doctrine.entity_manager.orm_default') + ), +]); diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..3e3fe97 --- /dev/null +++ b/composer.json @@ -0,0 +1,99 @@ +{ + "name": "zendframework/zend-expressive-skeleton", + "description": "Zend expressive skeleton. Begin developing PSR-15 middleware applications in seconds!", + "type": "project", + "homepage": "https://github.com/zendframework/zend-expressive-skeleton", + "license": "BSD-3-Clause", + "keywords": [ + "skeleton", + "middleware", + "psr", + "psr-7", + "psr-11", + "psr-15", + "zf", + "zendframework", + "zend-expressive" + ], + "config": { + "sort-packages": true + }, + "extra": { + "zf": { + "component-whitelist": [ + "zendframework/zend-expressive", + "zendframework/zend-expressive-helpers", + "zendframework/zend-expressive-router", + "zendframework/zend-httphandlerrunner", + "zendframework/zend-expressive-fastroute" + ] + } + }, + "support": { + "issues": "https://github.com/zendframework/zend-expressive-skeleton/issues", + "source": "https://github.com/zendframework/zend-expressive-skeleton", + "rss": "https://github.com/zendframework/zend-expressive-skeleton/releases.atom", + "slack": "https://zendframework-slack.herokuapp.com", + "forum": "https://discourse.zendframework.com/c/questions/expressive" + }, + "require": { + "php": "^7.1", + "dasprid/container-interop-doctrine": "^1.1", + "doctrine/orm": "^2.6", + "gedmo/doctrine-extensions": "^2.4", + "roave/security-advisories": "dev-master", + "symfony/console": "^4.0", + "tuupola/cors-middleware": "^0.7.0", + "zendframework/zend-component-installer": "^2.1.1", + "zendframework/zend-config-aggregator": "^1.0", + "zendframework/zend-diactoros": "^1.7.1", + "zendframework/zend-expressive": "^3.0.1", + "zendframework/zend-expressive-fastroute": "^3.0", + "zendframework/zend-expressive-helpers": "^5.0", + "zendframework/zend-filter": "^2.7", + "zendframework/zend-form": "^2.11", + "zendframework/zend-hydrator": "^2.3", + "zendframework/zend-json": "^3.1", + "zendframework/zend-servicemanager": "^3.3", + "zendframework/zend-stdlib": "^3.1" + }, + "require-dev": { + "phpunit/phpunit": "^7.0.1", + "squizlabs/php_codesniffer": "^2.9.1", + "zendframework/zend-expressive-tooling": "^1.0", + "zfcampus/zf-development-mode": "^3.1", + "filp/whoops": "^2.1.12" + }, + "autoload": { + "psr-4": { + "App\\": "src/App/", + "DoctrineExpressiveModule\\": "src/DoctrineExpressiveModule/" + } + }, + "autoload-dev": { + "psr-4": { + "AppTest\\": "test/AppTest/" + } + }, + "scripts": { + "post-create-project-cmd": [ + "@development-enable" + ], + "development-disable": "zf-development-mode disable", + "development-enable": "zf-development-mode enable", + "development-status": "zf-development-mode status", + "expressive": "expressive --ansi", + "check": [ + "@cs-check", + "@test", + "@analyze" + ], + "analyze": "phpstan analyze -l max -c ./phpstan.installer.neon ./src ./config", + "clear-config-cache": "php bin/clear-config-cache.php", + "cs-check": "phpcs", + "cs-fix": "phpcbf", + "serve": "php -S 0.0.0.0:8080 -t public/", + "test": "phpunit --colors=always", + "test-coverage": "phpunit --colors=always --coverage-clover clover.xml" + } +} diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000..d2f9e66 --- /dev/null +++ b/composer.lock @@ -0,0 +1,4736 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "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": "f30cef69b43fa78cf3e1a64684b41ca4", + "packages": [ + { + "name": "behat/transliterator", + "version": "v1.2.0", + "source": { + "type": "git", + "url": "https://github.com/Behat/Transliterator.git", + "reference": "826ce7e9c2a6664c0d1f381cbb38b1fb80a7ee2c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Behat/Transliterator/zipball/826ce7e9c2a6664c0d1f381cbb38b1fb80a7ee2c", + "reference": "826ce7e9c2a6664c0d1f381cbb38b1fb80a7ee2c", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "chuyskywalker/rolling-curl": "^3.1", + "php-yaoi/php-yaoi": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2-dev" + } + }, + "autoload": { + "psr-0": { + "Behat\\Transliterator": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Artistic-1.0" + ], + "description": "String transliterator", + "keywords": [ + "i18n", + "slug", + "transliterator" + ], + "time": "2017-04-04T11:38:05+00:00" + }, + { + "name": "container-interop/container-interop", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/container-interop/container-interop.git", + "reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/container-interop/container-interop/zipball/79cbf1341c22ec75643d841642dd5d6acd83bdb8", + "reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8", + "shasum": "" + }, + "require": { + "psr/container": "^1.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Interop\\Container\\": "src/Interop/Container/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Promoting the interoperability of container objects (DIC, SL, etc.)", + "homepage": "https://github.com/container-interop/container-interop", + "time": "2017-02-14T19:40:03+00:00" + }, + { + "name": "dasprid/container-interop-doctrine", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/DASPRiD/container-interop-doctrine.git", + "reference": "b9f3afc00ce997e469d7fdd6fed7b8d400763290" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/DASPRiD/container-interop-doctrine/zipball/b9f3afc00ce997e469d7fdd6fed7b8d400763290", + "reference": "b9f3afc00ce997e469d7fdd6fed7b8d400763290", + "shasum": "" + }, + "require": { + "doctrine/common": "^2.6", + "doctrine/dbal": "^2.5", + "doctrine/orm": "^2.5", + "php": "^5.5|^7.0", + "psr/container": "^1.0.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8", + "squizlabs/php_codesniffer": "^2.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "ContainerInteropDoctrine\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-2-Clause" + ], + "description": "Doctrine factories for container-interop", + "homepage": "https://github.com/DASPRiD/container-interop-doctrine", + "time": "2018-01-24T23:25:49+00:00" + }, + { + "name": "doctrine/annotations", + "version": "v1.6.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/annotations.git", + "reference": "c7f2050c68a9ab0bdb0f98567ec08d80ea7d24d5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/annotations/zipball/c7f2050c68a9ab0bdb0f98567ec08d80ea7d24d5", + "reference": "c7f2050c68a9ab0bdb0f98567ec08d80ea7d24d5", + "shasum": "" + }, + "require": { + "doctrine/lexer": "1.*", + "php": "^7.1" + }, + "require-dev": { + "doctrine/cache": "1.*", + "phpunit/phpunit": "^6.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.6.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" + } + }, + "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": "Docblock Annotations Parser", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "annotations", + "docblock", + "parser" + ], + "time": "2017-12-06T07:11:42+00:00" + }, + { + "name": "doctrine/cache", + "version": "v1.7.1", + "source": { + "type": "git", + "url": "https://github.com/doctrine/cache.git", + "reference": "b3217d58609e9c8e661cd41357a54d926c4a2a1a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/cache/zipball/b3217d58609e9c8e661cd41357a54d926c4a2a1a", + "reference": "b3217d58609e9c8e661cd41357a54d926c4a2a1a", + "shasum": "" + }, + "require": { + "php": "~7.1" + }, + "conflict": { + "doctrine/common": ">2.2,<2.4" + }, + "require-dev": { + "alcaeus/mongo-php-adapter": "^1.1", + "mongodb/mongodb": "^1.1", + "phpunit/phpunit": "^5.7", + "predis/predis": "~1.0" + }, + "suggest": { + "alcaeus/mongo-php-adapter": "Required to use legacy MongoDB driver" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.7.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache" + } + }, + "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": "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": "doctrine/collections", + "version": "v1.5.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/collections.git", + "reference": "a01ee38fcd999f34d9bfbcee59dbda5105449cbf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/collections/zipball/a01ee38fcd999f34d9bfbcee59dbda5105449cbf", + "reference": "a01ee38fcd999f34d9bfbcee59dbda5105449cbf", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "require-dev": { + "doctrine/coding-standard": "~0.1@dev", + "phpunit/phpunit": "^5.7" + }, + "type": "library", + "extra": { + "branch-alias": { + "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": { + "Doctrine\\Common\\": "lib/Doctrine/Common" + } + }, + "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": "Common Library for Doctrine projects", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "annotations", + "collections", + "eventmanager", + "persistence", + "spl" + ], + "time": "2017-08-31T08:43:38+00:00" + }, + { + "name": "doctrine/dbal", + "version": "v2.7.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/dbal.git", + "reference": "f76bf5ef631cec551a86c2291fc749534febebf1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/f76bf5ef631cec551a86c2291fc749534febebf1", + "reference": "f76bf5ef631cec551a86c2291fc749534febebf1", + "shasum": "" + }, + "require": { + "doctrine/common": "^2.7.1", + "ext-pdo": "*", + "php": "^7.1" + }, + "require-dev": { + "doctrine/coding-standard": "^4.0", + "phpunit/phpunit": "^7.0", + "phpunit/phpunit-mock-objects": "!=3.2.4,!=3.2.5", + "symfony/console": "^2.0.5||^3.0", + "symfony/phpunit-bridge": "^3.4.5|^4.0.5" + }, + "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.7.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": "2018-04-01T23:33:17+00:00" + }, + { + "name": "doctrine/inflector", + "version": "v1.3.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/inflector.git", + "reference": "5527a48b7313d15261292c149e55e26eae771b0a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/5527a48b7313d15261292c149e55e26eae771b0a", + "reference": "5527a48b7313d15261292c149e55e26eae771b0a", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "require-dev": { + "phpunit/phpunit": "^6.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\Inflector\\": "lib/Doctrine/Common/Inflector" + } + }, + "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": "Common String Manipulations with regard to casing and singular/plural rules.", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "inflection", + "pluralize", + "singularize", + "string" + ], + "time": "2018-01-09T20:05:19+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": [ + "MIT" + ], + "authors": [ + { + "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.6.1", + "source": { + "type": "git", + "url": "https://github.com/doctrine/doctrine2.git", + "reference": "87ee409783a4a322b5597ebaae558661404055a7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/doctrine2/zipball/87ee409783a4a322b5597ebaae558661404055a7", + "reference": "87ee409783a4a322b5597ebaae558661404055a7", + "shasum": "" + }, + "require": { + "doctrine/annotations": "~1.5", + "doctrine/cache": "~1.6", + "doctrine/collections": "^1.4", + "doctrine/common": "^2.7.1", + "doctrine/dbal": "^2.6", + "doctrine/instantiator": "~1.1", + "ext-pdo": "*", + "php": "^7.1", + "symfony/console": "~3.0|~4.0" + }, + "require-dev": { + "doctrine/coding-standard": "^1.0", + "phpunit/phpunit": "^6.5", + "squizlabs/php_codesniffer": "^3.2", + "symfony/yaml": "~3.4|~4.0" + }, + "suggest": { + "symfony/yaml": "If you want to use YAML Metadata Mapping Driver" + }, + "bin": [ + "bin/doctrine" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.6.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\ORM\\": "lib/Doctrine/ORM" + } + }, + "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": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "Object-Relational-Mapper for PHP", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "database", + "orm" + ], + "time": "2018-02-27T07:30:56+00:00" + }, + { + "name": "fig/http-message-util", + "version": "1.1.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message-util.git", + "reference": "20b2c280cb6914b7b83089720df44e490f4b42f0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message-util/zipball/20b2c280cb6914b7b83089720df44e490f4b42f0", + "reference": "20b2c280cb6914b7b83089720df44e490f4b42f0", + "shasum": "" + }, + "require": { + "php": "^5.3 || ^7.0", + "psr/http-message": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Fig\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Utility classes and constants for use with PSR-7 (psr/http-message)", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "time": "2017-02-09T16:10:21+00:00" + }, + { + "name": "gedmo/doctrine-extensions", + "version": "v2.4.33", + "source": { + "type": "git", + "url": "https://github.com/Atlantic18/DoctrineExtensions.git", + "reference": "d5fdc573b6a2ecfa29c070ecb3db8397ac55ed78" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Atlantic18/DoctrineExtensions/zipball/d5fdc573b6a2ecfa29c070ecb3db8397ac55ed78", + "reference": "d5fdc573b6a2ecfa29c070ecb3db8397ac55ed78", + "shasum": "" + }, + "require": { + "behat/transliterator": "~1.2", + "doctrine/common": "~2.4", + "php": ">=5.3.2" + }, + "require-dev": { + "doctrine/common": ">=2.5.0", + "doctrine/mongodb-odm": ">=1.0.2", + "doctrine/orm": ">=2.5.0", + "phpunit/phpunit": "*", + "symfony/yaml": "~2.6|~3.0|~4.0" + }, + "suggest": { + "doctrine/mongodb-odm": "to use the extensions with the MongoDB ODM", + "doctrine/orm": "to use the extensions with the ORM" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.4.x-dev" + } + }, + "autoload": { + "psr-0": { + "Gedmo\\": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "David Buchmann", + "email": "david@liip.ch" + }, + { + "name": "Gediminas Morkevicius", + "email": "gediminas.morkevicius@gmail.com" + }, + { + "name": "Gustavo Falco", + "email": "comfortablynumb84@gmail.com" + } + ], + "description": "Doctrine2 behavioral extensions", + "homepage": "http://gediminasm.org/", + "keywords": [ + "Blameable", + "behaviors", + "doctrine2", + "extensions", + "gedmo", + "loggable", + "nestedset", + "sluggable", + "sortable", + "timestampable", + "translatable", + "tree", + "uploadable" + ], + "time": "2018-01-08T14:13:45+00:00" + }, + { + "name": "http-interop/http-factory", + "version": "0.3.0", + "source": { + "type": "git", + "url": "https://github.com/http-interop/http-factory.git", + "reference": "c2587cc0a6f74987fefb5b8074acfd32c69a4b0f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/http-interop/http-factory/zipball/c2587cc0a6f74987fefb5b8074acfd32c69a4b0f", + "reference": "c2587cc0a6f74987fefb5b8074acfd32c69a4b0f", + "shasum": "" + }, + "require": { + "php": ">=5.3.0", + "psr/http-message": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Interop\\Http\\Factory\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP message factories", + "keywords": [ + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" + ], + "time": "2017-03-24T14:48:51+00:00" + }, + { + "name": "neomerx/cors-psr7", + "version": "v1.0.12", + "source": { + "type": "git", + "url": "https://github.com/neomerx/cors-psr7.git", + "reference": "24944f39483d1a89f66ae9d58cca9f82b8815b35" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/neomerx/cors-psr7/zipball/24944f39483d1a89f66ae9d58cca9f82b8815b35", + "reference": "24944f39483d1a89f66ae9d58cca9f82b8815b35", + "shasum": "" + }, + "require": { + "php": ">=5.6.0", + "psr/http-message": "^1.0", + "psr/log": "^1.0" + }, + "require-dev": { + "mockery/mockery": "^0.9.9", + "phpunit/phpunit": "^5.7", + "scrutinizer/ocular": "^1.1", + "squizlabs/php_codesniffer": "^3.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Neomerx\\Cors\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "neomerx", + "email": "info@neomerx.com" + } + ], + "description": "Framework agnostic (PSR-7) CORS implementation (www.w3.org/TR/cors/)", + "homepage": "https://github.com/neomerx/cors-psr7", + "keywords": [ + "Cross Origin Resource Sharing", + "Cross-Origin Resource Sharing", + "cors", + "neomerx", + "psr-7", + "psr7", + "w3.org", + "www.w3.org" + ], + "time": "2017-09-03T22:31:57+00:00" + }, + { + "name": "nikic/fast-route", + "version": "v1.3.0", + "source": { + "type": "git", + "url": "https://github.com/nikic/FastRoute.git", + "reference": "181d480e08d9476e61381e04a71b34dc0432e812" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/FastRoute/zipball/181d480e08d9476e61381e04a71b34dc0432e812", + "reference": "181d480e08d9476e61381e04a71b34dc0432e812", + "shasum": "" + }, + "require": { + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35|~5.7" + }, + "type": "library", + "autoload": { + "psr-4": { + "FastRoute\\": "src/" + }, + "files": [ + "src/functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov", + "email": "nikic@php.net" + } + ], + "description": "Fast request router for PHP", + "keywords": [ + "router", + "routing" + ], + "time": "2018-02-13T20:26:39+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/http-server-handler", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-server-handler.git", + "reference": "439d92054dc06097f2406ec074a2627839955a02" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-server-handler/zipball/439d92054dc06097f2406ec074a2627839955a02", + "reference": "439d92054dc06097f2406ec074a2627839955a02", + "shasum": "" + }, + "require": { + "php": ">=7.0", + "psr/http-message": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Server\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP server-side request handler", + "keywords": [ + "handler", + "http", + "http-interop", + "psr", + "psr-15", + "psr-7", + "request", + "response", + "server" + ], + "time": "2018-01-22T17:04:15+00:00" + }, + { + "name": "psr/http-server-middleware", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-server-middleware.git", + "reference": "ea17eb1fb2c8df6db919cc578451a8013c6a0ae5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-server-middleware/zipball/ea17eb1fb2c8df6db919cc578451a8013c6a0ae5", + "reference": "ea17eb1fb2c8df6db919cc578451a8013c6a0ae5", + "shasum": "" + }, + "require": { + "php": ">=7.0", + "psr/http-message": "^1.0", + "psr/http-server-handler": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Server\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP server-side middleware", + "keywords": [ + "http", + "http-interop", + "middleware", + "psr", + "psr-15", + "psr-7", + "request", + "response" + ], + "time": "2018-01-22T17:08:31+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": "roave/security-advisories", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/Roave/SecurityAdvisories.git", + "reference": "c83f6aa0ed08f680c012656d411d1b7c94003012" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/c83f6aa0ed08f680c012656d411d1b7c94003012", + "reference": "c83f6aa0ed08f680c012656d411d1b7c94003012", + "shasum": "" + }, + "conflict": { + "3f/pygmentize": "<1.2", + "adodb/adodb-php": "<5.20.6", + "amphp/artax": "<1.0.6|>=2,<2.0.6", + "amphp/http": "<1.0.1", + "asymmetricrypt/asymmetricrypt": ">=0,<9.9.99", + "aws/aws-sdk-php": ">=3,<3.2.1", + "bugsnag/bugsnag-laravel": ">=2,<2.0.2", + "cakephp/cakephp": ">=1.3,<1.3.18|>=2,<2.4.99|>=2.5,<2.5.99|>=2.6,<2.6.12|>=2.7,<2.7.6|>=3,<3.0.15|>=3.1,<3.1.4", + "cart2quote/module-quotation": ">=4.1.6,<=4.4.5|>=5,<5.4.4", + "cartalyst/sentry": "<=2.1.6", + "codeigniter/framework": "<=3.0.6", + "composer/composer": "<=1.0.0-alpha11", + "contao-components/mediaelement": ">=2.14.2,<2.21.1", + "contao/core": ">=2,<3.5.32", + "contao/core-bundle": ">=4,<4.4.8", + "contao/listing-bundle": ">=4,<4.4.8", + "contao/newsletter-bundle": ">=4,<4.1", + "doctrine/annotations": ">=1,<1.2.7", + "doctrine/cache": ">=1,<1.3.2|>=1.4,<1.4.2", + "doctrine/common": ">=2,<2.4.3|>=2.5,<2.5.1", + "doctrine/dbal": ">=2,<2.0.8|>=2.1,<2.1.2", + "doctrine/doctrine-bundle": "<1.5.2", + "doctrine/doctrine-module": "<=0.7.1", + "doctrine/mongodb-odm": ">=1,<1.0.2", + "doctrine/mongodb-odm-bundle": ">=2,<3.0.1", + "doctrine/orm": ">=2,<2.4.8|>=2.5,<2.5.1", + "dompdf/dompdf": ">=0.6,<0.6.2", + "drupal/core": ">=7,<7.58|>=8,<8.4.6|>=8.5,<8.5.1", + "drupal/drupal": ">=7,<7.58|>=8,<8.4.6|>=8.5,<8.5.1", + "erusev/parsedown": "<1.7", + "ezsystems/ezpublish-legacy": ">=5.3,<5.3.12.3|>=5.4,<5.4.11.3|>=2017.8,<2017.8.1.1|>=2017.12,<2017.12.2.1", + "firebase/php-jwt": "<2", + "friendsofsymfony/rest-bundle": ">=1.2,<1.2.2", + "friendsofsymfony/user-bundle": ">=1.2,<1.3.5", + "gree/jose": "<=2.2", + "gregwar/rst": "<1.0.3", + "guzzlehttp/guzzle": ">=6,<6.2.1|>=4.0.0-rc2,<4.2.4|>=5,<5.3.1", + "illuminate/auth": ">=4,<4.0.99|>=4.1,<=4.1.31|>=4.2,<=4.2.22|>=5,<=5.0.35|>=5.1,<=5.1.46|>=5.2,<=5.2.45|>=5.3,<=5.3.31|>=5.4,<=5.4.36|>=5.5,<5.5.10", + "illuminate/database": ">=4,<4.0.99|>=4.1,<4.1.29", + "illuminate/encryption": ">=4,<=4.0.11|>=4.1,<=4.1.31|>=4.2,<=4.2.22|>=5,<=5.0.35|>=5.1,<=5.1.46|>=5.2,<=5.2.45|>=5.3,<=5.3.31|>=5.4,<=5.4.36|>=5.5,<5.5.40|>=5.6,<5.6.15", + "joomla/session": "<1.3.1", + "laravel/framework": ">=4,<4.0.99|>=4.1,<=4.1.31|>=4.2,<=4.2.22|>=5,<=5.0.35|>=5.1,<=5.1.46|>=5.2,<=5.2.45|>=5.3,<=5.3.31|>=5.4,<=5.4.36|>=5.5,<5.5.40|>=5.6,<5.6.15", + "laravel/socialite": ">=1,<1.0.99|>=2,<2.0.10", + "magento/magento1ce": ">=1.5.0.1,<1.9.3.2", + "magento/magento1ee": ">=1.9,<1.14.3.2", + "magento/magento2ce": ">=2,<2.2", + "monolog/monolog": ">=1.8,<1.12", + "namshi/jose": "<2.2", + "onelogin/php-saml": "<2.10.4", + "oro/crm": ">=1.7,<1.7.4", + "oro/platform": ">=1.7,<1.7.4", + "padraic/humbug_get_contents": "<1.1.2", + "pagarme/pagarme-php": ">=0,<3", + "paragonie/random_compat": "<2", + "phpmailer/phpmailer": ">=5,<5.2.24", + "phpunit/phpunit": ">=4.8.19,<4.8.28|>=5.0.10,<5.6.3", + "phpxmlrpc/extras": "<0.6.1", + "propel/propel": ">=2.0.0-alpha1,<=2.0.0-alpha7", + "propel/propel1": ">=1,<=1.7.1", + "pusher/pusher-php-server": "<2.2.1", + "sabre/dav": ">=1.6,<1.6.99|>=1.7,<1.7.11|>=1.8,<1.8.9", + "shopware/shopware": "<5.3.7", + "silverstripe/cms": ">=3,<=3.0.11|>=3.1,<3.1.11", + "silverstripe/forum": "<=0.6.1|>=0.7,<=0.7.3", + "silverstripe/framework": ">=3,<3.3", + "silverstripe/userforms": "<3", + "simplesamlphp/saml2": "<1.10.6|>=2,<2.3.8|>=3,<3.1.4", + "simplesamlphp/simplesamlphp": "<1.15.2", + "simplesamlphp/simplesamlphp-module-infocard": "<1.0.1", + "socalnick/scn-social-auth": "<1.15.2", + "squizlabs/php_codesniffer": ">=1,<2.8.1|>=3,<3.0.1", + "stormpath/sdk": ">=0,<9.9.99", + "swiftmailer/swiftmailer": ">=4,<5.4.5", + "symfony/dependency-injection": ">=2,<2.0.17", + "symfony/form": ">=2.3,<2.3.35|>=2.4,<2.6.12|>=2.7,<2.7.38|>=2.8,<2.8.31|>=3,<3.2.14|>=3.3,<3.3.13", + "symfony/framework-bundle": ">=2,<2.3.18|>=2.4,<2.4.8|>=2.5,<2.5.2", + "symfony/http-foundation": ">=2,<2.3.27|>=2.4,<2.5.11|>=2.6,<2.6.6", + "symfony/http-kernel": ">=2,<2.3.29|>=2.4,<2.5.12|>=2.6,<2.6.8", + "symfony/intl": ">=2.7,<2.7.38|>=2.8,<2.8.31|>=3,<3.2.14|>=3.3,<3.3.13", + "symfony/routing": ">=2,<2.0.19", + "symfony/security": ">=2,<2.0.25|>=2.1,<2.1.13|>=2.2,<2.2.9|>=2.3,<2.3.37|>=2.4,<2.6.13|>=2.7,<2.7.9|>=2.7.30,<2.7.32|>=2.8.23,<2.8.25|>=3.2.10,<3.2.12|>=3.3.3,<3.3.5", + "symfony/security-core": ">=2.4,<2.6.13|>=2.7,<2.7.9|>=2.7.30,<2.7.32|>=2.8,<2.8.6|>=2.8.23,<2.8.25|>=3,<3.0.6|>=3.2.10,<3.2.12|>=3.3.3,<3.3.5", + "symfony/security-csrf": ">=2.7,<2.7.38|>=2.8,<2.8.31|>=3,<3.2.14|>=3.3,<3.3.13", + "symfony/security-http": ">=2.3,<2.3.41|>=2.4,<2.7.38|>=2.8,<2.8.31|>=3,<3.2.14|>=3.3,<3.3.13", + "symfony/serializer": ">=2,<2.0.11", + "symfony/symfony": ">=2,<2.3.41|>=2.4,<2.7.38|>=2.8,<2.8.31|>=3,<3.2.14|>=3.3,<3.3.13", + "symfony/translation": ">=2,<2.0.17", + "symfony/validator": ">=2,<2.0.24|>=2.1,<2.1.12|>=2.2,<2.2.5|>=2.3,<2.3.3", + "symfony/web-profiler-bundle": ">=2,<2.3.19|>=2.4,<2.4.9|>=2.5,<2.5.4", + "symfony/yaml": ">=2,<2.0.22|>=2.1,<2.1.7", + "thelia/backoffice-default-template": ">=2.1,<2.1.2", + "thelia/thelia": ">=2.1.0-beta1,<2.1.3|>=2.1,<2.1.2", + "titon/framework": ">=0,<9.9.99", + "twig/twig": "<1.20", + "typo3/cms": ">=6.2,<6.2.30|>=7,<7.6.22|>=8,<8.7.5", + "typo3/flow": ">=1,<1.0.4|>=1.1,<1.1.1|>=2,<2.0.1|>=2.3,<2.3.16|>=3,<3.0.10|>=3.1,<3.1.7|>=3.2,<3.2.7|>=3.3,<3.3.5", + "typo3/neos": ">=1.1,<1.1.3|>=1.2,<1.2.13|>=2,<2.0.4", + "willdurand/js-translation-bundle": "<2.1.1", + "yiisoft/yii": ">=1.1.14,<1.1.15", + "yiisoft/yii2": "<2.0.15", + "yiisoft/yii2-bootstrap": "<2.0.4", + "yiisoft/yii2-dev": "<2.0.15", + "yiisoft/yii2-elasticsearch": "<2.0.5", + "yiisoft/yii2-gii": "<2.0.4", + "yiisoft/yii2-jui": "<2.0.4", + "yiisoft/yii2-redis": "<2.0.8", + "zendframework/zend-cache": ">=2.4,<2.4.8|>=2.5,<2.5.3", + "zendframework/zend-captcha": ">=2,<2.4.9|>=2.5,<2.5.2", + "zendframework/zend-crypt": ">=2,<2.4.9|>=2.5,<2.5.2", + "zendframework/zend-db": ">=2,<2.0.99|>=2.1,<2.1.99|>=2.2,<2.2.10|>=2.3,<2.3.5", + "zendframework/zend-diactoros": ">=1,<1.0.4", + "zendframework/zend-form": ">=2,<2.2.7|>=2.3,<2.3.1", + "zendframework/zend-http": ">=2,<2.0.99|>=2.1,<2.1.99|>=2.3,<2.3.8|>=2.4,<2.4.1", + "zendframework/zend-json": ">=2.1,<2.1.6|>=2.2,<2.2.6", + "zendframework/zend-ldap": ">=2,<2.0.99|>=2.1,<2.1.99|>=2.2,<2.2.8|>=2.3,<2.3.3", + "zendframework/zend-mail": ">=2,<2.4.11|>=2.5,<2.7.2", + "zendframework/zend-navigation": ">=2,<2.2.7|>=2.3,<2.3.1", + "zendframework/zend-session": ">=2,<2.0.99|>=2.1,<2.1.99|>=2.2,<2.2.9|>=2.3,<2.3.4", + "zendframework/zend-validator": ">=2.3,<2.3.6", + "zendframework/zend-view": ">=2,<2.2.7|>=2.3,<2.3.1", + "zendframework/zend-xmlrpc": ">=2.1,<2.1.6|>=2.2,<2.2.6", + "zendframework/zendframework": ">=2,<2.4.11|>=2.5,<2.5.1", + "zendframework/zendframework1": "<1.12.20", + "zendframework/zendopenid": ">=2,<2.0.2", + "zendframework/zendxml": ">=1,<1.0.1", + "zetacomponents/mail": "<1.8.2", + "zf-commons/zfc-user": "<1.2.2", + "zfcampus/zf-apigility-doctrine": ">=1,<1.0.3", + "zfr/zfr-oauth2-server-module": "<0.1.2" + }, + "type": "metapackage", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "role": "maintainer" + } + ], + "description": "Prevents installation of composer packages with known security vulnerabilities: no API, simply require it", + "time": "2018-04-02T06:47:13+00:00" + }, + { + "name": "symfony/console", + "version": "v4.0.7", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "aad9a6fe47319f22748fd764f52d3a7ca6fa6b64" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/aad9a6fe47319f22748fd764f52d3a7ca6fa6b64", + "reference": "aad9a6fe47319f22748fd764f52d3a7ca6fa6b64", + "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": "2018-04-03T05:24:00+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.7.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "78be803ce01e55d3491c1397cf1c64beb9c1b63b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/78be803ce01e55d3491c1397cf1c64beb9c1b63b", + "reference": "78be803ce01e55d3491c1397cf1c64beb9c1b63b", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.7-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": "2018-01-30T19:27:44+00:00" + }, + { + "name": "tuupola/callable-handler", + "version": "0.3.0", + "source": { + "type": "git", + "url": "https://github.com/tuupola/callable-handler.git", + "reference": "5141efa1e974687a3fa53338811a988198f50662" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/tuupola/callable-handler/zipball/5141efa1e974687a3fa53338811a988198f50662", + "reference": "5141efa1e974687a3fa53338811a988198f50662", + "shasum": "" + }, + "require": { + "php": "^7.0", + "psr/http-server-middleware": "^1.0" + }, + "require-dev": { + "codedungeon/phpunit-result-printer": "^0.4.4", + "overtrue/phplint": "^1.0", + "phpunit/phpunit": "^6.5", + "squizlabs/php_codesniffer": "^3.2", + "tuupola/http-factory": "^0.3.0", + "zendframework/zend-diactoros": "^1.6" + }, + "type": "library", + "autoload": { + "psr-4": { + "Tuupola\\Middleware\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mika Tuupola", + "email": "tuupola@appelsiini.net", + "homepage": "https://appelsiini.net/", + "role": "Developer" + } + ], + "description": "Compatibility layer for PSR-7 double pass and PSR-15 middlewares.", + "homepage": "https://github.com/tuupola/callable-handler", + "keywords": [ + "middleware", + "psr-15", + "psr-7" + ], + "time": "2018-01-23T04:07:25+00:00" + }, + { + "name": "tuupola/cors-middleware", + "version": "0.7.0", + "source": { + "type": "git", + "url": "https://github.com/tuupola/cors-middleware.git", + "reference": "b0e2b7acacf22acae6ba029ee424fd6c073bb443" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/tuupola/cors-middleware/zipball/b0e2b7acacf22acae6ba029ee424fd6c073bb443", + "reference": "b0e2b7acacf22acae6ba029ee424fd6c073bb443", + "shasum": "" + }, + "require": { + "neomerx/cors-psr7": "^1.0", + "php": "^7.1", + "psr/http-server-middleware": "^1.0", + "tuupola/callable-handler": "^0.3.0", + "tuupola/http-factory": "^0.3.0" + }, + "require-dev": { + "codedungeon/phpunit-result-printer": "^0.4.4", + "equip/dispatch": "dev-approved-psr15 as 1.0.x-dev", + "overtrue/phplint": "^1.0", + "phpunit/phpunit": "^6.5", + "squizlabs/php_codesniffer": "^3.2", + "zendframework/zend-diactoros": "^1.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Tuupola\\Middleware\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mika Tuupola", + "email": "tuupola@appelsiini.net", + "homepage": "http://www.appelsiini.net/", + "role": "Developer" + } + ], + "description": "PSR-7 and PSR-15 CORS middleware", + "homepage": "https://github.com/tuupola/cors-middleware", + "keywords": [ + "cors", + "middleware", + "psr-15", + "psr-7" + ], + "time": "2018-01-25T02:29:07+00:00" + }, + { + "name": "tuupola/http-factory", + "version": "0.3.0", + "source": { + "type": "git", + "url": "https://github.com/tuupola/http-factory.git", + "reference": "57b2e19ff3f4af0bbee4e31fd282689be351f1ad" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/tuupola/http-factory/zipball/57b2e19ff3f4af0bbee4e31fd282689be351f1ad", + "reference": "57b2e19ff3f4af0bbee4e31fd282689be351f1ad", + "shasum": "" + }, + "require": { + "http-interop/http-factory": "^0.3.0" + }, + "require-dev": { + "http-interop/http-factory-tests": "^0.3.0", + "overtrue/phplint": "^0.2.1", + "phpunit/phpunit": "^5.7", + "squizlabs/php_codesniffer": "^3.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Tuupola\\Http\\Factory\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mika Tuupola", + "email": "tuupola@appelsiini.net", + "homepage": "http://www.appelsiini.net/", + "role": "Developer" + } + ], + "description": "Lightweight autodiscovering PSR-17 HTTP factories", + "homepage": "https://github.com/tuupola/http-factory", + "keywords": [ + "http", + "psr-17", + "psr-7" + ], + "time": "2017-07-15T22:03:15+00:00" + }, + { + "name": "zendframework/zend-component-installer", + "version": "2.1.1", + "source": { + "type": "git", + "url": "https://github.com/zendframework/zend-component-installer.git", + "reference": "788b74439fff056b848c47aeb3d8b63cf2fb2161" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/zend-component-installer/zipball/788b74439fff056b848c47aeb3d8b63cf2fb2161", + "reference": "788b74439fff056b848c47aeb3d8b63cf2fb2161", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.0", + "php": "^7.1" + }, + "require-dev": { + "composer/composer": "^1.5.2", + "malukenho/docheader": "^0.1.6", + "mikey179/vfsstream": "^1.6.5", + "phpunit/phpunit": "^5.7.23 || ^6.4.3", + "zendframework/zend-coding-standard": "~1.0.0" + }, + "type": "composer-plugin", + "extra": { + "branch-alias": { + "dev-master": "2.1.x-dev", + "dev-develop": "2.2.x-dev" + }, + "class": "Zend\\ComponentInstaller\\ComponentInstaller" + }, + "autoload": { + "psr-4": { + "Zend\\ComponentInstaller\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Composer plugin for automating component registration in zend-mvc and Expressive applications", + "keywords": [ + "ZendFramework", + "component installer", + "composer", + "plugin", + "zf" + ], + "time": "2018-03-21T16:53:56+00:00" + }, + { + "name": "zendframework/zend-config-aggregator", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/zendframework/zend-config-aggregator.git", + "reference": "46460b25c09fb572f807a00cf9dfe9c466792a76" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/zend-config-aggregator/zipball/46460b25c09fb572f807a00cf9dfe9c466792a76", + "reference": "46460b25c09fb572f807a00cf9dfe9c466792a76", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0", + "zendframework/zend-stdlib": "^2.7.7 || ^3.1.0" + }, + "require-dev": { + "malukenho/docheader": "^0.1.5", + "mikey179/vfsstream": "^1.6", + "phpunit/phpunit": "^5.7.21 || ^6.3", + "zendframework/zend-coding-standard": "~1.0.0", + "zendframework/zend-config": "^2.6 || ^3.0", + "zendframework/zend-servicemanager": "^2.7.7 || ^3.1.1" + }, + "suggest": { + "zendframework/zend-config": "Allows loading configuration from XML, INI, YAML, and JSON files" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev", + "dev-develop": "1.2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Zend\\ConfigAggregator\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Lightweight library for collecting and merging configuration from different sources", + "keywords": [ + "ZendFramework", + "config-aggregator", + "zf" + ], + "time": "2018-02-26T16:46:30+00:00" + }, + { + "name": "zendframework/zend-diactoros", + "version": "1.7.1", + "source": { + "type": "git", + "url": "https://github.com/zendframework/zend-diactoros.git", + "reference": "bf26aff803a11c5cc8eb7c4878a702c403ec67f1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/zend-diactoros/zipball/bf26aff803a11c5cc8eb7c4878a702c403ec67f1", + "reference": "bf26aff803a11c5cc8eb7c4878a702c403ec67f1", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0", + "psr/http-message": "^1.0" + }, + "provide": { + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "ext-dom": "*", + "ext-libxml": "*", + "phpunit/phpunit": "^5.7.16 || ^6.0.8", + "zendframework/zend-coding-standard": "~1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.7.x-dev", + "dev-develop": "1.8.x-dev" + } + }, + "autoload": { + "psr-4": { + "Zend\\Diactoros\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-2-Clause" + ], + "description": "PSR HTTP Message implementations", + "homepage": "https://github.com/zendframework/zend-diactoros", + "keywords": [ + "http", + "psr", + "psr-7" + ], + "time": "2018-02-26T15:44:50+00:00" + }, + { + "name": "zendframework/zend-escaper", + "version": "2.5.2", + "source": { + "type": "git", + "url": "https://github.com/zendframework/zend-escaper.git", + "reference": "2dcd14b61a72d8b8e27d579c6344e12c26141d4e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/zend-escaper/zipball/2dcd14b61a72d8b8e27d579c6344e12c26141d4e", + "reference": "2dcd14b61a72d8b8e27d579c6344e12c26141d4e", + "shasum": "" + }, + "require": { + "php": ">=5.5" + }, + "require-dev": { + "fabpot/php-cs-fixer": "1.7.*", + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.5-dev", + "dev-develop": "2.6-dev" + } + }, + "autoload": { + "psr-4": { + "Zend\\Escaper\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "homepage": "https://github.com/zendframework/zend-escaper", + "keywords": [ + "escaper", + "zf2" + ], + "time": "2016-06-30T19:48:38+00:00" + }, + { + "name": "zendframework/zend-expressive", + "version": "3.0.1", + "source": { + "type": "git", + "url": "https://github.com/zendframework/zend-expressive.git", + "reference": "7cbc574376f0a6712c98a7fc2afdcc385dc5fc9c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/zend-expressive/zipball/7cbc574376f0a6712c98a7fc2afdcc385dc5fc9c", + "reference": "7cbc574376f0a6712c98a7fc2afdcc385dc5fc9c", + "shasum": "" + }, + "require": { + "fig/http-message-util": "^1.1.2", + "php": "^7.1", + "psr/container": "^1.0", + "psr/http-message": "^1.0.1", + "psr/http-server-middleware": "^1.0", + "zendframework/zend-expressive-router": "^3.0", + "zendframework/zend-expressive-template": "^2.0", + "zendframework/zend-httphandlerrunner": "^1.0.1", + "zendframework/zend-stratigility": "^3.0" + }, + "conflict": { + "container-interop/container-interop": "<1.2.0", + "zendframework/zend-diactoros": "<1.7.1" + }, + "require-dev": { + "filp/whoops": "^1.1.10 || ^2.1.13", + "malukenho/docheader": "^0.1.6", + "mockery/mockery": "^1.0", + "phpstan/phpstan": "^0.9.2", + "phpstan/phpstan-strict-rules": "^0.9", + "phpunit/phpunit": "^7.0.1", + "zendframework/zend-coding-standard": "~1.0.0", + "zendframework/zend-diactoros": "^1.7.1", + "zendframework/zend-expressive-aurarouter": "^3.0", + "zendframework/zend-expressive-fastroute": "^3.0", + "zendframework/zend-expressive-zendrouter": "^3.0", + "zendframework/zend-servicemanager": "^2.7.8 || ^3.3" + }, + "suggest": { + "filp/whoops": "^2.1 to use the Whoops error handler", + "psr/http-message-implementation": "Please install a psr/http-message-implementation to consume Expressive; e.g., zendframework/zend-diactoros", + "zendframework/zend-auradi-config": "^1.0 to use Aura.Di dependency injection container", + "zendframework/zend-expressive-helpers": "^3.0 for its UrlHelper, ServerUrlHelper, and BodyParseMiddleware", + "zendframework/zend-expressive-tooling": "^1.0 for migration and development tools; require it with the --dev flag", + "zendframework/zend-pimple-config": "^1.0 to use Pimple for dependency injection container", + "zendframework/zend-servicemanager": "^3.3 to use zend-servicemanager for dependency injection" + }, + "bin": [ + "bin/expressive-tooling" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev", + "dev-develop": "3.1.x-dev" + }, + "zf": { + "config-provider": "Zend\\Expressive\\ConfigProvider" + } + }, + "autoload": { + "files": [ + "src/constants.php" + ], + "psr-4": { + "Zend\\Expressive\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "PSR-15 Middleware Microframework", + "keywords": [ + "PSR-11", + "ZendFramework", + "expressive", + "http", + "middleware", + "psr", + "psr-15", + "psr-7", + "zend-expressive", + "zf" + ], + "time": "2018-03-19T16:15:11+00:00" + }, + { + "name": "zendframework/zend-expressive-fastroute", + "version": "3.0.1", + "source": { + "type": "git", + "url": "https://github.com/zendframework/zend-expressive-fastroute.git", + "reference": "e5b94197c9145810055133a09a277a29239e1a64" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/zend-expressive-fastroute/zipball/e5b94197c9145810055133a09a277a29239e1a64", + "reference": "e5b94197c9145810055133a09a277a29239e1a64", + "shasum": "" + }, + "require": { + "fig/http-message-util": "^1.1.2", + "nikic/fast-route": "^1.2", + "php": "^7.1", + "psr/container": "^1.0", + "psr/http-message": "^1.0.1", + "zendframework/zend-expressive-router": "^3.0", + "zendframework/zend-stdlib": "^2.0 || ^3.1" + }, + "conflict": { + "container-interop/container-interop": "<1.2.0" + }, + "require-dev": { + "malukenho/docheader": "^0.1.6", + "mikey179/vfsstream": "^1.6.5", + "phpunit/phpunit": "^7.0.2", + "zendframework/zend-coding-standard": "~1.0.0", + "zendframework/zend-diactoros": "^1.7.1", + "zendframework/zend-stratigility": "^3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev", + "dev-develop": "3.1.x-dev" + }, + "zf": { + "config-provider": "Zend\\Expressive\\Router\\FastRouteRouter\\ConfigProvider" + } + }, + "autoload": { + "psr-4": { + "Zend\\Expressive\\Router\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "FastRoute integration for Expressive", + "keywords": [ + "FastRoute", + "ZendFramework", + "expressive", + "http", + "middleware", + "psr", + "psr-7", + "zend-expressive", + "zf" + ], + "time": "2018-03-20T16:34:28+00:00" + }, + { + "name": "zendframework/zend-expressive-helpers", + "version": "5.0.0", + "source": { + "type": "git", + "url": "https://github.com/zendframework/zend-expressive-helpers.git", + "reference": "196e7d4de290b422df4688338dd4fa47e48b4d2f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/zend-expressive-helpers/zipball/196e7d4de290b422df4688338dd4fa47e48b4d2f", + "reference": "196e7d4de290b422df4688338dd4fa47e48b4d2f", + "shasum": "" + }, + "require": { + "php": "^7.1", + "psr/container": "^1.0", + "psr/http-message": "^1.0.1", + "psr/http-server-middleware": "^1.0", + "zendframework/zend-expressive-router": "^3.0" + }, + "require-dev": { + "malukenho/docheader": "^0.1.6", + "mockery/mockery": "^1.0", + "phpunit/phpunit": "^7.0.2", + "zendframework/zend-coding-standard": "~1.0.0", + "zendframework/zend-diactoros": "^1.7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0.x-dev", + "dev-develop": "5.1.x-dev" + }, + "zf": { + "config-provider": "Zend\\Expressive\\Helper\\ConfigProvider" + } + }, + "autoload": { + "psr-4": { + "Zend\\Expressive\\Helper\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Helper/Utility classes for Expressive", + "keywords": [ + "ZendFramework", + "expressive", + "http", + "middleware", + "psr", + "psr-7", + "zend-expressive", + "zf" + ], + "time": "2018-03-15T16:42:27+00:00" + }, + { + "name": "zendframework/zend-expressive-router", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/zendframework/zend-expressive-router.git", + "reference": "6c7b039820d6feda9a1770cd71f9cc4120e8ec51" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/zend-expressive-router/zipball/6c7b039820d6feda9a1770cd71f9cc4120e8ec51", + "reference": "6c7b039820d6feda9a1770cd71f9cc4120e8ec51", + "shasum": "" + }, + "require": { + "fig/http-message-util": "^1.1.2", + "php": "^7.1", + "psr/container": "^1.0", + "psr/http-message": "^1.0.1", + "psr/http-server-middleware": "^1.0" + }, + "require-dev": { + "malukenho/docheader": "^0.1.6", + "phpunit/phpunit": "^7.0.2", + "zendframework/zend-coding-standard": "~1.0.0" + }, + "suggest": { + "zendframework/zend-expressive-aurarouter": "^3.0 to use the Aura.Router routing adapter", + "zendframework/zend-expressive-fastroute": "^3.0 to use the FastRoute routing adapter", + "zendframework/zend-expressive-zendrouter": "^3.0 to use the zend-router routing adapter" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev", + "dev-develop": "3.1.x-dev" + }, + "zf": { + "config-provider": "Zend\\Expressive\\Router\\ConfigProvider" + } + }, + "autoload": { + "psr-4": { + "Zend\\Expressive\\Router\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Router subcomponent for Expressive", + "keywords": [ + "ZendFramework", + "expressive", + "http", + "middleware", + "psr", + "psr-7", + "zend-expressive", + "zf" + ], + "time": "2018-03-21T16:49:35+00:00" + }, + { + "name": "zendframework/zend-expressive-template", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/zendframework/zend-expressive-template.git", + "reference": "b8b9ece61ed598a58223638933e2fd703ae4a5e9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/zend-expressive-template/zipball/b8b9ece61ed598a58223638933e2fd703ae4a5e9", + "reference": "b8b9ece61ed598a58223638933e2fd703ae4a5e9", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "require-dev": { + "malukenho/docheader": "^0.1.6", + "phpunit/phpunit": "^7.0.2", + "zendframework/zend-coding-standard": "~1.0.0" + }, + "suggest": { + "zendframework/zend-expressive-platesrenderer": "^2.0 to use the Plates template renderer", + "zendframework/zend-expressive-twigrenderer": "^2.0 to use the Twig template renderer", + "zendframework/zend-expressive-zendviewrenderer": "^2.0 to use the zend-view PhpRenderer template renderer" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev", + "dev-develop": "2.1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Zend\\Expressive\\Template\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Template subcomponent for Expressive", + "keywords": [ + "ZendFramework", + "expressive", + "template", + "zend-expressive", + "zf" + ], + "time": "2018-03-15T15:42:46+00:00" + }, + { + "name": "zendframework/zend-filter", + "version": "2.7.2", + "source": { + "type": "git", + "url": "https://github.com/zendframework/zend-filter.git", + "reference": "b8d0ff872f126631bf63a932e33aa2d22d467175" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/zend-filter/zipball/b8d0ff872f126631bf63a932e33aa2d22d467175", + "reference": "b8d0ff872f126631bf63a932e33aa2d22d467175", + "shasum": "" + }, + "require": { + "php": "^5.5 || ^7.0", + "zendframework/zend-stdlib": "^2.7 || ^3.0" + }, + "require-dev": { + "pear/archive_tar": "^1.4", + "phpunit/phpunit": "^6.0.10 || ^5.7.17", + "zendframework/zend-coding-standard": "~1.0.0", + "zendframework/zend-crypt": "^2.6 || ^3.0", + "zendframework/zend-servicemanager": "^2.7.5 || ^3.0.3", + "zendframework/zend-uri": "^2.5" + }, + "suggest": { + "zendframework/zend-crypt": "Zend\\Crypt component, for encryption filters", + "zendframework/zend-i18n": "Zend\\I18n component for filters depending on i18n functionality", + "zendframework/zend-servicemanager": "Zend\\ServiceManager component, for using the filter chain functionality", + "zendframework/zend-uri": "Zend\\Uri component, for the UriNormalize filter" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev", + "dev-develop": "2.8-dev" + }, + "zf": { + "component": "Zend\\Filter", + "config-provider": "Zend\\Filter\\ConfigProvider" + } + }, + "autoload": { + "psr-4": { + "Zend\\Filter\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "provides a set of commonly needed data filters", + "homepage": "https://github.com/zendframework/zend-filter", + "keywords": [ + "filter", + "zf2" + ], + "time": "2017-05-17T20:56:17+00:00" + }, + { + "name": "zendframework/zend-form", + "version": "2.11.0", + "source": { + "type": "git", + "url": "https://github.com/zendframework/zend-form.git", + "reference": "b68a9f07d93381613b68817091d0505ca94d3363" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/zend-form/zipball/b68a9f07d93381613b68817091d0505ca94d3363", + "reference": "b68a9f07d93381613b68817091d0505ca94d3363", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0", + "zendframework/zend-hydrator": "^1.1 || ^2.1", + "zendframework/zend-inputfilter": "^2.8", + "zendframework/zend-stdlib": "^2.7 || ^3.0" + }, + "require-dev": { + "doctrine/annotations": "~1.0", + "phpunit/phpunit": "^5.7.23 || ^6.5.3", + "zendframework/zend-cache": "^2.6.1", + "zendframework/zend-captcha": "^2.7.1", + "zendframework/zend-code": "^2.6 || ^3.0", + "zendframework/zend-coding-standard": "~1.0.0", + "zendframework/zend-escaper": "^2.5", + "zendframework/zend-eventmanager": "^2.6.2 || ^3.0", + "zendframework/zend-filter": "^2.6", + "zendframework/zend-i18n": "^2.6", + "zendframework/zend-servicemanager": "^2.7.5 || ^3.0.3", + "zendframework/zend-session": "^2.8.1", + "zendframework/zend-text": "^2.6", + "zendframework/zend-validator": "^2.6", + "zendframework/zend-view": "^2.6.2", + "zendframework/zendservice-recaptcha": "^3.0.0" + }, + "suggest": { + "zendframework/zend-captcha": "^2.7.1, required for using CAPTCHA form elements", + "zendframework/zend-code": "^2.6 || ^3.0, required to use zend-form annotations support", + "zendframework/zend-eventmanager": "^2.6.2 || ^3.0, reuired for zend-form annotations support", + "zendframework/zend-i18n": "^2.6, required when using zend-form view helpers", + "zendframework/zend-servicemanager": "^2.7.5 || ^3.0.3, required to use the form factories or provide services", + "zendframework/zend-view": "^2.6.2, required for using the zend-form view helpers", + "zendframework/zendservice-recaptcha": "in order to use the ReCaptcha form element" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.11.x-dev", + "dev-develop": "2.12.x-dev" + }, + "zf": { + "component": "Zend\\Form", + "config-provider": "Zend\\Form\\ConfigProvider" + } + }, + "autoload": { + "psr-4": { + "Zend\\Form\\": "src/" + }, + "files": [ + "autoload/formElementManagerPolyfill.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Validate and display simple and complex forms, casting forms to business objects and vice versa", + "keywords": [ + "ZendFramework", + "form", + "zf" + ], + "time": "2017-12-06T21:09:08+00:00" + }, + { + "name": "zendframework/zend-httphandlerrunner", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/zendframework/zend-httphandlerrunner.git", + "reference": "5e4c1e82a8bb1585020eafd32c49ece5a6ee98df" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/zend-httphandlerrunner/zipball/5e4c1e82a8bb1585020eafd32c49ece5a6ee98df", + "reference": "5e4c1e82a8bb1585020eafd32c49ece5a6ee98df", + "shasum": "" + }, + "require": { + "php": "^7.1", + "psr/http-message": "^1.0", + "psr/http-message-implementation": "^1.0", + "psr/http-server-handler": "^1.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.3", + "zendframework/zend-coding-standard": "~1.0.0", + "zendframework/zend-diactoros": "^1.7" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + }, + "zf": { + "config-provider": "Zend\\HttpHandlerRunner\\ConfigProvider" + } + }, + "autoload": { + "psr-4": { + "Zend\\HttpHandlerRunner\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Execute PSR-15 RequestHandlerInterface instances and emit responses they generate.", + "keywords": [ + "ZendFramework", + "components", + "expressive", + "psr-15", + "psr-7", + "zf" + ], + "time": "2018-02-21T20:33:02+00:00" + }, + { + "name": "zendframework/zend-hydrator", + "version": "2.3.1", + "source": { + "type": "git", + "url": "https://github.com/zendframework/zend-hydrator.git", + "reference": "de0d6465fbc4b7ca345fddc148834c321c4b361f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/zend-hydrator/zipball/de0d6465fbc4b7ca345fddc148834c321c4b361f", + "reference": "de0d6465fbc4b7ca345fddc148834c321c4b361f", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0", + "zendframework/zend-stdlib": "^3.0" + }, + "require-dev": { + "phpunit/phpunit": "^5.7.21 || ^6.3", + "zendframework/zend-coding-standard": "~1.0.0", + "zendframework/zend-eventmanager": "^3.0", + "zendframework/zend-filter": "^2.6", + "zendframework/zend-inputfilter": "^2.6", + "zendframework/zend-serializer": "^2.6.1", + "zendframework/zend-servicemanager": "^2.7.5 || ^3.0.3" + }, + "suggest": { + "zendframework/zend-eventmanager": "^2.6.2 || ^3.0, to support aggregate hydrator usage", + "zendframework/zend-filter": "^2.6, to support naming strategy hydrator usage", + "zendframework/zend-serializer": "^2.6.1, to use the SerializableStrategy", + "zendframework/zend-servicemanager": "^2.7.5 || ^3.0.3, to support hydrator plugin manager usage" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-release-1.0": "1.0-dev", + "dev-release-1.1": "1.1-dev", + "dev-master": "2.3-dev", + "dev-develop": "2.4-dev" + }, + "zf": { + "component": "Zend\\Hydrator", + "config-provider": "Zend\\Hydrator\\ConfigProvider" + } + }, + "autoload": { + "psr-4": { + "Zend\\Hydrator\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "homepage": "https://github.com/zendframework/zend-hydrator", + "keywords": [ + "hydrator", + "zf2" + ], + "time": "2017-10-02T15:01:27+00:00" + }, + { + "name": "zendframework/zend-inputfilter", + "version": "2.8.1", + "source": { + "type": "git", + "url": "https://github.com/zendframework/zend-inputfilter.git", + "reference": "55d1430db559e9781b147e73c2c0ce6635d8efe2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/zend-inputfilter/zipball/55d1430db559e9781b147e73c2c0ce6635d8efe2", + "reference": "55d1430db559e9781b147e73c2c0ce6635d8efe2", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0", + "zendframework/zend-filter": "^2.6", + "zendframework/zend-servicemanager": "^2.7.10 || ^3.3.1", + "zendframework/zend-stdlib": "^2.7 || ^3.0", + "zendframework/zend-validator": "^2.10.1" + }, + "require-dev": { + "phpunit/phpunit": "^5.7.23 || ^6.4.3", + "zendframework/zend-coding-standard": "~1.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8.x-dev", + "dev-develop": "2.9.x-dev" + }, + "zf": { + "component": "Zend\\InputFilter", + "config-provider": "Zend\\InputFilter\\ConfigProvider" + } + }, + "autoload": { + "psr-4": { + "Zend\\InputFilter\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Normalize and validate input sets from the web, APIs, the CLI, and more, including files", + "keywords": [ + "ZendFramework", + "inputfilter", + "zf" + ], + "time": "2018-01-22T19:41:18+00:00" + }, + { + "name": "zendframework/zend-json", + "version": "3.1.0", + "source": { + "type": "git", + "url": "https://github.com/zendframework/zend-json.git", + "reference": "4dd940e8e6f32f1d36ea6b0677ea57c540c7c19c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/zend-json/zipball/4dd940e8e6f32f1d36ea6b0677ea57c540c7c19c", + "reference": "4dd940e8e6f32f1d36ea6b0677ea57c540c7c19c", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^5.7.23 || ^6.4.3", + "zendframework/zend-coding-standard": "~1.0.0", + "zendframework/zend-stdlib": "^2.7.7 || ^3.1" + }, + "suggest": { + "zendframework/zend-json-server": "For implementing JSON-RPC servers", + "zendframework/zend-xml2json": "For converting XML documents to JSON" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1.x-dev", + "dev-develop": "3.2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Zend\\Json\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "provides convenience methods for serializing native PHP to JSON and decoding JSON to native PHP", + "keywords": [ + "ZendFramework", + "json", + "zf" + ], + "time": "2018-01-04T17:51:34+00:00" + }, + { + "name": "zendframework/zend-servicemanager", + "version": "3.3.2", + "source": { + "type": "git", + "url": "https://github.com/zendframework/zend-servicemanager.git", + "reference": "9f35a104b8d4d3b32da5f4a3b6efc0dd62e5af42" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/zend-servicemanager/zipball/9f35a104b8d4d3b32da5f4a3b6efc0dd62e5af42", + "reference": "9f35a104b8d4d3b32da5f4a3b6efc0dd62e5af42", + "shasum": "" + }, + "require": { + "container-interop/container-interop": "^1.2", + "php": "^5.6 || ^7.0", + "psr/container": "^1.0", + "zendframework/zend-stdlib": "^3.1" + }, + "provide": { + "container-interop/container-interop-implementation": "^1.2", + "psr/container-implementation": "^1.0" + }, + "require-dev": { + "mikey179/vfsstream": "^1.6.5", + "ocramius/proxy-manager": "^1.0 || ^2.0", + "phpbench/phpbench": "^0.13.0", + "phpunit/phpunit": "^5.7.25 || ^6.4.4", + "zendframework/zend-coding-standard": "~1.0.0" + }, + "suggest": { + "ocramius/proxy-manager": "ProxyManager 1.* to handle lazy initialization of services", + "zendframework/zend-stdlib": "zend-stdlib ^2.5 if you wish to use the MergeReplaceKey or MergeRemoveKey features in Config instances" + }, + "bin": [ + "bin/generate-deps-for-config-factory", + "bin/generate-factory-for-class" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.3-dev", + "dev-develop": "4.0-dev" + } + }, + "autoload": { + "psr-4": { + "Zend\\ServiceManager\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Factory-Driven Dependency Injection Container", + "keywords": [ + "PSR-11", + "ZendFramework", + "dependency-injection", + "di", + "dic", + "service-manager", + "servicemanager", + "zf" + ], + "time": "2018-01-29T16:48:37+00:00" + }, + { + "name": "zendframework/zend-stdlib", + "version": "3.1.0", + "source": { + "type": "git", + "url": "https://github.com/zendframework/zend-stdlib.git", + "reference": "debedcfc373a293f9250cc9aa03cf121428c8e78" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/zend-stdlib/zipball/debedcfc373a293f9250cc9aa03cf121428c8e78", + "reference": "debedcfc373a293f9250cc9aa03cf121428c8e78", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0" + }, + "require-dev": { + "athletic/athletic": "~0.1", + "phpunit/phpunit": "~4.0", + "squizlabs/php_codesniffer": "^2.6.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev", + "dev-develop": "3.2-dev" + } + }, + "autoload": { + "psr-4": { + "Zend\\Stdlib\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "homepage": "https://github.com/zendframework/zend-stdlib", + "keywords": [ + "stdlib", + "zf2" + ], + "time": "2016-09-13T14:38:50+00:00" + }, + { + "name": "zendframework/zend-stratigility", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/zendframework/zend-stratigility.git", + "reference": "89fc799df3ce7d279bc06575252d466be9c1b5d6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/zend-stratigility/zipball/89fc799df3ce7d279bc06575252d466be9c1b5d6", + "reference": "89fc799df3ce7d279bc06575252d466be9c1b5d6", + "shasum": "" + }, + "require": { + "fig/http-message-util": "^1.1", + "php": "^7.1", + "psr/http-message": "^1.0", + "psr/http-server-middleware": "^1.0", + "zendframework/zend-escaper": "^2.3" + }, + "conflict": { + "zendframework/zend-diactoros": "<1.7.1" + }, + "require-dev": { + "malukenho/docheader": "^0.1.6", + "phpunit/phpunit": "^7.0.1", + "zendframework/zend-coding-standard": "~1.0.0", + "zendframework/zend-diactoros": "^1.7.1" + }, + "suggest": { + "psr/http-message-implementation": "Please install a psr/http-message-implementation to consume Stratigility; e.g., zendframework/zend-diactoros" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev", + "dev-develop": "3.1.x-dev" + } + }, + "autoload": { + "files": [ + "src/functions/double-pass-middleware.php", + "src/functions/host.php", + "src/functions/middleware.php", + "src/functions/path.php" + ], + "psr-4": { + "Zend\\Stratigility\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "PSR-7 middleware foundation for building and dispatching middleware pipelines", + "keywords": [ + "ZendFramework", + "http", + "middleware", + "psr-15", + "psr-7", + "zf" + ], + "time": "2018-03-15T14:10:32+00:00" + }, + { + "name": "zendframework/zend-validator", + "version": "2.10.2", + "source": { + "type": "git", + "url": "https://github.com/zendframework/zend-validator.git", + "reference": "38109ed7d8e46cfa71bccbe7e6ca80cdd035f8c9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/zend-validator/zipball/38109ed7d8e46cfa71bccbe7e6ca80cdd035f8c9", + "reference": "38109ed7d8e46cfa71bccbe7e6ca80cdd035f8c9", + "shasum": "" + }, + "require": { + "container-interop/container-interop": "^1.1", + "php": "^5.6 || ^7.0", + "zendframework/zend-stdlib": "^2.7.6 || ^3.1" + }, + "require-dev": { + "phpunit/phpunit": "^6.0.8 || ^5.7.15", + "zendframework/zend-cache": "^2.6.1", + "zendframework/zend-coding-standard": "~1.0.0", + "zendframework/zend-config": "^2.6", + "zendframework/zend-db": "^2.7", + "zendframework/zend-filter": "^2.6", + "zendframework/zend-http": "^2.5.4", + "zendframework/zend-i18n": "^2.6", + "zendframework/zend-math": "^2.6", + "zendframework/zend-servicemanager": "^2.7.5 || ^3.0.3", + "zendframework/zend-session": "^2.8", + "zendframework/zend-uri": "^2.5" + }, + "suggest": { + "zendframework/zend-db": "Zend\\Db component, required by the (No)RecordExists validator", + "zendframework/zend-filter": "Zend\\Filter component, required by the Digits validator", + "zendframework/zend-i18n": "Zend\\I18n component to allow translation of validation error messages", + "zendframework/zend-i18n-resources": "Translations of validator messages", + "zendframework/zend-math": "Zend\\Math component, required by the Csrf validator", + "zendframework/zend-servicemanager": "Zend\\ServiceManager component to allow using the ValidatorPluginManager and validator chains", + "zendframework/zend-session": "Zend\\Session component, ^2.8; required by the Csrf validator", + "zendframework/zend-uri": "Zend\\Uri component, required by the Uri and Sitemap\\Loc validators" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.10.x-dev", + "dev-develop": "2.11.x-dev" + }, + "zf": { + "component": "Zend\\Validator", + "config-provider": "Zend\\Validator\\ConfigProvider" + } + }, + "autoload": { + "psr-4": { + "Zend\\Validator\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "provides a set of commonly needed validators", + "homepage": "https://github.com/zendframework/zend-validator", + "keywords": [ + "validator", + "zf2" + ], + "time": "2018-02-01T17:05:33+00:00" + } + ], + "packages-dev": [ + { + "name": "filp/whoops", + "version": "2.1.14", + "source": { + "type": "git", + "url": "https://github.com/filp/whoops.git", + "reference": "c6081b8838686aa04f1e83ba7e91f78b7b2a23e6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/filp/whoops/zipball/c6081b8838686aa04f1e83ba7e91f78b7b2a23e6", + "reference": "c6081b8838686aa04f1e83ba7e91f78b7b2a23e6", + "shasum": "" + }, + "require": { + "php": "^5.5.9 || ^7.0", + "psr/log": "^1.0.1" + }, + "require-dev": { + "mockery/mockery": "0.9.*", + "phpunit/phpunit": "^4.8.35 || ^5.7", + "symfony/var-dumper": "^2.6 || ^3.0" + }, + "suggest": { + "symfony/var-dumper": "Pretty print complex values better with var-dumper available", + "whoops/soap": "Formats errors as SOAP responses" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "Whoops\\": "src/Whoops/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Filipe Dobreira", + "homepage": "https://github.com/filp", + "role": "Developer" + } + ], + "description": "php error handling for cool kids", + "homepage": "https://filp.github.io/whoops/", + "keywords": [ + "error", + "exception", + "handling", + "library", + "throwable", + "whoops" + ], + "time": "2017-11-23T18:22:44+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": "ocramius/package-versions", + "version": "1.3.0", + "source": { + "type": "git", + "url": "https://github.com/Ocramius/PackageVersions.git", + "reference": "4489d5002c49d55576fa0ba786f42dbb009be46f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Ocramius/PackageVersions/zipball/4489d5002c49d55576fa0ba786f42dbb009be46f", + "reference": "4489d5002c49d55576fa0ba786f42dbb009be46f", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.0.0", + "php": "^7.1.0" + }, + "require-dev": { + "composer/composer": "^1.6.3", + "ext-zip": "*", + "infection/infection": "^0.7.1", + "phpunit/phpunit": "^7.0.0" + }, + "type": "composer-plugin", + "extra": { + "class": "PackageVersions\\Installer", + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "PackageVersions\\": "src/PackageVersions" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "Composer plugin that provides efficient querying for installed package versions (no runtime IO)", + "time": "2018-02-05T13:05:30+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": "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.3.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "94fd0001232e47129dd3504189fa1c7225010d08" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/94fd0001232e47129dd3504189fa1c7225010d08", + "reference": "94fd0001232e47129dd3504189fa1c7225010d08", + "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-30T07:14:17+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.5", + "source": { + "type": "git", + "url": "https://github.com/phpspec/prophecy.git", + "reference": "dfd6be44111a7c41c2e884a336cc4f461b3b2401" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/dfd6be44111a7c41c2e884a336cc4f461b3b2401", + "reference": "dfd6be44111a7c41c2e884a336cc4f461b3b2401", + "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 || ^6.5" + }, + "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": "2018-02-19T10:16:54+00:00" + }, + { + "name": "phpunit/php-code-coverage", + "version": "6.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "f8ca4b604baf23dab89d87773c28cc07405189ba" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/f8ca4b604baf23dab89d87773c28cc07405189ba", + "reference": "f8ca4b604baf23dab89d87773c28cc07405189ba", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-xmlwriter": "*", + "php": "^7.1", + "phpunit/php-file-iterator": "^1.4.2", + "phpunit/php-text-template": "^1.2.1", + "phpunit/php-token-stream": "^3.0", + "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": "^7.0" + }, + "suggest": { + "ext-xdebug": "^2.6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "6.0-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": "2018-02-02T07:01:41+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": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "8b8454ea6958c3dee38453d3bd571e023108c91f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/8b8454ea6958c3dee38453d3bd571e023108c91f", + "reference": "8b8454ea6958c3dee38453d3bd571e023108c91f", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "require-dev": { + "phpunit/phpunit": "^7.0" + }, + "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", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "time": "2018-02-01T13:07:23+00:00" + }, + { + "name": "phpunit/php-token-stream", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-token-stream.git", + "reference": "21ad88bbba7c3d93530d93994e0a33cd45f02ace" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/21ad88bbba7c3d93530d93994e0a33cd45f02ace", + "reference": "21ad88bbba7c3d93530d93994e0a33cd45f02ace", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": "^7.1" + }, + "require-dev": { + "phpunit/phpunit": "^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.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": "2018-02-01T13:16:43+00:00" + }, + { + "name": "phpunit/phpunit", + "version": "7.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "536f4d853c12d8189963435088e8ff7c0daeab2e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/536f4d853c12d8189963435088e8ff7c0daeab2e", + "reference": "536f4d853c12d8189963435088e8ff7c0daeab2e", + "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.1", + "phpspec/prophecy": "^1.7", + "phpunit/php-code-coverage": "^6.0.1", + "phpunit/php-file-iterator": "^1.4.3", + "phpunit/php-text-template": "^1.2.1", + "phpunit/php-timer": "^2.0", + "phpunit/phpunit-mock-objects": "^6.0", + "sebastian/comparator": "^2.1", + "sebastian/diff": "^3.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" + }, + "require-dev": { + "ext-pdo": "*" + }, + "suggest": { + "ext-xdebug": "*", + "phpunit/php-invoker": "^2.0" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "7.0-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": "2018-03-26T07:36:48+00:00" + }, + { + "name": "phpunit/phpunit-mock-objects", + "version": "6.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", + "reference": "e3249dedc2d99259ccae6affbc2684eac37c2e53" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/e3249dedc2d99259ccae6affbc2684eac37c2e53", + "reference": "e3249dedc2d99259ccae6affbc2684eac37c2e53", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.0.5", + "php": "^7.1", + "phpunit/php-text-template": "^1.2.1", + "sebastian/exporter": "^3.1" + }, + "require-dev": { + "phpunit/phpunit": "^7.0" + }, + "suggest": { + "ext-soap": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "6.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": "2018-02-15T05:27:38+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.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "34369daee48eafb2651bea869b4b15d75ccc35f9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/34369daee48eafb2651bea869b4b15d75ccc35f9", + "reference": "34369daee48eafb2651bea869b4b15d75ccc35f9", + "shasum": "" + }, + "require": { + "php": "^7.0", + "sebastian/diff": "^2.0 || ^3.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": "2018-02-01T13:46:46+00:00" + }, + { + "name": "sebastian/diff", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "e09160918c66281713f1c324c1f4c4c3037ba1e8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/e09160918c66281713f1c324c1f4c4c3037ba1e8", + "reference": "e09160918c66281713f1c324c1f4c4c3037ba1e8", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "require-dev": { + "phpunit/phpunit": "^7.0", + "symfony/process": "^2 || ^3.3 || ^4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.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", + "udiff", + "unidiff", + "unified diff" + ], + "time": "2018-02-01T13:45:15+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": "squizlabs/php_codesniffer", + "version": "2.9.1", + "source": { + "type": "git", + "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", + "reference": "dcbed1074f8244661eecddfc2a675430d8d33f62" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/dcbed1074f8244661eecddfc2a675430d8d33f62", + "reference": "dcbed1074f8244661eecddfc2a675430d8d33f62", + "shasum": "" + }, + "require": { + "ext-simplexml": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": ">=5.1.2" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "bin": [ + "scripts/phpcs", + "scripts/phpcbf" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "autoload": { + "classmap": [ + "CodeSniffer.php", + "CodeSniffer/CLI.php", + "CodeSniffer/Exception.php", + "CodeSniffer/File.php", + "CodeSniffer/Fixer.php", + "CodeSniffer/Report.php", + "CodeSniffer/Reporting.php", + "CodeSniffer/Sniff.php", + "CodeSniffer/Tokens.php", + "CodeSniffer/Reports/", + "CodeSniffer/Tokenizers/", + "CodeSniffer/DocGenerators/", + "CodeSniffer/Standards/AbstractPatternSniff.php", + "CodeSniffer/Standards/AbstractScopeSniff.php", + "CodeSniffer/Standards/AbstractVariableSniff.php", + "CodeSniffer/Standards/IncorrectPatternException.php", + "CodeSniffer/Standards/Generic/Sniffs/", + "CodeSniffer/Standards/MySource/Sniffs/", + "CodeSniffer/Standards/PEAR/Sniffs/", + "CodeSniffer/Standards/PSR1/Sniffs/", + "CodeSniffer/Standards/PSR2/Sniffs/", + "CodeSniffer/Standards/Squiz/Sniffs/", + "CodeSniffer/Standards/Zend/Sniffs/" + ] + }, + "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-05-22T02:43:20+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.3.0", + "source": { + "type": "git", + "url": "https://github.com/webmozart/assert.git", + "reference": "0df1908962e7a3071564e857d86874dad1ef204a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozart/assert/zipball/0df1908962e7a3071564e857d86874dad1ef204a", + "reference": "0df1908962e7a3071564e857d86874dad1ef204a", + "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" + ], + "time": "2018-01-29T19:49:41+00:00" + }, + { + "name": "zendframework/zend-code", + "version": "3.3.0", + "source": { + "type": "git", + "url": "https://github.com/zendframework/zend-code.git", + "reference": "6b1059db5b368db769e4392c6cb6cc139e56640d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/zend-code/zipball/6b1059db5b368db769e4392c6cb6cc139e56640d", + "reference": "6b1059db5b368db769e4392c6cb6cc139e56640d", + "shasum": "" + }, + "require": { + "php": "^7.1", + "zendframework/zend-eventmanager": "^2.6 || ^3.0" + }, + "require-dev": { + "doctrine/annotations": "~1.0", + "ext-phar": "*", + "phpunit/phpunit": "^6.2.3", + "zendframework/zend-coding-standard": "^1.0.0", + "zendframework/zend-stdlib": "^2.7 || ^3.0" + }, + "suggest": { + "doctrine/annotations": "Doctrine\\Common\\Annotations >=1.0 for annotation features", + "zendframework/zend-stdlib": "Zend\\Stdlib component" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev", + "dev-develop": "3.3-dev" + } + }, + "autoload": { + "psr-4": { + "Zend\\Code\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "provides facilities to generate arbitrary code using an object oriented interface", + "homepage": "https://github.com/zendframework/zend-code", + "keywords": [ + "code", + "zf2" + ], + "time": "2017-10-20T15:21:32+00:00" + }, + { + "name": "zendframework/zend-eventmanager", + "version": "3.2.0", + "source": { + "type": "git", + "url": "https://github.com/zendframework/zend-eventmanager.git", + "reference": "9d72db10ceb6e42fb92350c0cb54460da61bd79c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/zend-eventmanager/zipball/9d72db10ceb6e42fb92350c0cb54460da61bd79c", + "reference": "9d72db10ceb6e42fb92350c0cb54460da61bd79c", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0" + }, + "require-dev": { + "athletic/athletic": "^0.1", + "container-interop/container-interop": "^1.1.0", + "phpunit/phpunit": "^6.0.7 || ^5.7.14", + "zendframework/zend-coding-standard": "~1.0.0", + "zendframework/zend-stdlib": "^2.7.3 || ^3.0" + }, + "suggest": { + "container-interop/container-interop": "^1.1.0, to use the lazy listeners feature", + "zendframework/zend-stdlib": "^2.7.3 || ^3.0, to use the FilterChain feature" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev", + "dev-develop": "3.3-dev" + } + }, + "autoload": { + "psr-4": { + "Zend\\EventManager\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Trigger and listen to events within a PHP application", + "homepage": "https://github.com/zendframework/zend-eventmanager", + "keywords": [ + "event", + "eventmanager", + "events", + "zf2" + ], + "time": "2017-07-11T19:17:22+00:00" + }, + { + "name": "zendframework/zend-expressive-tooling", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/zendframework/zend-expressive-tooling.git", + "reference": "0e5b030961cd980323dd48965d13d5cb904b51de" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/zend-expressive-tooling/zipball/0e5b030961cd980323dd48965d13d5cb904b51de", + "reference": "0e5b030961cd980323dd48965d13d5cb904b51de", + "shasum": "" + }, + "require": { + "ocramius/package-versions": "^1.3", + "php": "^7.1", + "symfony/console": "^2.8 || ^3.0 || ^4.0", + "zendframework/zend-code": "^2.6.3 || ^3.3", + "zendframework/zend-component-installer": "^2.0", + "zendframework/zend-expressive": "^3.0", + "zendframework/zend-expressive-router": "^3.0", + "zendframework/zend-stdlib": "^3.1", + "zendframework/zend-stratigility": "^3.0", + "zfcampus/zf-composer-autoloading": "^2.0" + }, + "require-dev": { + "malukenho/docheader": "^0.1.6", + "mikey179/vfsstream": "^1.6.5", + "mockery/mockery": "^1.0", + "php-mock/php-mock-phpunit": "^2.1", + "phpunit/phpunit": "^7.0.3", + "zendframework/zend-coding-standard": "~1.0.0" + }, + "bin": [ + "bin/expressive" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev", + "dev-develop": "1.1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Zend\\Expressive\\Tooling\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Migration and development tooling for Expressive", + "keywords": [ + "ZendFramework", + "http", + "middleware", + "psr", + "psr-7", + "zend-expressive", + "zf" + ], + "time": "2018-03-27T19:29:07+00:00" + }, + { + "name": "zfcampus/zf-composer-autoloading", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/zfcampus/zf-composer-autoloading.git", + "reference": "3643d9dc4d3f0b6011ff643672e1cf187e21a7f4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zfcampus/zf-composer-autoloading/zipball/3643d9dc4d3f0b6011ff643672e1cf187e21a7f4", + "reference": "3643d9dc4d3f0b6011ff643672e1cf187e21a7f4", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0", + "zendframework/zend-stdlib": "^3.1" + }, + "require-dev": { + "mikey179/vfsstream": "^1.6.4", + "mockery/mockery": "^0.9.8", + "php-mock/php-mock-phpunit": "^2.0 || ^1.1.2", + "phpunit/phpunit": "^6.0.7 || ^5.7.14", + "zendframework/zend-coding-standard": "~1.0.0" + }, + "bin": [ + "bin/zf-composer-autoloading" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "ZF\\ComposerAutoloading\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Sets up Composer-based autoloading for your Zend Framework modules", + "homepage": "http://apigility.org/", + "keywords": [ + "ZendFramework", + "autoloading", + "console", + "framework" + ], + "time": "2017-02-22T16:55:31+00:00" + }, + { + "name": "zfcampus/zf-development-mode", + "version": "3.1.0", + "source": { + "type": "git", + "url": "https://github.com/zfcampus/zf-development-mode.git", + "reference": "ffef6ab8cf84ee1d1a77a2b51ba2240d2707c05d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zfcampus/zf-development-mode/zipball/ffef6ab8cf84ee1d1a77a2b51ba2240d2707c05d", + "reference": "ffef6ab8cf84ee1d1a77a2b51ba2240d2707c05d", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0" + }, + "require-dev": { + "mikey179/vfsstream": "^1.6", + "phpunit/phpunit": "^5.4", + "squizlabs/php_codesniffer": "^2.3.1" + }, + "bin": [ + "bin/zf-development-mode" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev", + "dev-develop": "3.2-dev" + } + }, + "autoload": { + "psr-4": { + "ZF\\DevelopmentMode\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Zend Framework development mode script", + "homepage": "http://github.com/zfcampus/zf-development-mode", + "keywords": [ + "framework", + "zf2" + ], + "time": "2017-01-09T23:34:49+00:00" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": { + "roave/security-advisories": 20 + }, + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": "^7.1" + }, + "platform-dev": [] +} diff --git a/config/.gitignore b/config/.gitignore new file mode 100644 index 0000000..9604301 --- /dev/null +++ b/config/.gitignore @@ -0,0 +1 @@ +development.config.php diff --git a/config/autoload/.gitignore b/config/autoload/.gitignore new file mode 100644 index 0000000..1a83fda --- /dev/null +++ b/config/autoload/.gitignore @@ -0,0 +1,2 @@ +local.php +*.local.php diff --git a/config/autoload/dependencies.global.php b/config/autoload/dependencies.global.php new file mode 100644 index 0000000..a9ab249 --- /dev/null +++ b/config/autoload/dependencies.global.php @@ -0,0 +1,26 @@ + [ + // Use 'aliases' to alias a service name to another service. The + // key is the alias name, the value is the service to which it points. + 'aliases' => [ + // Fully\Qualified\ClassOrInterfaceName::class => Fully\Qualified\ClassName::class, + ], + // Use 'invokables' for constructor-less services, or services that do + // not require arguments to the constructor. Map a service name to the + // class name. + 'invokables' => [ + // Fully\Qualified\InterfaceName::class => Fully\Qualified\ClassName::class, + ], + // Use 'factories' for services provided by callbacks/factory classes. + 'factories' => [ + // Fully\Qualified\ClassName::class => Fully\Qualified\FactoryName::class, + ], + ], +]; diff --git a/config/autoload/development.local.php.dist b/config/autoload/development.local.php.dist new file mode 100644 index 0000000..99875e9 --- /dev/null +++ b/config/autoload/development.local.php.dist @@ -0,0 +1,35 @@ + [ + 'invokables' => [ + ], + 'factories' => [ + ErrorResponseGenerator::class => Container\WhoopsErrorResponseGeneratorFactory::class, + 'Zend\Expressive\Whoops' => Container\WhoopsFactory::class, + 'Zend\Expressive\WhoopsPageHandler' => Container\WhoopsPageHandlerFactory::class, + ], + ], + + 'whoops' => [ + 'json_exceptions' => [ + 'display' => true, + 'show_trace' => true, + 'ajax_only' => true, + ], + ], +]; diff --git a/config/autoload/doctrine.global.php b/config/autoload/doctrine.global.php new file mode 100644 index 0000000..16be3aa --- /dev/null +++ b/config/autoload/doctrine.global.php @@ -0,0 +1,76 @@ + [ + 'aliases' => [ + Doctrine\ORM\EntityManager::class => 'doctrine.entity_manager.orm_default', + ], + 'factories' => [ + 'doctrine.entity_manager.orm_default' => ContainerInteropDoctrine\EntityManagerFactory::class, + ], + ], + 'doctrine' => [ + 'driver' => [ + 'orm_default' => [ + 'class' => Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain::class, + 'drivers' => [ + 'App\Entity' => 'app_entity', + ], + ], + 'app_entity' => [ + 'class' => Doctrine\ORM\Mapping\Driver\AnnotationDriver::class, + 'cache' => 'array', + 'paths' => __DIR__ . '/../../src/App/Entity', + ], + ], + 'configuration' => [ + 'orm_default' => [ +// 'datetime_functions' => [ +// 'date' => Oro\ORM\Query\AST\Functions\SimpleFunction::class, +// 'time' => Oro\ORM\Query\AST\Functions\SimpleFunction::class, +// 'timestamp' => Oro\ORM\Query\AST\Functions\SimpleFunction::class, +// 'convert_tz' => Oro\ORM\Query\AST\Functions\DateTime\ConvertTz::class, +// ], + 'numeric_functions' => [ +// 'timestampdiff' => Oro\ORM\Query\AST\Functions\Numeric\TimestampDiff::class, +// 'dayofyear' => Oro\ORM\Query\AST\Functions\SimpleFunction::class, +// 'dayofmonth' => Oro\ORM\Query\AST\Functions\SimpleFunction::class, +// 'dayofweek' => Oro\ORM\Query\AST\Functions\SimpleFunction::class, +// 'week' => Oro\ORM\Query\AST\Functions\SimpleFunction::class, +// 'day' => Oro\ORM\Query\AST\Functions\SimpleFunction::class, +// 'hour' => Oro\ORM\Query\AST\Functions\SimpleFunction::class, +// 'minute' => Oro\ORM\Query\AST\Functions\SimpleFunction::class, +// 'month' => Oro\ORM\Query\AST\Functions\SimpleFunction::class, +// 'quarter' => Oro\ORM\Query\AST\Functions\SimpleFunction::class, +// 'second' => Oro\ORM\Query\AST\Functions\SimpleFunction::class, +// 'year' => Oro\ORM\Query\AST\Functions\SimpleFunction::class, +// 'sign' => Oro\ORM\Query\AST\Functions\Numeric\Sign::class, +// 'pow' => Oro\ORM\Query\AST\Functions\Numeric\Pow::class, + ], +// 'string_functions' => [ +// 'md5' => Oro\ORM\Query\AST\Functions\SimpleFunction::class, +// 'group_concat' => Oro\ORM\Query\AST\Functions\String\GroupConcat::class, +// 'cast' => Oro\ORM\Query\AST\Functions\Cast::class, +// 'concat_ws' => Oro\ORM\Query\AST\Functions\String\ConcatWs::class +// ] +// 'filters' => [ +// 'soft-deleteable' => Gedmo\SoftDeleteable\Filter\SoftDeleteableFilter::class, +// ], + ], + ], + 'event_manager' => [ + 'orm_default' => [ + 'subscribers' => [ + Gedmo\Timestampable\TimestampableListener::class, + // 'Gedmo\Tree\TreeListener', + // 'Gedmo\SoftDeleteable\SoftDeleteableListener', + // 'Gedmo\Translatable\TranslatableListener', + // 'Gedmo\Blameable\BlameableListener', + // 'Gedmo\Loggable\LoggableListener', + // 'Gedmo\Sortable\SortableListener', + // 'Gedmo\Sluggable\SluggableListener', + ], + ], + ], + ], +]; diff --git a/config/autoload/doctrine.local.dist.php b/config/autoload/doctrine.local.dist.php new file mode 100644 index 0000000..6549fbe --- /dev/null +++ b/config/autoload/doctrine.local.dist.php @@ -0,0 +1,14 @@ + [ + 'connection' => [ + 'orm_default' => [ + 'params' => [ + 'url' => 'mysqli://user:passwd@host/database', + 'charset' => 'UTF8', + ], + ], + ], + ], +]; diff --git a/config/autoload/local.php.dist b/config/autoload/local.php.dist new file mode 100644 index 0000000..ec825d4 --- /dev/null +++ b/config/autoload/local.php.dist @@ -0,0 +1,12 @@ + true, + + // Enable debugging; typically used to provide debugging information within templates. + 'debug' => false, + + 'zend-expressive' => [ + // Provide templates for the error handling middleware to use when + // generating responses. + 'error_handler' => [ + 'template_404' => 'error::404', + 'template_error' => 'error::error', + ], + ], +]; diff --git a/config/config.php b/config/config.php new file mode 100644 index 0000000..70cd721 --- /dev/null +++ b/config/config.php @@ -0,0 +1,46 @@ + 'data/cache/config-cache.php', +]; + +$aggregator = new ConfigAggregator([ + \Zend\Form\ConfigProvider::class, + \Zend\InputFilter\ConfigProvider::class, + \Zend\Validator\ConfigProvider::class, + \Zend\Hydrator\ConfigProvider::class, + \Zend\Filter\ConfigProvider::class, + \Zend\Expressive\Router\FastRouteRouter\ConfigProvider::class, + \Zend\HttpHandlerRunner\ConfigProvider::class, + // Include cache configuration + new ArrayProvider($cacheConfig), + + \Zend\Expressive\Helper\ConfigProvider::class, + \Zend\Expressive\ConfigProvider::class, + \Zend\Expressive\Router\ConfigProvider::class, + + // Default App module config + App\ConfigProvider::class, + DoctrineExpressiveModule\ConfigProvider::class, + + // Load application config in a pre-defined order in such a way that local settings + // overwrite global settings. (Loaded as first to last): + // - `global.php` + // - `*.global.php` + // - `local.php` + // - `*.local.php` + new PhpFileProvider(realpath(__DIR__) . '/autoload/{{,*.}global,{,*.}local}.php'), + + // Load development config if it exists + new PhpFileProvider(realpath(__DIR__) . '/development.config.php'), +], $cacheConfig['config_cache_path']); + +return $aggregator->getMergedConfig(); diff --git a/config/container.php b/config/container.php new file mode 100644 index 0000000..740fe23 --- /dev/null +++ b/config/container.php @@ -0,0 +1,14 @@ + true, + ConfigAggregator::ENABLE_CACHE => false, +]; diff --git a/config/pipeline.php b/config/pipeline.php new file mode 100644 index 0000000..b838955 --- /dev/null +++ b/config/pipeline.php @@ -0,0 +1,78 @@ +pipe(ErrorHandler::class); + $app->pipe(ServerUrlMiddleware::class); + + // Pipe more middleware here that you want to execute on every request: + // - bootstrapping + // - pre-conditions + // - modifications to outgoing responses + // + // Piped Middleware may be either callables or service names. Middleware may + // also be passed as an array; each item in the array must resolve to + // middleware eventually (i.e., callable or service name). + // + // Middleware can be attached to specific paths, allowing you to mix and match + // applications under a common domain. The handlers in each middleware + // attached this way will see a URI with the matched path segment removed. + // + // i.e., path of "/api/member/profile" only passes "/member/profile" to $apiMiddleware + // - $app->pipe('/api', $apiMiddleware); + // - $app->pipe('/docs', $apiDocMiddleware); + // - $app->pipe('/files', $filesMiddleware); + + // Register the routing middleware in the middleware pipeline. + // This middleware registers the Zend\Expressive\Router\RouteResult request attribute. + $app->pipe(RouteMiddleware::class); + + // The following handle routing failures for common conditions: + // - HEAD request but no routes answer that method + // - OPTIONS request but no routes answer that method + // - method not allowed + // Order here matters; the MethodNotAllowedMiddleware should be placed + // after the Implicit*Middleware. + $app->pipe(ImplicitHeadMiddleware::class); +// $app->pipe(ImplicitOptionsMiddleware::class); + $app->pipe(CorsMiddleware::class); + $app->pipe(MethodNotAllowedMiddleware::class); + + // Seed the UrlHelper with the routing results: + $app->pipe(UrlHelperMiddleware::class); + + // Add more middleware here that needs to introspect the routing results; this + // might include: + // + // - route-based authentication + // - route-based validation + // - etc. + + // Register the dispatch middleware in the middleware pipeline + $app->pipe(DispatchMiddleware::class); + + // At this point, if no Response is returned by any middleware, the + // NotFoundHandler kicks in; alternately, you can provide other fallback + // middleware to execute. + $app->pipe(NotFoundHandler::class); +}; diff --git a/config/routes.php b/config/routes.php new file mode 100644 index 0000000..eb319ca --- /dev/null +++ b/config/routes.php @@ -0,0 +1,41 @@ +get('/', App\Handler\HomePageHandler::class, 'home'); + * $app->post('/album', App\Handler\AlbumCreateHandler::class, 'album.create'); + * $app->put('/album/:id', App\Handler\AlbumUpdateHandler::class, 'album.put'); + * $app->patch('/album/:id', App\Handler\AlbumUpdateHandler::class, 'album.patch'); + * $app->delete('/album/:id', App\Handler\AlbumDeleteHandler::class, 'album.delete'); + * + * Or with multiple request methods: + * + * $app->route('/contact', App\Handler\ContactHandler::class, ['GET', 'POST', ...], 'contact'); + * + * Or handling all request methods: + * + * $app->route('/contact', App\Handler\ContactHandler::class)->setName('contact'); + * + * or: + * + * $app->route( + * '/contact', + * App\Handler\ContactHandler::class, + * Zend\Expressive\Router\Route::HTTP_METHOD_ANY, + * 'contact' + * ); + */ +return function (Application $app, MiddlewareFactory $factory, ContainerInterface $container) : void { + $app->get('/', App\Handler\HomePageHandler::class, 'home'); + $app->get('/api/ping', App\Handler\PingHandler::class, 'api.ping'); + + $app->route('/api/team[/{id:\d+}]', App\Handler\TeamHandler::class)->setName('api.team'); + $app->route('/api/slide[/{id:\d+}]', App\Handler\SlideHandler::class)->setName('api.slide'); +}; diff --git a/data/.gitignore b/data/.gitignore new file mode 100644 index 0000000..5381e79 --- /dev/null +++ b/data/.gitignore @@ -0,0 +1,4 @@ +* +!cache +!cache/.gitkeep +!.gitignore diff --git a/data/cache/.gitkeep b/data/cache/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/phpcs.xml.dist b/phpcs.xml.dist new file mode 100644 index 0000000..de3035d --- /dev/null +++ b/phpcs.xml.dist @@ -0,0 +1,20 @@ + + + Expressive Skeleton coding standard + + + + + + + + + + + + + + + + src + diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 0000000..e9e72c0 --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,17 @@ + + + + + ./test + + + + + + ./src + + + diff --git a/public/.htaccess b/public/.htaccess new file mode 100644 index 0000000..cd6355d --- /dev/null +++ b/public/.htaccess @@ -0,0 +1,19 @@ +RewriteEngine On +# The following rule allows authentication to work with fast-cgi +RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] +# The following rule tells Apache that if the requested filename +# exists, simply serve it. +RewriteCond %{REQUEST_FILENAME} -s [OR] +RewriteCond %{REQUEST_FILENAME} -l [OR] +RewriteCond %{REQUEST_FILENAME} -d +RewriteRule ^.*$ - [NC,L] + +# The following rewrites all other queries to index.php. The +# condition ensures that if you are using Apache aliases to do +# mass virtual hosting, the base path will be prepended to +# allow proper resolution of the index.php file; it will work +# in non-aliased environments as well, providing a safe, one-size +# fits all solution. +RewriteCond %{REQUEST_URI}::$1 ^(/.+)(.+)::\2$ +RewriteRule ^(.*) - [E=BASE:%1] +RewriteRule ^(.*)$ %{ENV:BASE}index.php [NC,L] diff --git a/public/index.php b/public/index.php new file mode 100644 index 0000000..fd11502 --- /dev/null +++ b/public/index.php @@ -0,0 +1,30 @@ +get(\Zend\Expressive\Application::class); + $factory = $container->get(\Zend\Expressive\MiddlewareFactory::class); + + // Execute programmatic/declarative middleware pipeline and routing + // configuration statements + (require 'config/pipeline.php')($app, $factory, $container); + (require 'config/routes.php')($app, $factory, $container); + + $app->run(); +})(); diff --git a/src/App/ConfigProvider.php b/src/App/ConfigProvider.php new file mode 100644 index 0000000..f78f484 --- /dev/null +++ b/src/App/ConfigProvider.php @@ -0,0 +1,61 @@ + $this->getDependencies(), + 'templates' => $this->getTemplates(), + ]; + } + + /** + * Returns the container dependencies + */ + public function getDependencies() : array + { + return [ + 'invokables' => [ + Handler\PingHandler::class => Handler\PingHandler::class, + ], + 'factories' => [ + Handler\HomePageHandler::class => Handler\HomePageHandlerFactory::class, + Handler\TeamHandler::class => Handler\TeamHandlerFactory::class, + + Service\TeamService::class => Service\TeamServiceFactory::class, + Service\SlideManager::class => Service\SlideManagerFactory::class, + ], + ]; + } + + /** + * Returns the templates configuration + */ + public function getTemplates() : array + { + return [ + 'paths' => [ + 'app' => ['templates/app'], + 'error' => ['templates/error'], + 'layout' => ['templates/layout'], + ], + ]; + } +} diff --git a/src/App/Entity/Slide.php b/src/App/Entity/Slide.php new file mode 100644 index 0000000..31d682d --- /dev/null +++ b/src/App/Entity/Slide.php @@ -0,0 +1,209 @@ +id; + } + + /** + * @param int $id + * @return Slide + */ + public function setId(int $id): Slide + { + $this->id = $id; + return $this; + } + + /** + * @return string + */ + public function getTitle(): ?string + { + return $this->title; + } + + /** + * @param string $title + * @return Slide + */ + public function setTitle(string $title) + { + $this->title = $title; + return $this; + } + + /** + * @return Team + */ + public function getTeam(): ?Team + { + return $this->team; + } + + /** + * @param Team $team + * @return Slide + */ + public function setTeam(Team $team): Slide + { + $this->team = $team; + return $this; + } + + /** + * @return string + */ + public function getSlideData(): ?string + { + return $this->slideData; + } + + /** + * @param string $slideData + * @return Slide + */ + public function setSlideData(string $slideData): Slide + { + $this->slideData = $slideData; + return $this; + } + + /** + * @return bool + */ + public function isVisible(): ?bool + { + return $this->isVisible; + } + + /** + * @param bool $isVisible + * @return Slide + */ + public function setIsVisible(bool $isVisible): Slide + { + $this->isVisible = $isVisible; + return $this; + } + + /** + * @return \DateTimeImmutable + */ + public function getCreatedAt(): ?\DateTimeImmutable + { + return $this->createdAt; + } + + /** + * @param \DateTimeImmutable $createdAt + * @return Slide + */ + public function setCreatedAt(\DateTimeImmutable $createdAt): Slide + { + $this->createdAt = $createdAt; + return $this; + } + + /** + * @return \DateTimeImmutable + */ + public function getUpdatedAt(): ?\DateTimeImmutable + { + return $this->updatedAt; + } + + /** + * @param \DateTimeImmutable $updatedAt + * @return Slide + */ + public function setUpdatedAt(\DateTimeImmutable $updatedAt): Slide + { + $this->updatedAt = $updatedAt; + return $this; + } + + /** + * @return array + */ + public function jsonSerialize() + { + return [ + 'id' => $this->getId(), + 'title' => $this->getTitle(), + 'team' => $this->getTeam(), + 'slideData' => $this->getSlideData(), + 'isVisible' => $this->isVisible(), + 'createdAt' => $this->getCreatedAt() + ? $this->getCreatedAt()->format("Y-m-d H:i:s") + : null, + 'updatedAt' => $this->getUpdatedAt() + ? $this->getUpdatedAt()->format("Y-m-d H:i:s") + : null, + ]; + } +} diff --git a/src/App/Entity/Team.php b/src/App/Entity/Team.php new file mode 100644 index 0000000..8d196ab --- /dev/null +++ b/src/App/Entity/Team.php @@ -0,0 +1,234 @@ +slides = new ArrayCollection; + $this->members = new \ArrayObject; + } + + /** + * @return int + */ + public function getId(): ?int + { + return $this->id; + } + + /** + * @param int $id + * @return Team + */ + public function setId(int $id): Team + { + $this->id = $id; + return $this; + } + + /** + * @return string + */ + public function getName(): ?string + { + return $this->name; + } + + /** + * @param string $name + * @return Team + */ + public function setName(string $name): Team + { + $this->name = $name; + return $this; + } + + /** + * @return array + */ + public function getMembers() + { + return $this->members; + } + + /** + * @param array $members + * @return Team + */ + public function setMembers(array $members): Team + { + $this->members = $members; + return $this; + } + + /** + * @param Slide $slide + * @return Team + */ + public function addSlides(Slide $slide): Team + { + if (!$this->slides->contains($slide)) { + $this->slides->removeElement($slide); + } + return $this; + } + + /** + * @return Slide[]|Collection + */ + public function getSlides(): ?Collection + { + return $this->slides; + } + + /** + * @param Slide $slide + * @return Team + */ + public function removeSlide(Slide $slide): Team + { + if ($this->slides->contains($slide)) { + $this->slides->removeElement($slide); + } + return $this; + } + + /** + * @return bool + */ + public function isActive(): ?bool + { + return $this->isActive; + } + + /** + * @param bool $isActive + * @return Team + */ + public function setIsActive(bool $isActive): Team + { + $this->isActive = $isActive; + return $this; + } + + /** + * @return \DateTimeImmutable + */ + public function getCreatedAt(): ?\DateTimeImmutable + { + return $this->createdAt; + } + + /** + * @param \DateTimeImmutable $createdAt + * @return Team + */ + public function setCreatedAt(\DateTimeImmutable $createdAt): Team + { + $this->createdAt = $createdAt; + return $this; + } + + /** + * @return \DateTimeImmutable + */ + public function getUpdatedAt(): ?\DateTimeImmutable + { + return $this->updatedAt; + } + + /** + * @param \DateTimeImmutable $updatedAt + * @return Team + */ + public function setUpdatedAt(\DateTimeImmutable $updatedAt): Team + { + $this->updatedAt = $updatedAt; + return $this; + } + + /** + * @return array + */ + public function jsonSerialize() + { + return [ + 'id' => $this->getId(), + 'name' => $this->getName(), + 'members' => $this->getMembers(), + 'isActive' => $this->isActive(), + 'createdAt' => $this->getCreatedAt() + ? $this->getCreatedAt()->format("Y-m-d H:i:s") + : null, + 'updatedAt' => $this->getUpdatedAt() + ? $this->getUpdatedAt()->format("Y-m-d H:i:s") + : null, + ]; + } +} diff --git a/src/App/Form/Slide.php b/src/App/Form/Slide.php new file mode 100644 index 0000000..808e452 --- /dev/null +++ b/src/App/Form/Slide.php @@ -0,0 +1,73 @@ +getMethod()); + $id = $request->getAttribute(static::IDENTIFIER_NAME); + + switch ($requestMethod) { + case 'GET': + return isset($id) + ? $this->get($request) + : $this->getList($request); + case 'POST': + return $this->create($request); + case 'PUT': + return $this->update($request); + case 'DELETE': + return isset($id) + ? $this->delete($request) + : $this->deleteList($request); + case 'HEAD': + return $this->head($request); + case 'OPTIONS': + return $this->options($request); + case 'PATCH': + return $this->patch($request); + default: + return $this->createResponse(['content' => 'Method not allowed'], 405); + } + } + + public function get(ServerRequestInterface $request) + { + return $this->createResponse(['content' => 'Method not allowed'], 405); + } + + public function getList(ServerRequestInterface $request) + { + return $this->createResponse(['content' => 'Method not allowed'], 405); + } + + public function create(ServerRequestInterface $request) + { + return $this->createResponse(['content' => 'Method not allowed'], 405); + } + + public function update(ServerRequestInterface $request) + { + return $this->createResponse(['content' => 'Method not allowed'], 405); + } + + public function delete(ServerRequestInterface $request) + { + return $this->createResponse(['content' => 'Method not allowed'], 405); + } + + public function deleteList(ServerRequestInterface $request) + { + return $this->createResponse(['content' => 'Method not allowed'], 405); + } + + public function head(ServerRequestInterface $request) + { + return $this->createResponse(['content' => 'Method not allowed'], 405); + } + + public function options(ServerRequestInterface $request) + { + return new EmptyResponse(200); + } + + public function patch(ServerRequestInterface $request) + { + return $this->createResponse(['content' => 'Method not allowed'], 405); + } + + final protected function createResponse($data, $status = 200) + { + return new JsonResponse($data, $status); + } + + /** + * + * @param ServerRequestInterface $request + * @return array|object + */ + public function getRequestData(ServerRequestInterface $request) + { + $body = $request->getParsedBody(); + + if (!empty($body)) { + return $body; + } + + return $this->parseRequestData( + $request->getBody()->getContents(), + $request->getHeaderLine('content-type') + ); + } + + /** + * + * @param string $input + * @param string $contentType + * @return mixed + */ + private function parseRequestData($input, $contentType) + { + $contentTypeParts = preg_split('/\s*[;,]\s*/', $contentType); + $parser = $this->returnParserContentType($contentTypeParts[0]); + + return $parser($input); + } + + /** + * + * @param string $contentType + * @return callable + */ + private function returnParserContentType(string $contentType): callable + { + if ($contentType === 'application/x-www-form-urlencoded') { + return function ($input) { + parse_str($input, $data); + return $data; + }; + } elseif ($contentType === 'application/json') { + return function ($input) { + $jsonDecoder = new Json(); + try { + return $jsonDecoder->decode($input, Json::TYPE_ARRAY); + } catch (\Exception $e) { + return false; + } + }; + } elseif ($contentType === 'multipart/form-data') { + return function ($input) { + return $input; + }; + } + + return function ($input) { + return $input; + }; + } +} diff --git a/src/App/Handler/HomePageHandler.php b/src/App/Handler/HomePageHandler.php new file mode 100644 index 0000000..b969d39 --- /dev/null +++ b/src/App/Handler/HomePageHandler.php @@ -0,0 +1,94 @@ +router = $router; + $this->template = $template; + $this->containerName = $containerName; + } + + public function handle(ServerRequestInterface $request) : ResponseInterface + { + if (! $this->template) { + return new JsonResponse([ + 'welcome' => 'Congratulations! You have installed the zend-expressive skeleton application.', + 'docsUrl' => 'https://docs.zendframework.com/zend-expressive/', + ]); + } + + $data = []; + + switch ($this->containerName) { + case 'Aura\Di\Container': + $data['containerName'] = 'Aura.Di'; + $data['containerDocs'] = 'http://auraphp.com/packages/2.x/Di.html'; + break; + case 'Pimple\Container': + $data['containerName'] = 'Pimple'; + $data['containerDocs'] = 'https://pimple.symfony.com/'; + break; + case 'Zend\ServiceManager\ServiceManager': + $data['containerName'] = 'Zend Servicemanager'; + $data['containerDocs'] = 'https://docs.zendframework.com/zend-servicemanager/'; + break; + case 'Auryn\Injector': + $data['containerName'] = 'Auryn'; + $data['containerDocs'] = 'https://github.com/rdlowrey/Auryn'; + break; + case 'Symfony\Component\DependencyInjection\ContainerBuilder': + $data['containerName'] = 'Symfony DI Container'; + $data['containerDocs'] = 'https://symfony.com/doc/current/service_container.html'; + break; + } + + if ($this->router instanceof Router\AuraRouter) { + $data['routerName'] = 'Aura.Router'; + $data['routerDocs'] = 'http://auraphp.com/packages/2.x/Router.html'; + } elseif ($this->router instanceof Router\FastRouteRouter) { + $data['routerName'] = 'FastRoute'; + $data['routerDocs'] = 'https://github.com/nikic/FastRoute'; + } elseif ($this->router instanceof Router\ZendRouter) { + $data['routerName'] = 'Zend Router'; + $data['routerDocs'] = 'https://docs.zendframework.com/zend-router/'; + } + + if ($this->template instanceof PlatesRenderer) { + $data['templateName'] = 'Plates'; + $data['templateDocs'] = 'http://platesphp.com/'; + } elseif ($this->template instanceof TwigRenderer) { + $data['templateName'] = 'Twig'; + $data['templateDocs'] = 'http://twig.sensiolabs.org/documentation'; + } elseif ($this->template instanceof ZendViewRenderer) { + $data['templateName'] = 'Zend View'; + $data['templateDocs'] = 'https://docs.zendframework.com/zend-view/'; + } + + return new HtmlResponse($this->template->render('app::home-page', $data)); + } +} diff --git a/src/App/Handler/HomePageHandlerFactory.php b/src/App/Handler/HomePageHandlerFactory.php new file mode 100644 index 0000000..576e950 --- /dev/null +++ b/src/App/Handler/HomePageHandlerFactory.php @@ -0,0 +1,23 @@ +get(RouterInterface::class); + $template = $container->has(TemplateRendererInterface::class) + ? $container->get(TemplateRendererInterface::class) + : null; + + return new HomePageHandler($router, $template, get_class($container)); + } +} diff --git a/src/App/Handler/PingHandler.php b/src/App/Handler/PingHandler.php new file mode 100644 index 0000000..cd1c43d --- /dev/null +++ b/src/App/Handler/PingHandler.php @@ -0,0 +1,18 @@ + time()]); + } +} diff --git a/src/App/Handler/SlideHandler.php b/src/App/Handler/SlideHandler.php new file mode 100644 index 0000000..98aedc4 --- /dev/null +++ b/src/App/Handler/SlideHandler.php @@ -0,0 +1,73 @@ +slideManager = $teamService; + } + + /** + * @param ServerRequestInterface $request + * @return ResponseInterface + */ + public function getList(ServerRequestInterface $request): ResponseInterface + { + return new JsonResponse($this->slideManager->listSlides()); + } + + /** + * @param ServerRequestInterface $request + * @return ResponseInterface + */ + public function get(ServerRequestInterface $request): ResponseInterface + { + $id = $request->getAttribute('id'); + return new JsonResponse($this->slideManager->getSlide((int)$id)); + } + + /** + * @param ServerRequestInterface $request + * @return JsonResponse + * @throws \Doctrine\ORM\ORMException + * @throws \Doctrine\ORM\OptimisticLockException + */ + public function create(ServerRequestInterface $request) + { + $data = $this->getRequestData($request); + try { + return new JsonResponse($this->slideManager->addSlide($data)); + } catch (UniqueConstraintViolationException $e) { + return new JsonResponse([ + 'message' => 'The field `name` must be unique', + ], 500); + } catch (\InvalidArgumentException $e) { + return new JsonResponse([ + 'message' => $e->getMessage(), + ], 500); + } + } + + /** + * @param ServerRequestInterface $request + * @return JsonResponse + * @throws \Doctrine\ORM\ORMException + */ + public function delete(ServerRequestInterface $request) + { + $id = $request->getAttribute('id'); + return new JsonResponse($this->slideManager->removeSlide($id)); + } +} diff --git a/src/App/Handler/SlideHandlerFactory.php b/src/App/Handler/SlideHandlerFactory.php new file mode 100644 index 0000000..e203743 --- /dev/null +++ b/src/App/Handler/SlideHandlerFactory.php @@ -0,0 +1,22 @@ +get(SlideManager::class); + return new SlideHandler($slideManager); + } +} diff --git a/src/App/Handler/TeamHandler.php b/src/App/Handler/TeamHandler.php new file mode 100644 index 0000000..81afc6f --- /dev/null +++ b/src/App/Handler/TeamHandler.php @@ -0,0 +1,73 @@ +teamService = $teamService; + } + + /** + * @param ServerRequestInterface $request + * @return ResponseInterface + */ + public function getList(ServerRequestInterface $request): ResponseInterface + { + return new JsonResponse($this->teamService->listTeams()); + } + + /** + * @param ServerRequestInterface $request + * @return ResponseInterface + */ + public function get(ServerRequestInterface $request): ResponseInterface + { + $id = $request->getAttribute('id'); + return new JsonResponse($this->teamService->getTeam((int)$id)); + } + + /** + * @param ServerRequestInterface $request + * @return JsonResponse + * @throws \Doctrine\ORM\ORMException + * @throws \Doctrine\ORM\OptimisticLockException + */ + public function create(ServerRequestInterface $request) + { + $data = $this->getRequestData($request); + try { + return new JsonResponse($this->teamService->addTeam($data)); + } catch (UniqueConstraintViolationException $e) { + return new JsonResponse([ + 'message' => 'The field `name` must be unique', + ], 500); + } catch (\InvalidArgumentException $e) { + return new JsonResponse([ + 'message' => $e->getMessage(), + ], 500); + } + } + + /** + * @param ServerRequestInterface $request + * @return JsonResponse + * @throws \Doctrine\ORM\ORMException + */ + public function delete(ServerRequestInterface $request) + { + $id = $request->getAttribute('id'); + return new JsonResponse($this->teamService->removeTeam($id)); + } +} diff --git a/src/App/Handler/TeamHandlerFactory.php b/src/App/Handler/TeamHandlerFactory.php new file mode 100644 index 0000000..741e425 --- /dev/null +++ b/src/App/Handler/TeamHandlerFactory.php @@ -0,0 +1,22 @@ +get(TeamService::class); + return new TeamHandler($teamService); + } +} diff --git a/src/App/Service/SlideManager.php b/src/App/Service/SlideManager.php new file mode 100644 index 0000000..e8d88cc --- /dev/null +++ b/src/App/Service/SlideManager.php @@ -0,0 +1,124 @@ +em = $em; + $this->form = $form; + } + + /** + * @return array + */ + public function listSlides(): array + { + return $this->em->getRepository(self::ENTITY_NAME)->findBy([ + 'isActive' => true, + ]); + } + + /** + * @param int $id + * @return Slide + */ + public function getSlide(int $id): Slide + { + /** @var Slide $entity */ + $entity = $this->em->getRepository(self::ENTITY_NAME)->find($id); + return $entity; + } + + /** + * @param array $data + * @return Slide + * @throws \Doctrine\ORM\ORMException + * @throws \Doctrine\ORM\OptimisticLockException + * @throws \Doctrine\DBAL\Exception\UniqueConstraintViolationException + */ + public function addSlide(array $data) + { + $entity = new Slide(); + $this->form + ->bind($entity) + ->setData($data); + + if ($this->form->isValid()) { + $this->em->persist($entity); + $this->em->flush(); + return $entity; + } else { + $messages = $this->form->getMessages(); + $fields = array_keys($messages); + throw new \InvalidArgumentException(sprintf( + "The following fields are invalid: (%s)", + implode(", ", $fields) + )); + } + } + + /** + * @param int $id + * @param array $data + * @return bool + * @throws \Doctrine\ORM\ORMException + * @throws \Doctrine\ORM\OptimisticLockException + */ + public function changeSlide(int $id, array $data): bool + { + if (null === ($entity = $this->getSlide($id))) { + return false; + } + $this->form + ->bind($entity) + ->setData($data); + + if ($this->form->isValid()) { + $this->em->flush(); + return true; + } + return false; + } + + /** + * @param int $id + * @return bool + * @throws \Doctrine\ORM\ORMException + */ + public function removeSlide(int $id): bool + { + if (null !== ($entity = $this->getSlide($id))) { + $this->em->remove($entity); + return true; + } + return false; + } + + /** + * @param int $id + * @param bool $isVisible + * @return bool + * @throws \Doctrine\ORM\ORMException + * @throws \Doctrine\ORM\OptimisticLockException + */ + public function setSlideVisible(int $id, bool $isVisible): bool + { + return $this->changeSlide($id, ['isVisible' => $isVisible]); + } +} diff --git a/src/App/Service/SlideManagerFactory.php b/src/App/Service/SlideManagerFactory.php new file mode 100644 index 0000000..e399319 --- /dev/null +++ b/src/App/Service/SlideManagerFactory.php @@ -0,0 +1,23 @@ +get(EntityManager::class); + $formBuilder = $container->get(AnnotationBuilder::class); + /** @var Form $form */ + $form = $formBuilder->createForm(Team::class); + return new SlideManager($em, $form); + } +} \ No newline at end of file diff --git a/src/App/Service/TeamService.php b/src/App/Service/TeamService.php new file mode 100644 index 0000000..4e37f87 --- /dev/null +++ b/src/App/Service/TeamService.php @@ -0,0 +1,124 @@ +em = $em; + $this->form = $form; + } + + /** + * @return array + */ + public function listTeams(): array + { + return $this->em->getRepository(self::ENTITY_NAME)->findBy([ + 'isActive' => true, + ]); + } + + /** + * @param int $id + * @return Team + */ + public function getTeam(int $id): ?Team + { + /** @var Team $entity */ + $entity = $this->em->getRepository(self::ENTITY_NAME)->find($id); + return $entity; + } + + /** + * @param array $data + * @return Team + * @throws \Doctrine\ORM\ORMException + * @throws \Doctrine\ORM\OptimisticLockException + * @throws \Doctrine\DBAL\Exception\UniqueConstraintViolationException + */ + public function addTeam(array $data): Team + { + $entity = new Team(); + $this->form + ->bind($entity) + ->setData($data); + + if ($this->form->isValid()) { + $this->em->persist($entity); + $this->em->flush(); + return $entity; + } else { + $messages = $this->form->getMessages(); + $fields = array_keys($messages); + throw new \InvalidArgumentException(sprintf( + "The following fields are invalid: (%s)", + implode(", ", $fields) + )); + } + } + + /** + * @param int $id + * @param array $data + * @return bool + * @throws \Doctrine\ORM\ORMException + * @throws \Doctrine\ORM\OptimisticLockException + */ + public function changeTeam(int $id, array $data): bool + { + if (null === ($entity = $this->getTeam($id))) { + return false; + } + $this->form + ->bind($entity) + ->setData($data); + + if ($this->form->isValid()) { + $this->em->flush(); + return true; + } + return false; + } + + /** + * @param int $id + * @return bool + * @throws \Doctrine\ORM\ORMException + */ + public function removeTeam(int $id): bool + { + if (null !== ($entity = $this->getTeam($id))) { + $this->em->remove($entity); + return true; + } + return false; + } + + /** + * @param int $id + * @param bool $isVisible + * @return bool + * @throws \Doctrine\ORM\ORMException + * @throws \Doctrine\ORM\OptimisticLockException + */ + public function setTeamActive(int $id, bool $isVisible): bool + { + return $this->changeTeam($id, ['isVisible' => $isVisible]); + } +} diff --git a/src/App/Service/TeamServiceFactory.php b/src/App/Service/TeamServiceFactory.php new file mode 100644 index 0000000..2806f5f --- /dev/null +++ b/src/App/Service/TeamServiceFactory.php @@ -0,0 +1,23 @@ +get(EntityManager::class); + $formBuilder = $container->get(AnnotationBuilder::class); + /** @var Form $form */ + $form = $formBuilder->createForm(Team::class); + return new TeamService($em, $form); + } +} \ No newline at end of file diff --git a/src/DoctrineExpressiveModule/ConfigProvider.php b/src/DoctrineExpressiveModule/ConfigProvider.php new file mode 100644 index 0000000..2768362 --- /dev/null +++ b/src/DoctrineExpressiveModule/ConfigProvider.php @@ -0,0 +1,48 @@ + $this->getDependencies(), + ]; + } + + /** + * Returns the container dependencies + */ + public function getDependencies() : array + { + return [ + 'aliases' => [ + 'doctrine.hydrator' => Hydrator\DoctrineObject::class, + 'EventManager' => EventManager::class, + ], + 'invokables' => [ + EventManager::class => EventManager::class, + ], + 'factories' => [ + Hydrator\DoctrineObject::class => Hydrator\DoctrineObjectFactory::class, + ], + ]; + } +} diff --git a/src/DoctrineExpressiveModule/Form/Element/Exception/InvalidRepositoryResultException.php b/src/DoctrineExpressiveModule/Form/Element/Exception/InvalidRepositoryResultException.php new file mode 100644 index 0000000..968e053 --- /dev/null +++ b/src/DoctrineExpressiveModule/Form/Element/Exception/InvalidRepositoryResultException.php @@ -0,0 +1,9 @@ +proxy) { + $this->proxy = new Proxy(); + } + return $this->proxy; + } + + /** + * @param array|\Traversable $options + * @return self + */ + public function setOptions($options) + { + $this->getProxy()->setOptions($options); + return parent::setOptions($options); + } + + /** + * @param string $key + * @param mixed $value + * @return self + */ + public function setOption($key, $value) + { + $this->getProxy()->setOptions([$key => $value]); + return parent::setOption($key, $value); + } + + /** + * {@inheritDoc} + */ + public function setValue($value) + { + if ($value instanceof \Traversable) { + $value = ArrayUtils::iteratorToArray($value); + } elseif ($value == null) { + return parent::setValue([]); + } elseif (! is_array($value)) { + $value = (array)$value; + } + + return parent::setValue(array_map([$this->getProxy(), 'getValue'], $value)); + } + + /** + * {@inheritDoc} + */ + public function getValueOptions() + { + if (! empty($this->valueOptions)) { + return $this->valueOptions; + } + + $proxyValueOptions = $this->getProxy()->getValueOptions(); + + if (! empty($proxyValueOptions)) { + $this->setValueOptions($proxyValueOptions); + } + + return $this->valueOptions; + } +} diff --git a/src/DoctrineExpressiveModule/Form/Element/ObjectRadio.php b/src/DoctrineExpressiveModule/Form/Element/ObjectRadio.php new file mode 100644 index 0000000..05c4315 --- /dev/null +++ b/src/DoctrineExpressiveModule/Form/Element/ObjectRadio.php @@ -0,0 +1,73 @@ +proxy) { + $this->proxy = new Proxy(); + } + return $this->proxy; + } + + /** + * @param array|\Traversable $options + * @return self + */ + public function setOptions($options) + { + $this->getProxy()->setOptions($options); + return parent::setOptions($options); + } + + /** + * @param string $key + * @param mixed $value + * @return self + */ + public function setOption($key, $value) + { + $this->getProxy()->setOptions([$key => $value]); + return parent::setOption($key, $value); + } + + /** + * {@inheritDoc} + */ + public function setValue($value) + { + return parent::setValue($this->getProxy()->getValue($value)); + } + + /** + * {@inheritDoc} + */ + public function getValueOptions() + { + if (! empty($this->valueOptions)) { + return $this->valueOptions; + } + + $proxyValueOptions = $this->getProxy()->getValueOptions(); + + if (! empty($proxyValueOptions)) { + $this->setValueOptions($proxyValueOptions); + } + + return $this->valueOptions; + } +} diff --git a/src/DoctrineExpressiveModule/Form/Element/ObjectSelect.php b/src/DoctrineExpressiveModule/Form/Element/ObjectSelect.php new file mode 100644 index 0000000..2adeacd --- /dev/null +++ b/src/DoctrineExpressiveModule/Form/Element/ObjectSelect.php @@ -0,0 +1,88 @@ +proxy) { + $this->proxy = new Proxy(); + } + return $this->proxy; + } + + /** + * @param array|\Traversable $options + * @return self + */ + public function setOptions($options) + { + $this->getProxy()->setOptions($options); + return parent::setOptions($options); + } + + /** + * @param string $key + * @param mixed $value + * @return self + */ + public function setOption($key, $value) + { + $this->getProxy()->setOptions([$key => $value]); + return parent::setOption($key, $value); + } + + /** + * {@inheritDoc} + */ + public function setValue($value) + { + $multiple = $this->getAttribute('multiple'); + + if (true === $multiple || 'multiple' === $multiple) { + if ($value instanceof \Traversable) { + $value = ArrayUtils::iteratorToArray($value); + } elseif ($value == null) { + return parent::setValue([]); + } elseif (! is_array($value)) { + $value = (array) $value; + } + + return parent::setValue(array_map([$this->getProxy(), 'getValue'], $value)); + } + + return parent::setValue($this->getProxy()->getValue($value)); + } + + /** + * {@inheritDoc} + */ + public function getValueOptions() + { + if (! empty($this->valueOptions)) { + return $this->valueOptions; + } + + $proxyValueOptions = $this->getProxy()->getValueOptions(); + + if (! empty($proxyValueOptions)) { + $this->setValueOptions($proxyValueOptions); + } + + return $this->valueOptions; + } +} diff --git a/src/DoctrineExpressiveModule/Form/Element/Proxy.php b/src/DoctrineExpressiveModule/Form/Element/Proxy.php new file mode 100644 index 0000000..fa73e2a --- /dev/null +++ b/src/DoctrineExpressiveModule/Form/Element/Proxy.php @@ -0,0 +1,653 @@ +setObjectManager($options['object_manager']); + } + + if (isset($options['target_class'])) { + $this->setTargetClass($options['target_class']); + } + + if (isset($options['property'])) { + $this->setProperty($options['property']); + } + + if (isset($options['label_generator'])) { + $this->setLabelGenerator($options['label_generator']); + } + + if (isset($options['find_method'])) { + $this->setFindMethod($options['find_method']); + } + + if (isset($options['is_method'])) { + $this->setIsMethod($options['is_method']); + } + + if (isset($options['display_empty_item'])) { + $this->setDisplayEmptyItem($options['display_empty_item']); + } + + if (isset($options['empty_item_label'])) { + $this->setEmptyItemLabel($options['empty_item_label']); + } + + if (isset($options['option_attributes'])) { + $this->setOptionAttributes($options['option_attributes']); + } + + if (isset($options['optgroup_identifier'])) { + $this->setOptgroupIdentifier($options['optgroup_identifier']); + } + + if (isset($options['optgroup_default'])) { + $this->setOptgroupDefault($options['optgroup_default']); + } + } + + public function getValueOptions() + { + if (empty($this->valueOptions)) { + $this->loadValueOptions(); + } + + return $this->valueOptions; + } + + /** + * @return array|Traversable + */ + public function getObjects() + { + $this->loadObjects(); + + return $this->objects; + } + + /** + * Set the label for the empty option + * + * @param string $emptyItemLabel + * + * @return Proxy + */ + public function setEmptyItemLabel($emptyItemLabel) + { + $this->emptyItemLabel = $emptyItemLabel; + + return $this; + } + + /** + * @return string + */ + public function getEmptyItemLabel() + { + return $this->emptyItemLabel; + } + + /** + * @return array + */ + public function getOptionAttributes() + { + return $this->option_attributes; + } + + /** + * @param array $option_attributes + */ + public function setOptionAttributes(array $option_attributes) + { + $this->option_attributes = $option_attributes; + } + + /** + * Set a flag, whether to include the empty option at the beginning or not + * + * @param boolean $displayEmptyItem + * + * @return Proxy + */ + public function setDisplayEmptyItem($displayEmptyItem) + { + $this->displayEmptyItem = $displayEmptyItem; + + return $this; + } + + /** + * @return boolean + */ + public function getDisplayEmptyItem() + { + return $this->displayEmptyItem; + } + + /** + * Set the object manager + * + * @param ObjectManager $objectManager + * + * @return Proxy + */ + public function setObjectManager(ObjectManager $objectManager) + { + $this->objectManager = $objectManager; + + return $this; + } + + /** + * Get the object manager + * + * @return ObjectManager + */ + public function getObjectManager() + { + return $this->objectManager; + } + + /** + * Set the FQCN of the target object + * + * @param string $targetClass + * + * @return Proxy + */ + public function setTargetClass($targetClass) + { + $this->targetClass = $targetClass; + + return $this; + } + + /** + * Get the target class + * + * @return string + */ + public function getTargetClass() + { + return $this->targetClass; + } + + /** + * Set the property to use as the label in the options + * + * @param string $property + * + * @return Proxy + */ + public function setProperty($property) + { + $this->property = $property; + + return $this; + } + + /** + * @return mixed + */ + public function getProperty() + { + return $this->property; + } + + /** + * Set the label generator callable that is responsible for generating labels for the items in the collection + * + * @param callable $callable A callable used to create a label based off of an Entity + * + * @throws InvalidArgumentException + * + * @return void + */ + public function setLabelGenerator($callable) + { + if (! is_callable($callable)) { + throw new InvalidArgumentException( + 'Property "label_generator" needs to be a callable function or a \Closure' + ); + } + + $this->labelGenerator = $callable; + } + + /** + * @return callable|null + */ + public function getLabelGenerator() + { + return $this->labelGenerator; + } + + /** + * @return string|null + */ + public function getOptgroupIdentifier() + { + return $this->optgroupIdentifier; + } + + /** + * @param string $optgroupIdentifier + */ + public function setOptgroupIdentifier($optgroupIdentifier) + { + $this->optgroupIdentifier = (string) $optgroupIdentifier; + } + + /** + * @return string|null + */ + public function getOptgroupDefault() + { + return $this->optgroupDefault; + } + + /** + * @param string $optgroupDefault + */ + public function setOptgroupDefault($optgroupDefault) + { + $this->optgroupDefault = (string) $optgroupDefault; + } + + /** + * Set if the property is a method to use as the label in the options + * + * @param boolean $method + * + * @return Proxy + */ + public function setIsMethod($method) + { + $this->isMethod = (bool) $method; + + return $this; + } + + /** + * @return mixed + */ + public function getIsMethod() + { + return $this->isMethod; + } + + /** Set the findMethod property to specify the method to use on repository + * + * @param array $findMethod + * + * @return Proxy + */ + public function setFindMethod($findMethod) + { + $this->findMethod = $findMethod; + + return $this; + } + + /** + * Get findMethod definition + * + * @return array + */ + public function getFindMethod() + { + return $this->findMethod; + } + + /** + * @param $targetEntity + * + * @return string|null + */ + protected function generateLabel($targetEntity) + { + if (null === ($labelGenerator = $this->getLabelGenerator())) { + return null; + } + + return call_user_func($labelGenerator, $targetEntity); + } + + /** + * @param $value + * + * @return array|mixed|object + * @throws RuntimeException + */ + public function getValue($value) + { + if (! ($om = $this->getObjectManager())) { + throw new RuntimeException('No object manager was set'); + } + + if (! ($targetClass = $this->getTargetClass())) { + throw new RuntimeException('No target class was set'); + } + + $metadata = $om->getClassMetadata($targetClass); + + if (is_object($value)) { + if ($value instanceof Collection) { + $data = []; + + foreach ($value as $object) { + $values = $metadata->getIdentifierValues($object); + $data[] = array_shift($values); + } + + $value = $data; + } else { + $metadata = $om->getClassMetadata(get_class($value)); + $identifier = $metadata->getIdentifierFieldNames(); + + // TODO: handle composite (multiple) identifiers + if (null !== $identifier && count($identifier) > 1) { + //$value = $key; + } else { + $value = current($metadata->getIdentifierValues($value)); + } + } + } + + return $value; + } + + /** + * Load objects + * + * @throws RuntimeException + * @throws Exception\InvalidRepositoryResultException + * @return void + */ + protected function loadObjects() + { + if (! empty($this->objects)) { + return; + } + + $findMethod = (array) $this->getFindMethod(); + + if (! $findMethod) { + $findMethodName = 'findAll'; + $repository = $this->objectManager->getRepository($this->targetClass); + $objects = $repository->findAll(); + } else { + if (! isset($findMethod['name'])) { + throw new RuntimeException('No method name was set'); + } + $findMethodName = $findMethod['name']; + $findMethodParams = isset($findMethod['params']) ? array_change_key_case($findMethod['params']) : []; + $repository = $this->objectManager->getRepository($this->targetClass); + + if (! method_exists($repository, $findMethodName)) { + throw new RuntimeException( + sprintf( + 'Method "%s" could not be found in repository "%s"', + $findMethodName, + get_class($repository) + ) + ); + } + + $r = new ReflectionMethod($repository, $findMethodName); + $args = []; + + foreach ($r->getParameters() as $param) { + if (array_key_exists(strtolower($param->getName()), $findMethodParams)) { + $args[] = $findMethodParams[strtolower($param->getName())]; + } elseif ($param->isDefaultValueAvailable()) { + $args[] = $param->getDefaultValue(); + } elseif (! $param->isOptional()) { + throw new RuntimeException( + sprintf( + 'Required parameter "%s" with no default value for method "%s" in repository "%s"' + . ' was not provided', + $param->getName(), + $findMethodName, + get_class($repository) + ) + ); + } + } + $objects = $r->invokeArgs($repository, $args); + } + + $this->guardForArrayOrTraversable( + $objects, + sprintf('%s::%s() return value', get_class($repository), $findMethodName), + 'DoctrineModule\Form\Element\Exception\InvalidRepositoryResultException' + ); + + $this->objects = $objects; + } + + /** + * Load value options + * + * @throws RuntimeException + * @return void + */ + protected function loadValueOptions() + { + if (! ($om = $this->objectManager)) { + throw new RuntimeException('No object manager was set'); + } + + if (! ($targetClass = $this->targetClass)) { + throw new RuntimeException('No target class was set'); + } + + $metadata = $om->getClassMetadata($targetClass); + $identifier = $metadata->getIdentifierFieldNames(); + $objects = $this->getObjects(); + $options = []; + $optionAttributes = []; + + if ($this->displayEmptyItem) { + $options[''] = $this->getEmptyItemLabel(); + } + + foreach ($objects as $key => $object) { + if (null !== ($generatedLabel = $this->generateLabel($object))) { + $label = $generatedLabel; + } elseif ($property = $this->property) { + if ($this->isMethod == false && ! $metadata->hasField($property)) { + throw new RuntimeException( + sprintf( + 'Property "%s" could not be found in object "%s"', + $property, + $targetClass + ) + ); + } + + $getter = 'get' . Inflector::classify($property); + + if (! is_callable([$object, $getter])) { + throw new RuntimeException( + sprintf('Method "%s::%s" is not callable', $this->targetClass, $getter) + ); + } + + $label = $object->{$getter}(); + } else { + if (! is_callable([$object, '__toString'])) { + throw new RuntimeException( + sprintf( + '%s must have a "__toString()" method defined if you have not set a property' + . ' or method to use.', + $targetClass + ) + ); + } + + $label = (string) $object; + } + + if (null !== $identifier && count($identifier) > 1) { + $value = $key; + } else { + $value = current($metadata->getIdentifierValues($object)); + } + + foreach ($this->getOptionAttributes() as $optionKey => $optionValue) { + if (is_string($optionValue)) { + $optionAttributes[$optionKey] = $optionValue; + + continue; + } + + if (is_callable($optionValue)) { + $callableValue = call_user_func($optionValue, $object); + $optionAttributes[$optionKey] = (string) $callableValue; + + continue; + } + + throw new RuntimeException( + sprintf( + 'Parameter "option_attributes" expects an array of key => value where value is of type' + . '"string" or "callable". Value of type "%s" found.', + gettype($optionValue) + ) + ); + } + + // If no optgroup_identifier has been configured, apply default handling and continue + if (is_null($this->getOptgroupIdentifier())) { + $options[] = ['label' => $label, 'value' => $value, 'attributes' => $optionAttributes]; + + continue; + } + + // optgroup_identifier found, handle grouping + $optgroupGetter = 'get' . Inflector::classify($this->getOptgroupIdentifier()); + + if (! is_callable([$object, $optgroupGetter])) { + throw new RuntimeException( + sprintf('Method "%s::%s" is not callable', $this->targetClass, $optgroupGetter) + ); + } + + $optgroup = $object->{$optgroupGetter}(); + + // optgroup_identifier contains a valid group-name. Handle default grouping. + if (false === is_null($optgroup) && trim($optgroup) !== '') { + $options[$optgroup]['label'] = $optgroup; + $options[$optgroup]['options'][] = [ + 'label' => $label, + 'value' => $value, + 'attributes' => $optionAttributes, + ]; + + continue; + } + + $optgroupDefault = $this->getOptgroupDefault(); + + // No optgroup_default has been provided. Line up without a group + if (is_null($optgroupDefault)) { + $options[] = ['label' => $label, 'value' => $value, 'attributes' => $optionAttributes]; + + continue; + } + + // Line up entry with optgroup_default + $options[$optgroupDefault]['label'] = $optgroupDefault; + $options[$optgroupDefault]['options'][] = [ + 'label' => $label, + 'value' => $value, + 'attributes' => $optionAttributes, + ]; + } + + $this->valueOptions = $options; + } +} diff --git a/src/DoctrineExpressiveModule/Hydrator/DoctrineObject.php b/src/DoctrineExpressiveModule/Hydrator/DoctrineObject.php new file mode 100644 index 0000000..95445e6 --- /dev/null +++ b/src/DoctrineExpressiveModule/Hydrator/DoctrineObject.php @@ -0,0 +1,594 @@ +. + */ + +namespace DoctrineExpressiveModule\Hydrator; + +use DateTime; +use Doctrine\Common\Persistence\Mapping\ClassMetadata; +use Doctrine\Common\Persistence\ObjectManager; +use Doctrine\Common\Util\Inflector; +use InvalidArgumentException; +use RuntimeException; +use Traversable; +use Zend\Stdlib\ArrayUtils; +use Zend\Hydrator\AbstractHydrator; +use Zend\Hydrator\Filter\FilterProviderInterface; + +/** + * This hydrator has been completely refactored for DoctrineModule 0.7.0. It provides an easy and powerful way + * of extracting/hydrator objects in Doctrine, by handling most associations types. + * + * Starting from DoctrineModule 0.8.0, the hydrator can be used multiple times with different objects + * + * @license MIT + * @link http://www.doctrine-project.org/ + * @since 0.7.0 + * @author Michael Gallego + */ +class DoctrineObject extends AbstractHydrator +{ + /** + * @var ObjectManager + */ + protected $objectManager; + + /** + * @var ClassMetadata + */ + protected $metadata; + + /** + * @var bool + */ + protected $byValue = true; + + + /** + * Constructor + * + * @param ObjectManager $objectManager The ObjectManager to use + * @param bool $byValue If set to true, hydrator will always use entity's public API + */ + public function __construct(ObjectManager $objectManager, $byValue = true) + { + parent::__construct(); + + $this->objectManager = $objectManager; + $this->byValue = (bool) $byValue; + } + + /** + * Extract values from an object + * + * @param object $object + * @return array + */ + public function extract($object) + { + $this->prepare($object); + + if ($this->byValue) { + return $this->extractByValue($object); + } + + return $this->extractByReference($object); + } + + /** + * Hydrate $object with the provided $data. + * + * @param array $data + * @param object $object + * @return object + */ + public function hydrate(array $data, $object) + { + $this->prepare($object); + + if ($this->byValue) { + return $this->hydrateByValue($data, $object); + } + + return $this->hydrateByReference($data, $object); + } + + /** + * Prepare the hydrator by adding strategies to every collection valued associations + * + * @param object $object + * @return void + */ + protected function prepare($object) + { + $this->metadata = $this->objectManager->getClassMetadata(get_class($object)); + $this->prepareStrategies(); + } + + /** + * Prepare strategies before the hydrator is used + * + * @throws \InvalidArgumentException + * @return void + */ + protected function prepareStrategies() + { + $associations = $this->metadata->getAssociationNames(); + + foreach ($associations as $association) { + if ($this->metadata->isCollectionValuedAssociation($association)) { + // Add a strategy if the association has none set by user + if (!$this->hasStrategy($association)) { + if ($this->byValue) { + $this->addStrategy($association, new Strategy\AllowRemoveByValue()); + } else { + $this->addStrategy($association, new Strategy\AllowRemoveByReference()); + } + } + + $strategy = $this->getStrategy($association); + + if (!$strategy instanceof Strategy\AbstractCollectionStrategy) { + throw new InvalidArgumentException( + sprintf( + 'Strategies used for collections valued associations must inherit from ' + . 'Strategy\AbstractCollectionStrategy, %s given', + get_class($strategy) + ) + ); + } + + $strategy->setCollectionName($association) + ->setClassMetadata($this->metadata); + } + } + } + + /** + * Extract values from an object using a by-value logic (this means that it uses the entity + * API, in this case, getters) + * + * @param object $object + * @throws RuntimeException + * @return array + */ + protected function extractByValue($object) + { + $fieldNames = array_merge($this->metadata->getFieldNames(), $this->metadata->getAssociationNames()); + $methods = get_class_methods($object); + $filter = $object instanceof FilterProviderInterface + ? $object->getFilter() + : $this->filterComposite; + + $data = []; + foreach ($fieldNames as $fieldName) { + if ($filter && !$filter->filter($fieldName)) { + continue; + } + + $getter = 'get' . Inflector::classify($fieldName); + $isser = 'is' . Inflector::classify($fieldName); + + $dataFieldName = $this->computeExtractFieldName($fieldName); + if (in_array($getter, $methods)) { + $data[$dataFieldName] = $this->extractValue($fieldName, $object->$getter(), $object); + } elseif (in_array($isser, $methods)) { + $data[$dataFieldName] = $this->extractValue($fieldName, $object->$isser(), $object); + } elseif (substr($fieldName, 0, 2) === 'is' + && ctype_upper(substr($fieldName, 2, 1)) + && in_array($fieldName, $methods)) { + $data[$dataFieldName] = $this->extractValue($fieldName, $object->$fieldName(), $object); + } + + // Unknown fields are ignored + } + + return $data; + } + + /** + * Extract values from an object using a by-reference logic (this means that values are + * directly fetched without using the public API of the entity, in this case, getters) + * + * @param object $object + * @return array + */ + protected function extractByReference($object) + { + $fieldNames = array_merge($this->metadata->getFieldNames(), $this->metadata->getAssociationNames()); + $refl = $this->metadata->getReflectionClass(); + $filter = $object instanceof FilterProviderInterface + ? $object->getFilter() + : $this->filterComposite; + + $data = []; + foreach ($fieldNames as $fieldName) { + if ($filter && !$filter->filter($fieldName)) { + continue; + } + $reflProperty = $refl->getProperty($fieldName); + $reflProperty->setAccessible(true); + + $dataFieldName = $this->computeExtractFieldName($fieldName); + $data[$dataFieldName] = $this->extractValue($fieldName, $reflProperty->getValue($object), $object); + } + + return $data; + } + + /** + * Hydrate the object using a by-value logic (this means that it uses the entity API, in this + * case, setters) + * + * @param array $data + * @param object $object + * @throws RuntimeException + * @return object + */ + protected function hydrateByValue(array $data, $object) + { + $tryObject = $this->tryConvertArrayToObject($data, $object); + $metadata = $this->metadata; + + if (is_object($tryObject)) { + $object = $tryObject; + } + + foreach ($data as $field => $value) { + $field = $this->computeHydrateFieldName($field); + $value = $this->handleTypeConversions($value, $metadata->getTypeOfField($field)); + $setter = 'set' . Inflector::classify($field); + + if ($metadata->hasAssociation($field)) { + $target = $metadata->getAssociationTargetClass($field); + + if ($metadata->isSingleValuedAssociation($field)) { + if (! method_exists($object, $setter)) { + continue; + } + + $value = $this->toOne($target, $this->hydrateValue($field, $value, $data)); + + if (null === $value + && !current($metadata->getReflectionClass()->getMethod($setter)->getParameters())->allowsNull() + ) { + continue; + } + + $object->$setter($value); + } elseif ($metadata->isCollectionValuedAssociation($field)) { + $this->toMany($object, $field, $target, $value); + } + } else { + if (! method_exists($object, $setter)) { + continue; + } + + $object->$setter($this->hydrateValue($field, $value, $data)); + } + } + + return $object; + } + + /** + * Hydrate the object using a by-reference logic (this means that values are modified directly without + * using the public API, in this case setters, and hence override any logic that could be done in those + * setters) + * + * @param array $data + * @param object $object + * @return object + */ + protected function hydrateByReference(array $data, $object) + { + $tryObject = $this->tryConvertArrayToObject($data, $object); + $metadata = $this->metadata; + $refl = $metadata->getReflectionClass(); + + if (is_object($tryObject)) { + $object = $tryObject; + } + + foreach ($data as $field => $value) { + $field = $this->computeHydrateFieldName($field); + + // Ignore unknown fields + if (!$refl->hasProperty($field)) { + continue; + } + + $value = $this->handleTypeConversions($value, $metadata->getTypeOfField($field)); + $reflProperty = $refl->getProperty($field); + $reflProperty->setAccessible(true); + + if ($metadata->hasAssociation($field)) { + $target = $metadata->getAssociationTargetClass($field); + + if ($metadata->isSingleValuedAssociation($field)) { + $value = $this->toOne($target, $this->hydrateValue($field, $value, $data)); + $reflProperty->setValue($object, $value); + } elseif ($metadata->isCollectionValuedAssociation($field)) { + $this->toMany($object, $field, $target, $value); + } + } else { + $reflProperty->setValue($object, $this->hydrateValue($field, $value, $data)); + } + } + + return $object; + } + + /** + * This function tries, given an array of data, to convert it to an object if the given array contains + * an identifier for the object. This is useful in a context of updating existing entities, without ugly + * tricks like setting manually the existing id directly into the entity + * + * @param array $data The data that may contain identifiers keys + * @param object $object + * @return object + */ + protected function tryConvertArrayToObject($data, $object) + { + $metadata = $this->metadata; + $identifierNames = $metadata->getIdentifierFieldNames($object); + $identifierValues = []; + + if (empty($identifierNames)) { + return $object; + } + + foreach ($identifierNames as $identifierName) { + if (!isset($data[$identifierName])) { + return $object; + } + + $identifierValues[$identifierName] = $data[$identifierName]; + } + + return $this->find($identifierValues, $metadata->getName()); + } + + /** + * Handle ToOne associations + * + * When $value is an array but is not the $target's identifiers, $value is + * most likely an array of fieldset data. The identifiers will be determined + * and a target instance will be initialized and then hydrated. The hydrated + * target will be returned. + * + * @param string $target + * @param mixed $value + * @return object + */ + protected function toOne($target, $value) + { + $metadata = $this->objectManager->getClassMetadata($target); + + if (is_array($value) && array_keys($value) != $metadata->getIdentifier()) { + // $value is most likely an array of fieldset data + $identifiers = array_intersect_key( + $value, + array_flip($metadata->getIdentifier()) + ); + $object = $this->find($identifiers, $target) ?: new $target; + return $this->hydrate($value, $object); + } + + return $this->find($value, $target); + } + + /** + * Handle ToMany associations. In proper Doctrine design, Collections should not be swapped, so + * collections are always handled by reference. Internally, every collection is handled using specials + * strategies that inherit from AbstractCollectionStrategy class, and that add or remove elements but without + * changing the collection of the object + * + * @param object $object + * @param mixed $collectionName + * @param string $target + * @param mixed $values + * + * @throws \InvalidArgumentException + * + * @return void + */ + protected function toMany($object, $collectionName, $target, $values) + { + $metadata = $this->objectManager->getClassMetadata(ltrim($target, '\\')); + $identifier = $metadata->getIdentifier(); + + if (!is_array($values) && !$values instanceof Traversable) { + $values = (array)$values; + } + + $collection = []; + + // If the collection contains identifiers, fetch the objects from database + foreach ($values as $value) { + if ($value instanceof $target) { + // assumes modifications have already taken place in object + $collection[] = $value; + continue; + } elseif (empty($value)) { + // assumes no id and retrieves new $target + $collection[] = $this->find($value, $target); + continue; + } + + $find = []; + if (is_array($identifier)) { + foreach ($identifier as $field) { + switch (gettype($value)) { + case 'object': + $getter = 'get' . ucfirst($field); + if (method_exists($value, $getter)) { + $find[$field] = $value->$getter(); + } elseif (property_exists($value, $field)) { + $find[$field] = $value->$field; + } + break; + case 'array': + if (array_key_exists($field, $value) && $value[$field] != null) { + $find[$field] = $value[$field]; + unset($value[$field]); // removed identifier from persistable data + } + break; + default: + $find[$field] = $value; + break; + } + } + } + + if (!empty($find) && $found = $this->find($find, $target)) { + $collection[] = (is_array($value)) ? $this->hydrate($value, $found) : $found; + } else { + $collection[] = (is_array($value)) ? $this->hydrate($value, new $target) : new $target; + } + } + + $collection = array_filter( + $collection, + function ($item) { + return null !== $item; + } + ); + + // Set the object so that the strategy can extract the Collection from it + + /** @var \DoctrineModule\Stdlib\Hydrator\Strategy\AbstractCollectionStrategy $collectionStrategy */ + $collectionStrategy = $this->getStrategy($collectionName); + $collectionStrategy->setObject($object); + + // We could directly call hydrate method from the strategy, but if people want to override + // hydrateValue function, they can do it and do their own stuff + $this->hydrateValue($collectionName, $collection, $values); + } + + /** + * Handle various type conversions that should be supported natively by Doctrine (like DateTime) + * + * @param mixed $value + * @param string $typeOfField + * @return DateTime + */ + protected function handleTypeConversions($value, $typeOfField) + { + switch ($typeOfField) { + case 'datetimetz': + case 'datetime': + case 'time': + case 'date': + if ('' === $value) { + return null; + } + + if (is_int($value)) { + $dateTime = new DateTime(); + $dateTime->setTimestamp($value); + $value = $dateTime; + } elseif (is_string($value)) { + $value = new DateTime($value); + } + + break; + default: + } + + return $value; + } + + /** + * Find an object by a given target class and identifier + * + * @param mixed $identifiers + * @param string $targetClass + * + * @return object|null + */ + protected function find($identifiers, $targetClass) + { + if ($identifiers instanceof $targetClass) { + return $identifiers; + } + + if ($this->isNullIdentifier($identifiers)) { + return null; + } + + return $this->objectManager->find($targetClass, $identifiers); + } + + /** + * Verifies if a provided identifier is to be considered null + * + * @param mixed $identifier + * + * @return bool + */ + private function isNullIdentifier($identifier) + { + if (null === $identifier) { + return true; + } + + if ($identifier instanceof Traversable || is_array($identifier)) { + $nonNullIdentifiers = array_filter( + ArrayUtils::iteratorToArray($identifier), + function ($value) { + return null !== $value; + } + ); + + return empty($nonNullIdentifiers); + } + + return false; + } + + /** + * Applies the naming strategy if there is one set + * + * @param string $field + * + * @return string + */ + protected function computeHydrateFieldName($field) + { + if ($this->hasNamingStrategy()) { + $field = $this->getNamingStrategy()->hydrate($field); + } + return $field; + } + + /** + * Applies the naming strategy if there is one set + * + * @param string $field + * + * @return string + */ + protected function computeExtractFieldName($field) + { + if ($this->hasNamingStrategy()) { + $field = $this->getNamingStrategy()->extract($field); + } + return $field; + } +} diff --git a/src/DoctrineExpressiveModule/Hydrator/DoctrineObjectFactory.php b/src/DoctrineExpressiveModule/Hydrator/DoctrineObjectFactory.php new file mode 100644 index 0000000..d41e6c0 --- /dev/null +++ b/src/DoctrineExpressiveModule/Hydrator/DoctrineObjectFactory.php @@ -0,0 +1,15 @@ +get('doctrine.entity_manager.orm_default'); + return new DoctrineObject($em); + } +} diff --git a/src/DoctrineExpressiveModule/Hydrator/Filter/PropertyName.php b/src/DoctrineExpressiveModule/Hydrator/Filter/PropertyName.php new file mode 100644 index 0000000..c1c9067 --- /dev/null +++ b/src/DoctrineExpressiveModule/Hydrator/Filter/PropertyName.php @@ -0,0 +1,66 @@ +. + */ + +namespace DoctrineExpressiveModule\Hydrator\Filter; + +use Zend\Hydrator\Filter\FilterInterface; + +/** + * Provides a filter to restrict returned fields by whitelisting or + * blacklisting property names. + * + * @license MIT + * @link http://www.doctrine-project.org/ + * @author Liam O'Boyle + */ +class PropertyName implements FilterInterface +{ + /** + * The propteries to exclude. + * + * @var array + */ + protected $properties = []; + + /** + * Either an exclude or an include. + * + * @var bool + */ + protected $exclude = null; + + /** + * @param [ string | array ] $properties The properties to exclude or include. + * @param bool $exclude If the method should be excluded + */ + public function __construct($properties, $exclude = true) + { + $this->exclude = $exclude; + $this->properties = is_array($properties) + ? $properties + : [$properties]; + } + + public function filter($property) + { + return in_array($property, $this->properties) + ? !$this->exclude + : $this->exclude; + } +} diff --git a/src/DoctrineExpressiveModule/Hydrator/Strategy/AbstractCollectionStrategy.php b/src/DoctrineExpressiveModule/Hydrator/Strategy/AbstractCollectionStrategy.php new file mode 100644 index 0000000..2eff700 --- /dev/null +++ b/src/DoctrineExpressiveModule/Hydrator/Strategy/AbstractCollectionStrategy.php @@ -0,0 +1,190 @@ +. + */ + +namespace DoctrineExpressiveModule\Hydrator\Strategy; + +use InvalidArgumentException; +use Doctrine\Common\Collections\Collection; +use Doctrine\Common\Persistence\Mapping\ClassMetadata; +use Zend\Hydrator\Strategy\StrategyInterface; + +/** + * @license MIT + * @link http://www.doctrine-project.org/ + * @since 0.7.0 + * @author Michael Gallego + */ +abstract class AbstractCollectionStrategy implements StrategyInterface +{ + /** + * @var string + */ + protected $collectionName; + + /** + * @var ClassMetadata + */ + protected $metadata; + + /** + * @var object + */ + protected $object; + + + /** + * Set the name of the collection + * + * @param string $collectionName + * @return AbstractCollectionStrategy + */ + public function setCollectionName($collectionName) + { + $this->collectionName = (string) $collectionName; + return $this; + } + + /** + * Get the name of the collection + * + * @return string + */ + public function getCollectionName() + { + return $this->collectionName; + } + + /** + * Set the class metadata + * + * @param ClassMetadata $classMetadata + * @return AbstractCollectionStrategy + */ + public function setClassMetadata(ClassMetadata $classMetadata) + { + $this->metadata = $classMetadata; + return $this; + } + + /** + * Get the class metadata + * + * @return ClassMetadata + */ + public function getClassMetadata() + { + return $this->metadata; + } + + /** + * Set the object + * + * @param object $object + * + * @throws \InvalidArgumentException + * + * @return AbstractCollectionStrategy + */ + public function setObject($object) + { + if (!is_object($object)) { + throw new InvalidArgumentException( + sprintf('The parameter given to setObject method of %s class is not an object', get_called_class()) + ); + } + + $this->object = $object; + return $this; + } + + /** + * Get the object + * + * @return object + */ + public function getObject() + { + return $this->object; + } + + /** + * {@inheritDoc} + */ + public function extract($value) + { + return $value; + } + + /** + * Return the collection by value (using the public API) + * + * @throws \InvalidArgumentException + * + * @return Collection + */ + protected function getCollectionFromObjectByValue() + { + $object = $this->getObject(); + $getter = 'get' . ucfirst($this->getCollectionName()); + + if (!method_exists($object, $getter)) { + throw new InvalidArgumentException( + sprintf( + 'The getter %s to access collection %s in object %s does not exist', + $getter, + $this->getCollectionName(), + get_class($object) + ) + ); + } + + return $object->$getter(); + } + + /** + * Return the collection by reference (not using the public API) + * + * @return Collection + */ + protected function getCollectionFromObjectByReference() + { + $object = $this->getObject(); + $refl = $this->getClassMetadata()->getReflectionClass(); + $reflProperty = $refl->getProperty($this->getCollectionName()); + + $reflProperty->setAccessible(true); + + return $reflProperty->getValue($object); + } + + + /** + * This method is used internally by array_udiff to check if two objects are equal, according to their + * SPL hash. This is needed because the native array_diff only compare strings + * + * @param object $a + * @param object $b + * + * @return int + */ + protected function compareObjects($a, $b) + { + return strcmp(spl_object_hash($a), spl_object_hash($b)); + } +} diff --git a/src/DoctrineExpressiveModule/Hydrator/Strategy/AllowRemoveByReference.php b/src/DoctrineExpressiveModule/Hydrator/Strategy/AllowRemoveByReference.php new file mode 100644 index 0000000..94c33ef --- /dev/null +++ b/src/DoctrineExpressiveModule/Hydrator/Strategy/AllowRemoveByReference.php @@ -0,0 +1,58 @@ +. + */ + +namespace DoctrineExpressiveModule\Hydrator\Strategy; + +/** + * When this strategy is used for Collections, if the new collection does not contain elements that are present in + * the original collection, then this strategy remove elements from the original collection. For instance, if the + * collection initially contains elements A and B, and that the new collection contains elements B and C, then the + * final collection will contain elements B and C (while element A will be asked to be removed). + * + * This strategy is by reference, this means it won't use public API to add/remove elements to the collection + * + * @license MIT + * @link http://www.doctrine-project.org/ + * @since 0.7.0 + * @author Michael Gallego + */ +class AllowRemoveByReference extends AbstractCollectionStrategy +{ + /** + * {@inheritDoc} + */ + public function hydrate($value) + { + $collection = $this->getCollectionFromObjectByReference(); + $collectionArray = $collection->toArray(); + + $toAdd = array_udiff($value, $collectionArray, [$this, 'compareObjects']); + $toRemove = array_udiff($collectionArray, $value, [$this, 'compareObjects']); + + foreach ($toAdd as $element) { + $collection->add($element); + } + + foreach ($toRemove as $element) { + $collection->removeElement($element); + } + + return $collection; + } +} diff --git a/src/DoctrineExpressiveModule/Hydrator/Strategy/AllowRemoveByValue.php b/src/DoctrineExpressiveModule/Hydrator/Strategy/AllowRemoveByValue.php new file mode 100644 index 0000000..30a2806 --- /dev/null +++ b/src/DoctrineExpressiveModule/Hydrator/Strategy/AllowRemoveByValue.php @@ -0,0 +1,76 @@ +. + */ + +namespace DoctrineExpressiveModule\Hydrator\Strategy; + +use Doctrine\Common\Collections\Collection; +use LogicException; +use Doctrine\Common\Collections\ArrayCollection; + +/** + * When this strategy is used for Collections, if the new collection does not contain elements that are present in + * the original collection, then this strategy remove elements from the original collection. For instance, if the + * collection initially contains elements A and B, and that the new collection contains elements B and C, then the + * final collection will contain elements B and C (while element A will be asked to be removed). + * + * This strategy is by value, this means it will use the public API (in this case, adder and remover) + * + * @license MIT + * @link http://www.doctrine-project.org/ + * @since 0.7.0 + * @author Michael Gallego + */ +class AllowRemoveByValue extends AbstractCollectionStrategy +{ + /** + * {@inheritDoc} + */ + public function hydrate($value) + { + // AllowRemove strategy need "adder" and "remover" + $adder = 'add' . ucfirst($this->collectionName); + $remover = 'remove' . ucfirst($this->collectionName); + + if (!method_exists($this->object, $adder) || !method_exists($this->object, $remover)) { + throw new LogicException( + sprintf( + 'AllowRemove strategy for DoctrineModule hydrator requires both %s and %s to be defined in %s + entity domain code, but one or both seem to be missing', + $adder, + $remover, + get_class($this->object) + ) + ); + } + + $collection = $this->getCollectionFromObjectByValue(); + + if ($collection instanceof Collection) { + $collection = $collection->toArray(); + } + + $toAdd = new ArrayCollection(array_udiff($value, $collection, [$this, 'compareObjects'])); + $toRemove = new ArrayCollection(array_udiff($collection, $value, [$this, 'compareObjects'])); + + $this->object->$adder($toAdd); + $this->object->$remover($toRemove); + + return $collection; + } +} diff --git a/src/DoctrineExpressiveModule/Hydrator/Strategy/DisallowRemoveByReference.php b/src/DoctrineExpressiveModule/Hydrator/Strategy/DisallowRemoveByReference.php new file mode 100644 index 0000000..47eadc2 --- /dev/null +++ b/src/DoctrineExpressiveModule/Hydrator/Strategy/DisallowRemoveByReference.php @@ -0,0 +1,53 @@ +. + */ + +namespace DoctrineExpressiveModule\Hydrator\Strategy; + +/** + * When this strategy is used for Collections, if the new collection does not contain elements that are present in + * the original collection, then this strategy will not remove those elements. At most, it will add new elements. For + * instance, if the collection initially contains elements A and B, and that the new collection contains elements B + * and C, then the final collection will contain elements A, B and C. + * + * This strategy is by reference, this means it won't use the public API to remove elements + * + * @license MIT + * @link http://www.doctrine-project.org/ + * @since 0.7.0 + * @author Michael Gallego + */ +class DisallowRemoveByReference extends AbstractCollectionStrategy +{ + /** + * {@inheritDoc} + */ + public function hydrate($value) + { + $collection = $this->getCollectionFromObjectByReference(); + $collectionArray = $collection->toArray(); + + $toAdd = array_udiff($value, $collectionArray, [$this, 'compareObjects']); + + foreach ($toAdd as $element) { + $collection->add($element); + } + + return $collection; + } +} diff --git a/src/DoctrineExpressiveModule/Hydrator/Strategy/DisallowRemoveByValue.php b/src/DoctrineExpressiveModule/Hydrator/Strategy/DisallowRemoveByValue.php new file mode 100644 index 0000000..77df2be --- /dev/null +++ b/src/DoctrineExpressiveModule/Hydrator/Strategy/DisallowRemoveByValue.php @@ -0,0 +1,72 @@ +. + */ + +namespace DoctrineExpressiveModule\Hydrator\Strategy; + +use Doctrine\Common\Collections\Collection; +use LogicException; +use Doctrine\Common\Collections\ArrayCollection; + +/** + * When this strategy is used for Collections, if the new collection does not contain elements that are present in + * the original collection, then this strategy will not remove those elements. At most, it will add new elements. For + * instance, if the collection initially contains elements A and B, and that the new collection contains elements B + * and C, then the final collection will contain elements A, B and C. + * + * This strategy is by value, this means it will use the public API (in this case, remover) + * + * @license MIT + * @link http://www.doctrine-project.org/ + * @since 0.7.0 + * @author Michael Gallego + */ +class DisallowRemoveByValue extends AbstractCollectionStrategy +{ + /** + * {@inheritDoc} + */ + public function hydrate($value) + { + // AllowRemove strategy need "adder" + $adder = 'add' . ucfirst($this->collectionName); + + if (!method_exists($this->object, $adder)) { + throw new LogicException( + sprintf( + 'DisallowRemove strategy for DoctrineModule hydrator requires %s to + be defined in %s entity domain code, but it seems to be missing', + $adder, + get_class($this->object) + ) + ); + } + + $collection = $this->getCollectionFromObjectByValue(); + + if ($collection instanceof Collection) { + $collection = $collection->toArray(); + } + + $toAdd = new ArrayCollection(array_udiff($value, $collection, [$this, 'compareObjects'])); + + $this->object->$adder($toAdd); + + return $collection; + } +} diff --git a/src/DoctrineExpressiveModule/Validator/NoObjectExists.php b/src/DoctrineExpressiveModule/Validator/NoObjectExists.php new file mode 100644 index 0000000..a28b88a --- /dev/null +++ b/src/DoctrineExpressiveModule/Validator/NoObjectExists.php @@ -0,0 +1,43 @@ + + */ +class NoObjectExists extends ObjectExists +{ + /** + * Error constants + */ + const ERROR_OBJECT_FOUND = 'objectFound'; + + /** + * @var array Message templates + */ + protected $messageTemplates = [ + self::ERROR_OBJECT_FOUND => "An object matching '%value%' was found", + ]; + + /** + * {@inheritDoc} + */ + public function isValid($value) + { + $cleanedValue = $this->cleanSearchValue($value); + $match = $this->objectRepository->findOneBy($cleanedValue); + + if (is_object($match)) { + $this->error(self::ERROR_OBJECT_FOUND, $value); + + return false; + } + + return true; + } +} diff --git a/src/DoctrineExpressiveModule/Validator/ObjectExists.php b/src/DoctrineExpressiveModule/Validator/ObjectExists.php new file mode 100644 index 0000000..3b67ad0 --- /dev/null +++ b/src/DoctrineExpressiveModule/Validator/ObjectExists.php @@ -0,0 +1,175 @@ + + */ +class ObjectExists extends AbstractValidator +{ + /** + * Error constants + */ + const ERROR_NO_OBJECT_FOUND = 'noObjectFound'; + + /** + * @var array Message templates + */ + protected $messageTemplates = [ + self::ERROR_NO_OBJECT_FOUND => "No object matching '%value%' was found", + ]; + + /** + * ObjectRepository from which to search for entities + * + * @var ObjectRepository + */ + protected $objectRepository; + + /** + * Fields to be checked + * + * @var array + */ + protected $fields; + + /** + * Constructor + * + * @param array $options required keys are `object_repository`, which must be an instance of + * Doctrine\Common\Persistence\ObjectRepository, and `fields`, with either + * a string or an array of strings representing the fields to be matched by the validator. + * @throws \Zend\Validator\Exception\InvalidArgumentException + */ + public function __construct(array $options) + { + if (! isset($options['object_repository']) || ! $options['object_repository'] instanceof ObjectRepository) { + if (! array_key_exists('object_repository', $options)) { + $provided = 'nothing'; + } else { + if (is_object($options['object_repository'])) { + $provided = get_class($options['object_repository']); + } else { + $provided = getType($options['object_repository']); + } + } + + throw new Exception\InvalidArgumentException( + sprintf( + 'Option "object_repository" is required and must be an instance of' + . ' Doctrine\Common\Persistence\ObjectRepository, %s given', + $provided + ) + ); + } + + $this->objectRepository = $options['object_repository']; + + if (! isset($options['fields'])) { + throw new Exception\InvalidArgumentException( + 'Key `fields` must be provided and be a field or a list of fields to be used when searching for' + . ' existing instances' + ); + } + + $this->fields = $options['fields']; + $this->validateFields(); + + parent::__construct($options); + } + + /** + * Filters and validates the fields passed to the constructor + * + * @throws \Zend\Validator\Exception\InvalidArgumentException + * @return array + */ + private function validateFields() + { + $fields = (array) $this->fields; + + if (empty($fields)) { + throw new Exception\InvalidArgumentException('Provided fields list was empty!'); + } + + foreach ($fields as $key => $field) { + if (! is_string($field)) { + throw new Exception\InvalidArgumentException( + sprintf('Provided fields must be strings, %s provided for key %s', gettype($field), $key) + ); + } + } + + $this->fields = array_values($fields); + } + + /** + * @param string|array $value a field value or an array of field values if more fields have been configured to be + * matched + * @return array + * @throws \Zend\Validator\Exception\RuntimeException + */ + protected function cleanSearchValue($value) + { + $value = is_object($value) ? [$value] : (array) $value; + + if (ArrayUtils::isHashTable($value)) { + $matchedFieldsValues = []; + + foreach ($this->fields as $field) { + if (! array_key_exists($field, $value)) { + throw new Exception\RuntimeException( + sprintf( + 'Field "%s" was not provided, but was expected since the configured field lists needs' + . ' it for validation', + $field + ) + ); + } + + $matchedFieldsValues[$field] = $value[$field]; + } + } else { + $matchedFieldsValues = @array_combine($this->fields, $value); + + if (false === $matchedFieldsValues) { + throw new Exception\RuntimeException( + sprintf( + 'Provided values count is %s, while expected number of fields to be matched is %s', + count($value), + count($this->fields) + ) + ); + } + } + + return $matchedFieldsValues; + } + + /** + * {@inheritDoc} + */ + public function isValid($value) + { + $cleanedValue = $this->cleanSearchValue($value); + $match = $this->objectRepository->findOneBy($cleanedValue); + + if (is_object($match)) { + return true; + } + + $this->error(self::ERROR_NO_OBJECT_FOUND, $value); + + return false; + } +} diff --git a/src/DoctrineExpressiveModule/Validator/Service/AbstractValidatorFactory.php b/src/DoctrineExpressiveModule/Validator/Service/AbstractValidatorFactory.php new file mode 100644 index 0000000..d0a2bac --- /dev/null +++ b/src/DoctrineExpressiveModule/Validator/Service/AbstractValidatorFactory.php @@ -0,0 +1,121 @@ + + */ +abstract class AbstractValidatorFactory implements FactoryInterface +{ + const DEFAULT_OBJECTMANAGER_KEY = 'doctrine.entitymanager.orm_default'; + + protected $creationOptions = []; + + protected $validatorClass; + + /** + * @param ContainerInterface $container + * @param array $options + * @return \Doctrine\Common\Persistence\ObjectRepository + * @throws ServiceCreationException + */ + protected function getRepository(ContainerInterface $container, array $options) + { + if (empty($options['target_class'])) { + throw new ServiceCreationException(sprintf( + "Option 'target_class' is missing when creating validator %s", + __CLASS__ + )); + } + + $objectManager = $this->getObjectManager($container, $options); + $targetClassName = $options['target_class']; + $objectRepository = $objectManager->getRepository($targetClassName); + + return $objectRepository; + } + + /** + * @param ContainerInterface $container + * @param array $options + * @return \Doctrine\Common\Persistence\ObjectManager + */ + protected function getObjectManager(ContainerInterface $container, array $options) + { + $objectManager = ($options['object_manager']) ?? self::DEFAULT_OBJECTMANAGER_KEY; + + if (is_string($objectManager)) { + $objectManager = $container->get($objectManager); + } + + return $objectManager; + } + + /** + * @param array $options + * @return array + */ + protected function getFields(array $options) + { + if (isset($options['fields'])) { + return (array) $options['fields']; + } + + return []; + } + + /** + * Helper to merge options array passed to `__invoke` + * together with the options array created based on the above + * helper methods. + * + * @param array $previousOptions + * @param array $newOptions + * @return array + */ + protected function merge($previousOptions, $newOptions) + { + return ArrayUtils::merge($previousOptions, $newOptions, true); + } + + /** + * Helper method for ZF2 compatiblity. + * + * In ZF2 the plugin manager instance if passed to `createService` + * instead of the global service manager instance (as in ZF3). + * + * @param ContainerInterface $container + * @return ContainerInterface + */ + protected function container(ContainerInterface $container) + { + if ($container instanceof ServiceLocatorAwareInterface) { + $container = $container->getServiceLocator(); + } + + return $container; + } + + public function createService(ServiceLocatorInterface $serviceLocator) + { + return $this($serviceLocator, $this->validatorClass, $this->creationOptions); + } + + public function setCreationOptions(array $options) + { + $this->creationOptions = $options; + } +} diff --git a/src/DoctrineExpressiveModule/Validator/Service/Exception/ServiceCreationException.php b/src/DoctrineExpressiveModule/Validator/Service/Exception/ServiceCreationException.php new file mode 100644 index 0000000..62d76d6 --- /dev/null +++ b/src/DoctrineExpressiveModule/Validator/Service/Exception/ServiceCreationException.php @@ -0,0 +1,16 @@ + + */ +class ServiceCreationException extends BaseRuntimeException +{ +} diff --git a/src/DoctrineExpressiveModule/Validator/Service/NoObjectExistsFactory.php b/src/DoctrineExpressiveModule/Validator/Service/NoObjectExistsFactory.php new file mode 100644 index 0000000..84b9cae --- /dev/null +++ b/src/DoctrineExpressiveModule/Validator/Service/NoObjectExistsFactory.php @@ -0,0 +1,34 @@ + + */ +class NoObjectExistsFactory extends AbstractValidatorFactory +{ + protected $validatorClass = NoObjectExists::class; + + public function __invoke(ContainerInterface $container, $requestedName, array $options = null) + { + $container = $this->container($container); + + $repository = $this->getRepository($container, $options); + + $validator = new NoObjectExists($this->merge($options, [ + 'object_repository' => $repository, + 'fields' => $this->getFields($options), + ])); + + return $validator; + } +} diff --git a/src/DoctrineExpressiveModule/Validator/Service/ObjectExistsFactory.php b/src/DoctrineExpressiveModule/Validator/Service/ObjectExistsFactory.php new file mode 100644 index 0000000..53d7ac2 --- /dev/null +++ b/src/DoctrineExpressiveModule/Validator/Service/ObjectExistsFactory.php @@ -0,0 +1,34 @@ + + */ +class ObjectExistsFactory extends AbstractValidatorFactory +{ + protected $validatorClass = ObjectExists::class; + + public function __invoke(ContainerInterface $container, $requestedName, array $options = null) + { + $container = $this->container($container); + + $repository = $this->getRepository($container, $options); + + $validator = new ObjectExists($this->merge($options, [ + 'object_repository' => $repository, + 'fields' => $this->getFields($options), + ])); + + return $validator; + } +} diff --git a/src/DoctrineExpressiveModule/Validator/Service/UniqueObjectFactory.php b/src/DoctrineExpressiveModule/Validator/Service/UniqueObjectFactory.php new file mode 100644 index 0000000..c792c27 --- /dev/null +++ b/src/DoctrineExpressiveModule/Validator/Service/UniqueObjectFactory.php @@ -0,0 +1,28 @@ +container($container); + + $useContext = isset($options['use_context']) ? (boolean) $options['use_context'] : false; + + $validator = new UniqueObject($this->merge($options, [ + 'object_manager' => $this->getObjectManager($container, $options), + 'use_context' => $useContext, + 'object_repository' => $this->getRepository($container, $options), + 'fields' => $this->getFields($options), + ])); + + return $validator; + } +} diff --git a/src/DoctrineExpressiveModule/Validator/UniqueObject.php b/src/DoctrineExpressiveModule/Validator/UniqueObject.php new file mode 100644 index 0000000..a86e939 --- /dev/null +++ b/src/DoctrineExpressiveModule/Validator/UniqueObject.php @@ -0,0 +1,166 @@ + + */ +class UniqueObject extends ObjectExists +{ + /** + * Error constants + */ + const ERROR_OBJECT_NOT_UNIQUE = 'objectNotUnique'; + + /** + * @var array Message templates + */ + protected $messageTemplates = [ + self::ERROR_OBJECT_NOT_UNIQUE => "There is already another object matching '%value%'", + ]; + + /** + * @var ObjectManager + */ + protected $objectManager; + + /** + * @var boolean + */ + protected $useContext; + + /*** + * Constructor + * + * @param array $options required keys are `object_repository`, which must be an instance of + * Doctrine\Common\Persistence\ObjectRepository, `object_manager`, which + * must be an instance of Doctrine\Common\Persistence\ObjectManager, + * and `fields`, with either a string or an array of strings representing + * the fields to be matched by the validator. + * @throws Exception\InvalidArgumentException + */ + public function __construct(array $options) + { + parent::__construct($options); + + if (! isset($options['object_manager']) || ! $options['object_manager'] instanceof ObjectManager) { + if (! array_key_exists('object_manager', $options)) { + $provided = 'nothing'; + } else { + if (is_object($options['object_manager'])) { + $provided = get_class($options['object_manager']); + } else { + $provided = getType($options['object_manager']); + } + } + + throw new Exception\InvalidArgumentException( + sprintf( + 'Option "object_manager" is required and must be an instance of' + . ' Doctrine\Common\Persistence\ObjectManager, %s given', + $provided + ) + ); + } + + $this->objectManager = $options['object_manager']; + $this->useContext = isset($options['use_context']) ? (boolean) $options['use_context'] : false; + } + + /** + * Returns false if there is another object with the same field values but other identifiers. + * + * @param mixed $value + * @param array $context + * @return boolean + */ + public function isValid($value, $context = null) + { + if (! $this->useContext) { + $context = (array) $value; + } + + $cleanedValue = $this->cleanSearchValue($value); + $match = $this->objectRepository->findOneBy($cleanedValue); + + if (! is_object($match)) { + return true; + } + + $expectedIdentifiers = $this->getExpectedIdentifiers($context); + $foundIdentifiers = $this->getFoundIdentifiers($match); + + if (count(array_diff_assoc($expectedIdentifiers, $foundIdentifiers)) == 0) { + return true; + } + + $this->error(self::ERROR_OBJECT_NOT_UNIQUE, $value); + return false; + } + + /** + * Gets the identifiers from the matched object. + * + * @param object $match + * @return array + * @throws Exception\RuntimeException + */ + protected function getFoundIdentifiers($match) + { + return $this->objectManager + ->getClassMetadata($this->objectRepository->getClassName()) + ->getIdentifierValues($match); + } + + /** + * Gets the identifiers from the context. + * + * @param array|object $context + * @return array + * @throws Exception\RuntimeException + */ + protected function getExpectedIdentifiers($context = null) + { + if ($context === null) { + throw new Exception\RuntimeException( + 'Expected context to be an array but is null' + ); + } + + $className = $this->objectRepository->getClassName(); + + if ($context instanceof $className) { + return $this->objectManager + ->getClassMetadata($this->objectRepository->getClassName()) + ->getIdentifierValues($context); + } + + $result = []; + foreach ($this->getIdentifiers() as $identifierField) { + if (! array_key_exists($identifierField, $context)) { + throw new Exception\RuntimeException(\sprintf('Expected context to contain %s', $identifierField)); + } + + $result[$identifierField] = $context[$identifierField]; + } + return $result; + } + + + /** + * @return array the names of the identifiers + */ + protected function getIdentifiers() + { + return $this->objectManager + ->getClassMetadata($this->objectRepository->getClassName()) + ->getIdentifierFieldNames(); + } +} diff --git a/test/AppTest/Handler/HomePageHandlerFactoryTest.php b/test/AppTest/Handler/HomePageHandlerFactoryTest.php new file mode 100644 index 0000000..df7f4ef --- /dev/null +++ b/test/AppTest/Handler/HomePageHandlerFactoryTest.php @@ -0,0 +1,52 @@ +container = $this->prophesize(ContainerInterface::class); + $router = $this->prophesize(RouterInterface::class); + + $this->container->get(RouterInterface::class)->willReturn($router); + } + + public function testFactoryWithoutTemplate() + { + $factory = new HomePageHandlerFactory(); + $this->container->has(TemplateRendererInterface::class)->willReturn(false); + + $this->assertInstanceOf(HomePageHandlerFactory::class, $factory); + + $homePage = $factory($this->container->reveal(), null, get_class($this->container->reveal())); + + $this->assertInstanceOf(HomePageHandler::class, $homePage); + } + + public function testFactoryWithTemplate() + { + $this->container->has(TemplateRendererInterface::class)->willReturn(true); + $this->container + ->get(TemplateRendererInterface::class) + ->willReturn($this->prophesize(TemplateRendererInterface::class)); + + $factory = new HomePageHandlerFactory(); + + $homePage = $factory($this->container->reveal(), null, get_class($this->container->reveal())); + + $this->assertInstanceOf(HomePageHandler::class, $homePage); + } +} diff --git a/test/AppTest/Handler/HomePageHandlerTest.php b/test/AppTest/Handler/HomePageHandlerTest.php new file mode 100644 index 0000000..82e9238 --- /dev/null +++ b/test/AppTest/Handler/HomePageHandlerTest.php @@ -0,0 +1,64 @@ +container = $this->prophesize(ContainerInterface::class); + $this->router = $this->prophesize(RouterInterface::class); + } + + public function testReturnsJsonResponseWhenNoTemplateRendererProvided() + { + $homePage = new HomePageHandler( + $this->router->reveal(), + null, + get_class($this->container->reveal()) + ); + $response = $homePage->handle( + $this->prophesize(ServerRequestInterface::class)->reveal() + ); + + $this->assertInstanceOf(JsonResponse::class, $response); + } + + public function testReturnsHtmlResponseWhenTemplateRendererProvided() + { + $renderer = $this->prophesize(TemplateRendererInterface::class); + $renderer + ->render('app::home-page', Argument::type('array')) + ->willReturn(''); + + $homePage = new HomePageHandler( + $this->router->reveal(), + $renderer->reveal(), + get_class($this->container->reveal()) + ); + + $response = $homePage->handle( + $this->prophesize(ServerRequestInterface::class)->reveal() + ); + + $this->assertInstanceOf(HtmlResponse::class, $response); + } +} diff --git a/test/AppTest/Handler/PingHandlerTest.php b/test/AppTest/Handler/PingHandlerTest.php new file mode 100644 index 0000000..143f68f --- /dev/null +++ b/test/AppTest/Handler/PingHandlerTest.php @@ -0,0 +1,26 @@ +handle( + $this->prophesize(ServerRequestInterface::class)->reveal() + ); + + $json = json_decode((string) $response->getBody()); + + $this->assertInstanceOf(JsonResponse::class, $response); + $this->assertTrue(isset($json->ack)); + } +}