diff --git a/.env b/.env new file mode 100644 index 0000000..0a1c125 --- /dev/null +++ b/.env @@ -0,0 +1,2 @@ +COMPOSE_PROJECT_NAME=openskosapi +COMPOSE_FILE=docker/docker-compose.yml \ No newline at end of file diff --git a/.gitignore b/.gitignore index 3734df6..96af672 100644 --- a/.gitignore +++ b/.gitignore @@ -1,20 +1,15 @@ -rsync.sh -application/configs/application.ini -.idea -cache/ -.sass-cache/ -public/data/export/* -/data/uploads/ -/data/solr/ -/public/data/icons/ +###> symfony/framework-bundle ### +/.env.local +/.env.local.php +/.env.*.local +/public/bundles/ +/var/ /vendor/ -/nbproject/ -/node_modules/ -/public/apidoc/ -/apidoc/ -/public/oaidoc/ -/application/configs/application.ini_backup.dist -/application/configs/application_corrupted.ini -/application/configs/application_backup.ini -/application/configs/custom.ini -/data/solr/data/ +api-docs.json +###< symfony/framework-bundle ### + +.DS_Store +.idea +###> friendsofphp/php-cs-fixer ### +/.php_cs.cache +###< friendsofphp/php-cs-fixer ### diff --git a/.php_cs b/.php_cs new file mode 100644 index 0000000..2418670 --- /dev/null +++ b/.php_cs @@ -0,0 +1,16 @@ +exclude(['var', 'vendor']) + ->in(__DIR__) +; + +return PhpCsFixer\Config::create() + ->setRules([ + '@PSR2' => true, + 'strict_param' => true, + 'array_syntax' => ['syntax' => 'short'], + '@Symfony' => true, + ]) + ->setFinder($finder) +; \ No newline at end of file diff --git a/README.md b/README.md index a5a5b45..a833d36 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,36 @@ # OpenSkos-API Restful API for OpenSkos + +## Development + +### Installation: + +* `composer install` +* `vendor/bin/grumphp git:init` -- grump will make sure that you have no mistakes before commit ;) + +### Tests + +Test are written using [PHPSpec](https://www.phpspec.net/en/stable/manual/introduction.html) +Run tests by: `vendor/bin/phpspec run` + +### Static analyser + +To have code strictly typed with nullability checks and etc. [Psalm](https://psalm.dev/) will help. +Run psalm by: `vendor/bin/psalm` + +### Development procedure: +* Pull latest master +* Create feature/bug branch `feature/code-and-short-title` +* Commit all needed changes +* Write documentation if needed under `doc/feature-name.md` +* Make sure you're code is covered by tests at least critical parts +* Submit PR to github. +* Wait for Approvals from dev-team and get ready for changes during PR discussion +* ...? +* Profit! + +## Swagger / OpenAPI documentation +Run `composer run docs` to generate api-docs.json file to use in Swagger UI + +## Docker +TODO diff --git a/bin/console b/bin/console new file mode 100755 index 0000000..19c2f6c --- /dev/null +++ b/bin/console @@ -0,0 +1,42 @@ +#!/usr/bin/env php +getParameterOption(['--env', '-e'], null, true)) { + putenv('APP_ENV='.$_SERVER['APP_ENV'] = $_ENV['APP_ENV'] = $env); +} + +if ($input->hasParameterOption('--no-debug', true)) { + putenv('APP_DEBUG='.$_SERVER['APP_DEBUG'] = $_ENV['APP_DEBUG'] = '0'); +} + +require dirname(__DIR__).'/config/bootstrap.php'; + +if ($_SERVER['APP_DEBUG']) { + umask(0000); + + if (class_exists(Debug::class)) { + Debug::enable(); + } +} + +$kernel = new Kernel($_SERVER['APP_ENV'], (bool) $_SERVER['APP_DEBUG']); +$application = new Application($kernel); +$application->run($input); diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..0095fa5 --- /dev/null +++ b/composer.json @@ -0,0 +1,74 @@ +{ + "type": "project", + "license": "proprietary", + "require": { + "php": "^7.3", + "ext-ctype": "*", + "ext-iconv": "*", + "easyrdf/easyrdf": "^0.9.1", + "ml/json-ld": "^1.1", + "sensio/framework-extra-bundle": "^5.3", + "symfony/console": "4.2.*", + "symfony/dotenv": "4.2.*", + "symfony/flex": "^1.1", + "symfony/framework-bundle": "4.2.*", + "symfony/property-access": "4.2.*", + "symfony/serializer": "4.2.*", + "symfony/yaml": "4.2.*", + "zircote/swagger-php": "^3.0" + }, + "config": { + "preferred-install": { + "*": "dist" + }, + "sort-packages": true + }, + "autoload": { + "psr-4": { + "App\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "App\\Tests\\": "tests/" + } + }, + "replace": { + "paragonie/random_compat": "2.*", + "symfony/polyfill-ctype": "*", + "symfony/polyfill-iconv": "*", + "symfony/polyfill-php71": "*", + "symfony/polyfill-php70": "*", + "symfony/polyfill-php56": "*" + }, + "scripts": { + "docs": "./vendor/bin/openapi --output api-docs.json --bootstrap ./src/Swagger.php src", + "auto-scripts": { + "cache:clear": "symfony-cmd", + "assets:install %PUBLIC_DIR%": "symfony-cmd" + }, + "post-install-cmd": [ + "@auto-scripts" + ], + "post-update-cmd": [ + "@auto-scripts" + ] + }, + "conflict": { + "symfony/symfony": "*" + }, + "extra": { + "symfony": { + "allow-contrib": false, + "require": "4.2.*" + } + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^2.15", + "phpro/grumphp": "^0.15.0", + "phpspec/phpspec": "^5.1", + "phpstan/phpstan": "^0.11.6", + "symfony/profiler-pack": "^1.0", + "vimeo/psalm": "^3.2" + } +} diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000..4d4c91c --- /dev/null +++ b/composer.lock @@ -0,0 +1,5842 @@ +{ + "_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": "19e1abc13f41f8f6478814959831e61c", + "packages": [ + { + "name": "doctrine/annotations", + "version": "v1.6.1", + "source": { + "type": "git", + "url": "https://github.com/doctrine/annotations.git", + "reference": "53120e0eb10355388d6ccbe462f1fea34ddadb24" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/annotations/zipball/53120e0eb10355388d6ccbe462f1fea34ddadb24", + "reference": "53120e0eb10355388d6ccbe462f1fea34ddadb24", + "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": "2019-03-25T19:12:02+00:00" + }, + { + "name": "doctrine/cache", + "version": "v1.8.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/cache.git", + "reference": "d768d58baee9a4862ca783840eca1b9add7a7f57" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/cache/zipball/d768d58baee9a4862ca783840eca1b9add7a7f57", + "reference": "d768d58baee9a4862ca783840eca1b9add7a7f57", + "shasum": "" + }, + "require": { + "php": "~7.1" + }, + "conflict": { + "doctrine/common": ">2.2,<2.4" + }, + "require-dev": { + "alcaeus/mongo-php-adapter": "^1.1", + "doctrine/coding-standard": "^4.0", + "mongodb/mongodb": "^1.1", + "phpunit/phpunit": "^7.0", + "predis/predis": "~1.0" + }, + "suggest": { + "alcaeus/mongo-php-adapter": "Required to use legacy MongoDB driver" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.8.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": "https://www.doctrine-project.org", + "keywords": [ + "cache", + "caching" + ], + "time": "2018-08-21T18:01:43+00:00" + }, + { + "name": "doctrine/collections", + "version": "v1.6.2", + "source": { + "type": "git", + "url": "https://github.com/doctrine/collections.git", + "reference": "c5e0bc17b1620e97c968ac409acbff28b8b850be" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/collections/zipball/c5e0bc17b1620e97c968ac409acbff28b8b850be", + "reference": "c5e0bc17b1620e97c968ac409acbff28b8b850be", + "shasum": "" + }, + "require": { + "php": "^7.1.3" + }, + "require-dev": { + "doctrine/coding-standard": "^6.0", + "phpstan/phpstan-shim": "^0.9.2", + "phpunit/phpunit": "^7.0", + "vimeo/psalm": "^3.2.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.6.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\Collections\\": "lib/Doctrine/Common/Collections" + } + }, + "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": "PHP Doctrine Collections library that adds additional functionality on top of PHP arrays.", + "homepage": "https://www.doctrine-project.org/projects/collections.html", + "keywords": [ + "array", + "collections", + "iterators", + "php" + ], + "time": "2019-06-09T13:48:14+00:00" + }, + { + "name": "doctrine/event-manager", + "version": "v1.0.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/event-manager.git", + "reference": "a520bc093a0170feeb6b14e9d83f3a14452e64b3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/event-manager/zipball/a520bc093a0170feeb6b14e9d83f3a14452e64b3", + "reference": "a520bc093a0170feeb6b14e9d83f3a14452e64b3", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "conflict": { + "doctrine/common": "<2.9@dev" + }, + "require-dev": { + "doctrine/coding-standard": "^4.0", + "phpunit/phpunit": "^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.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" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "Doctrine Event Manager component", + "homepage": "https://www.doctrine-project.org/projects/event-manager.html", + "keywords": [ + "event", + "eventdispatcher", + "eventmanager" + ], + "time": "2018-06-11T11:59:03+00:00" + }, + { + "name": "doctrine/lexer", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/doctrine/lexer.git", + "reference": "1febd6c3ef84253d7c815bed85fc622ad207a9f8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/1febd6c3ef84253d7c815bed85fc622ad207a9f8", + "reference": "1febd6c3ef84253d7c815bed85fc622ad207a9f8", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "require-dev": { + "phpunit/phpunit": "^4.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\Lexer\\": "lib/Doctrine/Common/Lexer" + } + }, + "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": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", + "homepage": "https://www.doctrine-project.org/projects/lexer.html", + "keywords": [ + "annotations", + "docblock", + "lexer", + "parser", + "php" + ], + "time": "2019-06-08T11:03:04+00:00" + }, + { + "name": "doctrine/persistence", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/doctrine/persistence.git", + "reference": "3da7c9d125591ca83944f477e65ed3d7b4617c48" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/persistence/zipball/3da7c9d125591ca83944f477e65ed3d7b4617c48", + "reference": "3da7c9d125591ca83944f477e65ed3d7b4617c48", + "shasum": "" + }, + "require": { + "doctrine/annotations": "^1.0", + "doctrine/cache": "^1.0", + "doctrine/collections": "^1.0", + "doctrine/event-manager": "^1.0", + "doctrine/reflection": "^1.0", + "php": "^7.1" + }, + "conflict": { + "doctrine/common": "<2.10@dev" + }, + "require-dev": { + "doctrine/coding-standard": "^5.0", + "phpstan/phpstan": "^0.8", + "phpunit/phpunit": "^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1.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" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "The Doctrine Persistence project is a set of shared interfaces and functionality that the different Doctrine object mappers share.", + "homepage": "https://doctrine-project.org/projects/persistence.html", + "keywords": [ + "mapper", + "object", + "odm", + "orm", + "persistence" + ], + "time": "2019-04-23T08:28:24+00:00" + }, + { + "name": "doctrine/reflection", + "version": "v1.0.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/reflection.git", + "reference": "02538d3f95e88eb397a5f86274deb2c6175c2ab6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/reflection/zipball/02538d3f95e88eb397a5f86274deb2c6175c2ab6", + "reference": "02538d3f95e88eb397a5f86274deb2c6175c2ab6", + "shasum": "" + }, + "require": { + "doctrine/annotations": "^1.0", + "ext-tokenizer": "*", + "php": "^7.1" + }, + "require-dev": { + "doctrine/coding-standard": "^4.0", + "doctrine/common": "^2.8", + "phpstan/phpstan": "^0.9.2", + "phpstan/phpstan-phpunit": "^0.9.4", + "phpunit/phpunit": "^7.0", + "squizlabs/php_codesniffer": "^3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.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" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "Doctrine Reflection component", + "homepage": "https://www.doctrine-project.org/projects/reflection.html", + "keywords": [ + "reflection" + ], + "time": "2018-06-14T14:45:07+00:00" + }, + { + "name": "easyrdf/easyrdf", + "version": "0.9.1", + "source": { + "type": "git", + "url": "https://github.com/njh/easyrdf.git", + "reference": "acd09dfe0555fbcfa254291e433c45fdd4652566" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/njh/easyrdf/zipball/acd09dfe0555fbcfa254291e433c45fdd4652566", + "reference": "acd09dfe0555fbcfa254291e433c45fdd4652566", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "ext-pcre": "*", + "php": ">=5.2.8" + }, + "require-dev": { + "phpunit/phpunit": "~3.5", + "sami/sami": "~1.4", + "squizlabs/php_codesniffer": "~1.4.3" + }, + "suggest": { + "ml/json-ld": "~1.0" + }, + "type": "library", + "autoload": { + "psr-0": { + "EasyRdf_": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nicholas Humfrey", + "email": "njh@aelius.com", + "homepage": "http://www.aelius.com/njh/", + "role": "Developer" + }, + { + "name": "Alexey Zakhlestin", + "email": "indeyets@gmail.com", + "role": "Developer" + } + ], + "description": "EasyRdf is a PHP library designed to make it easy to consume and produce RDF.", + "homepage": "http://www.easyrdf.org/", + "keywords": [ + "Linked Data", + "RDF", + "Semantic Web", + "Turtle", + "rdfa", + "sparql" + ], + "time": "2015-02-27T09:45:49+00:00" + }, + { + "name": "ml/iri", + "version": "1.1.4", + "target-dir": "ML/IRI", + "source": { + "type": "git", + "url": "https://github.com/lanthaler/IRI.git", + "reference": "cbd44fa913e00ea624241b38cefaa99da8d71341" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/lanthaler/IRI/zipball/cbd44fa913e00ea624241b38cefaa99da8d71341", + "reference": "cbd44fa913e00ea624241b38cefaa99da8d71341", + "shasum": "" + }, + "require": { + "lib-pcre": ">=4.0", + "php": ">=5.3.0" + }, + "type": "library", + "autoload": { + "psr-0": { + "ML\\IRI": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Markus Lanthaler", + "email": "mail@markus-lanthaler.com", + "homepage": "http://www.markus-lanthaler.com", + "role": "Developer" + } + ], + "description": "IRI handling for PHP", + "homepage": "http://www.markus-lanthaler.com", + "keywords": [ + "URN", + "iri", + "uri", + "url" + ], + "time": "2014-01-21T13:43:39+00:00" + }, + { + "name": "ml/json-ld", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/lanthaler/JsonLD.git", + "reference": "b5f82820c255cb64067b1c7adbb819cad4afa70a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/lanthaler/JsonLD/zipball/b5f82820c255cb64067b1c7adbb819cad4afa70a", + "reference": "b5f82820c255cb64067b1c7adbb819cad4afa70a", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ml/iri": "^1.1.1", + "php": ">=5.3.0" + }, + "require-dev": { + "json-ld/tests": "1.0", + "phpunit/phpunit": "^4" + }, + "type": "library", + "autoload": { + "psr-4": { + "ML\\JsonLD\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Markus Lanthaler", + "email": "mail@markus-lanthaler.com", + "homepage": "http://www.markus-lanthaler.com", + "role": "Developer" + } + ], + "description": "JSON-LD Processor for PHP", + "homepage": "http://www.markus-lanthaler.com", + "keywords": [ + "JSON-LD", + "jsonld" + ], + "time": "2018-11-18T20:26:18+00:00" + }, + { + "name": "psr/cache", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/cache.git", + "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/cache/zipball/d11b50ad223250cf17b86e38383413f5a6764bf8", + "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Cache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for caching libraries", + "keywords": [ + "cache", + "psr", + "psr-6" + ], + "time": "2016-08-06T20:24:11+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/log", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd", + "reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd", + "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": "2018-11-20T15:27:04+00:00" + }, + { + "name": "psr/simple-cache", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/simple-cache.git", + "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", + "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\SimpleCache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interfaces for simple caching", + "keywords": [ + "cache", + "caching", + "psr", + "psr-16", + "simple-cache" + ], + "time": "2017-10-23T01:57:42+00:00" + }, + { + "name": "sensio/framework-extra-bundle", + "version": "v5.3.1", + "source": { + "type": "git", + "url": "https://github.com/sensiolabs/SensioFrameworkExtraBundle.git", + "reference": "5f75c4658b03301cba17baa15a840b57b72b4262" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sensiolabs/SensioFrameworkExtraBundle/zipball/5f75c4658b03301cba17baa15a840b57b72b4262", + "reference": "5f75c4658b03301cba17baa15a840b57b72b4262", + "shasum": "" + }, + "require": { + "doctrine/annotations": "^1.0", + "doctrine/persistence": "^1.0", + "php": ">=7.1.3", + "symfony/config": "^3.4|^4.2", + "symfony/dependency-injection": "^3.4|^4.2", + "symfony/framework-bundle": "^3.4|^4.2", + "symfony/http-kernel": "^3.4|^4.2" + }, + "require-dev": { + "doctrine/doctrine-bundle": "^1.6", + "doctrine/orm": "^2.5", + "nyholm/psr7": "^1.1", + "symfony/browser-kit": "^3.4|^4.2", + "symfony/dom-crawler": "^3.4|^4.2", + "symfony/expression-language": "^3.4|^4.2", + "symfony/finder": "^3.4|^4.2", + "symfony/monolog-bridge": "^3.0|^4.0", + "symfony/monolog-bundle": "^3.2", + "symfony/phpunit-bridge": "^3.4.19|^4.1.8", + "symfony/psr-http-message-bridge": "^1.1", + "symfony/security-bundle": "^3.4|^4.2", + "symfony/twig-bundle": "^3.4|^4.2", + "symfony/yaml": "^3.4|^4.2", + "twig/twig": "~1.12|~2.0" + }, + "suggest": { + "symfony/expression-language": "", + "symfony/psr-http-message-bridge": "To use the PSR-7 converters", + "symfony/security-bundle": "" + }, + "type": "symfony-bundle", + "extra": { + "branch-alias": { + "dev-master": "5.3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Sensio\\Bundle\\FrameworkExtraBundle\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "This bundle provides a way to configure your controllers with annotations", + "keywords": [ + "annotations", + "controllers" + ], + "time": "2019-04-10T06:00:20+00:00" + }, + { + "name": "symfony/cache", + "version": "v4.2.9", + "source": { + "type": "git", + "url": "https://github.com/symfony/cache.git", + "reference": "bc64c1908e609969ce510763e0bd42797e79656d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/cache/zipball/bc64c1908e609969ce510763e0bd42797e79656d", + "reference": "bc64c1908e609969ce510763e0bd42797e79656d", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "psr/cache": "~1.0", + "psr/log": "~1.0", + "psr/simple-cache": "^1.0", + "symfony/contracts": "^1.0", + "symfony/var-exporter": "^4.2" + }, + "conflict": { + "doctrine/dbal": "<2.5", + "symfony/dependency-injection": "<3.4", + "symfony/var-dumper": "<3.4" + }, + "provide": { + "psr/cache-implementation": "1.0", + "psr/simple-cache-implementation": "1.0", + "symfony/cache-implementation": "1.0" + }, + "require-dev": { + "cache/integration-tests": "dev-master", + "doctrine/cache": "~1.6", + "doctrine/dbal": "~2.5", + "predis/predis": "~1.1", + "symfony/config": "~4.2", + "symfony/dependency-injection": "~3.4|~4.1", + "symfony/var-dumper": "^4.1.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Cache\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "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 Cache component with PSR-6, PSR-16, and tags", + "homepage": "https://symfony.com", + "keywords": [ + "caching", + "psr6" + ], + "time": "2019-05-11T18:09:18+00:00" + }, + { + "name": "symfony/config", + "version": "v4.2.9", + "source": { + "type": "git", + "url": "https://github.com/symfony/config.git", + "reference": "6bec7694d45aff68dec7b67dde3001f68dfaac64" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/config/zipball/6bec7694d45aff68dec7b67dde3001f68dfaac64", + "reference": "6bec7694d45aff68dec7b67dde3001f68dfaac64", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/filesystem": "~3.4|~4.0", + "symfony/polyfill-ctype": "~1.8" + }, + "conflict": { + "symfony/finder": "<3.4" + }, + "require-dev": { + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/event-dispatcher": "~3.4|~4.0", + "symfony/finder": "~3.4|~4.0", + "symfony/messenger": "~4.1", + "symfony/yaml": "~3.4|~4.0" + }, + "suggest": { + "symfony/yaml": "To use the yaml reference dumper" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Config\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Config Component", + "homepage": "https://symfony.com", + "time": "2019-05-09T16:56:19+00:00" + }, + { + "name": "symfony/console", + "version": "v4.2.9", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "7a293c9a4587a92e6a0e81edb0bea54071b1b99d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/7a293c9a4587a92e6a0e81edb0bea54071b1b99d", + "reference": "7a293c9a4587a92e6a0e81edb0bea54071b1b99d", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/contracts": "^1.0", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/dependency-injection": "<3.4", + "symfony/process": "<3.3" + }, + "provide": { + "psr/log-implementation": "1.0" + }, + "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.2-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": "2019-05-09T09:19:46+00:00" + }, + { + "name": "symfony/contracts", + "version": "v1.1.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/contracts.git", + "reference": "3f3f796d5f24a098a9da62828b8daa1b11494c1b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/contracts/zipball/3f3f796d5f24a098a9da62828b8daa1b11494c1b", + "reference": "3f3f796d5f24a098a9da62828b8daa1b11494c1b", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "psr/cache": "^1.0", + "psr/container": "^1.0" + }, + "replace": { + "symfony/cache-contracts": "self.version", + "symfony/event-dispatcher-contracts": "self.version", + "symfony/http-client-contracts": "self.version", + "symfony/service-contracts": "self.version", + "symfony/translation-contracts": "self.version" + }, + "require-dev": { + "symfony/polyfill-intl-idn": "^1.10" + }, + "suggest": { + "psr/event-dispatcher": "When using the EventDispatcher contracts", + "symfony/cache-implementation": "", + "symfony/event-dispatcher-implementation": "", + "symfony/http-client-implementation": "", + "symfony/service-implementation": "", + "symfony/translation-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\": "" + }, + "exclude-from-classmap": [ + "**/Tests/" + ] + }, + "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": "A set of abstractions extracted out of the Symfony components", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "time": "2019-06-20T06:46:26+00:00" + }, + { + "name": "symfony/debug", + "version": "v4.2.9", + "source": { + "type": "git", + "url": "https://github.com/symfony/debug.git", + "reference": "22b4d033e6bb6d94a928545a3456007b8d0da907" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/debug/zipball/22b4d033e6bb6d94a928545a3456007b8d0da907", + "reference": "22b4d033e6bb6d94a928545a3456007b8d0da907", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "psr/log": "~1.0" + }, + "conflict": { + "symfony/http-kernel": "<3.4" + }, + "require-dev": { + "symfony/http-kernel": "~3.4|~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Debug\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Debug Component", + "homepage": "https://symfony.com", + "time": "2019-05-20T16:15:26+00:00" + }, + { + "name": "symfony/dependency-injection", + "version": "v4.2.9", + "source": { + "type": "git", + "url": "https://github.com/symfony/dependency-injection.git", + "reference": "10edf0b791c5944486fb032115a141618e63ca67" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/10edf0b791c5944486fb032115a141618e63ca67", + "reference": "10edf0b791c5944486fb032115a141618e63ca67", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "psr/container": "^1.0", + "symfony/contracts": "^1.1.1" + }, + "conflict": { + "symfony/config": "<4.2", + "symfony/finder": "<3.4", + "symfony/proxy-manager-bridge": "<3.4", + "symfony/yaml": "<3.4" + }, + "provide": { + "psr/container-implementation": "1.0", + "symfony/service-implementation": "1.0" + }, + "require-dev": { + "symfony/config": "~4.2", + "symfony/expression-language": "~3.4|~4.0", + "symfony/yaml": "~3.4|~4.0" + }, + "suggest": { + "symfony/config": "", + "symfony/expression-language": "For using expressions in service container configuration", + "symfony/finder": "For using double-star glob patterns or when GLOB_BRACE portability is required", + "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them", + "symfony/yaml": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\DependencyInjection\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony DependencyInjection Component", + "homepage": "https://symfony.com", + "time": "2019-05-28T09:07:12+00:00" + }, + { + "name": "symfony/dotenv", + "version": "v4.2.9", + "source": { + "type": "git", + "url": "https://github.com/symfony/dotenv.git", + "reference": "b541d63b83532be55a020db8ed2e50598385a583" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/dotenv/zipball/b541d63b83532be55a020db8ed2e50598385a583", + "reference": "b541d63b83532be55a020db8ed2e50598385a583", + "shasum": "" + }, + "require": { + "php": "^7.1.3" + }, + "require-dev": { + "symfony/process": "~3.4|~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Dotenv\\": "" + }, + "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": "Registers environment variables from a .env file", + "homepage": "https://symfony.com", + "keywords": [ + "dotenv", + "env", + "environment" + ], + "time": "2019-04-01T07:32:59+00:00" + }, + { + "name": "symfony/event-dispatcher", + "version": "v4.2.9", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "fbce53cd74ac509cbe74b6f227622650ab759b02" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/fbce53cd74ac509cbe74b6f227622650ab759b02", + "reference": "fbce53cd74ac509cbe74b6f227622650ab759b02", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/contracts": "^1.0" + }, + "conflict": { + "symfony/dependency-injection": "<3.4" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "~3.4|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/expression-language": "~3.4|~4.0", + "symfony/stopwatch": "~3.4|~4.0" + }, + "suggest": { + "symfony/dependency-injection": "", + "symfony/http-kernel": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\EventDispatcher\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony EventDispatcher Component", + "homepage": "https://symfony.com", + "time": "2019-04-06T13:51:08+00:00" + }, + { + "name": "symfony/filesystem", + "version": "v4.2.9", + "source": { + "type": "git", + "url": "https://github.com/symfony/filesystem.git", + "reference": "e16b9e471703b2c60b95f14d31c1239f68f11601" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/e16b9e471703b2c60b95f14d31c1239f68f11601", + "reference": "e16b9e471703b2c60b95f14d31c1239f68f11601", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/polyfill-ctype": "~1.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Filesystem\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Filesystem Component", + "homepage": "https://symfony.com", + "time": "2019-02-07T11:40:08+00:00" + }, + { + "name": "symfony/finder", + "version": "v4.2.9", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "e0ff582c4b038567a7c6630f136488b1d793e6a9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/e0ff582c4b038567a7c6630f136488b1d793e6a9", + "reference": "e0ff582c4b038567a7c6630f136488b1d793e6a9", + "shasum": "" + }, + "require": { + "php": "^7.1.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Finder Component", + "homepage": "https://symfony.com", + "time": "2019-05-26T20:47:34+00:00" + }, + { + "name": "symfony/flex", + "version": "v1.2.7", + "source": { + "type": "git", + "url": "https://github.com/symfony/flex.git", + "reference": "8618b243d44bac71e4006062f245d807d84f7a6c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/flex/zipball/8618b243d44bac71e4006062f245d807d84f7a6c", + "reference": "8618b243d44bac71e4006062f245d807d84f7a6c", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.0", + "php": "^7.0" + }, + "require-dev": { + "composer/composer": "^1.0.2", + "symfony/dotenv": "^3.4|^4.0", + "symfony/phpunit-bridge": "^3.4.19|^4.1.8", + "symfony/process": "^2.7|^3.0|^4.0" + }, + "type": "composer-plugin", + "extra": { + "branch-alias": { + "dev-master": "1.2-dev" + }, + "class": "Symfony\\Flex\\Flex" + }, + "autoload": { + "psr-4": { + "Symfony\\Flex\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien.potencier@gmail.com" + } + ], + "description": "Composer plugin for Symfony", + "time": "2019-06-15T07:15:42+00:00" + }, + { + "name": "symfony/framework-bundle", + "version": "v4.2.9", + "source": { + "type": "git", + "url": "https://github.com/symfony/framework-bundle.git", + "reference": "6b51be8f4a8f7966efd54c212662db1bb6cb656a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/6b51be8f4a8f7966efd54c212662db1bb6cb656a", + "reference": "6b51be8f4a8f7966efd54c212662db1bb6cb656a", + "shasum": "" + }, + "require": { + "ext-xml": "*", + "php": "^7.1.3", + "symfony/cache": "~4.2", + "symfony/config": "~4.2", + "symfony/contracts": "^1.0.2", + "symfony/dependency-injection": "^4.2.5", + "symfony/event-dispatcher": "^4.1", + "symfony/filesystem": "~3.4|~4.0", + "symfony/finder": "~3.4|~4.0", + "symfony/http-foundation": "^4.2.5", + "symfony/http-kernel": "^4.2", + "symfony/polyfill-mbstring": "~1.0", + "symfony/routing": "^4.2.8" + }, + "conflict": { + "phpdocumentor/reflection-docblock": "<3.0", + "phpdocumentor/type-resolver": "<0.2.1", + "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0", + "symfony/asset": "<3.4", + "symfony/console": "<3.4", + "symfony/dotenv": "<4.2", + "symfony/form": "<4.2", + "symfony/messenger": "<4.2", + "symfony/property-info": "<3.4", + "symfony/serializer": "<4.2", + "symfony/stopwatch": "<3.4", + "symfony/translation": "<4.2", + "symfony/twig-bridge": "<4.1.1", + "symfony/validator": "<4.1", + "symfony/workflow": "<4.1" + }, + "require-dev": { + "doctrine/annotations": "~1.0", + "doctrine/cache": "~1.0", + "fig/link-util": "^1.0", + "phpdocumentor/reflection-docblock": "^3.0|^4.0", + "symfony/asset": "~3.4|~4.0", + "symfony/browser-kit": "~3.4|~4.0", + "symfony/console": "~3.4|~4.0", + "symfony/css-selector": "~3.4|~4.0", + "symfony/dom-crawler": "~3.4|~4.0", + "symfony/expression-language": "~3.4|~4.0", + "symfony/form": "^4.2.3", + "symfony/lock": "~3.4|~4.0", + "symfony/messenger": "^4.2", + "symfony/polyfill-intl-icu": "~1.0", + "symfony/process": "~3.4|~4.0", + "symfony/property-info": "~3.4|~4.0", + "symfony/security": "~3.4|~4.0", + "symfony/security-core": "~3.4|~4.0", + "symfony/security-csrf": "~3.4|~4.0", + "symfony/serializer": "^4.2", + "symfony/stopwatch": "~3.4|~4.0", + "symfony/templating": "~3.4|~4.0", + "symfony/translation": "~4.2", + "symfony/validator": "^4.1", + "symfony/var-dumper": "~3.4|~4.0", + "symfony/web-link": "~3.4|~4.0", + "symfony/workflow": "^4.1", + "symfony/yaml": "~3.4|~4.0", + "twig/twig": "~1.34|~2.4" + }, + "suggest": { + "ext-apcu": "For best performance of the system caches", + "symfony/console": "For using the console commands", + "symfony/form": "For using forms", + "symfony/property-info": "For using the property_info service", + "symfony/serializer": "For using the serializer service", + "symfony/validator": "For using validation", + "symfony/web-link": "For using web links, features such as preloading, prefetching or prerendering", + "symfony/yaml": "For using the debug:config and lint:yaml commands" + }, + "type": "symfony-bundle", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Bundle\\FrameworkBundle\\": "" + }, + "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 FrameworkBundle", + "homepage": "https://symfony.com", + "time": "2019-05-22T18:38:35+00:00" + }, + { + "name": "symfony/http-foundation", + "version": "v4.2.9", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-foundation.git", + "reference": "0d37a9bd2c7cbf887c29fee1a3301d74c73851dd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/0d37a9bd2c7cbf887c29fee1a3301d74c73851dd", + "reference": "0d37a9bd2c7cbf887c29fee1a3301d74c73851dd", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/polyfill-mbstring": "~1.1" + }, + "require-dev": { + "predis/predis": "~1.0", + "symfony/expression-language": "~3.4|~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpFoundation\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony HttpFoundation Component", + "homepage": "https://symfony.com", + "time": "2019-05-27T05:57:45+00:00" + }, + { + "name": "symfony/http-kernel", + "version": "v4.2.9", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-kernel.git", + "reference": "ca9c1fe747f9704afd5e3c9097b80db0e31d158f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/ca9c1fe747f9704afd5e3c9097b80db0e31d158f", + "reference": "ca9c1fe747f9704afd5e3c9097b80db0e31d158f", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "psr/log": "~1.0", + "symfony/contracts": "^1.0.2", + "symfony/debug": "~3.4|~4.0", + "symfony/event-dispatcher": "~4.1", + "symfony/http-foundation": "^4.1.1", + "symfony/polyfill-ctype": "~1.8" + }, + "conflict": { + "symfony/config": "<3.4", + "symfony/dependency-injection": "<4.2", + "symfony/translation": "<4.2", + "symfony/var-dumper": "<4.1.1", + "twig/twig": "<1.34|<2.4,>=2" + }, + "provide": { + "psr/log-implementation": "1.0" + }, + "require-dev": { + "psr/cache": "~1.0", + "symfony/browser-kit": "~3.4|~4.0", + "symfony/config": "~3.4|~4.0", + "symfony/console": "~3.4|~4.0", + "symfony/css-selector": "~3.4|~4.0", + "symfony/dependency-injection": "^4.2", + "symfony/dom-crawler": "~3.4|~4.0", + "symfony/expression-language": "~3.4|~4.0", + "symfony/finder": "~3.4|~4.0", + "symfony/process": "~3.4|~4.0", + "symfony/routing": "~3.4|~4.0", + "symfony/stopwatch": "~3.4|~4.0", + "symfony/templating": "~3.4|~4.0", + "symfony/translation": "~4.2", + "symfony/var-dumper": "^4.1.1" + }, + "suggest": { + "symfony/browser-kit": "", + "symfony/config": "", + "symfony/console": "", + "symfony/dependency-injection": "", + "symfony/var-dumper": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpKernel\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony HttpKernel Component", + "homepage": "https://symfony.com", + "time": "2019-05-28T12:07:12+00:00" + }, + { + "name": "symfony/inflector", + "version": "v4.2.9", + "source": { + "type": "git", + "url": "https://github.com/symfony/inflector.git", + "reference": "275e54941a4f17a471c68d2a00e2513fc1fd4a78" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/inflector/zipball/275e54941a4f17a471c68d2a00e2513fc1fd4a78", + "reference": "275e54941a4f17a471c68d2a00e2513fc1fd4a78", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/polyfill-ctype": "~1.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Inflector\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Inflector Component", + "homepage": "https://symfony.com", + "keywords": [ + "inflection", + "pluralize", + "singularize", + "string", + "symfony", + "words" + ], + "time": "2019-01-16T20:31:39+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.11.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "fe5e94c604826c35a32fa832f35bd036b6799609" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fe5e94c604826c35a32fa832f35bd036b6799609", + "reference": "fe5e94c604826c35a32fa832f35bd036b6799609", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.11-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": "2019-02-06T07:57:58+00:00" + }, + { + "name": "symfony/property-access", + "version": "v4.2.9", + "source": { + "type": "git", + "url": "https://github.com/symfony/property-access.git", + "reference": "bc3930ff2007f41e50f6f3a34382b0cb77aa1f4d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/property-access/zipball/bc3930ff2007f41e50f6f3a34382b0cb77aa1f4d", + "reference": "bc3930ff2007f41e50f6f3a34382b0cb77aa1f4d", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/inflector": "~3.4|~4.0" + }, + "require-dev": { + "symfony/cache": "~3.4|~4.0" + }, + "suggest": { + "psr/cache-implementation": "To cache access methods." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\PropertyAccess\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony PropertyAccess Component", + "homepage": "https://symfony.com", + "keywords": [ + "access", + "array", + "extraction", + "index", + "injection", + "object", + "property", + "property path", + "reflection" + ], + "time": "2019-05-12T11:08:31+00:00" + }, + { + "name": "symfony/routing", + "version": "v4.2.9", + "source": { + "type": "git", + "url": "https://github.com/symfony/routing.git", + "reference": "c5ce09ed9db079dded1017a2494dbf6820efd204" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/routing/zipball/c5ce09ed9db079dded1017a2494dbf6820efd204", + "reference": "c5ce09ed9db079dded1017a2494dbf6820efd204", + "shasum": "" + }, + "require": { + "php": "^7.1.3" + }, + "conflict": { + "symfony/config": "<4.2", + "symfony/dependency-injection": "<3.4", + "symfony/yaml": "<3.4" + }, + "require-dev": { + "doctrine/annotations": "~1.0", + "psr/log": "~1.0", + "symfony/config": "~4.2", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/expression-language": "~3.4|~4.0", + "symfony/http-foundation": "~3.4|~4.0", + "symfony/yaml": "~3.4|~4.0" + }, + "suggest": { + "doctrine/annotations": "For using the annotation loader", + "symfony/config": "For using the all-in-one router or any loader", + "symfony/expression-language": "For using expression matching", + "symfony/http-foundation": "For using a Symfony Request object", + "symfony/yaml": "For using the YAML loader" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Routing\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Routing Component", + "homepage": "https://symfony.com", + "keywords": [ + "router", + "routing", + "uri", + "url" + ], + "time": "2019-05-20T16:15:26+00:00" + }, + { + "name": "symfony/serializer", + "version": "v4.2.9", + "source": { + "type": "git", + "url": "https://github.com/symfony/serializer.git", + "reference": "9b9ee567109c3d1196b5a2fe095a506c3b8125f7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/serializer/zipball/9b9ee567109c3d1196b5a2fe095a506c3b8125f7", + "reference": "9b9ee567109c3d1196b5a2fe095a506c3b8125f7", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/polyfill-ctype": "~1.8" + }, + "conflict": { + "phpdocumentor/type-resolver": "<0.2.1", + "symfony/dependency-injection": "<3.4", + "symfony/property-access": "<3.4", + "symfony/property-info": "<3.4", + "symfony/yaml": "<3.4" + }, + "require-dev": { + "doctrine/annotations": "~1.0", + "doctrine/cache": "~1.0", + "phpdocumentor/reflection-docblock": "^3.0|^4.0", + "symfony/cache": "~3.4|~4.0", + "symfony/config": "~3.4|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/http-foundation": "~3.4|~4.0", + "symfony/property-access": "~3.4|~4.0", + "symfony/property-info": "^3.4.13|~4.0", + "symfony/validator": "~3.4|~4.0", + "symfony/yaml": "~3.4|~4.0" + }, + "suggest": { + "doctrine/annotations": "For using the annotation mapping. You will also need doctrine/cache.", + "doctrine/cache": "For using the default cached annotation reader and metadata cache.", + "psr/cache-implementation": "For using the metadata cache.", + "symfony/config": "For using the XML mapping loader.", + "symfony/http-foundation": "To use the DataUriNormalizer.", + "symfony/property-access": "For using the ObjectNormalizer.", + "symfony/property-info": "To deserialize relations.", + "symfony/yaml": "For using the default YAML mapping loader." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Serializer\\": "" + }, + "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 Serializer Component", + "homepage": "https://symfony.com", + "time": "2019-05-20T16:15:26+00:00" + }, + { + "name": "symfony/var-exporter", + "version": "v4.2.9", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-exporter.git", + "reference": "57e00f3e0a3deee65b67cf971455b98afeacca46" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/57e00f3e0a3deee65b67cf971455b98afeacca46", + "reference": "57e00f3e0a3deee65b67cf971455b98afeacca46", + "shasum": "" + }, + "require": { + "php": "^7.1.3" + }, + "require-dev": { + "symfony/var-dumper": "^4.1.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\VarExporter\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "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": "A blend of var_export() + serialize() to turn any serializable data structure to plain PHP code", + "homepage": "https://symfony.com", + "keywords": [ + "clone", + "construct", + "export", + "hydrate", + "instantiate", + "serialize" + ], + "time": "2019-04-09T20:09:28+00:00" + }, + { + "name": "symfony/yaml", + "version": "v4.2.9", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "6712daf03ee25b53abb14e7e8e0ede1a770efdb1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/6712daf03ee25b53abb14e7e8e0ede1a770efdb1", + "reference": "6712daf03ee25b53abb14e7e8e0ede1a770efdb1", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/polyfill-ctype": "~1.8" + }, + "conflict": { + "symfony/console": "<3.4" + }, + "require-dev": { + "symfony/console": "~3.4|~4.0" + }, + "suggest": { + "symfony/console": "For validating YAML files using the lint command" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Yaml\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Yaml Component", + "homepage": "https://symfony.com", + "time": "2019-03-30T15:58:42+00:00" + }, + { + "name": "zircote/swagger-php", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/zircote/swagger-php.git", + "reference": "f10ab7f81d89dba97653a980cc90cf4b7b73f543" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zircote/swagger-php/zipball/f10ab7f81d89dba97653a980cc90cf4b7b73f543", + "reference": "f10ab7f81d89dba97653a980cc90cf4b7b73f543", + "shasum": "" + }, + "require": { + "doctrine/annotations": "*", + "php": ">=7.0", + "symfony/finder": ">=2.2", + "symfony/yaml": ">=3.3" + }, + "require-dev": { + "phpunit/phpunit": ">=6.3", + "squizlabs/php_codesniffer": ">=3.3", + "zendframework/zend-form": "<2.8" + }, + "bin": [ + "bin/openapi" + ], + "type": "library", + "autoload": { + "psr-4": { + "OpenApi\\": "src" + }, + "files": [ + "src/functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Robert Allen", + "email": "zircote@gmail.com", + "homepage": "http://www.zircote.com" + }, + { + "name": "Bob Fanger", + "email": "bfanger@gmail.com", + "homepage": "http://bfanger.nl" + } + ], + "description": "swagger-php - Generate interactive documentation for your RESTful API using phpdoc annotations", + "homepage": "https://github.com/zircote/swagger-php/", + "keywords": [ + "api", + "json", + "rest", + "service discovery" + ], + "time": "2018-11-16T15:04:29+00:00" + } + ], + "packages-dev": [ + { + "name": "amphp/amp", + "version": "v2.1.2", + "source": { + "type": "git", + "url": "https://github.com/amphp/amp.git", + "reference": "f824f0df1da2cc042934fa267d7a227fff9276c9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/amp/zipball/f824f0df1da2cc042934fa267d7a227fff9276c9", + "reference": "f824f0df1da2cc042934fa267d7a227fff9276c9", + "shasum": "" + }, + "require": { + "php": ">=7" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "dev-master", + "amphp/phpunit-util": "^1", + "ext-json": "*", + "phpstan/phpstan": "^0.8.5", + "phpunit/phpunit": "^6.0.9", + "react/promise": "^2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Amp\\": "lib" + }, + "files": [ + "lib/functions.php", + "lib/Internal/functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bob Weinand", + "email": "bobwei9@hotmail.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + }, + { + "name": "Daniel Lowrey", + "email": "rdlowrey@php.net" + }, + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + } + ], + "description": "A non-blocking concurrency framework for PHP applications.", + "homepage": "http://amphp.org/amp", + "keywords": [ + "async", + "asynchronous", + "awaitable", + "concurrency", + "event", + "event-loop", + "future", + "non-blocking", + "promise" + ], + "time": "2019-05-31T18:42:02+00:00" + }, + { + "name": "amphp/byte-stream", + "version": "v1.6.0", + "source": { + "type": "git", + "url": "https://github.com/amphp/byte-stream.git", + "reference": "c75af3778b5511deb1d760e4709cade2dabc2295" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/byte-stream/zipball/c75af3778b5511deb1d760e4709cade2dabc2295", + "reference": "c75af3778b5511deb1d760e4709cade2dabc2295", + "shasum": "" + }, + "require": { + "amphp/amp": "^2" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "dev-master", + "amphp/phpunit-util": "^1", + "friendsofphp/php-cs-fixer": "^2.3", + "infection/infection": "^0.9.3", + "phpunit/phpunit": "^6" + }, + "type": "library", + "autoload": { + "psr-4": { + "Amp\\ByteStream\\": "lib" + }, + "files": [ + "lib/functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + }, + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + } + ], + "description": "A stream abstraction to make working with non-blocking I/O simple.", + "homepage": "http://amphp.org/byte-stream", + "keywords": [ + "amp", + "amphp", + "async", + "io", + "non-blocking", + "stream" + ], + "time": "2019-06-03T21:45:17+00:00" + }, + { + "name": "composer/ca-bundle", + "version": "1.1.4", + "source": { + "type": "git", + "url": "https://github.com/composer/ca-bundle.git", + "reference": "558f321c52faeb4828c03e7dc0cfe39a09e09a2d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/ca-bundle/zipball/558f321c52faeb4828c03e7dc0cfe39a09e09a2d", + "reference": "558f321c52faeb4828c03e7dc0cfe39a09e09a2d", + "shasum": "" + }, + "require": { + "ext-openssl": "*", + "ext-pcre": "*", + "php": "^5.3.2 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5", + "psr/log": "^1.0", + "symfony/process": "^2.5 || ^3.0 || ^4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\CaBundle\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "Lets you find a path to the system CA bundle, and includes a fallback to the Mozilla CA bundle.", + "keywords": [ + "cabundle", + "cacert", + "certificate", + "ssl", + "tls" + ], + "time": "2019-01-28T09:30:10+00:00" + }, + { + "name": "composer/composer", + "version": "1.8.6", + "source": { + "type": "git", + "url": "https://github.com/composer/composer.git", + "reference": "19b5f66a0e233eb944f134df34091fe1c5dfcc11" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/composer/zipball/19b5f66a0e233eb944f134df34091fe1c5dfcc11", + "reference": "19b5f66a0e233eb944f134df34091fe1c5dfcc11", + "shasum": "" + }, + "require": { + "composer/ca-bundle": "^1.0", + "composer/semver": "^1.0", + "composer/spdx-licenses": "^1.2", + "composer/xdebug-handler": "^1.1", + "justinrainbow/json-schema": "^3.0 || ^4.0 || ^5.0", + "php": "^5.3.2 || ^7.0", + "psr/log": "^1.0", + "seld/jsonlint": "^1.4", + "seld/phar-utils": "^1.0", + "symfony/console": "^2.7 || ^3.0 || ^4.0", + "symfony/filesystem": "^2.7 || ^3.0 || ^4.0", + "symfony/finder": "^2.7 || ^3.0 || ^4.0", + "symfony/process": "^2.7 || ^3.0 || ^4.0" + }, + "conflict": { + "symfony/console": "2.8.38" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7", + "phpunit/phpunit-mock-objects": "^2.3 || ^3.0" + }, + "suggest": { + "ext-openssl": "Enabling the openssl extension allows you to access https URLs for repositories and packages", + "ext-zip": "Enabling the zip extension allows you to unzip archives", + "ext-zlib": "Allow gzip compression of HTTP requests" + }, + "bin": [ + "bin/composer" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.8-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\": "src/Composer" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nils Adermann", + "email": "naderman@naderman.de", + "homepage": "http://www.naderman.de" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "Composer helps you declare, manage and install dependencies of PHP projects, ensuring you have the right stack everywhere.", + "homepage": "https://getcomposer.org/", + "keywords": [ + "autoload", + "dependency", + "package" + ], + "time": "2019-06-11T13:03:06+00:00" + }, + { + "name": "composer/semver", + "version": "1.5.0", + "source": { + "type": "git", + "url": "https://github.com/composer/semver.git", + "reference": "46d9139568ccb8d9e7cdd4539cab7347568a5e2e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/semver/zipball/46d9139568ccb8d9e7cdd4539cab7347568a5e2e", + "reference": "46d9139568ccb8d9e7cdd4539cab7347568a5e2e", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.5 || ^5.0.5", + "phpunit/phpunit-mock-objects": "2.3.0 || ^3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Semver\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nils Adermann", + "email": "naderman@naderman.de", + "homepage": "http://www.naderman.de" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + }, + { + "name": "Rob Bast", + "email": "rob.bast@gmail.com", + "homepage": "http://robbast.nl" + } + ], + "description": "Semver library that offers utilities, version constraint parsing and validation.", + "keywords": [ + "semantic", + "semver", + "validation", + "versioning" + ], + "time": "2019-03-19T17:25:45+00:00" + }, + { + "name": "composer/spdx-licenses", + "version": "1.5.1", + "source": { + "type": "git", + "url": "https://github.com/composer/spdx-licenses.git", + "reference": "a1aa51cf3ab838b83b0867b14e56fc20fbd55b3d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/spdx-licenses/zipball/a1aa51cf3ab838b83b0867b14e56fc20fbd55b3d", + "reference": "a1aa51cf3ab838b83b0867b14e56fc20fbd55b3d", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7 || 6.5 - 7" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Spdx\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nils Adermann", + "email": "naderman@naderman.de", + "homepage": "http://www.naderman.de" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + }, + { + "name": "Rob Bast", + "email": "rob.bast@gmail.com", + "homepage": "http://robbast.nl" + } + ], + "description": "SPDX licenses list and validation library.", + "keywords": [ + "license", + "spdx", + "validator" + ], + "time": "2019-03-26T10:23:26+00:00" + }, + { + "name": "composer/xdebug-handler", + "version": "1.3.3", + "source": { + "type": "git", + "url": "https://github.com/composer/xdebug-handler.git", + "reference": "46867cbf8ca9fb8d60c506895449eb799db1184f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/46867cbf8ca9fb8d60c506895449eb799db1184f", + "reference": "46867cbf8ca9fb8d60c506895449eb799db1184f", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0", + "psr/log": "^1.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Composer\\XdebugHandler\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "John Stevenson", + "email": "john-stevenson@blueyonder.co.uk" + } + ], + "description": "Restarts a process without xdebug.", + "keywords": [ + "Xdebug", + "performance" + ], + "time": "2019-05-27T17:52:04+00:00" + }, + { + "name": "doctrine/instantiator", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/instantiator.git", + "reference": "a2c590166b2133a4633738648b6b064edae0814a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/a2c590166b2133a4633738648b6b064edae0814a", + "reference": "a2c590166b2133a4633738648b6b064edae0814a", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "require-dev": { + "doctrine/coding-standard": "^6.0", + "ext-pdo": "*", + "ext-phar": "*", + "phpbench/phpbench": "^0.13", + "phpstan/phpstan-phpunit": "^0.11", + "phpstan/phpstan-shim": "^0.11", + "phpunit/phpunit": "^7.0" + }, + "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://www.doctrine-project.org/projects/instantiator.html", + "keywords": [ + "constructor", + "instantiate" + ], + "time": "2019-03-17T17:37:11+00:00" + }, + { + "name": "felixfbecker/advanced-json-rpc", + "version": "v3.0.3", + "source": { + "type": "git", + "url": "https://github.com/felixfbecker/php-advanced-json-rpc.git", + "reference": "241c470695366e7b83672be04ea0e64d8085a551" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/felixfbecker/php-advanced-json-rpc/zipball/241c470695366e7b83672be04ea0e64d8085a551", + "reference": "241c470695366e7b83672be04ea0e64d8085a551", + "shasum": "" + }, + "require": { + "netresearch/jsonmapper": "^1.0", + "php": ">=7.0", + "phpdocumentor/reflection-docblock": "^4.0.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "AdvancedJsonRpc\\": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "ISC" + ], + "authors": [ + { + "name": "Felix Becker", + "email": "felix.b@outlook.com" + } + ], + "description": "A more advanced JSONRPC implementation", + "time": "2018-09-10T08:58:41+00:00" + }, + { + "name": "felixfbecker/language-server-protocol", + "version": "v1.2.0", + "source": { + "type": "git", + "url": "https://github.com/felixfbecker/php-language-server-protocol.git", + "reference": "1bdd1bcc95428edf85ec04c7b558d0886c07280f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/felixfbecker/php-language-server-protocol/zipball/1bdd1bcc95428edf85ec04c7b558d0886c07280f", + "reference": "1bdd1bcc95428edf85ec04c7b558d0886c07280f", + "shasum": "" + }, + "require": { + "php": "^7.0" + }, + "require-dev": { + "phpstan/phpstan": "*", + "phpunit/phpunit": "^6.3", + "squizlabs/php_codesniffer": "^3.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "LanguageServerProtocol\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "ISC" + ], + "authors": [ + { + "name": "Felix Becker", + "email": "felix.b@outlook.com" + } + ], + "description": "PHP classes for the Language Server Protocol", + "keywords": [ + "language", + "microsoft", + "php", + "server" + ], + "time": "2018-09-25T11:42:25+00:00" + }, + { + "name": "friendsofphp/php-cs-fixer", + "version": "v2.15.1", + "source": { + "type": "git", + "url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git", + "reference": "20064511ab796593a3990669eff5f5b535001f7c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/20064511ab796593a3990669eff5f5b535001f7c", + "reference": "20064511ab796593a3990669eff5f5b535001f7c", + "shasum": "" + }, + "require": { + "composer/semver": "^1.4", + "composer/xdebug-handler": "^1.2", + "doctrine/annotations": "^1.2", + "ext-json": "*", + "ext-tokenizer": "*", + "php": "^5.6 || ^7.0", + "php-cs-fixer/diff": "^1.3", + "symfony/console": "^3.4.17 || ^4.1.6", + "symfony/event-dispatcher": "^3.0 || ^4.0", + "symfony/filesystem": "^3.0 || ^4.0", + "symfony/finder": "^3.0 || ^4.0", + "symfony/options-resolver": "^3.0 || ^4.0", + "symfony/polyfill-php70": "^1.0", + "symfony/polyfill-php72": "^1.4", + "symfony/process": "^3.0 || ^4.0", + "symfony/stopwatch": "^3.0 || ^4.0" + }, + "require-dev": { + "johnkary/phpunit-speedtrap": "^1.1 || ^2.0 || ^3.0", + "justinrainbow/json-schema": "^5.0", + "keradus/cli-executor": "^1.2", + "mikey179/vfsstream": "^1.6", + "php-coveralls/php-coveralls": "^2.1", + "php-cs-fixer/accessible-object": "^1.0", + "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.1", + "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.1", + "phpunit/phpunit": "^5.7.27 || ^6.5.8 || ^7.1", + "phpunitgoodpractices/traits": "^1.8", + "symfony/phpunit-bridge": "^4.3" + }, + "suggest": { + "ext-mbstring": "For handling non-UTF8 characters in cache signature.", + "php-cs-fixer/phpunit-constraint-isidenticalstring": "For IsIdenticalString constraint.", + "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "For XmlMatchesXsd constraint.", + "symfony/polyfill-mbstring": "When enabling `ext-mbstring` is not possible." + }, + "bin": [ + "php-cs-fixer" + ], + "type": "application", + "autoload": { + "psr-4": { + "PhpCsFixer\\": "src/" + }, + "classmap": [ + "tests/Test/AbstractFixerTestCase.php", + "tests/Test/AbstractIntegrationCaseFactory.php", + "tests/Test/AbstractIntegrationTestCase.php", + "tests/Test/Assert/AssertTokensTrait.php", + "tests/Test/IntegrationCase.php", + "tests/Test/IntegrationCaseFactory.php", + "tests/Test/IntegrationCaseFactoryInterface.php", + "tests/Test/InternalIntegrationCaseFactory.php", + "tests/TestCase.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Dariusz Rumiński", + "email": "dariusz.ruminski@gmail.com" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "A tool to automatically fix PHP code style", + "time": "2019-06-01T10:32:12+00:00" + }, + { + "name": "gitonomy/gitlib", + "version": "v1.0.4", + "source": { + "type": "git", + "url": "https://github.com/gitonomy/gitlib.git", + "reference": "932a960221ae3484a3e82553b3be478e56beb68d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/gitonomy/gitlib/zipball/932a960221ae3484a3e82553b3be478e56beb68d", + "reference": "932a960221ae3484a3e82553b3be478e56beb68d", + "shasum": "" + }, + "require": { + "php": "^5.3 || ^7.0", + "symfony/process": "^2.3|^3.0|^4.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35|^5.7", + "psr/log": "^1.0" + }, + "suggest": { + "psr/log": "Add some log" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "Gitonomy\\Git\\": "src/Gitonomy/Git/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Alexandre Salomé", + "email": "alexandre.salome@gmail.com", + "homepage": "http://alexandre-salome.fr" + }, + { + "name": "Julien DIDIER", + "email": "genzo.wm@gmail.com", + "homepage": "http://www.jdidier.net" + } + ], + "description": "Library for accessing git", + "homepage": "http://gitonomy.com", + "time": "2018-04-22T19:55:36+00:00" + }, + { + "name": "jean85/pretty-package-versions", + "version": "1.2", + "source": { + "type": "git", + "url": "https://github.com/Jean85/pretty-package-versions.git", + "reference": "75c7effcf3f77501d0e0caa75111aff4daa0dd48" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/75c7effcf3f77501d0e0caa75111aff4daa0dd48", + "reference": "75c7effcf3f77501d0e0caa75111aff4daa0dd48", + "shasum": "" + }, + "require": { + "ocramius/package-versions": "^1.2.0", + "php": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Jean85\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Alessandro Lai", + "email": "alessandro.lai85@gmail.com" + } + ], + "description": "A wrapper for ocramius/package-versions to get pretty versions strings", + "keywords": [ + "composer", + "package", + "release", + "versions" + ], + "time": "2018-06-13T13:22:40+00:00" + }, + { + "name": "justinrainbow/json-schema", + "version": "5.2.8", + "source": { + "type": "git", + "url": "https://github.com/justinrainbow/json-schema.git", + "reference": "dcb6e1006bb5fd1e392b4daa68932880f37550d4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/dcb6e1006bb5fd1e392b4daa68932880f37550d4", + "reference": "dcb6e1006bb5fd1e392b4daa68932880f37550d4", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "~2.2.20", + "json-schema/json-schema-test-suite": "1.2.0", + "phpunit/phpunit": "^4.8.35" + }, + "bin": [ + "bin/validate-json" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "JsonSchema\\": "src/JsonSchema/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bruno Prieto Reis", + "email": "bruno.p.reis@gmail.com" + }, + { + "name": "Justin Rainbow", + "email": "justin.rainbow@gmail.com" + }, + { + "name": "Igor Wiedler", + "email": "igor@wiedler.ch" + }, + { + "name": "Robert Schönthal", + "email": "seroscho@googlemail.com" + } + ], + "description": "A library to validate a json schema.", + "homepage": "https://github.com/justinrainbow/json-schema", + "keywords": [ + "json", + "schema" + ], + "time": "2019-01-14T23:55:14+00:00" + }, + { + "name": "monolog/monolog", + "version": "1.24.0", + "source": { + "type": "git", + "url": "https://github.com/Seldaek/monolog.git", + "reference": "bfc9ebb28f97e7a24c45bdc3f0ff482e47bb0266" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/bfc9ebb28f97e7a24c45bdc3f0ff482e47bb0266", + "reference": "bfc9ebb28f97e7a24c45bdc3f0ff482e47bb0266", + "shasum": "" + }, + "require": { + "php": ">=5.3.0", + "psr/log": "~1.0" + }, + "provide": { + "psr/log-implementation": "1.0.0" + }, + "require-dev": { + "aws/aws-sdk-php": "^2.4.9 || ^3.0", + "doctrine/couchdb": "~1.0@dev", + "graylog2/gelf-php": "~1.0", + "jakub-onderka/php-parallel-lint": "0.9", + "php-amqplib/php-amqplib": "~2.4", + "php-console/php-console": "^3.1.3", + "phpunit/phpunit": "~4.5", + "phpunit/phpunit-mock-objects": "2.3.0", + "ruflin/elastica": ">=0.90 <3.0", + "sentry/sentry": "^0.13", + "swiftmailer/swiftmailer": "^5.3|^6.0" + }, + "suggest": { + "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", + "doctrine/couchdb": "Allow sending log messages to a CouchDB server", + "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", + "ext-mongo": "Allow sending log messages to a MongoDB server", + "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", + "mongodb/mongodb": "Allow sending log messages to a MongoDB server via PHP Driver", + "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", + "php-console/php-console": "Allow sending log messages to Google Chrome", + "rollbar/rollbar": "Allow sending log messages to Rollbar", + "ruflin/elastica": "Allow sending log messages to an Elastic Search server", + "sentry/sentry": "Allow sending log messages to a Sentry server" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Monolog\\": "src/Monolog" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "Sends your logs to files, sockets, inboxes, databases and various web services", + "homepage": "http://github.com/Seldaek/monolog", + "keywords": [ + "log", + "logging", + "psr-3" + ], + "time": "2018-11-05T09:00:11+00:00" + }, + { + "name": "netresearch/jsonmapper", + "version": "v1.4.0", + "source": { + "type": "git", + "url": "https://github.com/cweiske/jsonmapper.git", + "reference": "3868fe1128ce1169228acdb623359dca74db5ef3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/cweiske/jsonmapper/zipball/3868fe1128ce1169228acdb623359dca74db5ef3", + "reference": "3868fe1128ce1169228acdb623359dca74db5ef3", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "phpunit/phpunit": "~4.8.35 || ~5.7 || ~6.4", + "squizlabs/php_codesniffer": "~1.5" + }, + "type": "library", + "autoload": { + "psr-0": { + "JsonMapper": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "OSL-3.0" + ], + "authors": [ + { + "name": "Christian Weiske", + "email": "cweiske@cweiske.de", + "homepage": "http://github.com/cweiske/jsonmapper/", + "role": "Developer" + } + ], + "description": "Map nested JSON structures onto PHP classes", + "time": "2017-11-28T21:30:01+00:00" + }, + { + "name": "nette/bootstrap", + "version": "v3.0.0", + "source": { + "type": "git", + "url": "https://github.com/nette/bootstrap.git", + "reference": "e1075af05c211915e03e0c86542f3ba5433df4a3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/bootstrap/zipball/e1075af05c211915e03e0c86542f3ba5433df4a3", + "reference": "e1075af05c211915e03e0c86542f3ba5433df4a3", + "shasum": "" + }, + "require": { + "nette/di": "^3.0", + "nette/utils": "^3.0", + "php": ">=7.1" + }, + "require-dev": { + "latte/latte": "^2.2", + "nette/application": "^3.0", + "nette/caching": "^3.0", + "nette/database": "^3.0", + "nette/forms": "^3.0", + "nette/http": "^3.0", + "nette/mail": "^3.0", + "nette/robot-loader": "^3.0", + "nette/safe-stream": "^2.2", + "nette/security": "^3.0", + "nette/tester": "^2.0", + "tracy/tracy": "^2.6" + }, + "suggest": { + "nette/robot-loader": "to use Configurator::createRobotLoader()", + "tracy/tracy": "to use Configurator::enableTracy()" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0", + "GPL-3.0" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "🅱 Nette Bootstrap: the simple way to configure and bootstrap your Nette application.", + "homepage": "https://nette.org", + "keywords": [ + "bootstrapping", + "configurator", + "nette" + ], + "time": "2019-03-26T12:59:07+00:00" + }, + { + "name": "nette/di", + "version": "v3.0.0", + "source": { + "type": "git", + "url": "https://github.com/nette/di.git", + "reference": "19d83539245aaacb59470828919182411061841f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/di/zipball/19d83539245aaacb59470828919182411061841f", + "reference": "19d83539245aaacb59470828919182411061841f", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "nette/neon": "^3.0", + "nette/php-generator": "^3.2.2", + "nette/robot-loader": "^3.2", + "nette/schema": "^1.0", + "nette/utils": "^3.0", + "php": ">=7.1" + }, + "conflict": { + "nette/bootstrap": "<3.0" + }, + "require-dev": { + "nette/tester": "^2.2", + "tracy/tracy": "^2.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ], + "files": [ + "src/compatibility.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0", + "GPL-3.0" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "💎 Nette Dependency Injection Container: Flexible, compiled and full-featured DIC with perfectly usable autowiring and support for all new PHP 7.1 features.", + "homepage": "https://nette.org", + "keywords": [ + "compiled", + "di", + "dic", + "factory", + "ioc", + "nette", + "static" + ], + "time": "2019-04-03T19:35:46+00:00" + }, + { + "name": "nette/finder", + "version": "v2.5.0", + "source": { + "type": "git", + "url": "https://github.com/nette/finder.git", + "reference": "6be1b83ea68ac558aff189d640abe242e0306fe2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/finder/zipball/6be1b83ea68ac558aff189d640abe242e0306fe2", + "reference": "6be1b83ea68ac558aff189d640abe242e0306fe2", + "shasum": "" + }, + "require": { + "nette/utils": "^2.4 || ~3.0.0", + "php": ">=7.1" + }, + "conflict": { + "nette/nette": "<2.2" + }, + "require-dev": { + "nette/tester": "^2.0", + "tracy/tracy": "^2.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.5-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0", + "GPL-3.0" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "? Nette Finder: find files and directories with an intuitive API.", + "homepage": "https://nette.org", + "keywords": [ + "filesystem", + "glob", + "iterator", + "nette" + ], + "time": "2019-02-28T18:13:25+00:00" + }, + { + "name": "nette/neon", + "version": "v3.0.0", + "source": { + "type": "git", + "url": "https://github.com/nette/neon.git", + "reference": "cbff32059cbdd8720deccf9e9eace6ee516f02eb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/neon/zipball/cbff32059cbdd8720deccf9e9eace6ee516f02eb", + "reference": "cbff32059cbdd8720deccf9e9eace6ee516f02eb", + "shasum": "" + }, + "require": { + "ext-iconv": "*", + "ext-json": "*", + "php": ">=7.0" + }, + "require-dev": { + "nette/tester": "^2.0", + "tracy/tracy": "^2.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0", + "GPL-3.0" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "? Nette NEON: encodes and decodes NEON file format.", + "homepage": "http://ne-on.org", + "keywords": [ + "export", + "import", + "neon", + "nette", + "yaml" + ], + "time": "2019-02-05T21:30:40+00:00" + }, + { + "name": "nette/php-generator", + "version": "v3.2.2", + "source": { + "type": "git", + "url": "https://github.com/nette/php-generator.git", + "reference": "acff8b136fad84b860a626d133e791f95781f9f5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/php-generator/zipball/acff8b136fad84b860a626d133e791f95781f9f5", + "reference": "acff8b136fad84b860a626d133e791f95781f9f5", + "shasum": "" + }, + "require": { + "nette/utils": "^2.4.2 || ~3.0.0", + "php": ">=7.1" + }, + "require-dev": { + "nette/tester": "^2.0", + "tracy/tracy": "^2.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0", + "GPL-3.0" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "🐘 Nette PHP Generator: generates neat PHP code for you. Supports new PHP 7.3 features.", + "homepage": "https://nette.org", + "keywords": [ + "code", + "nette", + "php", + "scaffolding" + ], + "time": "2019-03-15T03:41:13+00:00" + }, + { + "name": "nette/robot-loader", + "version": "v3.2.0", + "source": { + "type": "git", + "url": "https://github.com/nette/robot-loader.git", + "reference": "0712a0e39ae7956d6a94c0ab6ad41aa842544b5c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/robot-loader/zipball/0712a0e39ae7956d6a94c0ab6ad41aa842544b5c", + "reference": "0712a0e39ae7956d6a94c0ab6ad41aa842544b5c", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "nette/finder": "^2.5", + "nette/utils": "^3.0", + "php": ">=7.1" + }, + "require-dev": { + "nette/tester": "^2.0", + "tracy/tracy": "^2.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0", + "GPL-3.0" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "? Nette RobotLoader: high performance and comfortable autoloader that will search and autoload classes within your application.", + "homepage": "https://nette.org", + "keywords": [ + "autoload", + "class", + "interface", + "nette", + "trait" + ], + "time": "2019-03-08T21:57:24+00:00" + }, + { + "name": "nette/schema", + "version": "v1.0.0", + "source": { + "type": "git", + "url": "https://github.com/nette/schema.git", + "reference": "6241d8d4da39e825dd6cb5bfbe4242912f4d7e4d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/schema/zipball/6241d8d4da39e825dd6cb5bfbe4242912f4d7e4d", + "reference": "6241d8d4da39e825dd6cb5bfbe4242912f4d7e4d", + "shasum": "" + }, + "require": { + "nette/utils": "^3.0.1", + "php": ">=7.1" + }, + "require-dev": { + "nette/tester": "^2.2", + "tracy/tracy": "^2.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0", + "GPL-3.0" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "📐 Nette Schema: validating data structures against a given Schema.", + "homepage": "https://nette.org", + "keywords": [ + "config", + "nette" + ], + "time": "2019-04-03T15:53:25+00:00" + }, + { + "name": "nette/utils", + "version": "v3.0.1", + "source": { + "type": "git", + "url": "https://github.com/nette/utils.git", + "reference": "bd961f49b211997202bda1d0fbc410905be370d4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/utils/zipball/bd961f49b211997202bda1d0fbc410905be370d4", + "reference": "bd961f49b211997202bda1d0fbc410905be370d4", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "require-dev": { + "nette/tester": "~2.0", + "tracy/tracy": "^2.3" + }, + "suggest": { + "ext-gd": "to use Image", + "ext-iconv": "to use Strings::webalize() and toAscii()", + "ext-intl": "to use Strings::webalize(), toAscii(), normalize() and compare()", + "ext-json": "to use Nette\\Utils\\Json", + "ext-mbstring": "to use Strings::lower() etc...", + "ext-xml": "to use Strings::length() etc. when mbstring is not available" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0", + "GPL-3.0" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "🛠 Nette Utils: lightweight utilities for string & array manipulation, image handling, safe JSON encoding/decoding, validation, slug or strong password generating etc.", + "homepage": "https://nette.org", + "keywords": [ + "array", + "core", + "datetime", + "images", + "json", + "nette", + "paginator", + "password", + "slugify", + "string", + "unicode", + "utf-8", + "utility", + "validation" + ], + "time": "2019-03-22T01:00:30+00:00" + }, + { + "name": "nikic/php-parser", + "version": "v4.2.2", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "1bd73cc04c3843ad8d6b0bfc0956026a151fc420" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/1bd73cc04c3843ad8d6b0bfc0956026a151fc420", + "reference": "1bd73cc04c3843ad8d6b0bfc0956026a151fc420", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": ">=7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.5 || ^7.0" + }, + "bin": [ + "bin/php-parse" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov" + } + ], + "description": "A PHP parser written in PHP", + "keywords": [ + "parser", + "php" + ], + "time": "2019-05-25T20:07:01+00:00" + }, + { + "name": "ocramius/package-versions", + "version": "1.4.0", + "source": { + "type": "git", + "url": "https://github.com/Ocramius/PackageVersions.git", + "reference": "a4d4b60d0e60da2487bd21a2c6ac089f85570dbb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Ocramius/PackageVersions/zipball/a4d4b60d0e60da2487bd21a2c6ac089f85570dbb", + "reference": "a4d4b60d0e60da2487bd21a2c6ac089f85570dbb", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.0.0", + "php": "^7.1.0" + }, + "require-dev": { + "composer/composer": "^1.6.3", + "doctrine/coding-standard": "^5.0.1", + "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": "2019-02-21T12:16:21+00:00" + }, + { + "name": "openlss/lib-array2xml", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/nullivex/lib-array2xml.git", + "reference": "a91f18a8dfc69ffabe5f9b068bc39bb202c81d90" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nullivex/lib-array2xml/zipball/a91f18a8dfc69ffabe5f9b068bc39bb202c81d90", + "reference": "a91f18a8dfc69ffabe5f9b068bc39bb202c81d90", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "type": "library", + "autoload": { + "psr-0": { + "LSS": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Bryan Tong", + "email": "bryan@nullivex.com", + "homepage": "https://www.nullivex.com" + }, + { + "name": "Tony Butler", + "email": "spudz76@gmail.com", + "homepage": "https://www.nullivex.com" + } + ], + "description": "Array2XML conversion library credit to lalit.org", + "homepage": "https://www.nullivex.com", + "keywords": [ + "array", + "array conversion", + "xml", + "xml conversion" + ], + "time": "2019-03-29T20:06:56+00:00" + }, + { + "name": "php-cs-fixer/diff", + "version": "v1.3.0", + "source": { + "type": "git", + "url": "https://github.com/PHP-CS-Fixer/diff.git", + "reference": "78bb099e9c16361126c86ce82ec4405ebab8e756" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHP-CS-Fixer/diff/zipball/78bb099e9c16361126c86ce82ec4405ebab8e756", + "reference": "78bb099e9c16361126c86ce82ec4405ebab8e756", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^5.7.23 || ^6.4.3", + "symfony/process": "^3.3" + }, + "type": "library", + "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" + }, + { + "name": "SpacePossum" + } + ], + "description": "sebastian/diff v2 backport support for PHP5.6", + "homepage": "https://github.com/PHP-CS-Fixer", + "keywords": [ + "diff" + ], + "time": "2018-02-15T16:58:55+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.1", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "bdd9f737ebc2a01c06ea7ff4308ec6697db9b53c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/bdd9f737ebc2a01c06ea7ff4308ec6697db9b53c", + "reference": "bdd9f737ebc2a01c06ea7ff4308ec6697db9b53c", + "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": "2019-04-30T17:48:53+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": "phpro/grumphp", + "version": "v0.15.2", + "source": { + "type": "git", + "url": "https://github.com/phpro/grumphp.git", + "reference": "c153840bead6fbed370d35cc84c63dca33de0ca4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpro/grumphp/zipball/c153840bead6fbed370d35cc84c63dca33de0ca4", + "reference": "c153840bead6fbed370d35cc84c63dca33de0ca4", + "shasum": "" + }, + "require": { + "composer-plugin-api": "~1.0", + "composer/composer": "^1.0", + "doctrine/collections": "~1.2", + "gitonomy/gitlib": "^1.0.3", + "monolog/monolog": "~1.16", + "php": ">=7.0", + "seld/jsonlint": "~1.1", + "symfony/config": "~3.4|~4.0", + "symfony/console": "~3.4|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/event-dispatcher": "~3.4|~4.0", + "symfony/filesystem": "~3.4|~4.0", + "symfony/finder": "~3.4|~4.0", + "symfony/options-resolver": "~3.4|~4.0", + "symfony/process": "~3.4|~4.0", + "symfony/yaml": "~3.4|~4.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "~2", + "jakub-onderka/php-parallel-lint": "^0.9.2", + "nikic/php-parser": "~2.1", + "phpspec/phpspec": "^3.2.2", + "phpspec/prophecy": "^1.6.2", + "phpunit/phpunit": "^6.5|^7.0", + "sebastian/comparator": "^2.1", + "sebastian/diff": "^2.0", + "sebastian/exporter": "^3.1", + "sensiolabs/security-checker": "^5.0", + "squizlabs/php_codesniffer": "~2.9" + }, + "suggest": { + "allocine/twigcs": "Lets GrumPHP check Twig coding standard.", + "atoum/atoum": "Lets GrumPHP run your unit tests.", + "behat/behat": "Lets GrumPHP validate your project features.", + "brianium/paratest": "Lets GrumPHP run PHPUnit in parallel.", + "codeception/codeception": "Lets GrumPHP run your project's full stack tests", + "codegyre/robo": "Lets GrumPHP run your automated PHP tasks.", + "designsecurity/progpilot": "Lets GrumPHP be sure that there are no vulnerabilities in your code.", + "doctrine/orm": "Lets GrumPHP validate your Doctrine mapping files.", + "friendsofphp/php-cs-fixer": "Lets GrumPHP automatically fix your codestyle.", + "infection/infection": "Lets GrumPHP evaluate the quality your unit tests", + "jakub-onderka/php-parallel-lint": "Lets GrumPHP quickly lint your entire code base.", + "localheinz/composer-normalize": "Lets GrumPHP tidy and normalize your composer.json file.", + "maglnet/composer-require-checker": "Lets GrumPHP analyze composer dependencies.", + "malukenho/kawaii-gherkin": "Lets GrumPHP lint your Gherkin files.", + "nikic/php-parser": "Lets GrumPHP run static analyses through your PHP files.", + "phan/phan": "Lets GrumPHP unleash a static analyzer on your code", + "phing/phing": "Lets GrumPHP run your automated PHP tasks.", + "phpmd/phpmd": "Lets GrumPHP sort out the mess in your code", + "phpspec/phpspec": "Lets GrumPHP spec your code.", + "phpstan/phpstan": "Lets GrumPHP discover bugs in your code without running it.", + "phpunit/phpunit": "Lets GrumPHP run your unit tests.", + "povils/phpmnd": "Lets GrumPHP help you detect magic numbers in PHP code.", + "roave/security-advisories": "Lets GrumPHP be sure that there are no known security issues.", + "sebastian/phpcpd": "Lets GrumPHP find duplicated code.", + "sensiolabs/security-checker": "Lets GrumPHP be sure that there are no known security issues.", + "squizlabs/php_codesniffer": "Lets GrumPHP sniff on your code.", + "sstalle/php7cc": "Lets GrumPHP check PHP 5.3 - 5.6 code compatibility with PHP 7.", + "symfony/phpunit-bridge": "Lets GrumPHP run your unit tests with the phpunit-bridge of Symfony.", + "symplify/easycodingstandard": "Lets GrumPHP check coding standard.", + "vimeo/psalm": "Lets GrumPHP discover errors in your code without running it." + }, + "bin": [ + "bin/grumphp" + ], + "type": "composer-plugin", + "extra": { + "class": "GrumPHP\\Composer\\GrumPHPPlugin" + }, + "autoload": { + "psr-4": { + "GrumPHP\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Toon Verwerft", + "email": "toon.verwerft@phpro.be" + }, + { + "name": "Community", + "homepage": "https://github.com/phpro/grumphp/graphs/contributors" + } + ], + "description": "A composer plugin that enables source code quality checks.", + "time": "2019-05-17T11:56:59+00:00" + }, + { + "name": "phpspec/php-diff", + "version": "v1.1.0", + "source": { + "type": "git", + "url": "https://github.com/phpspec/php-diff.git", + "reference": "0464787bfa7cd13576c5a1e318709768798bec6a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpspec/php-diff/zipball/0464787bfa7cd13576c5a1e318709768798bec6a", + "reference": "0464787bfa7cd13576c5a1e318709768798bec6a", + "shasum": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-0": { + "Diff": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Chris Boulton", + "homepage": "http://github.com/chrisboulton" + } + ], + "description": "A comprehensive library for generating differences between two hashable objects (strings or arrays).", + "time": "2016-04-07T12:29:16+00:00" + }, + { + "name": "phpspec/phpspec", + "version": "5.1.0", + "source": { + "type": "git", + "url": "https://github.com/phpspec/phpspec.git", + "reference": "4badea737c34a6c8e2921fca0f6a1cbe4f724f2f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpspec/phpspec/zipball/4badea737c34a6c8e2921fca0f6a1cbe4f724f2f", + "reference": "4badea737c34a6c8e2921fca0f6a1cbe4f724f2f", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.0.5", + "ext-tokenizer": "*", + "php": "^7.1, <7.4", + "phpspec/php-diff": "^1.0.0", + "phpspec/prophecy": "^1.7", + "sebastian/exporter": "^1.0 || ^2.0 || ^3.0", + "symfony/console": "^3.4 || ^4.0", + "symfony/event-dispatcher": "^3.4 || ^4.0", + "symfony/finder": "^3.4 || ^4.0", + "symfony/process": "^3.4 || ^4.0", + "symfony/yaml": "^3.4 || ^4.0" + }, + "require-dev": { + "behat/behat": "^3.3", + "phpunit/phpunit": "^5.7 || ^6.0", + "symfony/filesystem": "^3.4 || ^4.0" + }, + "suggest": { + "phpspec/nyan-formatters": "Adds Nyan formatters" + }, + "bin": [ + "bin/phpspec" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.1.x-dev" + } + }, + "autoload": { + "psr-0": { + "PhpSpec": "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", + "homepage": "http://marcelloduarte.net/" + }, + { + "name": "Ciaran McNulty", + "homepage": "https://ciaranmcnulty.com/" + } + ], + "description": "Specification-oriented BDD framework for PHP 5.6+", + "homepage": "http://phpspec.net/", + "keywords": [ + "BDD", + "SpecBDD", + "TDD", + "spec", + "specification", + "testing", + "tests" + ], + "time": "2018-10-29T08:12:52+00:00" + }, + { + "name": "phpspec/prophecy", + "version": "1.8.1", + "source": { + "type": "git", + "url": "https://github.com/phpspec/prophecy.git", + "reference": "1927e75f4ed19131ec9bcc3b002e07fb1173ee76" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/1927e75f4ed19131ec9bcc3b002e07fb1173ee76", + "reference": "1927e75f4ed19131ec9bcc3b002e07fb1173ee76", + "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|^3.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 || ^7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.8.x-dev" + } + }, + "autoload": { + "psr-4": { + "Prophecy\\": "src/Prophecy" + } + }, + "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": "2019-06-13T12:50:23+00:00" + }, + { + "name": "phpstan/phpdoc-parser", + "version": "0.3.5", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpdoc-parser.git", + "reference": "8c4ef2aefd9788238897b678a985e1d5c8df6db4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/8c4ef2aefd9788238897b678a985e1d5c8df6db4", + "reference": "8c4ef2aefd9788238897b678a985e1d5c8df6db4", + "shasum": "" + }, + "require": { + "php": "~7.1" + }, + "require-dev": { + "consistence/coding-standard": "^3.5", + "jakub-onderka/php-parallel-lint": "^0.9.2", + "phing/phing": "^2.16.0", + "phpstan/phpstan": "^0.10", + "phpunit/phpunit": "^6.3", + "slevomat/coding-standard": "^4.7.2", + "squizlabs/php_codesniffer": "^3.3.2", + "symfony/process": "^3.4 || ^4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "0.3-dev" + } + }, + "autoload": { + "psr-4": { + "PHPStan\\PhpDocParser\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPDoc parser with support for nullable, intersection and generic types", + "time": "2019-06-07T19:13:52+00:00" + }, + { + "name": "phpstan/phpstan", + "version": "0.11.8", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan.git", + "reference": "fcf0081bf3a254ddacffa03e78be87842d0c09c9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/fcf0081bf3a254ddacffa03e78be87842d0c09c9", + "reference": "fcf0081bf3a254ddacffa03e78be87842d0c09c9", + "shasum": "" + }, + "require": { + "composer/xdebug-handler": "^1.3.0", + "jean85/pretty-package-versions": "^1.0.3", + "nette/bootstrap": "^2.4 || ^3.0", + "nette/di": "^2.4.7 || ^3.0", + "nette/robot-loader": "^3.0.1", + "nette/schema": "^1.0", + "nette/utils": "^2.4.5 || ^3.0", + "nikic/php-parser": "^4.0.2", + "php": "~7.1", + "phpstan/phpdoc-parser": "^0.3.4", + "symfony/console": "~3.2 || ~4.0", + "symfony/finder": "~3.2 || ~4.0" + }, + "conflict": { + "symfony/console": "3.4.16 || 4.1.5" + }, + "require-dev": { + "brianium/paratest": "^2.0", + "consistence/coding-standard": "^3.5", + "dealerdirect/phpcodesniffer-composer-installer": "^0.4.4", + "ext-intl": "*", + "ext-mysqli": "*", + "ext-soap": "*", + "ext-zip": "*", + "jakub-onderka/php-parallel-lint": "^1.0", + "localheinz/composer-normalize": "^1.1.0", + "phing/phing": "^2.16.0", + "phpstan/phpstan-deprecation-rules": "^0.11", + "phpstan/phpstan-php-parser": "^0.11", + "phpstan/phpstan-phpunit": "^0.11", + "phpstan/phpstan-strict-rules": "^0.11", + "phpunit/phpunit": "^7.0", + "slevomat/coding-standard": "^4.7.2", + "squizlabs/php_codesniffer": "^3.3.2" + }, + "bin": [ + "bin/phpstan" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "0.11-dev" + } + }, + "autoload": { + "psr-4": { + "PHPStan\\": [ + "src/", + "build/PHPStan" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPStan - PHP Static Analysis Tool", + "time": "2019-05-28T19:58:33+00:00" + }, + { + "name": "sebastian/comparator", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "5de4fc177adf9bce8df98d8d141a7559d7ccf6da" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/5de4fc177adf9bce8df98d8d141a7559d7ccf6da", + "reference": "5de4fc177adf9bce8df98d8d141a7559d7ccf6da", + "shasum": "" + }, + "require": { + "php": "^7.1", + "sebastian/diff": "^3.0", + "sebastian/exporter": "^3.1" + }, + "require-dev": { + "phpunit/phpunit": "^7.1" + }, + "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": "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-07-12T15:12:46+00:00" + }, + { + "name": "sebastian/diff", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "720fcc7e9b5cf384ea68d9d930d480907a0c1a29" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/720fcc7e9b5cf384ea68d9d930d480907a0c1a29", + "reference": "720fcc7e9b5cf384ea68d9d930d480907a0c1a29", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "require-dev": { + "phpunit/phpunit": "^7.5 || ^8.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": "2019-02-04T06:01:07+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/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": "seld/jsonlint", + "version": "1.7.1", + "source": { + "type": "git", + "url": "https://github.com/Seldaek/jsonlint.git", + "reference": "d15f59a67ff805a44c50ea0516d2341740f81a38" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/d15f59a67ff805a44c50ea0516d2341740f81a38", + "reference": "d15f59a67ff805a44c50ea0516d2341740f81a38", + "shasum": "" + }, + "require": { + "php": "^5.3 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" + }, + "bin": [ + "bin/jsonlint" + ], + "type": "library", + "autoload": { + "psr-4": { + "Seld\\JsonLint\\": "src/Seld/JsonLint/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "JSON Linter", + "keywords": [ + "json", + "linter", + "parser", + "validator" + ], + "time": "2018-01-24T12:46:19+00:00" + }, + { + "name": "seld/phar-utils", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/Seldaek/phar-utils.git", + "reference": "7009b5139491975ef6486545a39f3e6dad5ac30a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Seldaek/phar-utils/zipball/7009b5139491975ef6486545a39f3e6dad5ac30a", + "reference": "7009b5139491975ef6486545a39f3e6dad5ac30a", + "shasum": "" + }, + "require": { + "php": ">=5.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Seld\\PharUtils\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be" + } + ], + "description": "PHAR file format utilities, for when PHP phars you up", + "keywords": [ + "phra" + ], + "time": "2015-10-13T18:44:15+00:00" + }, + { + "name": "symfony/options-resolver", + "version": "v4.2.9", + "source": { + "type": "git", + "url": "https://github.com/symfony/options-resolver.git", + "reference": "664929ad1eb17ca140662fa49e713ae1c93fe0e8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/664929ad1eb17ca140662fa49e713ae1c93fe0e8", + "reference": "664929ad1eb17ca140662fa49e713ae1c93fe0e8", + "shasum": "" + }, + "require": { + "php": "^7.1.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\OptionsResolver\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony OptionsResolver Component", + "homepage": "https://symfony.com", + "keywords": [ + "config", + "configuration", + "options" + ], + "time": "2019-05-10T05:33:12+00:00" + }, + { + "name": "symfony/polyfill-php72", + "version": "v1.11.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php72.git", + "reference": "ab50dcf166d5f577978419edd37aa2bb8eabce0c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/ab50dcf166d5f577978419edd37aa2bb8eabce0c", + "reference": "ab50dcf166d5f577978419edd37aa2bb8eabce0c", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.11-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php72\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "time": "2019-02-06T07:57:58+00:00" + }, + { + "name": "symfony/process", + "version": "v4.2.9", + "source": { + "type": "git", + "url": "https://github.com/symfony/process.git", + "reference": "57f11a07b34f009ef64a3f95ad218f895ad95374" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/process/zipball/57f11a07b34f009ef64a3f95ad218f895ad95374", + "reference": "57f11a07b34f009ef64a3f95ad218f895ad95374", + "shasum": "" + }, + "require": { + "php": "^7.1.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Process\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Process Component", + "homepage": "https://symfony.com", + "time": "2019-05-26T20:47:34+00:00" + }, + { + "name": "symfony/profiler-pack", + "version": "v1.0.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/profiler-pack.git", + "reference": "99c4370632c2a59bb0444852f92140074ef02209" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/profiler-pack/zipball/99c4370632c2a59bb0444852f92140074ef02209", + "reference": "99c4370632c2a59bb0444852f92140074ef02209", + "shasum": "" + }, + "require": { + "php": "^7.0", + "symfony/stopwatch": "*", + "symfony/twig-bundle": "*", + "symfony/web-profiler-bundle": "*" + }, + "type": "symfony-pack", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A pack for the Symfony web profiler", + "time": "2018-12-10T12:11:44+00:00" + }, + { + "name": "symfony/stopwatch", + "version": "v4.2.9", + "source": { + "type": "git", + "url": "https://github.com/symfony/stopwatch.git", + "reference": "b1a5f646d56a3290230dbc8edf2a0d62cda23f67" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/b1a5f646d56a3290230dbc8edf2a0d62cda23f67", + "reference": "b1a5f646d56a3290230dbc8edf2a0d62cda23f67", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/contracts": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Stopwatch\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Stopwatch Component", + "homepage": "https://symfony.com", + "time": "2019-01-16T20:31:39+00:00" + }, + { + "name": "symfony/twig-bridge", + "version": "v4.2.9", + "source": { + "type": "git", + "url": "https://github.com/symfony/twig-bridge.git", + "reference": "43d65f955d05e21a4ee0904a6212790ba9b05093" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/43d65f955d05e21a4ee0904a6212790ba9b05093", + "reference": "43d65f955d05e21a4ee0904a6212790ba9b05093", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/contracts": "^1.0.2", + "twig/twig": "^1.41|^2.10" + }, + "conflict": { + "symfony/console": "<3.4", + "symfony/form": "<4.2.4", + "symfony/translation": "<4.2" + }, + "require-dev": { + "symfony/asset": "~3.4|~4.0", + "symfony/console": "~3.4|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/expression-language": "~3.4|~4.0", + "symfony/finder": "~3.4|~4.0", + "symfony/form": "^4.2.4", + "symfony/http-foundation": "~3.4|~4.0", + "symfony/http-kernel": "~3.4|~4.0", + "symfony/polyfill-intl-icu": "~1.0", + "symfony/routing": "~3.4|~4.0", + "symfony/security": "~3.4|~4.0", + "symfony/security-acl": "~2.8|~3.0", + "symfony/stopwatch": "~3.4|~4.0", + "symfony/templating": "~3.4|~4.0", + "symfony/translation": "~4.2", + "symfony/var-dumper": "~3.4|~4.0", + "symfony/web-link": "~3.4|~4.0", + "symfony/workflow": "~3.4|~4.0", + "symfony/yaml": "~3.4|~4.0" + }, + "suggest": { + "symfony/asset": "For using the AssetExtension", + "symfony/expression-language": "For using the ExpressionExtension", + "symfony/finder": "", + "symfony/form": "For using the FormExtension", + "symfony/http-kernel": "For using the HttpKernelExtension", + "symfony/routing": "For using the RoutingExtension", + "symfony/security": "For using the SecurityExtension", + "symfony/stopwatch": "For using the StopwatchExtension", + "symfony/templating": "For using the TwigEngine", + "symfony/translation": "For using the TranslationExtension", + "symfony/var-dumper": "For using the DumpExtension", + "symfony/web-link": "For using the WebLinkExtension", + "symfony/yaml": "For using the YamlExtension" + }, + "type": "symfony-bridge", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Bridge\\Twig\\": "" + }, + "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 Twig Bridge", + "homepage": "https://symfony.com", + "time": "2019-05-10T06:54:47+00:00" + }, + { + "name": "symfony/twig-bundle", + "version": "v4.2.9", + "source": { + "type": "git", + "url": "https://github.com/symfony/twig-bundle.git", + "reference": "3bb863ffabad2be25b9d5a5d8f7dd4458b8e2fa8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/twig-bundle/zipball/3bb863ffabad2be25b9d5a5d8f7dd4458b8e2fa8", + "reference": "3bb863ffabad2be25b9d5a5d8f7dd4458b8e2fa8", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/config": "~4.2", + "symfony/http-foundation": "~4.1", + "symfony/http-kernel": "~4.1", + "symfony/polyfill-ctype": "~1.8", + "symfony/twig-bridge": "^4.2", + "twig/twig": "~1.41|~2.10" + }, + "conflict": { + "symfony/dependency-injection": "<4.1", + "symfony/framework-bundle": "<4.1", + "symfony/translation": "<4.2" + }, + "require-dev": { + "doctrine/annotations": "~1.0", + "doctrine/cache": "~1.0", + "symfony/asset": "~3.4|~4.0", + "symfony/dependency-injection": "^4.2.5", + "symfony/expression-language": "~3.4|~4.0", + "symfony/finder": "~3.4|~4.0", + "symfony/form": "~3.4|~4.0", + "symfony/framework-bundle": "~4.1", + "symfony/routing": "~3.4|~4.0", + "symfony/stopwatch": "~3.4|~4.0", + "symfony/templating": "~3.4|~4.0", + "symfony/translation": "^4.2", + "symfony/web-link": "~3.4|~4.0", + "symfony/yaml": "~3.4|~4.0" + }, + "type": "symfony-bundle", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Bundle\\TwigBundle\\": "" + }, + "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 TwigBundle", + "homepage": "https://symfony.com", + "time": "2019-05-10T06:54:47+00:00" + }, + { + "name": "symfony/var-dumper", + "version": "v4.2.9", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-dumper.git", + "reference": "3c4084cb1537c0e2ad41aad622bbf55a44a5c9ce" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/3c4084cb1537c0e2ad41aad622bbf55a44a5c9ce", + "reference": "3c4084cb1537c0e2ad41aad622bbf55a44a5c9ce", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php72": "~1.5" + }, + "conflict": { + "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0", + "symfony/console": "<3.4" + }, + "require-dev": { + "ext-iconv": "*", + "symfony/console": "~3.4|~4.0", + "symfony/process": "~3.4|~4.0", + "twig/twig": "~1.34|~2.4" + }, + "suggest": { + "ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).", + "ext-intl": "To show region name in time zone dump", + "symfony/console": "To use the ServerDumpCommand and/or the bin/var-dump-server script" + }, + "bin": [ + "Resources/bin/var-dump-server" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "files": [ + "Resources/functions/dump.php" + ], + "psr-4": { + "Symfony\\Component\\VarDumper\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "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 mechanism for exploring and dumping PHP variables", + "homepage": "https://symfony.com", + "keywords": [ + "debug", + "dump" + ], + "time": "2019-05-01T12:55:36+00:00" + }, + { + "name": "symfony/web-profiler-bundle", + "version": "v4.2.9", + "source": { + "type": "git", + "url": "https://github.com/symfony/web-profiler-bundle.git", + "reference": "1bd05666e23aff4306d7b236b6ccdf6d2e99fe00" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/1bd05666e23aff4306d7b236b6ccdf6d2e99fe00", + "reference": "1bd05666e23aff4306d7b236b6ccdf6d2e99fe00", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/config": "^4.2", + "symfony/http-kernel": "^4.2.6", + "symfony/routing": "~3.4|~4.0", + "symfony/twig-bundle": "~4.2", + "symfony/var-dumper": "~3.4|~4.0", + "twig/twig": "^1.41|^2.10" + }, + "conflict": { + "symfony/dependency-injection": "<3.4", + "symfony/event-dispatcher": "<3.4", + "symfony/messenger": "<4.2", + "symfony/var-dumper": "<3.4" + }, + "require-dev": { + "symfony/console": "~3.4|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/stopwatch": "~3.4|~4.0" + }, + "type": "symfony-bundle", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Bundle\\WebProfilerBundle\\": "" + }, + "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 WebProfilerBundle", + "homepage": "https://symfony.com", + "time": "2019-05-26T20:47:34+00:00" + }, + { + "name": "twig/twig", + "version": "v2.11.3", + "source": { + "type": "git", + "url": "https://github.com/twigphp/Twig.git", + "reference": "699ed2342557c88789a15402de5eb834dedd6792" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/699ed2342557c88789a15402de5eb834dedd6792", + "reference": "699ed2342557c88789a15402de5eb834dedd6792", + "shasum": "" + }, + "require": { + "php": "^7.0", + "symfony/polyfill-ctype": "^1.8", + "symfony/polyfill-mbstring": "^1.3" + }, + "require-dev": { + "psr/container": "^1.0", + "symfony/debug": "^2.7", + "symfony/phpunit-bridge": "^3.4.19|^4.1.8|^5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.11-dev" + } + }, + "autoload": { + "psr-0": { + "Twig_": "lib/" + }, + "psr-4": { + "Twig\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com", + "homepage": "http://fabien.potencier.org", + "role": "Lead Developer" + }, + { + "name": "Armin Ronacher", + "email": "armin.ronacher@active-4.com", + "role": "Project Founder" + }, + { + "name": "Twig Team", + "homepage": "https://twig.symfony.com/contributors", + "role": "Contributors" + } + ], + "description": "Twig, the flexible, fast, and secure template language for PHP", + "homepage": "https://twig.symfony.com", + "keywords": [ + "templating" + ], + "time": "2019-06-18T15:37:11+00:00" + }, + { + "name": "vimeo/psalm", + "version": "3.4.5", + "source": { + "type": "git", + "url": "https://github.com/vimeo/psalm.git", + "reference": "a0866da88e605adaa648e9f1ad37f4990650f55c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/vimeo/psalm/zipball/a0866da88e605adaa648e9f1ad37f4990650f55c", + "reference": "a0866da88e605adaa648e9f1ad37f4990650f55c", + "shasum": "" + }, + "require": { + "amphp/amp": "^2.1", + "amphp/byte-stream": "^1.5", + "composer/xdebug-handler": "^1.1", + "felixfbecker/advanced-json-rpc": "^3.0.3", + "felixfbecker/language-server-protocol": "^1.2", + "netresearch/jsonmapper": "^1.0", + "nikic/php-parser": "^4.2", + "ocramius/package-versions": "^1.2", + "openlss/lib-array2xml": "^1.0", + "php": "^7.1", + "sebastian/diff": "^3.0", + "symfony/console": "^3.3||^4.0", + "webmozart/glob": "^4.1", + "webmozart/path-util": "^2.3" + }, + "provide": { + "psalm/psalm": "self.version" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.2", + "phpmyadmin/sql-parser": "^5.0", + "phpunit/phpunit": "^7.5 || ^8.0", + "psalm/plugin-phpunit": "^0.6", + "squizlabs/php_codesniffer": "3.4.0" + }, + "suggest": { + "ext-igbinary": "^2.0.5" + }, + "bin": [ + "psalm", + "psalter", + "psalm-language-server", + "psalm-plugin", + "psalm-refactor" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev", + "dev-2.x": "2.x-dev", + "dev-1.x": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psalm\\Plugin\\": "src/Psalm/Plugin", + "Psalm\\": "src/Psalm" + }, + "files": [ + "src/functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Matthew Brown" + } + ], + "description": "A static analysis tool for finding errors in PHP applications", + "keywords": [ + "code", + "inspection", + "php" + ], + "time": "2019-06-16T16:45:02+00:00" + }, + { + "name": "webmozart/assert", + "version": "1.4.0", + "source": { + "type": "git", + "url": "https://github.com/webmozart/assert.git", + "reference": "83e253c8e0be5b0257b881e1827274667c5c17a9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozart/assert/zipball/83e253c8e0be5b0257b881e1827274667c5c17a9", + "reference": "83e253c8e0be5b0257b881e1827274667c5c17a9", + "shasum": "" + }, + "require": { + "php": "^5.3.3 || ^7.0", + "symfony/polyfill-ctype": "^1.8" + }, + "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-12-25T11:19:39+00:00" + }, + { + "name": "webmozart/glob", + "version": "4.1.0", + "source": { + "type": "git", + "url": "https://github.com/webmozart/glob.git", + "reference": "3cbf63d4973cf9d780b93d2da8eec7e4a9e63bbe" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozart/glob/zipball/3cbf63d4973cf9d780b93d2da8eec7e4a9e63bbe", + "reference": "3cbf63d4973cf9d780b93d2da8eec7e4a9e63bbe", + "shasum": "" + }, + "require": { + "php": "^5.3.3|^7.0", + "webmozart/path-util": "^2.2" + }, + "require-dev": { + "phpunit/phpunit": "^4.6", + "sebastian/version": "^1.0.1", + "symfony/filesystem": "^2.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.1-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Glob\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "A PHP implementation of Ant's glob.", + "time": "2015-12-29T11:14:33+00:00" + }, + { + "name": "webmozart/path-util", + "version": "2.3.0", + "source": { + "type": "git", + "url": "https://github.com/webmozart/path-util.git", + "reference": "d939f7edc24c9a1bb9c0dee5cb05d8e859490725" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozart/path-util/zipball/d939f7edc24c9a1bb9c0dee5cb05d8e859490725", + "reference": "d939f7edc24c9a1bb9c0dee5cb05d8e859490725", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "webmozart/assert": "~1.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.6", + "sebastian/version": "^1.0.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.3-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\PathUtil\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "A robust cross-platform utility for normalizing, comparing and modifying file paths.", + "time": "2015-12-17T08:42:14+00:00" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": "^7.3", + "ext-ctype": "*", + "ext-iconv": "*" + }, + "platform-dev": [] +} diff --git a/config/bootstrap.php b/config/bootstrap.php new file mode 100644 index 0000000..570bb92 --- /dev/null +++ b/config/bootstrap.php @@ -0,0 +1,21 @@ +=1.2) +if (is_array($env = @include dirname(__DIR__).'/.env.local.php')) { + $_ENV += $env; +} elseif (!class_exists(Dotenv::class)) { + throw new RuntimeException('Please run "composer require symfony/dotenv" to load the ".env" files configuring the application.'); +} else { + // load all the .env files + (new Dotenv(false))->loadEnv(dirname(__DIR__).'/.env'); +} + +$_SERVER += $_ENV; +$_SERVER['APP_ENV'] = $_ENV['APP_ENV'] = ($_SERVER['APP_ENV'] ?? $_ENV['APP_ENV'] ?? null) ?: 'dev'; +$_SERVER['APP_DEBUG'] = $_SERVER['APP_DEBUG'] ?? $_ENV['APP_DEBUG'] ?? 'prod' !== $_SERVER['APP_ENV']; +$_SERVER['APP_DEBUG'] = $_ENV['APP_DEBUG'] = (int) $_SERVER['APP_DEBUG'] || filter_var($_SERVER['APP_DEBUG'], FILTER_VALIDATE_BOOLEAN) ? '1' : '0'; diff --git a/config/bundles.php b/config/bundles.php new file mode 100644 index 0000000..7d86e4c --- /dev/null +++ b/config/bundles.php @@ -0,0 +1,8 @@ + ['all' => true], + Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle::class => ['all' => true], + Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true], + Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true], +]; diff --git a/config/packages/cache.yaml b/config/packages/cache.yaml new file mode 100644 index 0000000..93e620e --- /dev/null +++ b/config/packages/cache.yaml @@ -0,0 +1,19 @@ +framework: + cache: + # Put the unique name of your app here: the prefix seed + # is used to compute stable namespaces for cache keys. + #prefix_seed: your_vendor_name/app_name + + # The app cache caches to the filesystem by default. + # Other options include: + + # Redis + #app: cache.adapter.redis + #default_redis_provider: redis://localhost + + # APCu (not recommended with heavy random-write workloads as memory fragmentation can cause perf issues) + #app: cache.adapter.apcu + + # Namespaced pools use the above "app" backend by default + #pools: + #my.dedicated.cache: ~ diff --git a/config/packages/concept_scheme.yaml b/config/packages/concept_scheme.yaml new file mode 100644 index 0000000..d59b9ce --- /dev/null +++ b/config/packages/concept_scheme.yaml @@ -0,0 +1,22 @@ +services: + # default configuration for services in *this* file + _defaults: + autowire: true # Automatically injects dependencies in your services. + autoconfigure: true # Automatically registers your services as commands, event subscribers, etc. + + App\OpenSkos\ConceptScheme\Controller\: + resource: '../../src/OpenSkos/ConceptScheme/Controller/*' + tags: ['controller.service_arguments'] + + # TODO: Instead of building OpenSkosIriFactory we can create dedicate InstitutionIriFactory + # To cover all our needs + concept_scheme.iri_factory: + class: App\OpenSkos\OpenSkosIriFactory + arguments: + $namespace: 'http://tenant' + + App\OpenSkos\ConceptScheme\Sparql\SparqlConceptSchemeRepository: + arguments: + $iriFactory: '@concept_scheme.iri_factory' + + App\OpenSkos\ConceptScheme\ConceptSchemeRepository: '@App\OpenSkos\ConceptScheme\Sparql\SparqlConceptSchemeRepository' diff --git a/config/packages/databases.yaml b/config/packages/databases.yaml new file mode 100644 index 0000000..bc69147 --- /dev/null +++ b/config/packages/databases.yaml @@ -0,0 +1,5 @@ +parameters: + #query_uri: 'http://192.168.56.10:3030/beg-openskos-production/query' + #update_uri: 'http://192.168.56.10:3030/beg-openskos-production/update' + query_uri: 'http://jena-01.pictura-hosting.nl:3030/openskos-beg-test/query' + update_uri: 'http://jena-01.pictura-hosting.nl:3030/openskos-beg-test/update' diff --git a/config/packages/dev/routing.yaml b/config/packages/dev/routing.yaml new file mode 100644 index 0000000..4116679 --- /dev/null +++ b/config/packages/dev/routing.yaml @@ -0,0 +1,3 @@ +framework: + router: + strict_requirements: true diff --git a/config/packages/dev/web_profiler.yaml b/config/packages/dev/web_profiler.yaml new file mode 100644 index 0000000..e92166a --- /dev/null +++ b/config/packages/dev/web_profiler.yaml @@ -0,0 +1,6 @@ +web_profiler: + toolbar: true + intercept_redirects: false + +framework: + profiler: { only_exceptions: false } diff --git a/config/packages/framework.yaml b/config/packages/framework.yaml new file mode 100644 index 0000000..d3f884c --- /dev/null +++ b/config/packages/framework.yaml @@ -0,0 +1,17 @@ +framework: + secret: '%env(APP_SECRET)%' + #default_locale: en + #csrf_protection: true + #http_method_override: true + + # Enables session support. Note that the session will ONLY be started if you read or write from it. + # Remove or comment this section to explicitly disable session support. + session: + handler_id: ~ + cookie_secure: auto + cookie_samesite: lax + + #esi: true + #fragments: true + php_errors: + log: true diff --git a/config/packages/healthcheck.yaml b/config/packages/healthcheck.yaml new file mode 100644 index 0000000..6d2701c --- /dev/null +++ b/config/packages/healthcheck.yaml @@ -0,0 +1,9 @@ +#TODO: Think about moving this configuration file into src/Healthcheck/config so it will be close to the related code +services: + # default configuration for services in *this* file + _defaults: + autowire: true # Automatically injects dependencies in your services. + autoconfigure: true # Automatically registers your services as commands, event subscribers, etc. + + App\Healthcheck\PingController: + tags: ['controller.service_arguments'] diff --git a/config/packages/institution.yaml b/config/packages/institution.yaml new file mode 100644 index 0000000..9a0770e --- /dev/null +++ b/config/packages/institution.yaml @@ -0,0 +1,22 @@ +services: + # default configuration for services in *this* file + _defaults: + autowire: true # Automatically injects dependencies in your services. + autoconfigure: true # Automatically registers your services as commands, event subscribers, etc. + + App\OpenSkos\Institution\Controller\: + resource: '../../src/OpenSkos/Institution/Controller/*' + tags: ['controller.service_arguments'] + + # TODO: Instead of building OpenSkosIriFactory we can create dedicate InstitutionIriFactory + # To cover all our needs + institution.iri_factory: + class: App\OpenSkos\OpenSkosIriFactory + arguments: + $namespace: 'http://tenant' + + App\OpenSkos\Institution\Sparql\SparqlInstitutionRepository: + arguments: + $iriFactory: '@institution.iri_factory' + + App\OpenSkos\Institution\InstitutionRepository: '@App\OpenSkos\Institution\Sparql\SparqlInstitutionRepository' diff --git a/config/packages/openskos.yaml b/config/packages/openskos.yaml new file mode 100644 index 0000000..bc3c4ba --- /dev/null +++ b/config/packages/openskos.yaml @@ -0,0 +1,21 @@ +services: + # default configuration for services in *this* file + _defaults: + autowire: true # Automatically injects dependencies in your services. + autoconfigure: true # Automatically registers your services as commands, event subscribers, etc. + + + EasyRdf_Sparql_Client: + class: EasyRdf_Sparql_Client + arguments: + $queryUri: '%env(SPARQL_QUERY_URI)%' + $updateUri: '%env(SPARQL_UPDATE_URI)%' + + + App\EasyRdf\EasyRdfClient: + arguments: ['@EasyRdf_Sparql_Client'] + + App\Rdf\Sparql\Client: '@App\EasyRdf\EasyRdfClient' + + App\Rdf\Format\RdfFormatFactory: + factory: [ 'App\Rdf\Format\RdfFormatFactory', 'loadDefault' ] diff --git a/config/packages/routing.yaml b/config/packages/routing.yaml new file mode 100644 index 0000000..a15c4ec --- /dev/null +++ b/config/packages/routing.yaml @@ -0,0 +1,4 @@ +framework: + router: + strict_requirements: ~ + utf8: true diff --git a/config/packages/sensio_framework_extra.yaml b/config/packages/sensio_framework_extra.yaml new file mode 100644 index 0000000..1821ccc --- /dev/null +++ b/config/packages/sensio_framework_extra.yaml @@ -0,0 +1,3 @@ +sensio_framework_extra: + router: + annotations: false diff --git a/config/packages/set.yaml b/config/packages/set.yaml new file mode 100644 index 0000000..a613d64 --- /dev/null +++ b/config/packages/set.yaml @@ -0,0 +1,22 @@ +services: + # default configuration for services in *this* file + _defaults: + autowire: true # Automatically injects dependencies in your services. + autoconfigure: true # Automatically registers your services as commands, event subscribers, etc. + + App\OpenSkos\Set\Controller\: + resource: '../../src/OpenSkos/Set/Controller/*' + tags: ['controller.service_arguments'] + + # TODO: Instead of building OpenSkosIriFactory we can create dedicate InstitutionIriFactory + # To cover all our needs + set.iri_factory: + class: App\OpenSkos\OpenSkosIriFactory + arguments: + $namespace: 'http://tenant' + + App\OpenSkos\Set\Sparql\SparqlSetRepository: + arguments: + $iriFactory: '@set.iri_factory' + + App\OpenSkos\Set\SetRepository: '@App\OpenSkos\Set\Sparql\SparqlSetRepository' diff --git a/config/packages/test/framework.yaml b/config/packages/test/framework.yaml new file mode 100644 index 0000000..d051c84 --- /dev/null +++ b/config/packages/test/framework.yaml @@ -0,0 +1,4 @@ +framework: + test: true + session: + storage_id: session.storage.mock_file diff --git a/config/packages/test/routing.yaml b/config/packages/test/routing.yaml new file mode 100644 index 0000000..4116679 --- /dev/null +++ b/config/packages/test/routing.yaml @@ -0,0 +1,3 @@ +framework: + router: + strict_requirements: true diff --git a/config/packages/test/web_profiler.yaml b/config/packages/test/web_profiler.yaml new file mode 100644 index 0000000..03752de --- /dev/null +++ b/config/packages/test/web_profiler.yaml @@ -0,0 +1,6 @@ +web_profiler: + toolbar: false + intercept_redirects: false + +framework: + profiler: { collect: false } diff --git a/config/packages/twig.yaml b/config/packages/twig.yaml new file mode 100644 index 0000000..d1582a2 --- /dev/null +++ b/config/packages/twig.yaml @@ -0,0 +1,4 @@ +twig: + default_path: '%kernel.project_dir%/templates' + debug: '%kernel.debug%' + strict_variables: '%kernel.debug%' diff --git a/config/routes.yaml b/config/routes.yaml new file mode 100644 index 0000000..c3283aa --- /dev/null +++ b/config/routes.yaml @@ -0,0 +1,3 @@ +#index: +# path: / +# controller: App\Controller\DefaultController::index diff --git a/config/routes/annotations.yaml b/config/routes/annotations.yaml new file mode 100644 index 0000000..e9b76aa --- /dev/null +++ b/config/routes/annotations.yaml @@ -0,0 +1,18 @@ +#TODO: Move this configuration into package level. +#TODO: For example into config/packages/healthcheck.yaml + +healthcheck: + resource: ../../src/Healthcheck/ + type: annotation + +institution: + resource: ../../src/OpenSkos/Institution/Controller + type: annotation + +set: + resource: ../../src/OpenSkos/Set/Controller + type: annotation + +conceptscheme: + resource: ../../src/OpenSkos/ConceptScheme/Controller + type: annotation diff --git a/config/routes/dev/twig.yaml b/config/routes/dev/twig.yaml new file mode 100644 index 0000000..f4ee839 --- /dev/null +++ b/config/routes/dev/twig.yaml @@ -0,0 +1,3 @@ +_errors: + resource: '@TwigBundle/Resources/config/routing/errors.xml' + prefix: /_error diff --git a/config/routes/dev/web_profiler.yaml b/config/routes/dev/web_profiler.yaml new file mode 100644 index 0000000..c82beff --- /dev/null +++ b/config/routes/dev/web_profiler.yaml @@ -0,0 +1,7 @@ +web_profiler_wdt: + resource: '@WebProfilerBundle/Resources/config/routing/wdt.xml' + prefix: /_wdt + +web_profiler_profiler: + resource: '@WebProfilerBundle/Resources/config/routing/profiler.xml' + prefix: /_profiler diff --git a/config/services.yaml b/config/services.yaml new file mode 100644 index 0000000..58478b3 --- /dev/null +++ b/config/services.yaml @@ -0,0 +1,30 @@ +# This file is the entry point to configure your own services. +# Files in the packages/ subdirectory configure your dependencies. + +# Put parameters here that don't need to change on each machine where the app is deployed +# https://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration +parameters: + + +imports: + - { resource: './packages/databases.yaml' } + +services: + # default configuration for services in *this* file + + App\Rest\ControllerResponseListener: + autowire: true + tags: + - { name: 'kernel.event_listener', event: 'kernel.view' } + + App\Serializer\RdfEncoder: + autowire: true + tags: ['serializer.encoder'] + + App\Rest\ArgumentResolver\ApiRequestResolver: + autowire: true + tags: ['controller.argument_value_resolver'] + + App\Rest\ArgumentResolver\InternalResourceIdResolver: + tags: + - { name: controller.argument_value_resolver, priority: 100 } \ No newline at end of file diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml new file mode 100644 index 0000000..5cce7b0 --- /dev/null +++ b/docker/docker-compose.yml @@ -0,0 +1,28 @@ +version: "3.5" + +services: + fpm: + build: + context: .. + dockerfile: docker/fpm/Dockerfile + networks: + - default + - openskos + env_file: + - fpm/symfony.env + volumes: + - ../:/app + + nginx: + build: nginx + env_file: + - nginx/default.env + ports: + - 9020:80 + volumes: + - ./nginx:/app:ro + +networks: + openskos: + external: + name: openskos \ No newline at end of file diff --git a/docker/fpm/Dockerfile b/docker/fpm/Dockerfile new file mode 100644 index 0000000..cccda46 --- /dev/null +++ b/docker/fpm/Dockerfile @@ -0,0 +1,20 @@ +FROM php:7.3-fpm + +WORKDIR /app + +RUN apt update \ + && apt install -y libicu-dev \ + && docker-php-ext-install intl \ + && docker-php-ext-enable opcache \ + && rm -rf /var/lib/apt/lists/* \ + && mkdir -p /app/var + +COPY docker/fpm/php.ini /usr/local/etc/ + +COPY bin bin/ +COPY config config/ +COPY src src/ +COPY public public/ +COPY vendor vendor/ +COPY composer.* ./ + diff --git a/docker/fpm/php.ini b/docker/fpm/php.ini new file mode 100644 index 0000000..a427aa1 --- /dev/null +++ b/docker/fpm/php.ini @@ -0,0 +1,366 @@ +[global] +error_log = /proc/self/fd/2 +short_open_tag = off + +[www] +; if we send this to /proc/self/fd/1, it never appears +access.log = /proc/self/fd/2 + +clear_env = no + +; Ensure worker stdout and stderr are sent to the main error log. +catch_workers_output = yes + +;Default Configuration Below + +user = www-data +group = www-data + +listen = 127.0.0.1:9000 + +; Choose how the process manager will control the number of child processes. +; Possible Values: +; static - a fixed number (pm.max_children) of child processes; +; dynamic - the number of child processes are set dynamically based on the +; following directives. With this process management, there will be +; always at least 1 children. +; pm.max_children - the maximum number of children that can +; be alive at the same time. +; pm.start_servers - the number of children created on startup. +; pm.min_spare_servers - the minimum number of children in 'idle' +; state (waiting to process). If the number +; of 'idle' processes is less than this +; number then some children will be created. +; pm.max_spare_servers - the maximum number of children in 'idle' +; state (waiting to process). If the number +; of 'idle' processes is greater than this +; number then some children will be killed. +; ondemand - no children are created at startup. Children will be forked when +; new requests will connect. The following parameter are used: +; pm.max_children - the maximum number of children that +; can be alive at the same time. +; pm.process_idle_timeout - The number of seconds after which +; an idle process will be killed. +; Note: This value is mandatory. +pm = dynamic + +; The number of child processes to be created when pm is set to 'static' and the +; maximum number of child processes when pm is set to 'dynamic' or 'ondemand'. +; This value sets the limit on the number of simultaneous requests that will be +; served. Equivalent to the ApacheMaxClients directive with mpm_prefork. +; Equivalent to the PHP_FCGI_CHILDREN environment variable in the original PHP +; CGI. The below defaults are based on a server without much resources. Don't +; forget to tweak pm.* to fit your needs. +; Note: Used when pm is set to 'static', 'dynamic' or 'ondemand' +; Note: This value is mandatory. +pm.max_children = 5 + +; The number of child processes created on startup. +; Note: Used only when pm is set to 'dynamic' +; Default Value: min_spare_servers + (max_spare_servers - min_spare_servers) / 2 +pm.start_servers = 2 + +; The desired minimum number of idle server processes. +; Note: Used only when pm is set to 'dynamic' +; Note: Mandatory when pm is set to 'dynamic' +pm.min_spare_servers = 1 + +; The desired maximum number of idle server processes. +; Note: Used only when pm is set to 'dynamic' +; Note: Mandatory when pm is set to 'dynamic' +pm.max_spare_servers = 3 + +; The number of seconds after which an idle process will be killed. +; Note: Used only when pm is set to 'ondemand' +; Default Value: 10s +;pm.process_idle_timeout = 10s; + +; The number of requests each child process should execute before respawning. +; This can be useful to work around memory leaks in 3rd party libraries. For +; endless request processing specify '0'. Equivalent to PHP_FCGI_MAX_REQUESTS. +; Default Value: 0 +;pm.max_requests = 500 + +; The URI to view the FPM status page. If this value is not set, no URI will be +; recognized as a status page. It shows the following informations: +; pool - the name of the pool; +; process manager - static, dynamic or ondemand; +; start time - the date and time FPM has started; +; start since - number of seconds since FPM has started; +; accepted conn - the number of request accepted by the pool; +; listen queue - the number of request in the queue of pending +; connections (see backlog in listen(2)); +; max listen queue - the maximum number of requests in the queue +; of pending connections since FPM has started; +; listen queue len - the size of the socket queue of pending connections; +; idle processes - the number of idle processes; +; active processes - the number of active processes; +; total processes - the number of idle + active processes; +; max active processes - the maximum number of active processes since FPM +; has started; +; max children reached - number of times, the process limit has been reached, +; when pm tries to start more children (works only for +; pm 'dynamic' and 'ondemand'); +; Value are updated in real time. +; Example output: +; pool: www +; process manager: static +; start time: 01/Jul/2011:17:53:49 +0200 +; start since: 62636 +; accepted conn: 190460 +; listen queue: 0 +; max listen queue: 1 +; listen queue len: 42 +; idle processes: 4 +; active processes: 11 +; total processes: 15 +; max active processes: 12 +; max children reached: 0 +; +; By default the status page output is formatted as text/plain. Passing either +; 'html', 'xml' or 'json' in the query string will return the corresponding +; output syntax. Example: +; http://www.foo.bar/status +; http://www.foo.bar/status?json +; http://www.foo.bar/status?html +; http://www.foo.bar/status?xml +; +; By default the status page only outputs short status. Passing 'full' in the +; query string will also return status for each pool process. +; Example: +; http://www.foo.bar/status?full +; http://www.foo.bar/status?json&full +; http://www.foo.bar/status?html&full +; http://www.foo.bar/status?xml&full +; The Full status returns for each process: +; pid - the PID of the process; +; state - the state of the process (Idle, Running, ...); +; start time - the date and time the process has started; +; start since - the number of seconds since the process has started; +; requests - the number of requests the process has served; +; request duration - the duration in µs of the requests; +; request method - the request method (GET, POST, ...); +; request URI - the request URI with the query string; +; content length - the content length of the request (only with POST); +; user - the user (PHP_AUTH_USER) (or '-' if not set); +; script - the main script called (or '-' if not set); +; last request cpu - the %cpu the last request consumed +; it's always 0 if the process is not in Idle state +; because CPU calculation is done when the request +; processing has terminated; +; last request memory - the max amount of memory the last request consumed +; it's always 0 if the process is not in Idle state +; because memory calculation is done when the request +; processing has terminated; +; If the process is in Idle state, then informations are related to the +; last request the process has served. Otherwise informations are related to +; the current request being served. +; Example output: +; ************************ +; pid: 31330 +; state: Running +; start time: 01/Jul/2011:17:53:49 +0200 +; start since: 63087 +; requests: 12808 +; request duration: 1250261 +; request method: GET +; request URI: /test_mem.php?N=10000 +; content length: 0 +; user: - +; script: /home/fat/web/docs/php/test_mem.php +; last request cpu: 0.00 +; last request memory: 0 +; +; Note: There is a real-time FPM status monitoring sample web page available +; It's available in: /usr/local/share/php/fpm/status.html +; +; Note: The value must start with a leading slash (/). The value can be +; anything, but it may not be a good idea to use the .php extension or it +; may conflict with a real PHP file. +; Default Value: not set +;pm.status_path = /status + +; The ping URI to call the monitoring page of FPM. If this value is not set, no +; URI will be recognized as a ping page. This could be used to test from outside +; that FPM is alive and responding, or to +; - create a graph of FPM availability (rrd or such); +; - remove a server from a group if it is not responding (load balancing); +; - trigger alerts for the operating team (24/7). +; Note: The value must start with a leading slash (/). The value can be +; anything, but it may not be a good idea to use the .php extension or it +; may conflict with a real PHP file. +; Default Value: not set +;ping.path = /ping + +; This directive may be used to customize the response of a ping request. The +; response is formatted as text/plain with a 200 response code. +; Default Value: pong +;ping.response = pong + +; The access log file +; Default: not set +;access.log = log/$pool.access.log + +; The access log format. +; The following syntax is allowed +; %%: the '%' character +; %C: %CPU used by the request +; it can accept the following format: +; - %{user}C for user CPU only +; - %{system}C for system CPU only +; - %{total}C for user + system CPU (default) +; %d: time taken to serve the request +; it can accept the following format: +; - %{seconds}d (default) +; - %{miliseconds}d +; - %{mili}d +; - %{microseconds}d +; - %{micro}d +; %e: an environment variable (same as $_ENV or $_SERVER) +; it must be associated with embraces to specify the name of the env +; variable. Some exemples: +; - server specifics like: %{REQUEST_METHOD}e or %{SERVER_PROTOCOL}e +; - HTTP headers like: %{HTTP_HOST}e or %{HTTP_USER_AGENT}e +; %f: script filename +; %l: content-length of the request (for POST request only) +; %m: request method +; %M: peak of memory allocated by PHP +; it can accept the following format: +; - %{bytes}M (default) +; - %{kilobytes}M +; - %{kilo}M +; - %{megabytes}M +; - %{mega}M +; %n: pool name +; %o: output header +; it must be associated with embraces to specify the name of the header: +; - %{Content-Type}o +; - %{X-Powered-By}o +; - %{Transfert-Encoding}o +; - .... +; %p: PID of the child that serviced the request +; %P: PID of the parent of the child that serviced the request +; %q: the query string +; %Q: the '?' character if query string exists +; %r: the request URI (without the query string, see %q and %Q) +; %R: remote IP address +; %s: status (response code) +; %t: server time the request was received +; it can accept a strftime(3) format: +; %d/%b/%Y:%H:%M:%S %z (default) +; The strftime(3) format must be encapsuled in a %{}t tag +; e.g. for a ISO8601 formatted timestring, use: %{%Y-%m-%dT%H:%M:%S%z}t +; %T: time the log has been written (the request has finished) +; it can accept a strftime(3) format: +; %d/%b/%Y:%H:%M:%S %z (default) +; The strftime(3) format must be encapsuled in a %{}t tag +; e.g. for a ISO8601 formatted timestring, use: %{%Y-%m-%dT%H:%M:%S%z}t +; %u: remote user +; +; Default: "%R - %u %t \"%m %r\" %s" +;access.format = "%R - %u %t \"%m %r%Q%q\" %s %f %{mili}d %{kilo}M %C%%" + +; The log file for slow requests +; Default Value: not set +; Note: slowlog is mandatory if request_slowlog_timeout is set +;slowlog = log/$pool.log.slow + +; The timeout for serving a single request after which a PHP backtrace will be +; dumped to the 'slowlog' file. A value of '0s' means 'off'. +; Available units: s(econds)(default), m(inutes), h(ours), or d(ays) +; Default Value: 0 +;request_slowlog_timeout = 0 + +; Depth of slow log stack trace. +; Default Value: 20 +;request_slowlog_trace_depth = 20 + +; The timeout for serving a single request after which the worker process will +; be killed. This option should be used when the 'max_execution_time' ini option +; does not stop script execution for some reason. A value of '0' means 'off'. +; Available units: s(econds)(default), m(inutes), h(ours), or d(ays) +; Default Value: 0 +;request_terminate_timeout = 0 + +; Set open file descriptor rlimit. +; Default Value: system defined value +;rlimit_files = 1024 + +; Set max core size rlimit. +; Possible Values: 'unlimited' or an integer greater or equal to 0 +; Default Value: system defined value +;rlimit_core = 0 + +; Chroot to this directory at the start. This value must be defined as an +; absolute path. When this value is not set, chroot is not used. +; Note: you can prefix with '$prefix' to chroot to the pool prefix or one +; of its subdirectories. If the pool prefix is not set, the global prefix +; will be used instead. +; Note: chrooting is a great security feature and should be used whenever +; possible. However, all PHP paths will be relative to the chroot +; (error_log, sessions.save_path, ...). +; Default Value: not set +;chroot = + +; Chdir to this directory at the start. +; Note: relative path can be used. +; Default Value: current directory or / when chroot +;chdir = /var/www + +; Redirect worker stdout and stderr into main error log. If not set, stdout and +; stderr will be redirected to /dev/null according to FastCGI specs. +; Note: on highloaded environement, this can cause some delay in the page +; process time (several ms). +; Default Value: no +;catch_workers_output = yes + +; Clear environment in FPM workers +; Prevents arbitrary environment variables from reaching FPM worker processes +; by clearing the environment in workers before env vars specified in this +; pool configuration are added. +; Setting to "no" will make all environment variables available to PHP code +; via getenv(), $_ENV and $_SERVER. +; Default Value: yes +;clear_env = no + +; Limits the extensions of the main script FPM will allow to parse. This can +; prevent configuration mistakes on the web server side. You should only limit +; FPM to .php extensions to prevent malicious users to use other extensions to +; execute php code. +; Note: set an empty value to allow all extensions. +; Default Value: .php +;security.limit_extensions = .php .php3 .php4 .php5 .php7 + +; Pass environment variables like LD_LIBRARY_PATH. All $VARIABLEs are taken from +; the current environment. +; Default Value: clean env +;env[HOSTNAME] = $HOSTNAME +;env[PATH] = /usr/local/bin:/usr/bin:/bin +;env[TMP] = /tmp +;env[TMPDIR] = /tmp +;env[TEMP] = /tmp + +; Additional php.ini defines, specific to this pool of workers. These settings +; overwrite the values previously defined in the php.ini. The directives are the +; same as the PHP SAPI: +; php_value/php_flag - you can set classic ini defines which can +; be overwritten from PHP call 'ini_set'. +; php_admin_value/php_admin_flag - these directives won't be overwritten by +; PHP call 'ini_set' +; For php_*flag, valid values are on, off, 1, 0, true, false, yes or no. + +; Defining 'extension' will load the corresponding shared extension from +; extension_dir. Defining 'disable_functions' or 'disable_classes' will not +; overwrite previously defined php.ini values, but will append the new value +; instead. + +; Note: path INI options can be relative and will be expanded with the prefix +; (pool, global or /usr/local) + +; Default Value: nothing is defined by default except the values in php.ini and +; specified at startup with the -d argument +;php_admin_value[sendmail_path] = /usr/sbin/sendmail -t -i -f www@my.domain.com +;php_flag[display_errors] = off +;php_admin_value[error_log] = /var/log/fpm-php.www.log +;php_admin_flag[log_errors] = on +;php_admin_value[memory_limit] = 32M diff --git a/docker/fpm/symfony.env b/docker/fpm/symfony.env new file mode 100644 index 0000000..81c7270 --- /dev/null +++ b/docker/fpm/symfony.env @@ -0,0 +1,13 @@ +# This file is a "template" of which env vars need to be defined for your application +# Copy this file to .env file for development, create environment variables when deploying to production +# https://symfony.com/doc/current/best_practices/configuration.html#infrastructure-related-configuration + +###> symfony/framework-bundle ### +APP_ENV=dev +APP_SECRET=be45ec4c2dbfcb5df488a457fbe4216a +#TRUSTED_PROXIES=127.0.0.1,127.0.0.2 +#TRUSTED_HOSTS='^localhost|example\.com$' +###< symfony/framework-bundle ### + +SPARQL_QUERY_URI=http://openskos-jena-fuseki:3030/openskos/query +SPARQL_UPDATE_URI=http://openskos-jena-fuseki:3030/openskos/update \ No newline at end of file diff --git a/docker/nginx/Dockerfile b/docker/nginx/Dockerfile new file mode 100644 index 0000000..f3ff567 --- /dev/null +++ b/docker/nginx/Dockerfile @@ -0,0 +1,8 @@ +FROM nginx + +WORKDIR /app + +COPY conf/ ./conf +COPY entrypoint.sh ./ + +CMD [ "/bin/bash", "entrypoint.sh" ] \ No newline at end of file diff --git a/docker/nginx/conf/www.d/.gitkeep b/docker/nginx/conf/www.d/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/docker/nginx/conf/www.d/cors.api.nginx b/docker/nginx/conf/www.d/cors.api.nginx new file mode 100644 index 0000000..2d16a8c --- /dev/null +++ b/docker/nginx/conf/www.d/cors.api.nginx @@ -0,0 +1,17 @@ +add_header 'Access-Control-Allow-Credentials' 'true' always; +add_header 'Access-Control-Allow-Origin' $http_origin always; +add_header 'Access-Control-Allow-Headers' $http_access_control_request_headers always; +add_header 'Access-Control-Allow-Methods' $http_access_control_request_method always; +add_header 'Access-Control-Max-Age' 1728000 always; + +if ($request_method = 'OPTIONS') { + add_header 'Access-Control-Allow-Credentials' 'true'; + add_header 'Access-Control-Allow-Origin' $http_origin; + add_header 'Access-Control-Allow-Headers' $http_access_control_request_headers; + add_header 'Access-Control-Allow-Methods' $http_access_control_request_method; + add_header 'Access-Control-Max-Age' 1728000; + + add_header 'Content-Type' 'text/plain; charset=utf-8'; + add_header 'Content-Length' 0; + return 204; +} \ No newline at end of file diff --git a/docker/nginx/conf/www.d/gzip.server.nginx b/docker/nginx/conf/www.d/gzip.server.nginx new file mode 100644 index 0000000..e0622e3 --- /dev/null +++ b/docker/nginx/conf/www.d/gzip.server.nginx @@ -0,0 +1,5 @@ + gzip on; + gzip_comp_level 2; + gzip_min_length 1000; + gzip_proxied expired no-cache no-store private auth; + gzip_types text/plain application/x-javascript application/javascript text/xml text/css application/xml; \ No newline at end of file diff --git a/docker/nginx/conf/www.d/real_ip.server.nginx b/docker/nginx/conf/www.d/real_ip.server.nginx new file mode 100644 index 0000000..68c0748 --- /dev/null +++ b/docker/nginx/conf/www.d/real_ip.server.nginx @@ -0,0 +1,4 @@ +proxy_set_header X-Real-IP $http_x_client_ip; +# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; +proxy_set_header X-Forwarded-For "$http_x_client_ip, $http_x_forwarded_for"; +#proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto; diff --git a/docker/nginx/conf/www.tpl.nginx b/docker/nginx/conf/www.tpl.nginx new file mode 100644 index 0000000..f84ae1c --- /dev/null +++ b/docker/nginx/conf/www.tpl.nginx @@ -0,0 +1,47 @@ +## +# Base configuration only for HTTP connections. +# For HTTPS, you need to update this configuration in order to add +# ssl related stuff +## +# This file is TEMPLATE. All variables like $EXAMPLE or ${EXAMPLE} must be substituded +# the best tools for that kind of substitusion is envsubst https://www.gnu.org/software/gettext/manual/html_node/envsubst-Invocation.html +## +# TODO: Create production verion of that configuration. +# Remove: debug pathes (_profiler, _wdt) from location +# Add proper error redirects +## + +server { + listen $PORT; + server_name $DOMAIN; + + # Include server-related configuration + include www.d/*.server.nginx; + + # Location that forwards all request that didn't matched locations above to FPM server + # Replace location path '/' to appropriate value in other nginx configruations. + location / { + try_files $uri @fpm; + } + + # Named location to proxy HTTP request to Fast CGI server. + location @fpm { + # Include api location related configuration + include www.d/*.api.nginx; + + # General FPM Configuration + set $api_root $FPM_ROOT; + set $api_entrypoint $FPM_ENTRYPOINT; + fastcgi_pass $FPM_URL; + + include fastcgi_params; + fastcgi_param SCRIPT_FILENAME $api_root/$api_entrypoint; + fastcgi_param SCRIPT_NAME $api_entrypoint; + } + + # Restrict access to any other location. + # location / { + # return 403; + # } + +} \ No newline at end of file diff --git a/docker/nginx/default.env b/docker/nginx/default.env new file mode 100644 index 0000000..2ee4e20 --- /dev/null +++ b/docker/nginx/default.env @@ -0,0 +1,15 @@ +## +# Default Environmental Configuration for Nginx Server +## + +APP_ENV=dev + +PORT=80 +DOMAIN=http + +API_PREFIX=api + +# FPM Configuration MUST be syncronized with fpm service +FPM_ROOT=/app/public +FPM_ENTRYPOINT=index.php +FPM_URL=fpm:9000 \ No newline at end of file diff --git a/docker/nginx/entrypoint.sh b/docker/nginx/entrypoint.sh new file mode 100644 index 0000000..5713e51 --- /dev/null +++ b/docker/nginx/entrypoint.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +set -ex + +# Link dynamic configurations of www.conf to nginx +ln -rsf conf/www.d/ /etc/nginx/ + +# Process template file and replace default.conf of nginx +envsubst \ + '$PORT $DOMAIN $API_PREFIX + $FPM_ROOT $FPM_ENTRYPOINT $FPM_URL' \ + < conf/www.tpl.nginx \ + > /etc/nginx/conf.d/default.conf + +if [ "$APP_ENV" == "dev" ]; then + echo "Applied configuration: " + cat /etc/nginx/conf.d/default.conf + echo "" #Print End Of Line for good formatting + echo "End of Configuration." +fi + +# Run nginx +exec nginx-debug -g 'daemon off;' \ No newline at end of file diff --git a/grumphp.yml b/grumphp.yml new file mode 100644 index 0000000..08a8d02 --- /dev/null +++ b/grumphp.yml @@ -0,0 +1,13 @@ +parameters: + git_dir: . + bin_dir: vendor/bin + tasks: + phpcsfixer2: + allow_risky: true + config: .php_cs + psalm: + ignore_patterns: + - '/spec/' #Ignore PHPSpec + phpspec: ~ + + diff --git a/phpspec.yml b/phpspec.yml new file mode 100644 index 0000000..093932b --- /dev/null +++ b/phpspec.yml @@ -0,0 +1,4 @@ +suites: + default: + namespace: App + psr4_prefix: App \ No newline at end of file diff --git a/psalm.xml b/psalm.xml new file mode 100644 index 0000000..c94bb67 --- /dev/null +++ b/psalm.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/index.php b/public/index.php new file mode 100644 index 0000000..e30f90c --- /dev/null +++ b/public/index.php @@ -0,0 +1,27 @@ +handle($request); +$response->send(); +$kernel->terminate($request, $response); diff --git a/spec/EasyRdf/TripleFactorySpec.php b/spec/EasyRdf/TripleFactorySpec.php new file mode 100644 index 0000000..2cd1f21 --- /dev/null +++ b/spec/EasyRdf/TripleFactorySpec.php @@ -0,0 +1,71 @@ +parse($graphString, 'turtle'); + + $testData = $this::triplesFromGraph($graph); + + $testData->shouldBeTriples([ + new Triple( + new Iri('http://tenant/0e2a9a87-ea19-4704-90e6-a75b3baba80a'), + new Iri('http://www.w3.org/1999/02/22-rdf-syntax-ns#type'), + new Iri('http://www.w3.org/ns/org#FormalOrganization') + ), + new Triple( + new Iri('http://tenant/0e2a9a87-ea19-4704-90e6-a75b3baba80a'), + new Iri('http://openskos.org/xmlns#code'), + new StringLiteral('pic') + ), + new Triple( + new Iri('http://tenant/0e2a9a87-ea19-4704-90e6-a75b3baba80a'), + new Iri('http://www.w3.org/2004/02/skos/core#prefLabel'), + new StringLiteral('Doe, John', 'nl') + ), + new Triple( + new Iri('http://tenant/0e2a9a87-ea19-4704-90e6-a75b3baba80a'), + new Iri('http://openskos.org/xmlns#disableSearchInOtherTenants'), + new BooleanLiteral(false) + ), + new Triple( + new Iri('http://tenant/0e2a9a87-ea19-4704-90e6-a75b3baba80a'), + new Iri('http://purl.org/dc/terms/dateSubmitted'), + new DatetimeLiteral(new \DateTime('2019-02-05T15:25:05+00:00')) + ), + ]); + } + + public function getMatchers(): array + { + return [ + 'beTriples' => function (array $actual, array $expected) { + foreach ($actual as $i => $triple) { + $expTriple = (string) ($expected[$i] ?? ''); + if ((string) $triple !== $expTriple) { + throw new FailureException(sprintf( + "Expected triple\n\t%s\nat index #%d but got\n\t%s", + $expTriple, $i, $triple + )); + } + } + + return true; + }, + ]; + } +} diff --git a/spec/EasyRdf/example.ttl b/spec/EasyRdf/example.ttl new file mode 100644 index 0000000..6b36bb9 --- /dev/null +++ b/spec/EasyRdf/example.ttl @@ -0,0 +1,21 @@ + + + #Resource + a ; + + #Language independent string + + "pic" ; + + #Language dependent string + + "Doe, John"@nl ; + + #Boolean + + "false"^^ ; + + + #DateTime + + "2019-02-05T15:25:05+00:00"^^ . diff --git a/spec/OpenSkos/ApiRequestSpec.php b/spec/OpenSkos/ApiRequestSpec.php new file mode 100644 index 0000000..4df8997 --- /dev/null +++ b/spec/OpenSkos/ApiRequestSpec.php @@ -0,0 +1,27 @@ +beConstructedWith($format, 5); + $this->shouldThrow(InvalidApiRequestLevel::class)->duringInstantiation(); + + $this->beConstructedWith($format, 0); + $this->shouldThrow(InvalidApiRequestLevel::class)->duringInstantiation(); + } + + public function it_throws_exception_for_negative_paging( + RdfFormat $format + ) { + $this->beConstructedWith($format, 1, -1, -42); + $this->shouldThrow(\InvalidArgumentException::class)->duringInstantiation(); + } +} diff --git a/spec/OpenSkos/Institution/Sparql/SparqlInstitutionRepositorySpec.php b/spec/OpenSkos/Institution/Sparql/SparqlInstitutionRepositorySpec.php new file mode 100644 index 0000000..c8262e0 --- /dev/null +++ b/spec/OpenSkos/Institution/Sparql/SparqlInstitutionRepositorySpec.php @@ -0,0 +1,27 @@ +iriFactory = new OpenSkosIriFactory('http://tenant'); + $this->beConstructedWith($rdfClient, $this->iriFactory); + } + + public function it_will_return_null_if_no_one_triple_found_for_given_iri(Client $rdfClient) + { + $rdfClient->describe(Argument::any())->willReturn([]); + $this->findByIri(new Iri('http://tenant/iri'))->shouldBeNull(); + } +} diff --git a/spec/Rdf/Format/RdfFormatFactorySpec.php b/spec/Rdf/Format/RdfFormatFactorySpec.php new file mode 100644 index 0000000..eb0880c --- /dev/null +++ b/spec/Rdf/Format/RdfFormatFactorySpec.php @@ -0,0 +1,26 @@ +beConstructedThrough('loadDefault'); + } + + public function it_can_create_format_by_name() + { + $this->createFromName('json-ld')->shouldBe(JsonLd::instance()); + } + + public function it_should_throw_an_exception_when_format_is_not_found() + { + $this->shouldThrow(UnknownFormatException::class) + ->during('createFromName', ['unknown-format']); + } +} diff --git a/spec/Rdf/Sparql/SparqlQuerySpec.php b/spec/Rdf/Sparql/SparqlQuerySpec.php new file mode 100644 index 0000000..cb71f7b --- /dev/null +++ b/spec/Rdf/Sparql/SparqlQuerySpec.php @@ -0,0 +1,26 @@ +beConstructedThrough('describeAllOfType', + [ + new Iri('http://some-type'), + 200, // offset + 100, // limit + ] + ); + + $this->rawSparql()->shouldBe( + 'DESCRIBE ?x WHERE ' + .'{ ?x } ' + .'LIMIT 100 OFFSET 200' + ); + } +} diff --git a/spec/Rest/ArgumentResolver/ApiRequestResolverSpec.php b/spec/Rest/ArgumentResolver/ApiRequestResolverSpec.php new file mode 100644 index 0000000..6c3565a --- /dev/null +++ b/spec/Rest/ArgumentResolver/ApiRequestResolverSpec.php @@ -0,0 +1,67 @@ +formatFactory = RdfFormatFactory::loadDefault(); + } + + public function let() + { + $this->beConstructedWith($this->formatFactory); + } + + public function it_resolves_pagination_from_symfony_request( + ArgumentMetadata $argumentMetadata + ) { + $request = new Request( + [ + 'format' => 'json-ld', + 'limit' => '123', + 'offset' => '12', + 'level' => '1', + ] + ); + + /** @var ApiRequest $apiRequest */ + $apiRequest = $this->resolve($request, $argumentMetadata)->current(); + + $apiRequest->getFormat()->shouldBeAnInstanceOf(JsonLd::class); + $apiRequest->getLevel()->shouldBe(1); + $apiRequest->getLimit()->shouldBe(123); + $apiRequest->getOffset()->shouldBe(12); + } + + public function it_throws_an_exception_when_cant_resolve_format( + ArgumentMetadata $argumentMetadata + ) { + $request = new Request( + [ + 'format' => 'unknown-format', + 'limit' => '123', + 'offset' => '12', + 'level' => '1', + ] + ); + + $this->resolve($request, $argumentMetadata) + ->shouldThrow(InvalidApiRequest::class) + ->during('current'); + } +} diff --git a/spec/Serializer/RdfEncoderSpec.php b/spec/Serializer/RdfEncoderSpec.php new file mode 100644 index 0000000..37227e9 --- /dev/null +++ b/spec/Serializer/RdfEncoderSpec.php @@ -0,0 +1,87 @@ +triples = [ + new Triple( + new Iri('http://tenant/0e2a9a87-ea19-4704-90e6-a75b3baba80a'), + new Iri('http://www.w3.org/1999/02/22-rdf-syntax-ns#type'), + new Iri('http://www.w3.org/ns/org#FormalOrganization') + ), + new Triple( + new Iri('http://tenant/0e2a9a87-ea19-4704-90e6-a75b3baba80a'), + new Iri('http://openskos.org/xmlns#code'), + new StringLiteral('pic') + ), + new Triple( + new Iri('http://tenant/0e2a9a87-ea19-4704-90e6-a75b3baba80a'), + new Iri('http://www.w3.org/2004/02/skos/core#prefLabel'), + new StringLiteral('Doe, John', 'nl') + ), + new Triple( + new Iri('http://tenant/0e2a9a87-ea19-4704-90e6-a75b3baba80a'), + new Iri('http://openskos.org/xmlns#disableSearchInOtherTenants'), + new BooleanLiteral(false) + ), + new Triple( + new Iri('http://tenant/0e2a9a87-ea19-4704-90e6-a75b3baba80a'), + new Iri('http://purl.org/dc/terms/dateSubmitted'), + new DatetimeLiteral(new \DateTime('2019-02-05T15:25:05+00:00')) + ), + ]; + $this->beConstructedWith(RdfFormatFactory::loadDefault()); + } + + public function it_can_serialise_to_jsonld() + { + $res = $this->encode($this->triples, 'json-ld'); + $res->shouldBe(file_get_contents(__DIR__.'/example.jsonld')); + } + + public function it_can_serialise_to_turtle() + { + $res = $this->encode($this->triples, 'turtle'); + $res->shouldBe(file_get_contents(__DIR__.'/example.ttl')); + } + + public function it_can_serialise_to_rdfxml() + { + $res = $this->encode($this->triples, 'rdfxml'); + $expected = << + + + + pic + Doe, John + false + 2019-02-05T15:25:05Z + + + + +XML; + $res->shouldBe($expected); + } +} diff --git a/spec/Serializer/example.jsonld b/spec/Serializer/example.jsonld new file mode 100644 index 0000000..6698bae --- /dev/null +++ b/spec/Serializer/example.jsonld @@ -0,0 +1 @@ +[{"@id":"http://tenant/0e2a9a87-ea19-4704-90e6-a75b3baba80a","@type":["http://www.w3.org/ns/org#FormalOrganization"],"http://openskos.org/xmlns#code":[{"@value":"pic"}],"http://www.w3.org/2004/02/skos/core#prefLabel":[{"@value":"Doe, John","@language":"nl"}],"http://openskos.org/xmlns#disableSearchInOtherTenants":[{"@value":false}],"http://purl.org/dc/terms/dateSubmitted":[{"@value":"2019-02-05T15:25:05Z","@type":"http://www.w3.org/2001/XMLSchema#dateTime"}]},{"@id":"http://www.w3.org/ns/org#FormalOrganization"}] \ No newline at end of file diff --git a/spec/Serializer/example.ttl b/spec/Serializer/example.ttl new file mode 100644 index 0000000..4f7831b --- /dev/null +++ b/spec/Serializer/example.ttl @@ -0,0 +1,13 @@ +@prefix org: . +@prefix openskos: . +@prefix skos: . +@prefix dc: . +@prefix xsd: . + + + a org:FormalOrganization ; + openskos:code "pic" ; + skos:prefLabel "Doe, John"@nl ; + openskos:disableSearchInOtherTenants false ; + dc:dateSubmitted "2019-02-05T15:25:05Z"^^xsd:dateTime . + diff --git a/src/EasyRdf/EasyRdfClient.php b/src/EasyRdf/EasyRdfClient.php new file mode 100644 index 0000000..b571742 --- /dev/null +++ b/src/EasyRdf/EasyRdfClient.php @@ -0,0 +1,41 @@ +easyRdfClient = $easyRdfClient; + } + + /** + * @param SparqlQuery $query + * + * @return Triple[] + */ + public function describe(SparqlQuery $query): array + { + $graph = $this->easyRdfClient->query($query->rawSparql()); + + if (!$graph instanceof EasyRdf_Graph) { + // TODO: Add to SparqlQuery object isDescribe() method for such checks. + throw InvalidSparqlQuery::causedBy($query, 'Is not a DESCRIBE query'); + } + + return TripleFactory::triplesFromGraph($graph); + } +} diff --git a/src/EasyRdf/TripleFactory.php b/src/EasyRdf/TripleFactory.php new file mode 100644 index 0000000..79c6b72 --- /dev/null +++ b/src/EasyRdf/TripleFactory.php @@ -0,0 +1,72 @@ +getUri(): return BooleanLiteral::fromString($value); + case DatetimeLiteral::typeIri()->getUri(): return DatetimeLiteral::fromString($value); + default: return new StringLiteral($value, $arr['lang'] ?? null); + } + } + + return null; + } + + /** + * @param EasyRdf_Graph $graph + * + * @return Triple[] + */ + public static function triplesFromGraph(EasyRdf_Graph $graph): array + { + $resources = $graph->toRdfPhp(); + + $res = []; + foreach ($resources as $subject => $predicates) { + $subjectIri = new Iri($subject); + foreach ($predicates as $predicate => $objects) { + $predicateIri = new Iri($predicate); + foreach ($objects as $object) { + $rdfTerm = self::arrayToRdfTerm($object); + if (null === $rdfTerm) { + // TODO: Throw an exception? + continue; + } + $res[] = new Triple($subjectIri, $predicateIri, $rdfTerm); + } + } + } + + return $res; + } +} diff --git a/src/Healthcheck/PingController.php b/src/Healthcheck/PingController.php new file mode 100644 index 0000000..c19ce3b --- /dev/null +++ b/src/Healthcheck/PingController.php @@ -0,0 +1,32 @@ +getProjectDir().'/config/bundles.php'; + foreach ($contents as $class => $envs) { + if ($envs[$this->environment] ?? $envs['all'] ?? false) { + yield new $class(); + } + } + } + + public function getProjectDir(): string + { + return \dirname(__DIR__); + } + + protected function configureContainer(ContainerBuilder $container, LoaderInterface $loader): void + { + $container->addResource(new FileResource($this->getProjectDir().'/config/bundles.php')); + $container->setParameter('container.dumper.inline_class_loader', true); + $confDir = $this->getProjectDir().'/config'; + + $loader->load($confDir.'/{packages}/*'.self::CONFIG_EXTS, 'glob'); + $loader->load($confDir.'/{packages}/'.$this->environment.'/**/*'.self::CONFIG_EXTS, 'glob'); + $loader->load($confDir.'/{services}'.self::CONFIG_EXTS, 'glob'); + $loader->load($confDir.'/{services}_'.$this->environment.self::CONFIG_EXTS, 'glob'); + } + + protected function configureRoutes(RouteCollectionBuilder $routes): void + { + $confDir = $this->getProjectDir().'/config'; + + $routes->import($confDir.'/{routes}/'.$this->environment.'/**/*'.self::CONFIG_EXTS, '/', 'glob'); + $routes->import($confDir.'/{routes}/*'.self::CONFIG_EXTS, '/', 'glob'); + $routes->import($confDir.'/{routes}'.self::CONFIG_EXTS, '/', 'glob'); + } +} diff --git a/src/Ontology/Dc.php b/src/Ontology/Dc.php new file mode 100644 index 0000000..d388100 --- /dev/null +++ b/src/Ontology/Dc.php @@ -0,0 +1,31 @@ +format = $format; + $this->level = $level; + $this->offset = $offset; + $this->limit = $limit; + + if ($level < 1 || $level > 4) { + throw new InvalidApiRequestLevel($level); + } + if ($limit < 0 || $offset < 0) { + throw new \InvalidArgumentException( + "Limit and offset must be zero or higher. $limit and $offset passed" + ); + } + } + + /** + * @return int + */ + public function getLevel(): int + { + return $this->level; + } + + /** + * @return int + */ + public function getOffset(): int + { + return $this->offset; + } + + /** + * @return int + */ + public function getLimit(): int + { + return $this->limit; + } + + /** + * @return RdfFormat + */ + public function getFormat(): RdfFormat + { + return $this->format; + } +} diff --git a/src/OpenSkos/ConceptScheme/ConceptScheme.php b/src/OpenSkos/ConceptScheme/ConceptScheme.php new file mode 100644 index 0000000..1421def --- /dev/null +++ b/src/OpenSkos/ConceptScheme/ConceptScheme.php @@ -0,0 +1,105 @@ + Rdf::TYPE, + self::datesubmitted => DcTerms::DATESUBMITTED, + self::set => OpenSkos::SET, + self::uuid => OpenSkos::UUID, + self::creator => Dc::CREATOR, + self::tenant => OpenSkos::TENANT, + self::modified => DcTerms::MODIFIED, + self::title => DcTerms::TITLE, + self::description => DcTerms::DESCRIPTION, + self::hasTopConcept => Skos::HASTOPCONCEPT, + self::status => OpenSkos::STATUS, + self::dateDeleted => OpenSkos::DATE_DELETED, + self::deletedBy => OpenSkos::DELETEDBY, + self::modifiedBy => OpenSkos::MODIFIEDBY, + ]; + + /** + * @var VocabularyAwareResource + */ + private $resource; + + private function __construct( + Iri $subject, + ?VocabularyAwareResource $resource = null + ) { + if (null === $resource) { + $this->resource = new VocabularyAwareResource($subject, array_flip(self::$mapping)); + } else { + $this->resource = $resource; + } + } + + public function iri(): Iri + { + return $this->resource->iri(); + } + + /** + * @return Triple[] + */ + public function triples(): array + { + return $this->resource->triples(); + } + + /** + * @param Iri $subject + * + * @return ConceptScheme + */ + public static function createEmpty(Iri $subject): self + { + return new self($subject); + } + + /** + * @param Iri $subject + * @param Triple[] $triples + * + * @return ConceptScheme + */ + public static function fromTriples(Iri $subject, array $triples): self + { + $resource = VocabularyAwareResource::fromTriples($subject, $triples, self::$mapping); + + return new self($subject, $resource); + } +} diff --git a/src/OpenSkos/ConceptScheme/ConceptSchemeRepository.php b/src/OpenSkos/ConceptScheme/ConceptSchemeRepository.php new file mode 100644 index 0000000..688d3e2 --- /dev/null +++ b/src/OpenSkos/ConceptScheme/ConceptSchemeRepository.php @@ -0,0 +1,49 @@ +serializer = $serializer; + } + + /** + * @Route(path="/conceptschemes", methods={"GET"}) + * + * @param ApiRequest $apiRequest + * @param ConceptSchemeRepository $repository + * + * @return ListResponse + * + * @OA\Get( + * path="/conceptschemes", + * tags={"Conceptscheme"}, + * description="Retrieve a list of conceptschemes", + * @OA\Response(response="200", description="Succesfull retrieval of a list of conceptschemes") + * ) + */ + public function conceptschemes( + ApiRequest $apiRequest, + ConceptSchemeRepository $repository + ): ListResponse { + $conceptschemes = $repository->all($apiRequest->getOffset(), $apiRequest->getLimit()); + + return new ListResponse( + $conceptschemes, + count($conceptschemes), + $apiRequest->getOffset(), + $apiRequest->getFormat() + ); + } + + /** + * @Route(path="/conceptscheme/{id}", methods={"GET"}) + * + * @param InternalResourceId $id + * @param ApiRequest $apiRequest + * @param ConceptSchemeRepository $repository + * + * @return ScalarResponse + * + * @OA\Get( + * path="/conceptscheme/{id}", + * tags={"Conceptscheme"}, + * description="Retrieve a specific conceptscheme", + * @OA\Parameter( + * name="id", + * in="path", + * description="ID of conceptscheme to retrieve", + * required=true, + * @OA\Schema( + * type="string", + * format="UUID", + * minLength=36, + * maxLength=36 + * ) + * ), + * @OA\Response(response="200", description="Succesfull retrieval of a conceptscheme"), + * @OA\Response(response=404, description="Conceptscheme not found") + * ) + */ + public function conceptscheme( + InternalResourceId $id, + ApiRequest $apiRequest, + ConceptSchemeRepository $repository + ): ScalarResponse { + $conceptscheme = $repository->findOneBy( + new Iri(OpenSkos::CODE), + $id + ); + + if (null === $conceptscheme) { + throw new NotFoundHttpException("The conceptscheme $id could not be retreived."); + } + + return new ScalarResponse($conceptscheme, $apiRequest->getFormat()); + } +} diff --git a/src/OpenSkos/ConceptScheme/Sparql/SparqlConceptSchemeRepository.php b/src/OpenSkos/ConceptScheme/Sparql/SparqlConceptSchemeRepository.php new file mode 100644 index 0000000..7ed95de --- /dev/null +++ b/src/OpenSkos/ConceptScheme/Sparql/SparqlConceptSchemeRepository.php @@ -0,0 +1,114 @@ + + */ + private $skosRepository; + + /** + * @var OpenSkosIriFactory + */ + private $iriFactory; + + /** + * SparqlConceptSchemeRepository constructor. + * + * @param Client $rdfClient + * @param OpenSkosIriFactory $iriFactory + */ + public function __construct( + Client $rdfClient, + OpenSkosIriFactory $iriFactory + ) { + $this->rdfClient = $rdfClient; + + $this->skosRepository = new SkosResourceRepository( + function (Iri $iri, array $triples): ConceptScheme { + return ConceptScheme::fromTriples($iri, $triples); + }, + $this->rdfClient + ); + + $this->iriFactory = $iriFactory; + } + + /** + * @param int $offset + * @param int $limit + * + * @return array + */ + public function all(int $offset = 0, int $limit = 100): array + { + return $this->skosRepository->allOfType( + new Iri(Skos::CONCEPTSCHEME), + $offset, + $limit + ); + } + + /** + * @param Iri $iri + * + * @return ConceptScheme|null + */ + public function findByIri(Iri $iri): ?ConceptScheme + { + return $this->skosRepository->findByIri($iri); + } + + /** + * @param InternalResourceId $id + * + * @return ConceptScheme|null + */ + public function find(InternalResourceId $id): ?ConceptScheme + { + return $this->findByIri($this->iriFactory->fromInternalResourceId($id)); + } + + /** + * @param Iri $predicate + * @param InternalResourceId $object + * + * @return array|null + */ + public function findBy(Iri $predicate, InternalResourceId $object): ?array + { + return $this->skosRepository->findBy(new Iri(Org::FORMALORG), $predicate, $object); + } + + /** + * @param Iri $predicate + * @param InternalResourceId $object + * + * @return ConceptScheme|null + */ + public function findOneBy(Iri $predicate, InternalResourceId $object): ?ConceptScheme + { + $res = $this->skosRepository->findOneBy(new Iri(Org::FORMALORG), $predicate, $object); + + return $res; + } +} diff --git a/src/OpenSkos/Exception/InvalidApiRequest.php b/src/OpenSkos/Exception/InvalidApiRequest.php new file mode 100644 index 0000000..dbdbc54 --- /dev/null +++ b/src/OpenSkos/Exception/InvalidApiRequest.php @@ -0,0 +1,9 @@ +serializer = $serializer; + } + + /** + * @Route(path="/institutions", methods={"GET"}) + * + * @param ApiRequest $apiRequest + * @param InstitutionRepository $repository + * + * @return ListResponse + * + * @OA\Get( + * path="/institutions", + * tags={"Institutions"}, + * description="Retrieve a list of institutions", + * @OA\Response(response="200", description="Succesfull retrieval of a list of institutions") + * ) + */ + public function institutions( + ApiRequest $apiRequest, + InstitutionRepository $repository + ): ListResponse { + $institutions = $repository->all($apiRequest->getOffset(), $apiRequest->getLimit()); + + return new ListResponse( + $institutions, + count($institutions), + $apiRequest->getOffset(), + $apiRequest->getFormat() + ); + } + + /** + * @Route(path="/institution/{id}", methods={"GET"}) + * + * @param InternalResourceId $id + * @param ApiRequest $apiRequest + * @param InstitutionRepository $repository + * + * @return ScalarResponse + * + * @OA\Get( + * path="/institution/{id}", + * tags={"Institutions"}, + * description="Retrieve a specific institution", + * @OA\Parameter( + * name="id", + * in="path", + * description="ID of institution to retrieve", + * required=true, + * @OA\Schema( + * type="string", + * format="UUID", + * minLength=36, + * maxLength=36 + * ) + * ), + * @OA\Response(response="200", description="Succesfull retrieval of an institution"), + * @OA\Response(response=404, description="Institution not found") + * ) + */ + public function institution( + InternalResourceId $id, + ApiRequest $apiRequest, + InstitutionRepository $repository + ): ScalarResponse { + $institution = $repository->findOneBy( + new Iri(OpenSkos::CODE), + $id + ); + + if (null === $institution) { + throw new NotFoundHttpException("The institution $id could not be retreived."); + } + + return new ScalarResponse($institution, $apiRequest->getFormat()); + } +} diff --git a/src/OpenSkos/Institution/Institution.php b/src/OpenSkos/Institution/Institution.php new file mode 100644 index 0000000..6efdeaf --- /dev/null +++ b/src/OpenSkos/Institution/Institution.php @@ -0,0 +1,101 @@ + OpenSkos::CODE, + self::name => OpenSkos::NAME, + self::disableSearchInOtherTenants => OpenSkos::DISABLESEARCHINOTERTENANTS, + self::organisationUnit => VCard::ORGUNIT, + self::email => VCard::EMAIL, + self::website => OpenSkos::WEBPAGE, + self::streetAddress => VCard::ADR, + self::locality => VCard::LOCALITY, + self::postalCode => VCard::PCODE, + self::countryName => VCard::COUNTRY, + self::enableStatusesSystem => OpenSkos::ENABLESTATUSSESSYSTEMS, + self::enableSkosXl => OpenSkos::ENABLESKOSXL, + self::type => Rdf::TYPE, + ]; + + /** + * @var VocabularyAwareResource + */ + private $resource; + + private function __construct( + Iri $subject, + ?VocabularyAwareResource $resource = null + ) { + if (null === $resource) { + $this->resource = new VocabularyAwareResource($subject, array_flip(self::$mapping)); + } else { + $this->resource = $resource; + } + } + + public function iri(): Iri + { + return $this->resource->iri(); + } + + /** + * @return Triple[] + */ + public function triples(): array + { + return $this->resource->triples(); + } + + /** + * @param Iri $subject + * + * @return Institution + */ + public static function createEmpty(Iri $subject): self + { + return new self($subject); + } + + /** + * @param Iri $subject + * @param Triple[] $triples + * + * @return Institution + */ + public static function fromTriples(Iri $subject, array $triples): self + { + $resource = VocabularyAwareResource::fromTriples($subject, $triples, self::$mapping); + + return new self($subject, $resource); + } +} diff --git a/src/OpenSkos/Institution/InstitutionRepository.php b/src/OpenSkos/Institution/InstitutionRepository.php new file mode 100644 index 0000000..e32d399 --- /dev/null +++ b/src/OpenSkos/Institution/InstitutionRepository.php @@ -0,0 +1,49 @@ + + */ + private $skosRepository; + + /** + * @var OpenSkosIriFactory + */ + private $iriFactory; + + /** + * SparqlInstitutionRepository constructor. + * + * @param Client $rdfClient + * @param OpenSkosIriFactory $iriFactory + */ + public function __construct( + Client $rdfClient, + OpenSkosIriFactory $iriFactory + ) { + $this->rdfClient = $rdfClient; + + $this->skosRepository = new SkosResourceRepository( + function (Iri $iri, array $triples): Institution { + return Institution::fromTriples($iri, $triples); + }, + $this->rdfClient + ); + + $this->iriFactory = $iriFactory; + } + + /** + * @param int $offset + * @param int $limit + * + * @return array + */ + public function all(int $offset = 0, int $limit = 100): array + { + return $this->skosRepository->allOfType( + new Iri(Org::FORMALORG), + $offset, + $limit + ); + } + + /** + * @param Iri $iri + * + * @return Institution|null + */ + public function findByIri(Iri $iri): ?Institution + { + return $this->skosRepository->findByIri($iri); + } + + /** + * @param InternalResourceId $id + * + * @return Institution|null + */ + public function find(InternalResourceId $id): ?Institution + { + return $this->findByIri($this->iriFactory->fromInternalResourceId($id)); + } + + /** + * @param Iri $predicate + * @param InternalResourceId $object + * + * @return array|null + */ + public function findBy(Iri $predicate, InternalResourceId $object): ?array + { + return $this->skosRepository->findBy(new Iri(Org::FORMALORG), $predicate, $object); + } + + /** + * @param Iri $predicate + * @param InternalResourceId $object + * + * @return Institution|null + */ + public function findOneBy(Iri $predicate, InternalResourceId $object): ?Institution + { + $res = $this->skosRepository->findOneBy(new Iri(Org::FORMALORG), $predicate, $object); + + return $res; + } +} diff --git a/src/OpenSkos/InternalResourceId.php b/src/OpenSkos/InternalResourceId.php new file mode 100644 index 0000000..8ebc2e5 --- /dev/null +++ b/src/OpenSkos/InternalResourceId.php @@ -0,0 +1,40 @@ +id = $id; + } + + /** + * @return string + */ + public function id(): string + { + return $this->id; + } + + /** + * @return string + */ + public function __toString(): string + { + return "$this->id"; + } + + public function isEquals(self $that): bool + { + return $this->id === $that->id; + } +} diff --git a/src/OpenSkos/OpenSkosIriFactory.php b/src/OpenSkos/OpenSkosIriFactory.php new file mode 100644 index 0000000..d6dd262 --- /dev/null +++ b/src/OpenSkos/OpenSkosIriFactory.php @@ -0,0 +1,26 @@ +namespace = rtrim($namespace, '/'); + } + + public function fromInternalResourceId(InternalResourceId $id): Iri + { + return new Iri($this->namespace.'/'.$id->id()); + } +} diff --git a/src/OpenSkos/Set/Controller/Set.php b/src/OpenSkos/Set/Controller/Set.php new file mode 100644 index 0000000..ca7510b --- /dev/null +++ b/src/OpenSkos/Set/Controller/Set.php @@ -0,0 +1,109 @@ +serializer = $serializer; + } + + /** + * @Route(path="/sets", methods={"GET"}) + * + * @param ApiRequest $apiRequest + * @param SetRepository $repository + * + * @return ListResponse + * + * @OA\Get( + * path="/sets", + * tags={"Sets"}, + * description="Retrieve a list of sets", + * @OA\Response(response="200", description="Succesfull retrieval of a list of sets") + * ) + */ + public function sets(ApiRequest $apiRequest, SetRepository $repository): ListResponse + { + $sets = $repository->all($apiRequest->getOffset(), $apiRequest->getLimit()); + + return new ListResponse( + $sets, + count($sets), + $apiRequest->getOffset(), + $apiRequest->getFormat() + ); + } + + /** + * @Route(path="/set/{id}", methods={"GET"}) + * + * @param InternalResourceId $id + * @param ApiRequest $apiRequest + * @param SetRepository $repository + * + * @return ScalarResponse + * + * @OA\Get( + * path="/set/{id}", + * tags={"Sets"}, + * description="Retrieve a specific set", + * @OA\Parameter( + * name="id", + * in="path", + * description="ID of set to retrieve", + * required=true, + * @OA\Schema( + * type="string", + * format="UUID", + * minLength=36, + * maxLength=36 + * ) + * ), + * @OA\Response(response="200", description="Succesfull retrieval of an set"), + * @OA\Response(response=404, description="Set not found") + * ) + */ + public function set( + InternalResourceId $id, + ApiRequest $apiRequest, + SetRepository $repository + ): ScalarResponse { + $set = $repository->findOneBy( + new Iri(OpenSkos::CODE), + $id + ); + + if (null === $set) { + throw new NotFoundHttpException("The set $id could not be retreived."); + } + + return new ScalarResponse($set, $apiRequest->getFormat()); + } +} diff --git a/src/OpenSkos/Set/Set.php b/src/OpenSkos/Set/Set.php new file mode 100644 index 0000000..2f07981 --- /dev/null +++ b/src/OpenSkos/Set/Set.php @@ -0,0 +1,95 @@ + OpenSkos::TENANT, + self::code => OpenSkos::CODE, + self::allow_oai => OpenSkos::ALLOW_OAI, + self::conceptBaseUri => OpenSkos::CONCEPTBASEURI, + self::oai_baseURL => OpenSkos::OAI_BASEURL, + self::webpage => OpenSkos::WEBPAGE, + self::description => DcTerms::DESCRIPTION, + self::license => DcTerms::LICENSE, + self::publisher => DcTerms::PUBLISHER, + self::title => DC::TITLE, + ]; + + /** + * @var VocabularyAwareResource + */ + private $resource; + + private function __construct( + Iri $subject, + ?VocabularyAwareResource $resource = null + ) { + if (null === $resource) { + $this->resource = new VocabularyAwareResource($subject, array_flip(self::$mapping)); + } else { + $this->resource = $resource; + } + } + + public function iri(): Iri + { + return $this->resource->iri(); + } + + /** + * @return Triple[] + */ + public function triples(): array + { + return $this->resource->triples(); + } + + /** + * @param Iri $subject + * + * @return self + */ + public static function createEmpty(Iri $subject): self + { + return new self($subject); + } + + /** + * @param Iri $subject + * @param Triple[] $triples + * + * @return self + */ + public static function fromTriples(Iri $subject, array $triples): self + { + $resource = VocabularyAwareResource::fromTriples($subject, $triples, self::$mapping); + + return new self($subject, $resource); + } +} diff --git a/src/OpenSkos/Set/SetRepository.php b/src/OpenSkos/Set/SetRepository.php new file mode 100644 index 0000000..a4a780b --- /dev/null +++ b/src/OpenSkos/Set/SetRepository.php @@ -0,0 +1,42 @@ + + */ + private $skosRepository; + + /** + * @var OpenSkosIriFactory + */ + private $iriFactory; + + public function __construct( + Client $rdfClient, + OpenSkosIriFactory $iriFactory + ) { + $this->rdfClient = $rdfClient; + + $this->skosRepository = new SkosResourceRepository( + function (Iri $iri, array $triples): Set { + return Set::fromTriples($iri, $triples); + }, + $this->rdfClient + ); + + $this->iriFactory = $iriFactory; + } + + /** + * @param int $offset + * @param int $limit + * + * @return Set[] + */ + public function all(int $offset = 0, int $limit = 100): array + { + return $this->skosRepository->allOfType( + new Iri(OpenSkos::SET), + $offset, + $limit + ); + } + + public function findByIri(Iri $iri): ?Set + { + return $this->skosRepository->findByIri($iri); + } + + /** + * @param InternalResourceId $id + * + * @return Set|null + */ + public function find(InternalResourceId $id): ?Set + { + return $this->findByIri($this->iriFactory->fromInternalResourceId($id)); + } + + /** + * @param Iri $predicate + * @param InternalResourceId $object + * + * @return array + */ + public function findBy(Iri $predicate, InternalResourceId $object): ?array + { + return $this->skosRepository->findBy(new Iri(OpenSkos::SET), $predicate, $object); + } + + /** + * @param Iri $predicate + * @param InternalResourceId $object + * + * @return Set|null + */ + public function findOneBy(Iri $predicate, InternalResourceId $object): ?Set + { + $res = $this->skosRepository->findOneBy(new Iri(OpenSkos::SET), $predicate, $object); + + return $res; + } +} diff --git a/src/OpenSkos/SkosResourceRepository.php b/src/OpenSkos/SkosResourceRepository.php new file mode 100644 index 0000000..b1489f0 --- /dev/null +++ b/src/OpenSkos/SkosResourceRepository.php @@ -0,0 +1,138 @@ +): T $resourceFactory + * @param Client $rdfClient + */ + public function __construct( + callable $resourceFactory, + Client $rdfClient + ) { + $this->rdfClient = $rdfClient; + $this->resourceFactory = $resourceFactory; + } + + /** + * @param Iri $type + * @param int $offset + * @param int $limit + * + * @return array + * @psalm-return array + */ + public function allOfType( + Iri $type, + int $offset = 0, + int $limit = 100 + ): array { + $sparql = SparqlQuery::describeAllOfType( + $type, + $offset, + $limit + ); + $triples = $this->rdfClient->describe($sparql); + + //TODO: Move to separate helper class? + $groups = []; + foreach ($triples as $triple) { + $groups[$triple->getSubject()->getUri()][] = $triple; + } + + $res = []; + foreach ($groups as $iriString => $group) { + $res[] = call_user_func($this->resourceFactory, new Iri($iriString), $group); + } + + return $res; + } + + /** + * @param Iri $iri + * + * @return mixed + * @psalm-return T|null + */ + public function findByIri(Iri $iri) + { + $sparql = SparqlQuery::describeResource($iri); + $triples = $this->rdfClient->describe($sparql); + if (0 === count($triples)) { + return null; + } + + return call_user_func($this->resourceFactory, $iri, $triples); + } + + /** + * @param Iri $rdfType + * @param Iri $predicate + * @param InternalResourceId $object + * + * @return array + */ + public function findBy(Iri $rdfType, Iri $predicate, InternalResourceId $object): ?array + { + $sparql = SparqlQuery::describeByTypeAndPredicate($rdfType, $predicate, $object); + $triples = $this->rdfClient->describe($sparql); + if (0 === count($triples)) { + return null; + } + + //TODO: Move to separate helper class? + $groups = []; + foreach ($triples as $triple) { + $groups[$triple->getSubject()->getUri()][] = $triple; + } + + $res = []; + foreach ($groups as $iriString => $group) { + $res[] = call_user_func($this->resourceFactory, new Iri($iriString), $group); + } + + return $res; + } + + /** + * @param Iri $rdfType + * @param Iri $predicate + * @param InternalResourceId $object + * + * @return array|mixed|null + */ + public function findOneBy(Iri $rdfType, Iri $predicate, InternalResourceId $object) + { + $fullSet = $this->findBy($rdfType, $predicate, $object); + if (isset($fullSet) && is_array($fullSet)) { + $resourceTriples = $fullSet[0]; + + return $resourceTriples; + } + + return $fullSet; + } +} diff --git a/src/Rdf/Exception/ClientException.php b/src/Rdf/Exception/ClientException.php new file mode 100644 index 0000000..55a1d53 --- /dev/null +++ b/src/Rdf/Exception/ClientException.php @@ -0,0 +1,9 @@ +query = $query; + + return $obj; + } +} diff --git a/src/Rdf/Exception/InvalidUriException.php b/src/Rdf/Exception/InvalidUriException.php new file mode 100644 index 0000000..4ff6aff --- /dev/null +++ b/src/Rdf/Exception/InvalidUriException.php @@ -0,0 +1,24 @@ + + */ + private $formats = []; + + /** + * RdfFormatFactory constructor. + * + * @param RdfFormat[] $formats + */ + private function __construct( + array $formats + ) { + foreach ($formats as $format) { + $this->formats[$format->name()] = $format; + } + } + + /** + * @param string $name + * + * @return RdfFormat + * + * @throws UnknownFormatException + */ + public function createFromName(string $name): RdfFormat + { + if (!$this->exists($name)) { + throw UnknownFormatException::create($name); + } + + return $this->formats[$name]; + } + + /** + * @param string $name + * + * @return bool + */ + public function exists(string $name): bool + { + return isset($this->formats[$name]); + } + + /** + * @return RdfFormat[] + */ + public function formats(): array + { + return $this->formats; + } + + public static function loadDefault(): RdfFormatFactory + { + return new RdfFormatFactory([ + JsonLd::instance(), + RdfXml::instance(), + Turtle::instance(), + Ntriples::instance(), + Html::instance(), + ]); + } + + //TODO: load dynamically + // public static function loadFromNamespace(string $namespace) +} diff --git a/src/Rdf/Format/RdfXml.php b/src/Rdf/Format/RdfXml.php new file mode 100644 index 0000000..298c8b1 --- /dev/null +++ b/src/Rdf/Format/RdfXml.php @@ -0,0 +1,22 @@ +uri = $value; + } + + /** + * Output the uri as string. + * + * @return string + */ + public function __toString(): string + { + return $this->uri; + } + + /** + * @return string + */ + public function getUri(): string + { + return $this->uri; + } + + public function ntripleString(): string + { + return "<$this->uri>"; + } +} diff --git a/src/Rdf/Literal/BooleanLiteral.php b/src/Rdf/Literal/BooleanLiteral.php new file mode 100644 index 0000000..6613fff --- /dev/null +++ b/src/Rdf/Literal/BooleanLiteral.php @@ -0,0 +1,56 @@ +value = $value; + } + + public function value(): bool + { + return $this->value; + } + + public static function typeIri(): Iri + { + return new Iri('http://www.w3.org/2001/XMLSchema#bool'); + } + + /** + * Output the object as string. + * + * @return string + */ + public function __toString() + { + return (string) $this->value; + } + + /** + * @param string $value + * + * @return BooleanLiteral + */ + public static function fromString(string $value): self + { + switch ($value) { + case 'true': $bool = true; break; + case 'false': $bool = false; break; + default: throw new \InvalidArgumentException("Cant parse bool value: '$value'"); + } + + return new BooleanLiteral($bool); + } +} diff --git a/src/Rdf/Literal/DatetimeLiteral.php b/src/Rdf/Literal/DatetimeLiteral.php new file mode 100644 index 0000000..c04b1f1 --- /dev/null +++ b/src/Rdf/Literal/DatetimeLiteral.php @@ -0,0 +1,59 @@ +dateTime = $dateTime; + } + + public function value(): \DateTime + { + return $this->dateTime; + } + + public static function typeIri(): Iri + { + return new Iri('http://www.w3.org/2001/XMLSchema#dateTime'); + } + + /** + * Output the object as string. + * + * @return string + */ + public function __toString() + { + return (string) $this->dateTime->format('c'); + } + + /** + * @param string $value + * + * @return DatetimeLiteral + */ + public static function fromString(string $value): self + { + try { + return new self(new \DateTime($value)); + } catch (\Exception $e) { + throw new \InvalidArgumentException( + "Value '$value' can be parsed to DateTimeLiteral", + 0, + $e + ); + } + } +} diff --git a/src/Rdf/Literal/Literal.php b/src/Rdf/Literal/Literal.php new file mode 100644 index 0000000..1563a47 --- /dev/null +++ b/src/Rdf/Literal/Literal.php @@ -0,0 +1,11 @@ +value = $value; + $this->lang = $lang; + } + + public function value(): string + { + return $this->value; + } + + /** + * @return string|null + */ + public function lang(): ?string + { + return $this->lang; + } + + public static function typeIri(): Iri + { + return new Iri('http://www.w3.org/2001/XMLSchema#string'); + } + + /** + * Output the object as string. + * + * @return string + */ + public function __toString() + { + return $this->value; + } +} diff --git a/src/Rdf/RdfResource.php b/src/Rdf/RdfResource.php new file mode 100644 index 0000000..29d1682 --- /dev/null +++ b/src/Rdf/RdfResource.php @@ -0,0 +1,15 @@ +sparql = $sparql; + $this->variables = $variables; + } + + public function rawSparql(): string + { + //TODO: replace variables? + return $this->sparql; + } + + /** + * FIXME: Make it not static. + * + * @param Iri $type + * @param int $offset + * @param int $limit + * + * @return SparqlQuery + */ + public static function describeAllOfType( + Iri $type, + int $offset, + int $limit + ): SparqlQuery { + return new SparqlQuery( + sprintf( + 'DESCRIBE ?x WHERE { ?x <%s> <%s> } LIMIT %d OFFSET %d', + Rdf::TYPE, + $type->getUri(), + $limit, + $offset + ) + ); + } + + public static function describeResource( + Iri $subject + ): SparqlQuery { + return new SparqlQuery( + sprintf( + 'DESCRIBE <%s>', $subject->getUri() + ) + ); + } + + /** + * @param Iri $rdfType + * @param Iri $predicate + * @param $object + * + * @return SparqlQuery + */ + public static function describeByTypeAndPredicate( + Iri $rdfType, + Iri $predicate, + $object + ): SparqlQuery { + $queryString = << <%s>; + <%s> "%s" + } +QUERY_BY_TYPE_AND_PREDICATE; + + $queryString = sprintf($queryString, Rdf::TYPE, (string) $rdfType, (string) $predicate, $object); + + $retVal = new SparqlQuery($queryString); + + return $retVal; + } +} diff --git a/src/Rdf/Triple.php b/src/Rdf/Triple.php new file mode 100644 index 0000000..01af4b1 --- /dev/null +++ b/src/Rdf/Triple.php @@ -0,0 +1,84 @@ +subject = $subject; + $this->predicate = $predicate; + $this->object = $object; + + if (!($object instanceof Iri || $object instanceof Literal)) { + throw new \InvalidArgumentException('Object must be Iri|Literal got: '.get_class($object)); + } + } + + /** + * @return Iri + */ + public function getSubject(): Iri + { + return $this->subject; + } + + /** + * @return Iri + */ + public function getPredicate(): Iri + { + return $this->predicate; + } + + /** + * @return RdfTerm + */ + public function getObject(): RdfTerm + { + return $this->object; + } + + public function __toString(): string + { + if ($this->object instanceof Iri) { + $retVal = sprintf( + '<%s> <%s> <%s>', + $this->subject->getUri(), + $this->predicate->getUri(), + $this->object->getUri() + ); + + return $retVal; + } elseif ($this->object instanceof Literal) { + return sprintf( + '<%s> <%s> %s', + $this->subject->getUri(), + $this->predicate->getUri(), + $this->object->__toString() + ); + } + + throw new \LogicException('Object must be either Iri or Literal'); + } +} diff --git a/src/Rdf/VocabularyAwareResource.php b/src/Rdf/VocabularyAwareResource.php new file mode 100644 index 0000000..6bfff86 --- /dev/null +++ b/src/Rdf/VocabularyAwareResource.php @@ -0,0 +1,97 @@ + + */ + private $properties; + + /** + * @var array + */ + private $vocabulary; + + public function __construct(Iri $subject, array $vocabulary) + { + $this->subject = $subject; + + $this->properties = array_fill_keys( + $vocabulary, + null + ); + + $this->vocabulary = $vocabulary; + } + + /** + * @param Iri $iri + * @param Triple[] $triples + * @param array $mapping + * + * @return static + */ + public static function fromTriples(Iri $iri, array $triples, array $mapping) + { + $iriString = $iri->getUri(); + $obj = new self($iri, $mapping); + foreach ($triples as $triple) { + if ($triple->getSubject()->getUri() !== $iriString) { + // TODO: Should we skip, log or throw an exception? + continue; + } + + $predicateString = $triple->getPredicate()->getUri(); + if (false === array_key_exists($predicateString, $obj->properties)) { + continue; + } + $obj->triples[] = $triple; + $obj->properties[$predicateString] = $triple->getObject(); + } + + return $obj; + } + + public function iri(): Iri + { + return $this->subject; + } + + /** + * @return Triple[] + */ + public function triples(): array + { + return $this->triples; + } + + public function addProperty(Iri $property, RdfTerm $object): void + { + $iri = $property->getUri(); + if (!array_key_exists($iri, $this->properties)) { + throw new UnknownProperty($property); + } + + $this->properties[$iri] = $object; + + $this->triples[] = new Triple( + $this->subject, + $property, + $object + ); + } +} diff --git a/src/Rest/ArgumentResolver/ApiRequestResolver.php b/src/Rest/ArgumentResolver/ApiRequestResolver.php new file mode 100644 index 0000000..0524eb8 --- /dev/null +++ b/src/Rest/ArgumentResolver/ApiRequestResolver.php @@ -0,0 +1,71 @@ +formatFactory = $formatFactory; + } + + /** + * @param string|null $formatName + * + * @return RdfFormat|null + * + * @throws InvalidApiRequest + */ + private function resolveFormat(?string $formatName): ?RdfFormat + { + if (null === $formatName) { + return null; + } + + try { + return $this->formatFactory->createFromName($formatName); + } catch (UnknownFormatException $e) { + throw new InvalidApiRequest('Invalid Format', 0, $e); + } + } + + public function supports(Request $request, ArgumentMetadata $argument) + { + return ApiRequest::class === $argument->getType(); + } + + /** + * @param Request $request + * @param ArgumentMetadata $argument + * + * @return \Generator + * + * @throws InvalidApiRequest + */ + public function resolve(Request $request, ArgumentMetadata $argument) + { + yield new ApiRequest( + $this->resolveFormat($request->query->get('format')), + $request->query->getInt('level', 1), + $request->query->getInt('limit', 100), + $request->query->getInt('offset', 0) + ); + } +} diff --git a/src/Rest/ArgumentResolver/InternalResourceIdResolver.php b/src/Rest/ArgumentResolver/InternalResourceIdResolver.php new file mode 100644 index 0000000..281d164 --- /dev/null +++ b/src/Rest/ArgumentResolver/InternalResourceIdResolver.php @@ -0,0 +1,35 @@ +getType() + && $request->attributes->has($argument->getName()); + } + + /** + * @param Request $request + * @param ArgumentMetadata $argument + * + * @return \Generator + */ + public function resolve(Request $request, ArgumentMetadata $argument) + { + $value = $request->attributes->get($argument->getName()); + if (null === $value || !is_string($value)) { + throw new \InvalidArgumentException("Can't resolve InternalResourceId"); + } + + yield new InternalResourceId($value); + } +} diff --git a/src/Rest/ControllerResponseListener.php b/src/Rest/ControllerResponseListener.php new file mode 100644 index 0000000..03b9fd7 --- /dev/null +++ b/src/Rest/ControllerResponseListener.php @@ -0,0 +1,58 @@ +serializer = $serializer; + } + + /** + * Catch controller responses if they not native Response type. + * + * @param GetResponseForControllerResultEvent $event + */ + public function onKernelView(GetResponseForControllerResultEvent $event): void + { + $res = $event->getControllerResult(); + + if ($res instanceof ScalarResponse) { + $triples = $res->doc()->triples(); + } elseif ($res instanceof ListResponse) { + $triples = (function () use ($res): \Generator { + foreach ($res->getDocs() as $doc) { + foreach ($doc->triples() as $triple) { + yield $triple; + } + } + })(); + } else { + return; + } + + $content = $this->serializer->serialize($triples, $res->format()->name()); + $httpResponse = new Response( + $content, + Response::HTTP_OK, + [ + 'Content-Type' => $res->format()->contentTypeString(), + ] + ); + + $event->setResponse($httpResponse); + } +} diff --git a/src/Rest/ListResponse.php b/src/Rest/ListResponse.php new file mode 100644 index 0000000..e4ccaeb --- /dev/null +++ b/src/Rest/ListResponse.php @@ -0,0 +1,74 @@ +docs = $docs; + $this->total = $total; + $this->offset = $offset; + $this->format = $format; + } + + /** + * @return RdfResource[] + */ + public function getDocs(): array + { + return $this->docs; + } + + /** + * @return int + */ + public function getTotal(): int + { + return $this->total; + } + + /** + * @return int + */ + public function getOffset(): int + { + return $this->offset; + } + + /** + * @return RdfFormat + */ + public function format(): RdfFormat + { + return $this->format; + } +} diff --git a/src/Rest/ScalarResponse.php b/src/Rest/ScalarResponse.php new file mode 100644 index 0000000..4d0e788 --- /dev/null +++ b/src/Rest/ScalarResponse.php @@ -0,0 +1,50 @@ +doc = $doc; + $this->format = $format; + } + + /** + * @return RdfResource + */ + public function doc(): RdfResource + { + return $this->doc; + } + + public function format(): RdfFormat + { + return $this->format; + } +} diff --git a/src/Rest/SkosResponse.php b/src/Rest/SkosResponse.php new file mode 100644 index 0000000..c3faa6a --- /dev/null +++ b/src/Rest/SkosResponse.php @@ -0,0 +1,10 @@ + + */ + private $formatMap = []; + + public function __construct( + RdfFormatFactory $formatFactory + ) { + $this->formatFactory = $formatFactory; + + $this->formatMap = [ + JsonLd::instance()->name() => 'jsonld', + RdfXml::instance()->name() => 'rdfxml', + Ntriples::instance()->name() => 'ntriples', + Turtle::instance()->name() => 'turtle', + ]; + } + + /** + * @param string $format + * + * @return bool + */ + public function supportsEncoding($format) + { + return $this->formatFactory->exists($format); + } + + /** + * EasyRdf is used an an intermediate format between the TripleStore and its serialised formats. + * + * @param $data + * @param string $format + * @param array $context + * + * @return string + */ + public function encode($data, $format, array $context = []) + { + if (!is_iterable($data)) { + throw new UnsupportedException('data is not an iterable'); + } + + /** @var iterable $data */ + $graph = $this->tripleSetToEasyRdfGraph($data); + + return (string) $graph->serialise($this->formatMap[$format] ?? $format); + } + + private function literalToEasyRdf(Literal $literal): \EasyRdf_Literal + { + if ($literal instanceof BooleanLiteral) { + $value = new \EasyRdf_Literal_Boolean($literal->value()); + } elseif ($literal instanceof DatetimeLiteral) { + $value = new \EasyRdf_Literal_DateTime($literal->value()); + } elseif ($literal instanceof StringLiteral) { + $value = new \EasyRdf_Literal( + $literal->value(), + $literal->lang() + ); + } else { + $value = new \EasyRdf_Literal( + (string) $literal, + null, + $literal->typeIri()->getUri() + ); + } + + return $value; + } + + /** + * @param iterable $triples + * + * @return EasyRdf_Graph + */ + private function tripleSetToEasyRdfGraph(iterable $triples): EasyRdf_Graph + { + $graph = new EasyRdf_Graph('http://openskos.org'); + \EasyRdf_Namespace::set('openskos', OpenSkos::NAME_SPACE); + + foreach ($triples as $triple) { + $subject = $triple->getSubject(); + $predicate = $triple->getPredicate(); + $object = $triple->getObject(); + + if ($object instanceof Literal) { + $graph->addLiteral( + $subject->getUri(), + $predicate->getUri(), + $this->literalToEasyRdf($object) + ); + } elseif ($object instanceof Iri) { + $graph->addResource( + $subject->getUri(), + $predicate->getUri(), + $object->getUri() + ); + } + } + + return $graph; + } +} diff --git a/src/Swagger.php b/src/Swagger.php new file mode 100644 index 0000000..02d69f0 --- /dev/null +++ b/src/Swagger.php @@ -0,0 +1,29 @@ + + + + + {% block title %}Welcome!{% endblock %} + {% block stylesheets %}{% endblock %} + + + {% block body %}{% endblock %} + {% block javascripts %}{% endblock %} + +