diff --git a/Sources/API/.htaccess b/Sources/API/.htaccess deleted file mode 100644 index 7ded04e..0000000 --- a/Sources/API/.htaccess +++ /dev/null @@ -1,3 +0,0 @@ -RewriteEngine on -RewriteCond %{REQUEST_FILENAME} !-f -RewriteRule . index.php [L] \ No newline at end of file diff --git a/Sources/API/api/inscrit/add.php b/Sources/API/api/inscrit/add.php deleted file mode 100644 index b637268..0000000 --- a/Sources/API/api/inscrit/add.php +++ /dev/null @@ -1,3 +0,0 @@ - \ No newline at end of file diff --git a/Sources/API/api/inscrit/read.php b/Sources/API/api/inscrit/read.php deleted file mode 100644 index 936cf78..0000000 --- a/Sources/API/api/inscrit/read.php +++ /dev/null @@ -1,35 +0,0 @@ -connect(); - $inscrit = new Inscrit($db); - - $results = $inscrit->read(); - $num = $results->rowCount(); - - if($num > 0){ - $inscrit_array = array(); - - while($row = $results->fetch(PDO::FETCH_ASSOC)){ - extract($row); - - $inscrit_item = array( - 'id' => $id, - 'nom' => $nom, - 'prenom' => $prenom, - 'mail' => $mail, - 'mdp' => $mdp - ); - array_push($inscrit_array, $inscrit_item); - } - - echo json_encode($inscrit_array); - } else { - echo json_encode(array('message' => 'No Inscrit Found')); - } -?> \ No newline at end of file diff --git a/Sources/API/api/inscrit/readFromMail.php b/Sources/API/api/inscrit/readFromMail.php deleted file mode 100644 index 505ef65..0000000 --- a/Sources/API/api/inscrit/readFromMail.php +++ /dev/null @@ -1,34 +0,0 @@ -connect(); - $inscrit = new Inscrit($db); - - $results = $inscrit->readMdpFromMail($mail); - $num = $results->rowCount(); - - if($num > 0){ - $inscrit_array = array(); - - while($row = $results->fetch(PDO::FETCH_ASSOC)){ - extract($row); - - $inscrit_item = array( - 'id' => $id, - 'nom' => $nom, - 'prenom' => $prenom, - 'mail' => $mail, - 'mdp' => $mdp - ); - array_push($inscrit_array, $inscrit_item); - } - echo json_encode($inscrit_array); - } else { - echo json_encode(array('message' => 'No Inscrit with mail='.$mail)); - } -?> \ No newline at end of file diff --git a/Sources/API/composer.json b/Sources/API/composer.json new file mode 100644 index 0000000..0158a81 --- /dev/null +++ b/Sources/API/composer.json @@ -0,0 +1,6 @@ +{ + "require": { + "slim/slim": "4.*", + "slim/psr7": "^1.6" + } +} diff --git a/Sources/API/composer.lock b/Sources/API/composer.lock new file mode 100644 index 0000000..8ff62b8 --- /dev/null +++ b/Sources/API/composer.lock @@ -0,0 +1,774 @@ +{ + "_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#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "3330638b65a325a8387769d50108b43a", + "packages": [ + { + "name": "fig/http-message-util", + "version": "1.1.5", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message-util.git", + "reference": "9d94dc0154230ac39e5bf89398b324a86f63f765" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message-util/zipball/9d94dc0154230ac39e5bf89398b324a86f63f765", + "reference": "9d94dc0154230ac39e5bf89398b324a86f63f765", + "shasum": "" + }, + "require": { + "php": "^5.3 || ^7.0 || ^8.0" + }, + "suggest": { + "psr/http-message": "The package containing the PSR-7 interfaces" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Fig\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Utility classes and constants for use with PSR-7 (psr/http-message)", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "support": { + "issues": "https://github.com/php-fig/http-message-util/issues", + "source": "https://github.com/php-fig/http-message-util/tree/1.1.5" + }, + "time": "2020-11-24T22:02:12+00:00" + }, + { + "name": "nikic/fast-route", + "version": "v1.3.0", + "source": { + "type": "git", + "url": "https://github.com/nikic/FastRoute.git", + "reference": "181d480e08d9476e61381e04a71b34dc0432e812" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/FastRoute/zipball/181d480e08d9476e61381e04a71b34dc0432e812", + "reference": "181d480e08d9476e61381e04a71b34dc0432e812", + "shasum": "" + }, + "require": { + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35|~5.7" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "FastRoute\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov", + "email": "nikic@php.net" + } + ], + "description": "Fast request router for PHP", + "keywords": [ + "router", + "routing" + ], + "support": { + "issues": "https://github.com/nikic/FastRoute/issues", + "source": "https://github.com/nikic/FastRoute/tree/master" + }, + "time": "2018-02-13T20:26:39+00:00" + }, + { + "name": "psr/container", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "shasum": "" + }, + "require": { + "php": ">=7.4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://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" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/2.0.2" + }, + "time": "2021-11-05T16:47:00+00:00" + }, + { + "name": "psr/http-factory", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-factory.git", + "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/12ac7fcd07e5b077433f5f2bee95b3a771bf61be", + "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be", + "shasum": "" + }, + "require": { + "php": ">=7.0.0", + "psr/http-message": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interfaces for PSR-7 HTTP message factories", + "keywords": [ + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-factory/tree/master" + }, + "time": "2019-04-30T12:38:16+00:00" + }, + { + "name": "psr/http-message", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-message/tree/master" + }, + "time": "2016-08-06T14:39:51+00:00" + }, + { + "name": "psr/http-server-handler", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-server-handler.git", + "reference": "aff2f80e33b7f026ec96bb42f63242dc50ffcae7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-server-handler/zipball/aff2f80e33b7f026ec96bb42f63242dc50ffcae7", + "reference": "aff2f80e33b7f026ec96bb42f63242dc50ffcae7", + "shasum": "" + }, + "require": { + "php": ">=7.0", + "psr/http-message": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Server\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP server-side request handler", + "keywords": [ + "handler", + "http", + "http-interop", + "psr", + "psr-15", + "psr-7", + "request", + "response", + "server" + ], + "support": { + "issues": "https://github.com/php-fig/http-server-handler/issues", + "source": "https://github.com/php-fig/http-server-handler/tree/master" + }, + "time": "2018-10-30T16:46:14+00:00" + }, + { + "name": "psr/http-server-middleware", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-server-middleware.git", + "reference": "2296f45510945530b9dceb8bcedb5cb84d40c5f5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-server-middleware/zipball/2296f45510945530b9dceb8bcedb5cb84d40c5f5", + "reference": "2296f45510945530b9dceb8bcedb5cb84d40c5f5", + "shasum": "" + }, + "require": { + "php": ">=7.0", + "psr/http-message": "^1.0", + "psr/http-server-handler": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Server\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP server-side middleware", + "keywords": [ + "http", + "http-interop", + "middleware", + "psr", + "psr-15", + "psr-7", + "request", + "response" + ], + "support": { + "issues": "https://github.com/php-fig/http-server-middleware/issues", + "source": "https://github.com/php-fig/http-server-middleware/tree/master" + }, + "time": "2018-10-30T17:12:04+00:00" + }, + { + "name": "psr/log", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001", + "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "support": { + "source": "https://github.com/php-fig/log/tree/3.0.0" + }, + "time": "2021-07-14T16:46:02+00:00" + }, + { + "name": "ralouphie/getallheaders", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/ralouphie/getallheaders.git", + "reference": "120b605dfeb996808c31b6477290a714d356e822" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", + "reference": "120b605dfeb996808c31b6477290a714d356e822", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.1", + "phpunit/phpunit": "^5 || ^6.5" + }, + "type": "library", + "autoload": { + "files": [ + "src/getallheaders.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ralph Khattar", + "email": "ralph.khattar@gmail.com" + } + ], + "description": "A polyfill for getallheaders.", + "support": { + "issues": "https://github.com/ralouphie/getallheaders/issues", + "source": "https://github.com/ralouphie/getallheaders/tree/develop" + }, + "time": "2019-03-08T08:55:37+00:00" + }, + { + "name": "slim/psr7", + "version": "1.6", + "source": { + "type": "git", + "url": "https://github.com/slimphp/Slim-Psr7.git", + "reference": "3471c22c1a0d26c51c78f6aeb06489d38cf46a4d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/slimphp/Slim-Psr7/zipball/3471c22c1a0d26c51c78f6aeb06489d38cf46a4d", + "reference": "3471c22c1a0d26c51c78f6aeb06489d38cf46a4d", + "shasum": "" + }, + "require": { + "fig/http-message-util": "^1.1.5", + "php": "^7.4 || ^8.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.0", + "ralouphie/getallheaders": "^3.0", + "symfony/polyfill-php80": "^1.26" + }, + "provide": { + "psr/http-factory-implementation": "1.0", + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "adriansuter/php-autoload-override": "^1.3", + "ext-json": "*", + "http-interop/http-factory-tests": "^0.9.0", + "php-http/psr7-integration-tests": "dev-master", + "phpspec/prophecy": "^1.15", + "phpspec/prophecy-phpunit": "^2.0", + "phpstan/phpstan": "^1.8", + "phpunit/phpunit": "^9.5", + "squizlabs/php_codesniffer": "^3.7" + }, + "type": "library", + "autoload": { + "psr-4": { + "Slim\\Psr7\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Josh Lockhart", + "email": "hello@joshlockhart.com", + "homepage": "http://joshlockhart.com" + }, + { + "name": "Andrew Smith", + "email": "a.smith@silentworks.co.uk", + "homepage": "http://silentworks.co.uk" + }, + { + "name": "Rob Allen", + "email": "rob@akrabat.com", + "homepage": "http://akrabat.com" + }, + { + "name": "Pierre Berube", + "email": "pierre@lgse.com", + "homepage": "http://www.lgse.com" + } + ], + "description": "Strict PSR-7 implementation", + "homepage": "https://www.slimframework.com", + "keywords": [ + "http", + "psr-7", + "psr7" + ], + "support": { + "issues": "https://github.com/slimphp/Slim-Psr7/issues", + "source": "https://github.com/slimphp/Slim-Psr7/tree/1.6" + }, + "time": "2022-11-05T18:50:24+00:00" + }, + { + "name": "slim/slim", + "version": "4.11.0", + "source": { + "type": "git", + "url": "https://github.com/slimphp/Slim.git", + "reference": "b0f4ca393ea037be9ac7292ba7d0a34d18bac0c7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/slimphp/Slim/zipball/b0f4ca393ea037be9ac7292ba7d0a34d18bac0c7", + "reference": "b0f4ca393ea037be9ac7292ba7d0a34d18bac0c7", + "shasum": "" + }, + "require": { + "ext-json": "*", + "nikic/fast-route": "^1.3", + "php": "^7.4 || ^8.0", + "psr/container": "^1.0 || ^2.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.0", + "psr/http-server-handler": "^1.0", + "psr/http-server-middleware": "^1.0", + "psr/log": "^1.1 || ^2.0 || ^3.0" + }, + "require-dev": { + "adriansuter/php-autoload-override": "^1.3", + "ext-simplexml": "*", + "guzzlehttp/psr7": "^2.4", + "httpsoft/http-message": "^1.0", + "httpsoft/http-server-request": "^1.0", + "laminas/laminas-diactoros": "^2.17", + "nyholm/psr7": "^1.5", + "nyholm/psr7-server": "^1.0", + "phpspec/prophecy": "^1.15", + "phpspec/prophecy-phpunit": "^2.0", + "phpstan/phpstan": "^1.8", + "phpunit/phpunit": "^9.5", + "slim/http": "^1.2", + "slim/psr7": "^1.5", + "squizlabs/php_codesniffer": "^3.7" + }, + "suggest": { + "ext-simplexml": "Needed to support XML format in BodyParsingMiddleware", + "ext-xml": "Needed to support XML format in BodyParsingMiddleware", + "php-di/php-di": "PHP-DI is the recommended container library to be used with Slim", + "slim/psr7": "Slim PSR-7 implementation. See https://www.slimframework.com/docs/v4/start/installation.html for more information." + }, + "type": "library", + "autoload": { + "psr-4": { + "Slim\\": "Slim" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Josh Lockhart", + "email": "hello@joshlockhart.com", + "homepage": "https://joshlockhart.com" + }, + { + "name": "Andrew Smith", + "email": "a.smith@silentworks.co.uk", + "homepage": "http://silentworks.co.uk" + }, + { + "name": "Rob Allen", + "email": "rob@akrabat.com", + "homepage": "http://akrabat.com" + }, + { + "name": "Pierre Berube", + "email": "pierre@lgse.com", + "homepage": "http://www.lgse.com" + }, + { + "name": "Gabriel Manricks", + "email": "gmanricks@me.com", + "homepage": "http://gabrielmanricks.com" + } + ], + "description": "Slim is a PHP micro framework that helps you quickly write simple yet powerful web applications and APIs", + "homepage": "https://www.slimframework.com", + "keywords": [ + "api", + "framework", + "micro", + "router" + ], + "support": { + "docs": "https://www.slimframework.com/docs/v4/", + "forum": "https://discourse.slimframework.com/", + "irc": "irc://irc.freenode.net:6667/slimphp", + "issues": "https://github.com/slimphp/Slim/issues", + "rss": "https://www.slimframework.com/blog/feed.rss", + "slack": "https://slimphp.slack.com/", + "source": "https://github.com/slimphp/Slim", + "wiki": "https://github.com/slimphp/Slim/wiki" + }, + "funding": [ + { + "url": "https://opencollective.com/slimphp", + "type": "open_collective" + }, + { + "url": "https://tidelift.com/funding/github/packagist/slim/slim", + "type": "tidelift" + } + ], + "time": "2022-11-06T16:33:39+00:00" + }, + { + "name": "symfony/polyfill-php80", + "version": "v1.27.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936", + "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php80\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php80/tree/v1.27.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-11-03T14:55:06+00:00" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": [], + "platform-dev": [], + "plugin-api-version": "2.2.0" +} diff --git a/Sources/API/gateways/Inscrit.php b/Sources/API/gateways/Inscrit.php deleted file mode 100644 index d3571be..0000000 --- a/Sources/API/gateways/Inscrit.php +++ /dev/null @@ -1,53 +0,0 @@ -conn = $db; - } - - public function read(){ - $query = 'SELECT - i.id as id, - i.nom as nom, - i.prenom as prenom, - i.mail as mail, - i.mdp as mdp - FROM - '.$this->table.' i - ORDER BY - i.id'; - - $stmt = $this->conn->prepare($query); - $stmt->execute(); - return $stmt; - } - - public function readMdpFromMail($mail){ - $query = 'SELECT - i.id as id, - i.nom as nom, - i.prenom as prenom, - i.mail as mail, - i.mdp as mdp - FROM - '.$this->table.' i - WHERE - i.mail=:mail - '; - $stmt = $this->conn->prepare($query); - $stmt->bindValue(':mail',$mail, PDO::PARAM_STR); - $stmt->execute(); - return $stmt; - } - } - -?> \ No newline at end of file diff --git a/Sources/API/index.php b/Sources/API/index.php deleted file mode 100644 index c35daea..0000000 --- a/Sources/API/index.php +++ /dev/null @@ -1,34 +0,0 @@ -setBasePath('/~vincent/ConsEco/Sources/API'); - -$router->map( 'GET', '/', function(){ - echo 'Hello World'; -}); - -$router->map('GET|POST','/Inscrit', function(){ - require(__DIR__.'/api/inscrit/read.php'); -}); - -$router->map('GET','/Inscrit/[*:mail]', function($mail){ - require(__DIR__.'/api/inscrit/readFromMail.php'); -}); - -$router->match('POST|GET','/Inscrit/add', function(){ - require(__DIR__.'/api/Inscrit/add.php'); -}); - -$match = $router->match(); - -if($match!=null) { - if( is_array($match) && is_callable( $match['target'] ) && isset($match['params']) ) { - call_user_func_array( $match['target'], $match['params']); - }else{ - $match['target'](); - } -} -else { - echo 'ERROR 404'; -} -?> diff --git a/Sources/API/public/index.php b/Sources/API/public/index.php new file mode 100644 index 0000000..8e9fd6e --- /dev/null +++ b/Sources/API/public/index.php @@ -0,0 +1,20 @@ +get('/', function (Request $request, Response $response, $args) { + $response->getBody()->write("Hello world!"); + return $response; +}); + +require __DIR__.'/../routes/Inscrit.php'; + +$app->run(); +?> \ No newline at end of file diff --git a/Sources/API/routes/Inscrit.php b/Sources/API/routes/Inscrit.php new file mode 100644 index 0000000..244949f --- /dev/null +++ b/Sources/API/routes/Inscrit.php @@ -0,0 +1,60 @@ +get('/Inscrit', function(Request $request, Response $response){ + $query = "SELECT * FROM Inscrit"; + + try{ + $db = new Database(); + $conn = $db->connect(); + + $stmt = $conn->query($query); + $inscrits = $stmt->fetchAll(PDO::FETCH_OBJ); + + $db = null; + $response->getBody()->write(json_encode($inscrits)); + return $response + ->withHeader('content-type', 'application/json') + ->withStatus(200); + } catch(PDOException $e){ + $error = array("message" => $e->getMessage()); + + $response->getBody()->write(json_encode($error)); + return $response + ->withHeader('content-type', 'application/json') + ->withStatus(500); + } +}); + +$app->post('/Inscrit/one', function(Request $request, Response $response,array $args){ + $mail = $request->getParsedBody(); + $query = 'SELECT * FROM Inscrit WHERE mail=:mail'; + + try{ + $db = new Database(); + $conn = $db->connect(); + + $stmt = $conn->prepare($query); + $stmt->bindValue(':mail',$mail, PDO::PARAM_STR); + + $inscrit = $stmt->fetchAll(PDO::FETCH_OBJ); + + $db = null; + $response->getBody()->write(json_encode($inscrit)); + return $response + ->withHeader('content-type', 'application/json') + ->withStatus(200); + } catch(PDOException $e){ + $error = array("message" => $e->getMessage()); + + $response->getBody()->write(json_encode($error)); + return $response + ->withHeader('content-type', 'application/json') + ->withStatus(500); + } +}); +?> \ No newline at end of file diff --git a/Sources/API/vendor/altorouter/altorouter/.travis.yml b/Sources/API/vendor/altorouter/altorouter/.travis.yml deleted file mode 100644 index 3bf3161..0000000 --- a/Sources/API/vendor/altorouter/altorouter/.travis.yml +++ /dev/null @@ -1,7 +0,0 @@ -language: php -php: - - 5.3 - - 5.4 - - 5.5 - -script: phpunit --coverage-text ./ diff --git a/Sources/API/vendor/altorouter/altorouter/AltoRouter.php b/Sources/API/vendor/altorouter/altorouter/AltoRouter.php deleted file mode 100644 index 67e76ab..0000000 --- a/Sources/API/vendor/altorouter/altorouter/AltoRouter.php +++ /dev/null @@ -1,270 +0,0 @@ - '[0-9]++', - 'a' => '[0-9A-Za-z]++', - 'h' => '[0-9A-Fa-f]++', - '*' => '.+?', - '**' => '.++', - '' => '[^/\.]++' - ); - - /** - * Create router in one call from config. - * - * @param array $routes - * @param string $basePath - * @param array $matchTypes - */ - public function __construct( $routes = array(), $basePath = '', $matchTypes = array() ) { - $this->addRoutes($routes); - $this->setBasePath($basePath); - $this->addMatchTypes($matchTypes); - } - - /** - * Add multiple routes at once from array in the following format: - * - * $routes = array( - * array($method, $route, $target, $name) - * ); - * - * @param array $routes - * @return void - * @author Koen Punt - */ - public function addRoutes($routes){ - if(!is_array($routes) && !$routes instanceof Traversable) { - throw new \Exception('Routes should be an array or an instance of Traversable'); - } - foreach($routes as $route) { - call_user_func_array(array($this, 'map'), $route); - } - } - - /** - * Set the base path. - * Useful if you are running your application from a subdirectory. - */ - public function setBasePath($basePath) { - $this->basePath = $basePath; - } - - /** - * Add named match types. It uses array_merge so keys can be overwritten. - * - * @param array $matchTypes The key is the name and the value is the regex. - */ - public function addMatchTypes($matchTypes) { - $this->matchTypes = array_merge($this->matchTypes, $matchTypes); - } - - /** - * Map a route to a target - * - * @param string $method One of 4 HTTP Methods, or a pipe-separated list of multiple HTTP Methods (GET|POST|PUT|DELETE) - * @param string $route The route regex, custom regex must start with an @. You can use multiple pre-set regex filters, like [i:id] - * @param mixed $target The target where this route should point to. Can be anything. - * @param string $name Optional name of this route. Supply if you want to reverse route this url in your application. - */ - public function map($method, $route, $target, $name = null) { - - $this->routes[] = array($method, $route, $target, $name); - - if($name) { - if(isset($this->namedRoutes[$name])) { - throw new \Exception("Can not redeclare route '{$name}'"); - } else { - $this->namedRoutes[$name] = $route; - } - - } - - return; - } - - /** - * Reversed routing - * - * Generate the URL for a named route. Replace regexes with supplied parameters - * - * @param string $routeName The name of the route. - * @param array @params Associative array of parameters to replace placeholders with. - * @return string The URL of the route with named parameters in place. - */ - public function generate($routeName, array $params = array()) { - - // Check if named route exists - if(!isset($this->namedRoutes[$routeName])) { - throw new \Exception("Route '{$routeName}' does not exist."); - } - - // Replace named parameters - $route = $this->namedRoutes[$routeName]; - - // prepend base path to route url again - $url = $this->basePath . $route; - - if (preg_match_all('`(/|\.|)\[([^:\]]*+)(?::([^:\]]*+))?\](\?|)`', $route, $matches, PREG_SET_ORDER)) { - - foreach($matches as $match) { - list($block, $pre, $type, $param, $optional) = $match; - - if ($pre) { - $block = substr($block, 1); - } - - if(isset($params[$param])) { - $url = str_replace($block, $params[$param], $url); - } elseif ($optional) { - $url = str_replace($pre . $block, '', $url); - } - } - - - } - - return $url; - } - - /** - * Match a given Request Url against stored routes - * @param string $requestUrl - * @param string $requestMethod - * @return array|boolean Array with route information on success, false on failure (no match). - */ - public function match($requestUrl = null, $requestMethod = null) { - - $params = array(); - $match = false; - - // set Request Url if it isn't passed as parameter - if($requestUrl === null) { - $requestUrl = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '/'; - } - - // strip base path from request url - $requestUrl = substr($requestUrl, strlen($this->basePath)); - - // Strip query string (?a=b) from Request Url - if (($strpos = strpos($requestUrl, '?')) !== false) { - $requestUrl = substr($requestUrl, 0, $strpos); - } - - // set Request Method if it isn't passed as a parameter - if($requestMethod === null) { - $requestMethod = isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : 'GET'; - } - - // Force request_order to be GP - // http://www.mail-archive.com/internals@lists.php.net/msg33119.html - $_REQUEST = array_merge($_GET, $_POST); - - foreach($this->routes as $handler) { - list($method, $_route, $target, $name) = $handler; - - $methods = explode('|', $method); - $method_match = false; - - // Check if request method matches. If not, abandon early. (CHEAP) - foreach($methods as $method) { - if (strcasecmp($requestMethod, $method) === 0) { - $method_match = true; - break; - } - } - - // Method did not match, continue to next route. - if(!$method_match) continue; - - // Check for a wildcard (matches all) - if ($_route === '*') { - $match = true; - } elseif (isset($_route[0]) && $_route[0] === '@') { - $match = preg_match('`' . substr($_route, 1) . '`u', $requestUrl, $params); - } else { - $route = null; - $regex = false; - $j = 0; - $n = isset($_route[0]) ? $_route[0] : null; - $i = 0; - - // Find the longest non-regex substring and match it against the URI - while (true) { - if (!isset($_route[$i])) { - break; - } elseif (false === $regex) { - $c = $n; - $regex = $c === '[' || $c === '(' || $c === '.'; - if (false === $regex && false !== isset($_route[$i+1])) { - $n = $_route[$i + 1]; - $regex = $n === '?' || $n === '+' || $n === '*' || $n === '{'; - } - if (false === $regex && $c !== '/' && (!isset($requestUrl[$j]) || $c !== $requestUrl[$j])) { - continue 2; - } - $j++; - } - $route .= $_route[$i++]; - } - - $regex = $this->compileRoute($route); - $match = preg_match($regex, $requestUrl, $params); - } - - if(($match == true || $match > 0)) { - - if($params) { - foreach($params as $key => $value) { - if(is_numeric($key)) unset($params[$key]); - } - } - - return array( - 'target' => $target, - 'params' => $params, - 'name' => $name - ); - } - } - return false; - } - - /** - * Compile the regex for a given route (EXPENSIVE) - */ - private function compileRoute($route) { - if (preg_match_all('`(/|\.|)\[([^:\]]*+)(?::([^:\]]*+))?\](\?|)`', $route, $matches, PREG_SET_ORDER)) { - - $matchTypes = $this->matchTypes; - foreach($matches as $match) { - list($block, $pre, $type, $param, $optional) = $match; - - if (isset($matchTypes[$type])) { - $type = $matchTypes[$type]; - } - if ($pre === '.') { - $pre = '\.'; - } - - //Older versions of PCRE require the 'P' in (?P) - $pattern = '(?:' - . ($pre !== '' ? $pre : null) - . '(' - . ($param !== '' ? "?P<$param>" : null) - . $type - . '))' - . ($optional !== '' ? '?' : null); - - $route = str_replace($block, $pattern, $route); - } - - } - return "`^$route$`u"; - } -} diff --git a/Sources/API/vendor/altorouter/altorouter/AltoRouterTest.php b/Sources/API/vendor/altorouter/altorouter/AltoRouterTest.php deleted file mode 100644 index 2462cd8..0000000 --- a/Sources/API/vendor/altorouter/altorouter/AltoRouterTest.php +++ /dev/null @@ -1,423 +0,0 @@ -namedRoutes; - } - - public function getRoutes(){ - return $this->routes; - } - - public function getBasePath(){ - return $this->basePath; - } - -} - -class SimpleTraversable implements Iterator{ - - protected $_position = 0; - - protected $_data = array( - array('GET', '/foo', 'foo_action', null), - array('POST', '/bar', 'bar_action', 'second_route') - ); - - public function current(){ - return $this->_data[$this->_position]; - } - public function key(){ - return $this->_position; - } - public function next(){ - ++$this->_position; - } - public function rewind(){ - $this->_position = 0; - } - public function valid(){ - return isset($this->_data[$this->_position]); - } - -} - -/** - * Generated by PHPUnit_SkeletonGenerator 1.2.1 on 2013-07-14 at 17:47:46. - */ -class AltoRouterTest extends PHPUnit_Framework_TestCase -{ - /** - * @var AltoRouter - */ - protected $router; - - /** - * Sets up the fixture, for example, opens a network connection. - * This method is called before a test is executed. - */ - protected function setUp() - { - $this->router = new AltoRouterDebug; - } - - /** - * Tears down the fixture, for example, closes a network connection. - * This method is called after a test is executed. - */ - protected function tearDown() - { - } - - /** - * @covers AltoRouter::addRoutes - */ - public function testAddRoutes() - { - $method = 'POST'; - $route = '/[:controller]/[:action]'; - $target = function(){}; - - $this->router->addRoutes(array( - array($method, $route, $target), - array($method, $route, $target, 'second_route') - )); - - $routes = $this->router->getRoutes(); - - $this->assertEquals(array($method, $route, $target, null), $routes[0]); - $this->assertEquals(array($method, $route, $target, 'second_route'), $routes[1]); - } - - /** - * @covers AltoRouter::addRoutes - */ - public function testAddRoutesAcceptsTraverable() - { - $traversable = new SimpleTraversable(); - $this->router->addRoutes($traversable); - - $traversable->rewind(); - - $first = $traversable->current(); - $traversable->next(); - $second = $traversable->current(); - - $routes = $this->router->getRoutes(); - - $this->assertEquals($first, $routes[0]); - $this->assertEquals($second, $routes[1]); - } - - /** - * @covers AltoRouter::addRoutes - * @expectedException Exception - */ - public function testAddRoutesThrowsExceptionOnInvalidArgument() - { - $this->router->addRoutes(new stdClass); - } - - /** - * @covers AltoRouter::setBasePath - */ - public function testSetBasePath() - { - $basePath = $this->router->setBasePath('/some/path'); - $this->assertEquals('/some/path', $this->router->getBasePath()); - - $basePath = $this->router->setBasePath('/some/path'); - $this->assertEquals('/some/path', $this->router->getBasePath()); - } - - /** - * @covers AltoRouter::map - */ - public function testMap() - { - $method = 'POST'; - $route = '/[:controller]/[:action]'; - $target = function(){}; - - $this->router->map($method, $route, $target); - - $routes = $this->router->getRoutes(); - - $this->assertEquals(array($method, $route, $target, null), $routes[0]); - } - - /** - * @covers AltoRouter::map - */ - public function testMapWithName() - { - $method = 'POST'; - $route = '/[:controller]/[:action]'; - $target = function(){}; - $name = 'myroute'; - - $this->router->map($method, $route, $target, $name); - - $routes = $this->router->getRoutes(); - $this->assertEquals(array($method, $route, $target, $name), $routes[0]); - - $named_routes = $this->router->getNamedRoutes(); - $this->assertEquals($route, $named_routes[$name]); - - try{ - $this->router->map($method, $route, $target, $name); - $this->fail('Should not be able to add existing named route'); - }catch(Exception $e){ - $this->assertEquals("Can not redeclare route '{$name}'", $e->getMessage()); - } - } - - - /** - * @covers AltoRouter::generate - */ - public function testGenerate() - { - $params = array( - 'controller' => 'test', - 'action' => 'someaction' - ); - - $this->router->map('GET', '/[:controller]/[:action]', function(){}, 'foo_route'); - - $this->assertEquals('/test/someaction', - $this->router->generate('foo_route', $params)); - - $params = array( - 'controller' => 'test', - 'action' => 'someaction', - 'type' => 'json' - ); - - $this->assertEquals('/test/someaction', - $this->router->generate('foo_route', $params)); - - } - - public function testGenerateWithOptionalUrlParts() - { - $this->router->map('GET', '/[:controller]/[:action].[:type]?', function(){}, 'bar_route'); - - $params = array( - 'controller' => 'test', - 'action' => 'someaction' - ); - - $this->assertEquals('/test/someaction', - $this->router->generate('bar_route', $params)); - - $params = array( - 'controller' => 'test', - 'action' => 'someaction', - 'type' => 'json' - ); - - $this->assertEquals('/test/someaction.json', - $this->router->generate('bar_route', $params)); - } - - public function testGenerateWithNonexistingRoute() - { - try{ - $this->router->generate('nonexisting_route'); - $this->fail('Should trigger an exception on nonexisting named route'); - }catch(Exception $e){ - $this->assertEquals("Route 'nonexisting_route' does not exist.", $e->getMessage()); - } - } - - /** - * @covers AltoRouter::match - * @covers AltoRouter::compileRoute - */ - public function testMatch() - { - $this->router->map('GET', '/foo/[:controller]/[:action]', 'foo_action', 'foo_route'); - - $this->assertEquals(array( - 'target' => 'foo_action', - 'params' => array( - 'controller' => 'test', - 'action' => 'do' - ), - 'name' => 'foo_route' - ), $this->router->match('/foo/test/do', 'GET')); - - $this->assertFalse($this->router->match('/foo/test/do', 'POST')); - - $this->assertEquals(array( - 'target' => 'foo_action', - 'params' => array( - 'controller' => 'test', - 'action' => 'do' - ), - 'name' => 'foo_route' - ), $this->router->match('/foo/test/do?param=value', 'GET')); - - } - - public function testMatchWithFixedParamValues() - { - $this->router->map('POST','/users/[i:id]/[delete|update:action]', 'usersController#doAction', 'users_do'); - - $this->assertEquals(array( - 'target' => 'usersController#doAction', - 'params' => array( - 'id' => 1, - 'action' => 'delete' - ), - 'name' => 'users_do' - ), $this->router->match('/users/1/delete', 'POST')); - - $this->assertFalse($this->router->match('/users/1/delete', 'GET')); - $this->assertFalse($this->router->match('/users/abc/delete', 'POST')); - $this->assertFalse($this->router->match('/users/1/create', 'GET')); - } - - public function testMatchWithServerVars() - { - $this->router->map('GET', '/foo/[:controller]/[:action]', 'foo_action', 'foo_route'); - - $_SERVER['REQUEST_URI'] = '/foo/test/do'; - $_SERVER['REQUEST_METHOD'] = 'GET'; - - $this->assertEquals(array( - 'target' => 'foo_action', - 'params' => array( - 'controller' => 'test', - 'action' => 'do' - ), - 'name' => 'foo_route' - ), $this->router->match()); - } - - public function testMatchWithOptionalUrlParts() - { - $this->router->map('GET', '/bar/[:controller]/[:action].[:type]?', 'bar_action', 'bar_route'); - - $this->assertEquals(array( - 'target' => 'bar_action', - 'params' => array( - 'controller' => 'test', - 'action' => 'do', - 'type' => 'json' - ), - 'name' => 'bar_route' - ), $this->router->match('/bar/test/do.json', 'GET')); - - } - - public function testMatchWithWildcard() - { - $this->router->map('GET', '/a', 'foo_action', 'foo_route'); - $this->router->map('GET', '*', 'bar_action', 'bar_route'); - - $this->assertEquals(array( - 'target' => 'bar_action', - 'params' => array(), - 'name' => 'bar_route' - ), $this->router->match('/everything', 'GET')); - - } - - public function testMatchWithCustomRegexp() - { - $this->router->map('GET', '@^/[a-z]*$', 'bar_action', 'bar_route'); - - $this->assertEquals(array( - 'target' => 'bar_action', - 'params' => array(), - 'name' => 'bar_route' - ), $this->router->match('/everything', 'GET')); - - $this->assertFalse($this->router->match('/some-other-thing', 'GET')); - - } - - public function testMatchWithUnicodeRegex() - { - $pattern = '/(?[^'; - // Arabic characters - $pattern .= '\x{0600}-\x{06FF}'; - $pattern .= '\x{FB50}-\x{FDFD}'; - $pattern .= '\x{FE70}-\x{FEFF}'; - $pattern .= '\x{0750}-\x{077F}'; - // Alphanumeric, /, _, - and space characters - $pattern .= 'a-zA-Z0-9\/_-\s'; - // 'ZERO WIDTH NON-JOINER' - $pattern .= '\x{200C}'; - $pattern .= ']+)'; - - $this->router->map('GET', '@' . $pattern, 'unicode_action', 'unicode_route'); - - $this->assertEquals(array( - 'target' => 'unicode_action', - 'name' => 'unicode_route', - 'params' => array( - 'path' => '大家好' - ) - ), $this->router->match('/大家好', 'GET')); - - $this->assertFalse($this->router->match('/﷽‎', 'GET')); - } - - /** - * @covers AltoRouter::addMatchTypes - */ - public function testMatchWithCustomNamedRegex() - { - $this->router->addMatchTypes(array('cId' => '[a-zA-Z]{2}[0-9](?:_[0-9]++)?')); - $this->router->map('GET', '/bar/[cId:customId]', 'bar_action', 'bar_route'); - - $this->assertEquals(array( - 'target' => 'bar_action', - 'params' => array( - 'customId' => 'AB1', - ), - 'name' => 'bar_route' - ), $this->router->match('/bar/AB1', 'GET')); - - $this->assertEquals(array( - 'target' => 'bar_action', - 'params' => array( - 'customId' => 'AB1_0123456789', - ), - 'name' => 'bar_route' - ), $this->router->match('/bar/AB1_0123456789', 'GET')); - - $this->assertFalse($this->router->match('/some-other-thing', 'GET')); - - } - - public function testMatchWithCustomNamedUnicodeRegex() - { - $pattern = '[^'; - // Arabic characters - $pattern .= '\x{0600}-\x{06FF}'; - $pattern .= '\x{FB50}-\x{FDFD}'; - $pattern .= '\x{FE70}-\x{FEFF}'; - $pattern .= '\x{0750}-\x{077F}'; - $pattern .= ']+'; - - $this->router->addMatchTypes(array('nonArabic' => $pattern)); - $this->router->map('GET', '/bar/[nonArabic:string]', 'non_arabic_action', 'non_arabic_route'); - - $this->assertEquals(array( - 'target' => 'non_arabic_action', - 'name' => 'non_arabic_route', - 'params' => array( - 'string' => 'some-path' - ) - ), $this->router->match('/bar/some-path', 'GET')); - - $this->assertFalse($this->router->match('/﷽‎', 'GET')); - } -} diff --git a/Sources/API/vendor/altorouter/altorouter/README.md b/Sources/API/vendor/altorouter/altorouter/README.md deleted file mode 100644 index cb2acb3..0000000 --- a/Sources/API/vendor/altorouter/altorouter/README.md +++ /dev/null @@ -1,92 +0,0 @@ -# AltoRouter [![Build Status](https://api.travis-ci.org/dannyvankooten/AltoRouter.png)](http://travis-ci.org/dannyvankooten/AltoRouter) -AltoRouter is a small but powerful routing class for PHP 5.3+, heavily inspired by [klein.php](https://github.com/chriso/klein.php/). - -* Dynamic routing with named parameters -* Reversed routing -* Flexible regular expression routing (inspired by [Sinatra](http://www.sinatrarb.com/)) -* Custom regexes - -## Getting started - -1. PHP 5.3.x is required -2. Install AltoRouter using Composer or manually -2. Setup URL rewriting so that all requests are handled by **index.php** -3. Create an instance of AltoRouter, map your routes and match a request. -4. Have a look at the basic example in the `examples` directory for a better understanding on how to use AltoRouter. - -## Routing -```php -$router = new AltoRouter(); -$router->setBasePath('/AltoRouter'); // (optional) the subdir AltoRouter lives in - -// mapping routes -$router->map('GET|POST','/', 'home#index', 'home'); -$router->map('GET','/users', array('c' => 'UserController', 'a' => 'ListAction')); -$router->map('GET','/users/[i:id]', 'users#show', 'users_show'); -$router->map('POST','/users/[i:id]/[delete|update:action]', 'usersController#doAction', 'users_do'); - -// reversed routing -$router->generate('users_show', array('id' => 5)); - -``` - -**You can use the following limits on your named parameters. AltoRouter will create the correct regexes for you.** - -```php -* // Match all request URIs -[i] // Match an integer -[i:id] // Match an integer as 'id' -[a:action] // Match alphanumeric characters as 'action' -[h:key] // Match hexadecimal characters as 'key' -[:action] // Match anything up to the next / or end of the URI as 'action' -[create|edit:action] // Match either 'create' or 'edit' as 'action' -[*] // Catch all (lazy, stops at the next trailing slash) -[*:trailing] // Catch all as 'trailing' (lazy) -[**:trailing] // Catch all (possessive - will match the rest of the URI) -.[:format]? // Match an optional parameter 'format' - a / or . before the block is also optional -``` - -**Some more complicated examples** - -```php -@/(?[A-Za-z]{2}_[A-Za-z]{2})$ // custom regex, matches language codes like "en_us" etc. -/posts/[*:title][i:id] // Matches "/posts/this-is-a-title-123" -/output.[xml|json:format]? // Matches "/output", "output.xml", "output.json" -/[:controller]?/[:action]? // Matches the typical /controller/action format -``` - -**The character before the colon (the 'match type') is a shortcut for one of the following regular expressions** - -```php -'i' => '[0-9]++' -'a' => '[0-9A-Za-z]++' -'h' => '[0-9A-Fa-f]++' -'*' => '.+?' -'**' => '.++' -'' => '[^/\.]++' -``` - -**New match types can be added using the `addMatchTypes()` method** - -```php -$router->addMatchTypes(array('cId' => '[a-zA-Z]{2}[0-9](?:_[0-9]++)?')); -``` - - -## Contributors -- [Danny van Kooten](https://github.com/dannyvankooten) -- [Koen Punt](https://github.com/koenpunt) -- [John Long](https://github.com/adduc) -- [Niahoo Osef](https://github.com/niahoo) - -## License - -(MIT License) - -Copyright (c) 2012-2013 Danny van Kooten - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/Sources/API/vendor/altorouter/altorouter/composer.json b/Sources/API/vendor/altorouter/altorouter/composer.json deleted file mode 100644 index 58e86c4..0000000 --- a/Sources/API/vendor/altorouter/altorouter/composer.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "name": "altorouter/altorouter", - "description": "A lightning fast router for PHP", - "keywords": ["router", "routing", "lightweight"], - "homepage": "https://github.com/dannyvankooten/AltoRouter", - "license": "MIT", - "authors": [ - { - "name": "Danny van Kooten", - "email": "dannyvankooten@gmail.com", - "homepage": "http://dannyvankooten.com/" - }, - { - "name": "Koen Punt", - "homepage": "https://github.com/koenpunt" - }, - { - "name": "niahoo", - "homepage": "https://github.com/niahoo" - } - ], - "require": { - "php": ">=5.3.0" - }, - "autoload": { - "classmap": ["AltoRouter.php"] - } -} diff --git a/Sources/API/vendor/altorouter/altorouter/examples/basic/.htaccess b/Sources/API/vendor/altorouter/altorouter/examples/basic/.htaccess deleted file mode 100644 index d7e1320..0000000 --- a/Sources/API/vendor/altorouter/altorouter/examples/basic/.htaccess +++ /dev/null @@ -1,3 +0,0 @@ -RewriteEngine On -RewriteCond %{REQUEST_FILENAME} !-f -RewriteRule . index.php [L] diff --git a/Sources/API/vendor/altorouter/altorouter/examples/basic/index.php b/Sources/API/vendor/altorouter/altorouter/examples/basic/index.php deleted file mode 100644 index 8326695..0000000 --- a/Sources/API/vendor/altorouter/altorouter/examples/basic/index.php +++ /dev/null @@ -1,27 +0,0 @@ -setBasePath('/AltoRouter/examples/basic'); -$router->map('GET|POST','/', 'home#index', 'home'); -$router->map('GET','/users/', array('c' => 'UserController', 'a' => 'ListAction')); -$router->map('GET','/users/[i:id]', 'users#show', 'users_show'); -$router->map('POST','/users/[i:id]/[delete|update:action]', 'usersController#doAction', 'users_do'); - -// match current request -$match = $router->match(); -?> -

AltoRouter

- -

Current request:

-
-	Target: 
-	Params: 
-	Name: 	
-
- -

Try these requests:

-

GET generate('home'); ?>

-

GET generate('users_show', array('id' => 5)); ?>

-

diff --git a/Sources/API/vendor/autoload.php b/Sources/API/vendor/autoload.php index fbdc425..86e67b0 100644 --- a/Sources/API/vendor/autoload.php +++ b/Sources/API/vendor/autoload.php @@ -2,24 +2,6 @@ // autoload.php @generated by Composer -if (PHP_VERSION_ID < 50600) { - if (!headers_sent()) { - header('HTTP/1.1 500 Internal Server Error'); - } - $err = 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL; - if (!ini_get('display_errors')) { - if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') { - fwrite(STDERR, $err); - } elseif (!headers_sent()) { - echo $err; - } - } - trigger_error( - $err, - E_USER_ERROR - ); -} - require_once __DIR__ . '/composer/autoload_real.php'; -return ComposerAutoloaderInit2724f76bdbf961b3280ed7526287b513::getLoader(); +return ComposerAutoloaderInita934429c0ea4f4482346c5d296943a81::getLoader(); diff --git a/Sources/API/vendor/composer.json b/Sources/API/vendor/composer.json deleted file mode 100644 index cd42de9..0000000 --- a/Sources/API/vendor/composer.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "require": { - "altorouter/altorouter": "1.1.0" - } -} \ No newline at end of file diff --git a/Sources/API/vendor/composer.lock b/Sources/API/vendor/composer.lock deleted file mode 100644 index b987ae6..0000000 --- a/Sources/API/vendor/composer.lock +++ /dev/null @@ -1,74 +0,0 @@ -{ - "_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#installing-dependencies", - "This file is @generated automatically" - ], - "content-hash": "fdb55ab3a826cc81720434dd90eab926", - "packages": [ - { - "name": "altorouter/altorouter", - "version": "v1.1.0", - "source": { - "type": "git", - "url": "https://github.com/dannyvankooten/AltoRouter.git", - "reference": "09d9d946c546bae6d22a7654cdb3b825ffda54b4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/dannyvankooten/AltoRouter/zipball/09d9d946c546bae6d22a7654cdb3b825ffda54b4", - "reference": "09d9d946c546bae6d22a7654cdb3b825ffda54b4", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "type": "library", - "autoload": { - "classmap": [ - "AltoRouter.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Danny van Kooten", - "email": "dannyvankooten@gmail.com", - "homepage": "http://dannyvankooten.com/" - }, - { - "name": "Koen Punt", - "homepage": "https://github.com/koenpunt" - }, - { - "name": "niahoo", - "homepage": "https://github.com/niahoo" - } - ], - "description": "A lightning fast router for PHP", - "homepage": "https://github.com/dannyvankooten/AltoRouter", - "keywords": [ - "lightweight", - "router", - "routing" - ], - "support": { - "issues": "https://github.com/dannyvankooten/AltoRouter/issues", - "source": "https://github.com/dannyvankooten/AltoRouter/tree/master" - }, - "time": "2014-04-16T09:44:40+00:00" - } - ], - "packages-dev": [], - "aliases": [], - "minimum-stability": "stable", - "stability-flags": [], - "prefer-stable": false, - "prefer-lowest": false, - "platform": [], - "platform-dev": [], - "plugin-api-version": "2.3.0" -} diff --git a/Sources/API/vendor/composer.phar b/Sources/API/vendor/composer.phar deleted file mode 100755 index 6d799eb..0000000 Binary files a/Sources/API/vendor/composer.phar and /dev/null differ diff --git a/Sources/API/vendor/composer/InstalledVersions.php b/Sources/API/vendor/composer/InstalledVersions.php index c6b54af..d50e0c9 100644 --- a/Sources/API/vendor/composer/InstalledVersions.php +++ b/Sources/API/vendor/composer/InstalledVersions.php @@ -21,14 +21,12 @@ use Composer\Semver\VersionParser; * See also https://getcomposer.org/doc/07-runtime.md#installed-versions * * To require its presence, you can require `composer-runtime-api ^2.0` - * - * @final */ class InstalledVersions { /** * @var mixed[]|null - * @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array}|array{}|null + * @psalm-var array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array}|array{}|null */ private static $installed; @@ -39,7 +37,7 @@ class InstalledVersions /** * @var array[] - * @psalm-var array}> + * @psalm-var array}> */ private static $installedByVendor = array(); @@ -243,7 +241,7 @@ class InstalledVersions /** * @return array - * @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool} + * @psalm-return array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string} */ public static function getRootPackage() { @@ -257,7 +255,7 @@ class InstalledVersions * * @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect. * @return array[] - * @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} + * @psalm-return array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array} */ public static function getRawData() { @@ -280,7 +278,7 @@ class InstalledVersions * Returns the raw data of all installed.php which are currently loaded for custom implementations * * @return array[] - * @psalm-return list}> + * @psalm-return list}> */ public static function getAllRawData() { @@ -303,7 +301,7 @@ class InstalledVersions * @param array[] $data A vendor/composer/installed.php data set * @return void * - * @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} $data + * @psalm-param array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array} $data */ public static function reload($data) { @@ -313,7 +311,7 @@ class InstalledVersions /** * @return array[] - * @psalm-return list}> + * @psalm-return list}> */ private static function getInstalled() { diff --git a/Sources/API/vendor/composer/LICENSE b/Sources/API/vendor/composer/LICENSE index f27399a..62ecfd8 100644 --- a/Sources/API/vendor/composer/LICENSE +++ b/Sources/API/vendor/composer/LICENSE @@ -1,4 +1,3 @@ - Copyright (c) Nils Adermann, Jordi Boggiano Permission is hereby granted, free of charge, to any person obtaining a copy @@ -18,4 +17,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - diff --git a/Sources/API/vendor/composer/autoload_classmap.php b/Sources/API/vendor/composer/autoload_classmap.php index 6d812c2..dc15c48 100644 --- a/Sources/API/vendor/composer/autoload_classmap.php +++ b/Sources/API/vendor/composer/autoload_classmap.php @@ -2,10 +2,14 @@ // autoload_classmap.php @generated by Composer -$vendorDir = dirname(__DIR__); +$vendorDir = dirname(dirname(__FILE__)); $baseDir = dirname($vendorDir); return array( - 'AltoRouter' => $vendorDir . '/altorouter/altorouter/AltoRouter.php', + 'Attribute' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Attribute.php', 'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php', + 'PhpToken' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php', + 'Stringable' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Stringable.php', + 'UnhandledMatchError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php', + 'ValueError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/ValueError.php', ); diff --git a/Sources/API/vendor/composer/autoload_files.php b/Sources/API/vendor/composer/autoload_files.php new file mode 100644 index 0000000..33dd33f --- /dev/null +++ b/Sources/API/vendor/composer/autoload_files.php @@ -0,0 +1,12 @@ + $vendorDir . '/symfony/polyfill-php80/bootstrap.php', + '7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php', + '253c157292f75eb38082b5acb06f3f01' => $vendorDir . '/nikic/fast-route/src/functions.php', +); diff --git a/Sources/API/vendor/composer/autoload_namespaces.php b/Sources/API/vendor/composer/autoload_namespaces.php index 15a2ff3..b7fc012 100644 --- a/Sources/API/vendor/composer/autoload_namespaces.php +++ b/Sources/API/vendor/composer/autoload_namespaces.php @@ -2,7 +2,7 @@ // autoload_namespaces.php @generated by Composer -$vendorDir = dirname(__DIR__); +$vendorDir = dirname(dirname(__FILE__)); $baseDir = dirname($vendorDir); return array( diff --git a/Sources/API/vendor/composer/autoload_psr4.php b/Sources/API/vendor/composer/autoload_psr4.php index 3890ddc..5bba2b0 100644 --- a/Sources/API/vendor/composer/autoload_psr4.php +++ b/Sources/API/vendor/composer/autoload_psr4.php @@ -2,8 +2,17 @@ // autoload_psr4.php @generated by Composer -$vendorDir = dirname(__DIR__); +$vendorDir = dirname(dirname(__FILE__)); $baseDir = dirname($vendorDir); return array( + 'Symfony\\Polyfill\\Php80\\' => array($vendorDir . '/symfony/polyfill-php80'), + 'Slim\\Psr7\\' => array($vendorDir . '/slim/psr7/src'), + 'Slim\\' => array($vendorDir . '/slim/slim/Slim'), + 'Psr\\Log\\' => array($vendorDir . '/psr/log/src'), + 'Psr\\Http\\Server\\' => array($vendorDir . '/psr/http-server-handler/src', $vendorDir . '/psr/http-server-middleware/src'), + 'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-factory/src', $vendorDir . '/psr/http-message/src'), + 'Psr\\Container\\' => array($vendorDir . '/psr/container/src'), + 'Fig\\Http\\Message\\' => array($vendorDir . '/fig/http-message-util/src'), + 'FastRoute\\' => array($vendorDir . '/nikic/fast-route/src'), ); diff --git a/Sources/API/vendor/composer/autoload_real.php b/Sources/API/vendor/composer/autoload_real.php index 067933a..1db1e4c 100644 --- a/Sources/API/vendor/composer/autoload_real.php +++ b/Sources/API/vendor/composer/autoload_real.php @@ -2,7 +2,7 @@ // autoload_real.php @generated by Composer -class ComposerAutoloaderInit2724f76bdbf961b3280ed7526287b513 +class ComposerAutoloaderInita934429c0ea4f4482346c5d296943a81 { private static $loader; @@ -24,15 +24,57 @@ class ComposerAutoloaderInit2724f76bdbf961b3280ed7526287b513 require __DIR__ . '/platform_check.php'; - spl_autoload_register(array('ComposerAutoloaderInit2724f76bdbf961b3280ed7526287b513', 'loadClassLoader'), true, true); - self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__)); - spl_autoload_unregister(array('ComposerAutoloaderInit2724f76bdbf961b3280ed7526287b513', 'loadClassLoader')); + spl_autoload_register(array('ComposerAutoloaderInita934429c0ea4f4482346c5d296943a81', 'loadClassLoader'), true, true); + self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__))); + spl_autoload_unregister(array('ComposerAutoloaderInita934429c0ea4f4482346c5d296943a81', 'loadClassLoader')); - require __DIR__ . '/autoload_static.php'; - call_user_func(\Composer\Autoload\ComposerStaticInit2724f76bdbf961b3280ed7526287b513::getInitializer($loader)); + $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded()); + if ($useStaticLoader) { + require __DIR__ . '/autoload_static.php'; + + call_user_func(\Composer\Autoload\ComposerStaticInita934429c0ea4f4482346c5d296943a81::getInitializer($loader)); + } else { + $map = require __DIR__ . '/autoload_namespaces.php'; + foreach ($map as $namespace => $path) { + $loader->set($namespace, $path); + } + + $map = require __DIR__ . '/autoload_psr4.php'; + foreach ($map as $namespace => $path) { + $loader->setPsr4($namespace, $path); + } + + $classMap = require __DIR__ . '/autoload_classmap.php'; + if ($classMap) { + $loader->addClassMap($classMap); + } + } $loader->register(true); + if ($useStaticLoader) { + $includeFiles = Composer\Autoload\ComposerStaticInita934429c0ea4f4482346c5d296943a81::$files; + } else { + $includeFiles = require __DIR__ . '/autoload_files.php'; + } + foreach ($includeFiles as $fileIdentifier => $file) { + composerRequirea934429c0ea4f4482346c5d296943a81($fileIdentifier, $file); + } + return $loader; } } + +/** + * @param string $fileIdentifier + * @param string $file + * @return void + */ +function composerRequirea934429c0ea4f4482346c5d296943a81($fileIdentifier, $file) +{ + if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { + $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; + + require $file; + } +} diff --git a/Sources/API/vendor/composer/autoload_static.php b/Sources/API/vendor/composer/autoload_static.php index e084f89..2d0493e 100644 --- a/Sources/API/vendor/composer/autoload_static.php +++ b/Sources/API/vendor/composer/autoload_static.php @@ -4,17 +4,91 @@ namespace Composer\Autoload; -class ComposerStaticInit2724f76bdbf961b3280ed7526287b513 +class ComposerStaticInita934429c0ea4f4482346c5d296943a81 { + public static $files = array ( + 'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php', + '7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php', + '253c157292f75eb38082b5acb06f3f01' => __DIR__ . '/..' . '/nikic/fast-route/src/functions.php', + ); + + public static $prefixLengthsPsr4 = array ( + 'S' => + array ( + 'Symfony\\Polyfill\\Php80\\' => 23, + 'Slim\\Psr7\\' => 10, + 'Slim\\' => 5, + ), + 'P' => + array ( + 'Psr\\Log\\' => 8, + 'Psr\\Http\\Server\\' => 16, + 'Psr\\Http\\Message\\' => 17, + 'Psr\\Container\\' => 14, + ), + 'F' => + array ( + 'Fig\\Http\\Message\\' => 17, + 'FastRoute\\' => 10, + ), + ); + + public static $prefixDirsPsr4 = array ( + 'Symfony\\Polyfill\\Php80\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/polyfill-php80', + ), + 'Slim\\Psr7\\' => + array ( + 0 => __DIR__ . '/..' . '/slim/psr7/src', + ), + 'Slim\\' => + array ( + 0 => __DIR__ . '/..' . '/slim/slim/Slim', + ), + 'Psr\\Log\\' => + array ( + 0 => __DIR__ . '/..' . '/psr/log/src', + ), + 'Psr\\Http\\Server\\' => + array ( + 0 => __DIR__ . '/..' . '/psr/http-server-handler/src', + 1 => __DIR__ . '/..' . '/psr/http-server-middleware/src', + ), + 'Psr\\Http\\Message\\' => + array ( + 0 => __DIR__ . '/..' . '/psr/http-factory/src', + 1 => __DIR__ . '/..' . '/psr/http-message/src', + ), + 'Psr\\Container\\' => + array ( + 0 => __DIR__ . '/..' . '/psr/container/src', + ), + 'Fig\\Http\\Message\\' => + array ( + 0 => __DIR__ . '/..' . '/fig/http-message-util/src', + ), + 'FastRoute\\' => + array ( + 0 => __DIR__ . '/..' . '/nikic/fast-route/src', + ), + ); + public static $classMap = array ( - 'AltoRouter' => __DIR__ . '/..' . '/altorouter/altorouter/AltoRouter.php', + 'Attribute' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Attribute.php', 'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php', + 'PhpToken' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php', + 'Stringable' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Stringable.php', + 'UnhandledMatchError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php', + 'ValueError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/ValueError.php', ); public static function getInitializer(ClassLoader $loader) { return \Closure::bind(function () use ($loader) { - $loader->classMap = ComposerStaticInit2724f76bdbf961b3280ed7526287b513::$classMap; + $loader->prefixLengthsPsr4 = ComposerStaticInita934429c0ea4f4482346c5d296943a81::$prefixLengthsPsr4; + $loader->prefixDirsPsr4 = ComposerStaticInita934429c0ea4f4482346c5d296943a81::$prefixDirsPsr4; + $loader->classMap = ComposerStaticInita934429c0ea4f4482346c5d296943a81::$classMap; }, null, ClassLoader::class); } diff --git a/Sources/API/vendor/composer/installed.json b/Sources/API/vendor/composer/installed.json index d4c5dd8..b69dd50 100644 --- a/Sources/API/vendor/composer/installed.json +++ b/Sources/API/vendor/composer/installed.json @@ -1,29 +1,749 @@ { "packages": [ { - "name": "altorouter/altorouter", - "version": "v1.1.0", - "version_normalized": "1.1.0.0", + "name": "fig/http-message-util", + "version": "1.1.5", + "version_normalized": "1.1.5.0", "source": { "type": "git", - "url": "https://github.com/dannyvankooten/AltoRouter.git", - "reference": "09d9d946c546bae6d22a7654cdb3b825ffda54b4" + "url": "https://github.com/php-fig/http-message-util.git", + "reference": "9d94dc0154230ac39e5bf89398b324a86f63f765" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dannyvankooten/AltoRouter/zipball/09d9d946c546bae6d22a7654cdb3b825ffda54b4", - "reference": "09d9d946c546bae6d22a7654cdb3b825ffda54b4", + "url": "https://api.github.com/repos/php-fig/http-message-util/zipball/9d94dc0154230ac39e5bf89398b324a86f63f765", + "reference": "9d94dc0154230ac39e5bf89398b324a86f63f765", + "shasum": "" + }, + "require": { + "php": "^5.3 || ^7.0 || ^8.0" + }, + "suggest": { + "psr/http-message": "The package containing the PSR-7 interfaces" + }, + "time": "2020-11-24T22:02:12+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Fig\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Utility classes and constants for use with PSR-7 (psr/http-message)", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "support": { + "issues": "https://github.com/php-fig/http-message-util/issues", + "source": "https://github.com/php-fig/http-message-util/tree/1.1.5" + }, + "install-path": "../fig/http-message-util" + }, + { + "name": "nikic/fast-route", + "version": "v1.3.0", + "version_normalized": "1.3.0.0", + "source": { + "type": "git", + "url": "https://github.com/nikic/FastRoute.git", + "reference": "181d480e08d9476e61381e04a71b34dc0432e812" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/FastRoute/zipball/181d480e08d9476e61381e04a71b34dc0432e812", + "reference": "181d480e08d9476e61381e04a71b34dc0432e812", + "shasum": "" + }, + "require": { + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35|~5.7" + }, + "time": "2018-02-13T20:26:39+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "FastRoute\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov", + "email": "nikic@php.net" + } + ], + "description": "Fast request router for PHP", + "keywords": [ + "router", + "routing" + ], + "support": { + "issues": "https://github.com/nikic/FastRoute/issues", + "source": "https://github.com/nikic/FastRoute/tree/master" + }, + "install-path": "../nikic/fast-route" + }, + { + "name": "psr/container", + "version": "2.0.2", + "version_normalized": "2.0.2.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "shasum": "" + }, + "require": { + "php": ">=7.4.0" + }, + "time": "2021-11-05T16:47:00+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://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" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/2.0.2" + }, + "install-path": "../psr/container" + }, + { + "name": "psr/http-factory", + "version": "1.0.1", + "version_normalized": "1.0.1.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-factory.git", + "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/12ac7fcd07e5b077433f5f2bee95b3a771bf61be", + "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be", + "shasum": "" + }, + "require": { + "php": ">=7.0.0", + "psr/http-message": "^1.0" + }, + "time": "2019-04-30T12:38:16+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interfaces for PSR-7 HTTP message factories", + "keywords": [ + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-factory/tree/master" + }, + "install-path": "../psr/http-factory" + }, + { + "name": "psr/http-message", + "version": "1.0.1", + "version_normalized": "1.0.1.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", "shasum": "" }, "require": { "php": ">=5.3.0" }, - "time": "2014-04-16T09:44:40+00:00", + "time": "2016-08-06T14:39:51+00:00", "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, "installation-source": "dist", "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-message/tree/master" + }, + "install-path": "../psr/http-message" + }, + { + "name": "psr/http-server-handler", + "version": "1.0.1", + "version_normalized": "1.0.1.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-server-handler.git", + "reference": "aff2f80e33b7f026ec96bb42f63242dc50ffcae7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-server-handler/zipball/aff2f80e33b7f026ec96bb42f63242dc50ffcae7", + "reference": "aff2f80e33b7f026ec96bb42f63242dc50ffcae7", + "shasum": "" + }, + "require": { + "php": ">=7.0", + "psr/http-message": "^1.0" + }, + "time": "2018-10-30T16:46:14+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Psr\\Http\\Server\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP server-side request handler", + "keywords": [ + "handler", + "http", + "http-interop", + "psr", + "psr-15", + "psr-7", + "request", + "response", + "server" + ], + "support": { + "issues": "https://github.com/php-fig/http-server-handler/issues", + "source": "https://github.com/php-fig/http-server-handler/tree/master" + }, + "install-path": "../psr/http-server-handler" + }, + { + "name": "psr/http-server-middleware", + "version": "1.0.1", + "version_normalized": "1.0.1.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-server-middleware.git", + "reference": "2296f45510945530b9dceb8bcedb5cb84d40c5f5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-server-middleware/zipball/2296f45510945530b9dceb8bcedb5cb84d40c5f5", + "reference": "2296f45510945530b9dceb8bcedb5cb84d40c5f5", + "shasum": "" + }, + "require": { + "php": ">=7.0", + "psr/http-message": "^1.0", + "psr/http-server-handler": "^1.0" + }, + "time": "2018-10-30T17:12:04+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Psr\\Http\\Server\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP server-side middleware", + "keywords": [ + "http", + "http-interop", + "middleware", + "psr", + "psr-15", + "psr-7", + "request", + "response" + ], + "support": { + "issues": "https://github.com/php-fig/http-server-middleware/issues", + "source": "https://github.com/php-fig/http-server-middleware/tree/master" + }, + "install-path": "../psr/http-server-middleware" + }, + { + "name": "psr/log", + "version": "3.0.0", + "version_normalized": "3.0.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001", + "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "time": "2021-07-14T16:46:02+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Psr\\Log\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "support": { + "source": "https://github.com/php-fig/log/tree/3.0.0" + }, + "install-path": "../psr/log" + }, + { + "name": "ralouphie/getallheaders", + "version": "3.0.3", + "version_normalized": "3.0.3.0", + "source": { + "type": "git", + "url": "https://github.com/ralouphie/getallheaders.git", + "reference": "120b605dfeb996808c31b6477290a714d356e822" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", + "reference": "120b605dfeb996808c31b6477290a714d356e822", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.1", + "phpunit/phpunit": "^5 || ^6.5" + }, + "time": "2019-03-08T08:55:37+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "files": [ + "src/getallheaders.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ralph Khattar", + "email": "ralph.khattar@gmail.com" + } + ], + "description": "A polyfill for getallheaders.", + "support": { + "issues": "https://github.com/ralouphie/getallheaders/issues", + "source": "https://github.com/ralouphie/getallheaders/tree/develop" + }, + "install-path": "../ralouphie/getallheaders" + }, + { + "name": "slim/psr7", + "version": "1.6", + "version_normalized": "1.6.0.0", + "source": { + "type": "git", + "url": "https://github.com/slimphp/Slim-Psr7.git", + "reference": "3471c22c1a0d26c51c78f6aeb06489d38cf46a4d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/slimphp/Slim-Psr7/zipball/3471c22c1a0d26c51c78f6aeb06489d38cf46a4d", + "reference": "3471c22c1a0d26c51c78f6aeb06489d38cf46a4d", + "shasum": "" + }, + "require": { + "fig/http-message-util": "^1.1.5", + "php": "^7.4 || ^8.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.0", + "ralouphie/getallheaders": "^3.0", + "symfony/polyfill-php80": "^1.26" + }, + "provide": { + "psr/http-factory-implementation": "1.0", + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "adriansuter/php-autoload-override": "^1.3", + "ext-json": "*", + "http-interop/http-factory-tests": "^0.9.0", + "php-http/psr7-integration-tests": "dev-master", + "phpspec/prophecy": "^1.15", + "phpspec/prophecy-phpunit": "^2.0", + "phpstan/phpstan": "^1.8", + "phpunit/phpunit": "^9.5", + "squizlabs/php_codesniffer": "^3.7" + }, + "time": "2022-11-05T18:50:24+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Slim\\Psr7\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Josh Lockhart", + "email": "hello@joshlockhart.com", + "homepage": "http://joshlockhart.com" + }, + { + "name": "Andrew Smith", + "email": "a.smith@silentworks.co.uk", + "homepage": "http://silentworks.co.uk" + }, + { + "name": "Rob Allen", + "email": "rob@akrabat.com", + "homepage": "http://akrabat.com" + }, + { + "name": "Pierre Berube", + "email": "pierre@lgse.com", + "homepage": "http://www.lgse.com" + } + ], + "description": "Strict PSR-7 implementation", + "homepage": "https://www.slimframework.com", + "keywords": [ + "http", + "psr-7", + "psr7" + ], + "support": { + "issues": "https://github.com/slimphp/Slim-Psr7/issues", + "source": "https://github.com/slimphp/Slim-Psr7/tree/1.6" + }, + "install-path": "../slim/psr7" + }, + { + "name": "slim/slim", + "version": "4.11.0", + "version_normalized": "4.11.0.0", + "source": { + "type": "git", + "url": "https://github.com/slimphp/Slim.git", + "reference": "b0f4ca393ea037be9ac7292ba7d0a34d18bac0c7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/slimphp/Slim/zipball/b0f4ca393ea037be9ac7292ba7d0a34d18bac0c7", + "reference": "b0f4ca393ea037be9ac7292ba7d0a34d18bac0c7", + "shasum": "" + }, + "require": { + "ext-json": "*", + "nikic/fast-route": "^1.3", + "php": "^7.4 || ^8.0", + "psr/container": "^1.0 || ^2.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.0", + "psr/http-server-handler": "^1.0", + "psr/http-server-middleware": "^1.0", + "psr/log": "^1.1 || ^2.0 || ^3.0" + }, + "require-dev": { + "adriansuter/php-autoload-override": "^1.3", + "ext-simplexml": "*", + "guzzlehttp/psr7": "^2.4", + "httpsoft/http-message": "^1.0", + "httpsoft/http-server-request": "^1.0", + "laminas/laminas-diactoros": "^2.17", + "nyholm/psr7": "^1.5", + "nyholm/psr7-server": "^1.0", + "phpspec/prophecy": "^1.15", + "phpspec/prophecy-phpunit": "^2.0", + "phpstan/phpstan": "^1.8", + "phpunit/phpunit": "^9.5", + "slim/http": "^1.2", + "slim/psr7": "^1.5", + "squizlabs/php_codesniffer": "^3.7" + }, + "suggest": { + "ext-simplexml": "Needed to support XML format in BodyParsingMiddleware", + "ext-xml": "Needed to support XML format in BodyParsingMiddleware", + "php-di/php-di": "PHP-DI is the recommended container library to be used with Slim", + "slim/psr7": "Slim PSR-7 implementation. See https://www.slimframework.com/docs/v4/start/installation.html for more information." + }, + "time": "2022-11-06T16:33:39+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Slim\\": "Slim" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Josh Lockhart", + "email": "hello@joshlockhart.com", + "homepage": "https://joshlockhart.com" + }, + { + "name": "Andrew Smith", + "email": "a.smith@silentworks.co.uk", + "homepage": "http://silentworks.co.uk" + }, + { + "name": "Rob Allen", + "email": "rob@akrabat.com", + "homepage": "http://akrabat.com" + }, + { + "name": "Pierre Berube", + "email": "pierre@lgse.com", + "homepage": "http://www.lgse.com" + }, + { + "name": "Gabriel Manricks", + "email": "gmanricks@me.com", + "homepage": "http://gabrielmanricks.com" + } + ], + "description": "Slim is a PHP micro framework that helps you quickly write simple yet powerful web applications and APIs", + "homepage": "https://www.slimframework.com", + "keywords": [ + "api", + "framework", + "micro", + "router" + ], + "support": { + "docs": "https://www.slimframework.com/docs/v4/", + "forum": "https://discourse.slimframework.com/", + "irc": "irc://irc.freenode.net:6667/slimphp", + "issues": "https://github.com/slimphp/Slim/issues", + "rss": "https://www.slimframework.com/blog/feed.rss", + "slack": "https://slimphp.slack.com/", + "source": "https://github.com/slimphp/Slim", + "wiki": "https://github.com/slimphp/Slim/wiki" + }, + "funding": [ + { + "url": "https://opencollective.com/slimphp", + "type": "open_collective" + }, + { + "url": "https://tidelift.com/funding/github/packagist/slim/slim", + "type": "tidelift" + } + ], + "install-path": "../slim/slim" + }, + { + "name": "symfony/polyfill-php80", + "version": "v1.27.0", + "version_normalized": "1.27.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936", + "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "time": "2022-11-03T14:55:06+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "installation-source": "dist", + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php80\\": "" + }, "classmap": [ - "AltoRouter.php" + "Resources/stubs" ] }, "notification-url": "https://packagist.org/downloads/", @@ -32,31 +752,44 @@ ], "authors": [ { - "name": "Danny van Kooten", - "email": "dannyvankooten@gmail.com", - "homepage": "http://dannyvankooten.com/" + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" }, { - "name": "Koen Punt", - "homepage": "https://github.com/koenpunt" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" }, { - "name": "niahoo", - "homepage": "https://github.com/niahoo" + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "A lightning fast router for PHP", - "homepage": "https://github.com/dannyvankooten/AltoRouter", + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "homepage": "https://symfony.com", "keywords": [ - "lightweight", - "router", - "routing" + "compatibility", + "polyfill", + "portable", + "shim" ], "support": { - "issues": "https://github.com/dannyvankooten/AltoRouter/issues", - "source": "https://github.com/dannyvankooten/AltoRouter/tree/master" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.27.0" }, - "install-path": "../altorouter/altorouter" + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "install-path": "../symfony/polyfill-php80" } ], "dev": true, diff --git a/Sources/API/vendor/composer/installed.php b/Sources/API/vendor/composer/installed.php index c0e230c..e795d48 100644 --- a/Sources/API/vendor/composer/installed.php +++ b/Sources/API/vendor/composer/installed.php @@ -1,31 +1,142 @@ array( - 'name' => '__root__', 'pretty_version' => 'dev-master', 'version' => 'dev-master', - 'reference' => '451f8aec79f58d67eb8a9d6097c39c99d26f8b09', 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), + 'reference' => '7167670b929c4f3fec015404893ade05128b1ea4', + 'name' => '__root__', 'dev' => true, ), 'versions' => array( '__root__' => array( 'pretty_version' => 'dev-master', 'version' => 'dev-master', - 'reference' => '451f8aec79f58d67eb8a9d6097c39c99d26f8b09', 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), + 'reference' => '7167670b929c4f3fec015404893ade05128b1ea4', + 'dev_requirement' => false, + ), + 'fig/http-message-util' => array( + 'pretty_version' => '1.1.5', + 'version' => '1.1.5.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../fig/http-message-util', + 'aliases' => array(), + 'reference' => '9d94dc0154230ac39e5bf89398b324a86f63f765', + 'dev_requirement' => false, + ), + 'nikic/fast-route' => array( + 'pretty_version' => 'v1.3.0', + 'version' => '1.3.0.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../nikic/fast-route', + 'aliases' => array(), + 'reference' => '181d480e08d9476e61381e04a71b34dc0432e812', + 'dev_requirement' => false, + ), + 'psr/container' => array( + 'pretty_version' => '2.0.2', + 'version' => '2.0.2.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../psr/container', + 'aliases' => array(), + 'reference' => 'c71ecc56dfe541dbd90c5360474fbc405f8d5963', + 'dev_requirement' => false, + ), + 'psr/http-factory' => array( + 'pretty_version' => '1.0.1', + 'version' => '1.0.1.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../psr/http-factory', + 'aliases' => array(), + 'reference' => '12ac7fcd07e5b077433f5f2bee95b3a771bf61be', + 'dev_requirement' => false, + ), + 'psr/http-factory-implementation' => array( + 'dev_requirement' => false, + 'provided' => array( + 0 => '1.0', + ), + ), + 'psr/http-message' => array( + 'pretty_version' => '1.0.1', + 'version' => '1.0.1.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../psr/http-message', + 'aliases' => array(), + 'reference' => 'f6561bf28d520154e4b0ec72be95418abe6d9363', + 'dev_requirement' => false, + ), + 'psr/http-message-implementation' => array( + 'dev_requirement' => false, + 'provided' => array( + 0 => '1.0', + ), + ), + 'psr/http-server-handler' => array( + 'pretty_version' => '1.0.1', + 'version' => '1.0.1.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../psr/http-server-handler', + 'aliases' => array(), + 'reference' => 'aff2f80e33b7f026ec96bb42f63242dc50ffcae7', + 'dev_requirement' => false, + ), + 'psr/http-server-middleware' => array( + 'pretty_version' => '1.0.1', + 'version' => '1.0.1.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../psr/http-server-middleware', + 'aliases' => array(), + 'reference' => '2296f45510945530b9dceb8bcedb5cb84d40c5f5', + 'dev_requirement' => false, + ), + 'psr/log' => array( + 'pretty_version' => '3.0.0', + 'version' => '3.0.0.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../psr/log', + 'aliases' => array(), + 'reference' => 'fe5ea303b0887d5caefd3d431c3e61ad47037001', + 'dev_requirement' => false, + ), + 'ralouphie/getallheaders' => array( + 'pretty_version' => '3.0.3', + 'version' => '3.0.3.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../ralouphie/getallheaders', + 'aliases' => array(), + 'reference' => '120b605dfeb996808c31b6477290a714d356e822', + 'dev_requirement' => false, + ), + 'slim/psr7' => array( + 'pretty_version' => '1.6', + 'version' => '1.6.0.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../slim/psr7', + 'aliases' => array(), + 'reference' => '3471c22c1a0d26c51c78f6aeb06489d38cf46a4d', + 'dev_requirement' => false, + ), + 'slim/slim' => array( + 'pretty_version' => '4.11.0', + 'version' => '4.11.0.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../slim/slim', + 'aliases' => array(), + 'reference' => 'b0f4ca393ea037be9ac7292ba7d0a34d18bac0c7', 'dev_requirement' => false, ), - 'altorouter/altorouter' => array( - 'pretty_version' => 'v1.1.0', - 'version' => '1.1.0.0', - 'reference' => '09d9d946c546bae6d22a7654cdb3b825ffda54b4', + 'symfony/polyfill-php80' => array( + 'pretty_version' => 'v1.27.0', + 'version' => '1.27.0.0', 'type' => 'library', - 'install_path' => __DIR__ . '/../altorouter/altorouter', + 'install_path' => __DIR__ . '/../symfony/polyfill-php80', 'aliases' => array(), + 'reference' => '7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936', 'dev_requirement' => false, ), ), diff --git a/Sources/API/vendor/composer/platform_check.php b/Sources/API/vendor/composer/platform_check.php index 7621d4f..adfb472 100644 --- a/Sources/API/vendor/composer/platform_check.php +++ b/Sources/API/vendor/composer/platform_check.php @@ -4,8 +4,8 @@ $issues = array(); -if (!(PHP_VERSION_ID >= 50300)) { - $issues[] = 'Your Composer dependencies require a PHP version ">= 5.3.0". You are running ' . PHP_VERSION . '.'; +if (!(PHP_VERSION_ID >= 80000)) { + $issues[] = 'Your Composer dependencies require a PHP version ">= 8.0.0". You are running ' . PHP_VERSION . '.'; } if ($issues) { diff --git a/Sources/API/vendor/fig/http-message-util/.gitignore b/Sources/API/vendor/fig/http-message-util/.gitignore new file mode 100644 index 0000000..48b8bf9 --- /dev/null +++ b/Sources/API/vendor/fig/http-message-util/.gitignore @@ -0,0 +1 @@ +vendor/ diff --git a/Sources/API/vendor/fig/http-message-util/CHANGELOG.md b/Sources/API/vendor/fig/http-message-util/CHANGELOG.md new file mode 100644 index 0000000..1a02e54 --- /dev/null +++ b/Sources/API/vendor/fig/http-message-util/CHANGELOG.md @@ -0,0 +1,147 @@ +# Changelog + +All notable changes to this project will be documented in this file, in reverse chronological order by release. + +## 1.1.5 - 2020-11-24 + +### Added + +- [#19](https://github.com/php-fig/http-message-util/pull/19) adds support for PHP 8. + +### Changed + +- Nothing. + +### Deprecated + +- Nothing. + +### Removed + +- Nothing. + +### Fixed + +- Nothing. + +## 1.1.4 - 2020-02-05 + +### Added + +- Nothing. + +### Changed + +- Nothing. + +### Deprecated + +- Nothing. + +### Removed + +- [#15](https://github.com/php-fig/http-message-util/pull/15) removes the dependency on psr/http-message, as it is not technically necessary for usage of this package. + +### Fixed + +- Nothing. + +## 1.1.3 - 2018-11-19 + +### Added + +- [#10](https://github.com/php-fig/http-message-util/pull/10) adds the constants `StatusCodeInterface::STATUS_EARLY_HINTS` (103) and + `StatusCodeInterface::STATUS_TOO_EARLY` (425). + +### Changed + +- Nothing. + +### Deprecated + +- Nothing. + +### Removed + +- Nothing. + +### Fixed + +- Nothing. + +## 1.1.2 - 2017-02-09 + +### Added + +- [#4](https://github.com/php-fig/http-message-util/pull/4) adds the constant + `StatusCodeInterface::STATUS_MISDIRECTED_REQUEST` (421). + +### Deprecated + +- Nothing. + +### Removed + +- Nothing. + +### Fixed + +- Nothing. + +## 1.1.1 - 2017-02-06 + +### Added + +- [#3](https://github.com/php-fig/http-message-util/pull/3) adds the constant + `StatusCodeInterface::STATUS_IM_A_TEAPOT` (418). + +### Deprecated + +- Nothing. + +### Removed + +- Nothing. + +### Fixed + +- Nothing. + +## 1.1.0 - 2016-09-19 + +### Added + +- [#1](https://github.com/php-fig/http-message-util/pull/1) adds + `Fig\Http\Message\StatusCodeInterface`, with constants named after common + status reason phrases, with values indicating the status codes themselves. + +### Deprecated + +- Nothing. + +### Removed + +- Nothing. + +### Fixed + +- Nothing. + +## 1.0.0 - 2017-08-05 + +### Added + +- Adds `Fig\Http\Message\RequestMethodInterface`, with constants covering the + most common HTTP request methods as specified by the IETF. + +### Deprecated + +- Nothing. + +### Removed + +- Nothing. + +### Fixed + +- Nothing. diff --git a/Sources/API/vendor/fig/http-message-util/LICENSE b/Sources/API/vendor/fig/http-message-util/LICENSE new file mode 100644 index 0000000..e2fa347 --- /dev/null +++ b/Sources/API/vendor/fig/http-message-util/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2016 PHP Framework Interoperability Group + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/Sources/API/vendor/fig/http-message-util/README.md b/Sources/API/vendor/fig/http-message-util/README.md new file mode 100644 index 0000000..ea5b5aa --- /dev/null +++ b/Sources/API/vendor/fig/http-message-util/README.md @@ -0,0 +1,17 @@ +# PSR Http Message Util + +This repository holds utility classes and constants to facilitate common +operations of [PSR-7](https://www.php-fig.org/psr/psr-7/); the primary purpose is +to provide constants for referring to request methods, response status codes and +messages, and potentially common headers. + +Implementation of PSR-7 interfaces is **not** within the scope of this package. + +## Installation + +Install by adding the package as a [Composer](https://getcomposer.org) +requirement: + +```bash +$ composer require fig/http-message-util +``` diff --git a/Sources/API/vendor/fig/http-message-util/composer.json b/Sources/API/vendor/fig/http-message-util/composer.json new file mode 100644 index 0000000..8645893 --- /dev/null +++ b/Sources/API/vendor/fig/http-message-util/composer.json @@ -0,0 +1,28 @@ +{ + "name": "fig/http-message-util", + "description": "Utility classes and constants for use with PSR-7 (psr/http-message)", + "keywords": ["psr", "psr-7", "http", "http-message", "request", "response"], + "license": "MIT", + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "require": { + "php": "^5.3 || ^7.0 || ^8.0" + }, + "suggest": { + "psr/http-message": "The package containing the PSR-7 interfaces" + }, + "autoload": { + "psr-4": { + "Fig\\Http\\Message\\": "src/" + } + }, + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + } +} diff --git a/Sources/API/vendor/fig/http-message-util/src/RequestMethodInterface.php b/Sources/API/vendor/fig/http-message-util/src/RequestMethodInterface.php new file mode 100644 index 0000000..97d9a93 --- /dev/null +++ b/Sources/API/vendor/fig/http-message-util/src/RequestMethodInterface.php @@ -0,0 +1,34 @@ + + * class RequestFactory implements RequestMethodInterface + * { + * public static function factory( + * $uri = '/', + * $method = self::METHOD_GET, + * $data = [] + * ) { + * } + * } + * + */ +interface RequestMethodInterface +{ + const METHOD_HEAD = 'HEAD'; + const METHOD_GET = 'GET'; + const METHOD_POST = 'POST'; + const METHOD_PUT = 'PUT'; + const METHOD_PATCH = 'PATCH'; + const METHOD_DELETE = 'DELETE'; + const METHOD_PURGE = 'PURGE'; + const METHOD_OPTIONS = 'OPTIONS'; + const METHOD_TRACE = 'TRACE'; + const METHOD_CONNECT = 'CONNECT'; +} diff --git a/Sources/API/vendor/fig/http-message-util/src/StatusCodeInterface.php b/Sources/API/vendor/fig/http-message-util/src/StatusCodeInterface.php new file mode 100644 index 0000000..99b7e78 --- /dev/null +++ b/Sources/API/vendor/fig/http-message-util/src/StatusCodeInterface.php @@ -0,0 +1,107 @@ + + * class ResponseFactory implements StatusCodeInterface + * { + * public function createResponse($code = self::STATUS_OK) + * { + * } + * } + * + */ +interface StatusCodeInterface +{ + // Informational 1xx + const STATUS_CONTINUE = 100; + const STATUS_SWITCHING_PROTOCOLS = 101; + const STATUS_PROCESSING = 102; + const STATUS_EARLY_HINTS = 103; + // Successful 2xx + const STATUS_OK = 200; + const STATUS_CREATED = 201; + const STATUS_ACCEPTED = 202; + const STATUS_NON_AUTHORITATIVE_INFORMATION = 203; + const STATUS_NO_CONTENT = 204; + const STATUS_RESET_CONTENT = 205; + const STATUS_PARTIAL_CONTENT = 206; + const STATUS_MULTI_STATUS = 207; + const STATUS_ALREADY_REPORTED = 208; + const STATUS_IM_USED = 226; + // Redirection 3xx + const STATUS_MULTIPLE_CHOICES = 300; + const STATUS_MOVED_PERMANENTLY = 301; + const STATUS_FOUND = 302; + const STATUS_SEE_OTHER = 303; + const STATUS_NOT_MODIFIED = 304; + const STATUS_USE_PROXY = 305; + const STATUS_RESERVED = 306; + const STATUS_TEMPORARY_REDIRECT = 307; + const STATUS_PERMANENT_REDIRECT = 308; + // Client Errors 4xx + const STATUS_BAD_REQUEST = 400; + const STATUS_UNAUTHORIZED = 401; + const STATUS_PAYMENT_REQUIRED = 402; + const STATUS_FORBIDDEN = 403; + const STATUS_NOT_FOUND = 404; + const STATUS_METHOD_NOT_ALLOWED = 405; + const STATUS_NOT_ACCEPTABLE = 406; + const STATUS_PROXY_AUTHENTICATION_REQUIRED = 407; + const STATUS_REQUEST_TIMEOUT = 408; + const STATUS_CONFLICT = 409; + const STATUS_GONE = 410; + const STATUS_LENGTH_REQUIRED = 411; + const STATUS_PRECONDITION_FAILED = 412; + const STATUS_PAYLOAD_TOO_LARGE = 413; + const STATUS_URI_TOO_LONG = 414; + const STATUS_UNSUPPORTED_MEDIA_TYPE = 415; + const STATUS_RANGE_NOT_SATISFIABLE = 416; + const STATUS_EXPECTATION_FAILED = 417; + const STATUS_IM_A_TEAPOT = 418; + const STATUS_MISDIRECTED_REQUEST = 421; + const STATUS_UNPROCESSABLE_ENTITY = 422; + const STATUS_LOCKED = 423; + const STATUS_FAILED_DEPENDENCY = 424; + const STATUS_TOO_EARLY = 425; + const STATUS_UPGRADE_REQUIRED = 426; + const STATUS_PRECONDITION_REQUIRED = 428; + const STATUS_TOO_MANY_REQUESTS = 429; + const STATUS_REQUEST_HEADER_FIELDS_TOO_LARGE = 431; + const STATUS_UNAVAILABLE_FOR_LEGAL_REASONS = 451; + // Server Errors 5xx + const STATUS_INTERNAL_SERVER_ERROR = 500; + const STATUS_NOT_IMPLEMENTED = 501; + const STATUS_BAD_GATEWAY = 502; + const STATUS_SERVICE_UNAVAILABLE = 503; + const STATUS_GATEWAY_TIMEOUT = 504; + const STATUS_VERSION_NOT_SUPPORTED = 505; + const STATUS_VARIANT_ALSO_NEGOTIATES = 506; + const STATUS_INSUFFICIENT_STORAGE = 507; + const STATUS_LOOP_DETECTED = 508; + const STATUS_NOT_EXTENDED = 510; + const STATUS_NETWORK_AUTHENTICATION_REQUIRED = 511; +} diff --git a/Sources/API/vendor/nikic/fast-route/.gitignore b/Sources/API/vendor/nikic/fast-route/.gitignore new file mode 100644 index 0000000..e378a07 --- /dev/null +++ b/Sources/API/vendor/nikic/fast-route/.gitignore @@ -0,0 +1,5 @@ +/vendor/ +.idea/ + +# ignore lock file since we have no extra dependencies +composer.lock diff --git a/Sources/API/vendor/nikic/fast-route/.hhconfig b/Sources/API/vendor/nikic/fast-route/.hhconfig new file mode 100644 index 0000000..0c2153c --- /dev/null +++ b/Sources/API/vendor/nikic/fast-route/.hhconfig @@ -0,0 +1 @@ +assume_php=false diff --git a/Sources/API/vendor/nikic/fast-route/.travis.yml b/Sources/API/vendor/nikic/fast-route/.travis.yml new file mode 100644 index 0000000..10f8381 --- /dev/null +++ b/Sources/API/vendor/nikic/fast-route/.travis.yml @@ -0,0 +1,20 @@ +sudo: false +language: php + +php: + - 5.4 + - 5.5 + - 5.6 + - 7.0 + - 7.1 + - 7.2 + - hhvm + +script: + - ./vendor/bin/phpunit + +before_install: + - travis_retry composer self-update + +install: + - composer install diff --git a/Sources/API/vendor/nikic/fast-route/FastRoute.hhi b/Sources/API/vendor/nikic/fast-route/FastRoute.hhi new file mode 100644 index 0000000..8d50738 --- /dev/null +++ b/Sources/API/vendor/nikic/fast-route/FastRoute.hhi @@ -0,0 +1,126 @@ +; + } + + class RouteCollector { + public function __construct(RouteParser $routeParser, DataGenerator $dataGenerator); + public function addRoute(mixed $httpMethod, string $route, mixed $handler): void; + public function getData(): array; + } + + class Route { + public function __construct(string $httpMethod, mixed $handler, string $regex, array $variables); + public function matches(string $str): bool; + } + + interface DataGenerator { + public function addRoute(string $httpMethod, array $routeData, mixed $handler); + public function getData(): array; + } + + interface Dispatcher { + const int NOT_FOUND = 0; + const int FOUND = 1; + const int METHOD_NOT_ALLOWED = 2; + public function dispatch(string $httpMethod, string $uri): array; + } + + function simpleDispatcher( + (function(RouteCollector): void) $routeDefinitionCallback, + shape( + ?'routeParser' => classname, + ?'dataGenerator' => classname, + ?'dispatcher' => classname, + ?'routeCollector' => classname, + ) $options = shape()): Dispatcher; + + function cachedDispatcher( + (function(RouteCollector): void) $routeDefinitionCallback, + shape( + ?'routeParser' => classname, + ?'dataGenerator' => classname, + ?'dispatcher' => classname, + ?'routeCollector' => classname, + ?'cacheDisabled' => bool, + ?'cacheFile' => string, + ) $options = shape()): Dispatcher; +} + +namespace FastRoute\DataGenerator { + abstract class RegexBasedAbstract implements \FastRoute\DataGenerator { + protected abstract function getApproxChunkSize(); + protected abstract function processChunk($regexToRoutesMap); + + public function addRoute(string $httpMethod, array $routeData, mixed $handler): void; + public function getData(): array; + } + + class CharCountBased extends RegexBasedAbstract { + protected function getApproxChunkSize(): int; + protected function processChunk(array $regexToRoutesMap): array; + } + + class GroupCountBased extends RegexBasedAbstract { + protected function getApproxChunkSize(): int; + protected function processChunk(array $regexToRoutesMap): array; + } + + class GroupPosBased extends RegexBasedAbstract { + protected function getApproxChunkSize(): int; + protected function processChunk(array $regexToRoutesMap): array; + } + + class MarkBased extends RegexBasedAbstract { + protected function getApproxChunkSize(): int; + protected function processChunk(array $regexToRoutesMap): array; + } +} + +namespace FastRoute\Dispatcher { + abstract class RegexBasedAbstract implements \FastRoute\Dispatcher { + protected abstract function dispatchVariableRoute(array $routeData, string $uri): array; + + public function dispatch(string $httpMethod, string $uri): array; + } + + class GroupPosBased extends RegexBasedAbstract { + public function __construct(array $data); + protected function dispatchVariableRoute(array $routeData, string $uri): array; + } + + class GroupCountBased extends RegexBasedAbstract { + public function __construct(array $data); + protected function dispatchVariableRoute(array $routeData, string $uri): array; + } + + class CharCountBased extends RegexBasedAbstract { + public function __construct(array $data); + protected function dispatchVariableRoute(array $routeData, string $uri): array; + } + + class MarkBased extends RegexBasedAbstract { + public function __construct(array $data); + protected function dispatchVariableRoute(array $routeData, string $uri): array; + } +} + +namespace FastRoute\RouteParser { + class Std implements \FastRoute\RouteParser { + const string VARIABLE_REGEX = <<<'REGEX' +\{ + \s* ([a-zA-Z][a-zA-Z0-9_]*) \s* + (?: + : \s* ([^{}]*(?:\{(?-1)\}[^{}]*)*) + )? +\} +REGEX; + const string DEFAULT_DISPATCH_REGEX = '[^/]+'; + public function parse(string $route): array; + } +} diff --git a/Sources/API/vendor/nikic/fast-route/LICENSE b/Sources/API/vendor/nikic/fast-route/LICENSE new file mode 100644 index 0000000..478e764 --- /dev/null +++ b/Sources/API/vendor/nikic/fast-route/LICENSE @@ -0,0 +1,31 @@ +Copyright (c) 2013 by Nikita Popov. + +Some rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + * The names of the contributors may not be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Sources/API/vendor/nikic/fast-route/README.md b/Sources/API/vendor/nikic/fast-route/README.md new file mode 100644 index 0000000..91bd466 --- /dev/null +++ b/Sources/API/vendor/nikic/fast-route/README.md @@ -0,0 +1,313 @@ +FastRoute - Fast request router for PHP +======================================= + +This library provides a fast implementation of a regular expression based router. [Blog post explaining how the +implementation works and why it is fast.][blog_post] + +Install +------- + +To install with composer: + +```sh +composer require nikic/fast-route +``` + +Requires PHP 5.4 or newer. + +Usage +----- + +Here's a basic usage example: + +```php +addRoute('GET', '/users', 'get_all_users_handler'); + // {id} must be a number (\d+) + $r->addRoute('GET', '/user/{id:\d+}', 'get_user_handler'); + // The /{title} suffix is optional + $r->addRoute('GET', '/articles/{id:\d+}[/{title}]', 'get_article_handler'); +}); + +// Fetch method and URI from somewhere +$httpMethod = $_SERVER['REQUEST_METHOD']; +$uri = $_SERVER['REQUEST_URI']; + +// Strip query string (?foo=bar) and decode URI +if (false !== $pos = strpos($uri, '?')) { + $uri = substr($uri, 0, $pos); +} +$uri = rawurldecode($uri); + +$routeInfo = $dispatcher->dispatch($httpMethod, $uri); +switch ($routeInfo[0]) { + case FastRoute\Dispatcher::NOT_FOUND: + // ... 404 Not Found + break; + case FastRoute\Dispatcher::METHOD_NOT_ALLOWED: + $allowedMethods = $routeInfo[1]; + // ... 405 Method Not Allowed + break; + case FastRoute\Dispatcher::FOUND: + $handler = $routeInfo[1]; + $vars = $routeInfo[2]; + // ... call $handler with $vars + break; +} +``` + +### Defining routes + +The routes are defined by calling the `FastRoute\simpleDispatcher()` function, which accepts +a callable taking a `FastRoute\RouteCollector` instance. The routes are added by calling +`addRoute()` on the collector instance: + +```php +$r->addRoute($method, $routePattern, $handler); +``` + +The `$method` is an uppercase HTTP method string for which a certain route should match. It +is possible to specify multiple valid methods using an array: + +```php +// These two calls +$r->addRoute('GET', '/test', 'handler'); +$r->addRoute('POST', '/test', 'handler'); +// Are equivalent to this one call +$r->addRoute(['GET', 'POST'], '/test', 'handler'); +``` + +By default the `$routePattern` uses a syntax where `{foo}` specifies a placeholder with name `foo` +and matching the regex `[^/]+`. To adjust the pattern the placeholder matches, you can specify +a custom pattern by writing `{bar:[0-9]+}`. Some examples: + +```php +// Matches /user/42, but not /user/xyz +$r->addRoute('GET', '/user/{id:\d+}', 'handler'); + +// Matches /user/foobar, but not /user/foo/bar +$r->addRoute('GET', '/user/{name}', 'handler'); + +// Matches /user/foo/bar as well +$r->addRoute('GET', '/user/{name:.+}', 'handler'); +``` + +Custom patterns for route placeholders cannot use capturing groups. For example `{lang:(en|de)}` +is not a valid placeholder, because `()` is a capturing group. Instead you can use either +`{lang:en|de}` or `{lang:(?:en|de)}`. + +Furthermore parts of the route enclosed in `[...]` are considered optional, so that `/foo[bar]` +will match both `/foo` and `/foobar`. Optional parts are only supported in a trailing position, +not in the middle of a route. + +```php +// This route +$r->addRoute('GET', '/user/{id:\d+}[/{name}]', 'handler'); +// Is equivalent to these two routes +$r->addRoute('GET', '/user/{id:\d+}', 'handler'); +$r->addRoute('GET', '/user/{id:\d+}/{name}', 'handler'); + +// Multiple nested optional parts are possible as well +$r->addRoute('GET', '/user[/{id:\d+}[/{name}]]', 'handler'); + +// This route is NOT valid, because optional parts can only occur at the end +$r->addRoute('GET', '/user[/{id:\d+}]/{name}', 'handler'); +``` + +The `$handler` parameter does not necessarily have to be a callback, it could also be a controller +class name or any other kind of data you wish to associate with the route. FastRoute only tells you +which handler corresponds to your URI, how you interpret it is up to you. + +#### Shorcut methods for common request methods + +For the `GET`, `POST`, `PUT`, `PATCH`, `DELETE` and `HEAD` request methods shortcut methods are available. For example: + +```php +$r->get('/get-route', 'get_handler'); +$r->post('/post-route', 'post_handler'); +``` + +Is equivalent to: + +```php +$r->addRoute('GET', '/get-route', 'get_handler'); +$r->addRoute('POST', '/post-route', 'post_handler'); +``` + +#### Route Groups + +Additionally, you can specify routes inside of a group. All routes defined inside a group will have a common prefix. + +For example, defining your routes as: + +```php +$r->addGroup('/admin', function (RouteCollector $r) { + $r->addRoute('GET', '/do-something', 'handler'); + $r->addRoute('GET', '/do-another-thing', 'handler'); + $r->addRoute('GET', '/do-something-else', 'handler'); +}); +``` + +Will have the same result as: + + ```php +$r->addRoute('GET', '/admin/do-something', 'handler'); +$r->addRoute('GET', '/admin/do-another-thing', 'handler'); +$r->addRoute('GET', '/admin/do-something-else', 'handler'); + ``` + +Nested groups are also supported, in which case the prefixes of all the nested groups are combined. + +### Caching + +The reason `simpleDispatcher` accepts a callback for defining the routes is to allow seamless +caching. By using `cachedDispatcher` instead of `simpleDispatcher` you can cache the generated +routing data and construct the dispatcher from the cached information: + +```php +addRoute('GET', '/user/{name}/{id:[0-9]+}', 'handler0'); + $r->addRoute('GET', '/user/{id:[0-9]+}', 'handler1'); + $r->addRoute('GET', '/user/{name}', 'handler2'); +}, [ + 'cacheFile' => __DIR__ . '/route.cache', /* required */ + 'cacheDisabled' => IS_DEBUG_ENABLED, /* optional, enabled by default */ +]); +``` + +The second parameter to the function is an options array, which can be used to specify the cache +file location, among other things. + +### Dispatching a URI + +A URI is dispatched by calling the `dispatch()` method of the created dispatcher. This method +accepts the HTTP method and a URI. Getting those two bits of information (and normalizing them +appropriately) is your job - this library is not bound to the PHP web SAPIs. + +The `dispatch()` method returns an array whose first element contains a status code. It is one +of `Dispatcher::NOT_FOUND`, `Dispatcher::METHOD_NOT_ALLOWED` and `Dispatcher::FOUND`. For the +method not allowed status the second array element contains a list of HTTP methods allowed for +the supplied URI. For example: + + [FastRoute\Dispatcher::METHOD_NOT_ALLOWED, ['GET', 'POST']] + +> **NOTE:** The HTTP specification requires that a `405 Method Not Allowed` response include the +`Allow:` header to detail available methods for the requested resource. Applications using FastRoute +should use the second array element to add this header when relaying a 405 response. + +For the found status the second array element is the handler that was associated with the route +and the third array element is a dictionary of placeholder names to their values. For example: + + /* Routing against GET /user/nikic/42 */ + + [FastRoute\Dispatcher::FOUND, 'handler0', ['name' => 'nikic', 'id' => '42']] + +### Overriding the route parser and dispatcher + +The routing process makes use of three components: A route parser, a data generator and a +dispatcher. The three components adhere to the following interfaces: + +```php + 'FastRoute\\RouteParser\\Std', + 'dataGenerator' => 'FastRoute\\DataGenerator\\GroupCountBased', + 'dispatcher' => 'FastRoute\\Dispatcher\\GroupCountBased', +]); +``` + +The above options array corresponds to the defaults. By replacing `GroupCountBased` by +`GroupPosBased` you could switch to a different dispatching strategy. + +### A Note on HEAD Requests + +The HTTP spec requires servers to [support both GET and HEAD methods][2616-511]: + +> The methods GET and HEAD MUST be supported by all general-purpose servers + +To avoid forcing users to manually register HEAD routes for each resource we fallback to matching an +available GET route for a given resource. The PHP web SAPI transparently removes the entity body +from HEAD responses so this behavior has no effect on the vast majority of users. + +However, implementers using FastRoute outside the web SAPI environment (e.g. a custom server) MUST +NOT send entity bodies generated in response to HEAD requests. If you are a non-SAPI user this is +*your responsibility*; FastRoute has no purview to prevent you from breaking HTTP in such cases. + +Finally, note that applications MAY always specify their own HEAD method route for a given +resource to bypass this behavior entirely. + +### Credits + +This library is based on a router that [Levi Morrison][levi] implemented for the Aerys server. + +A large number of tests, as well as HTTP compliance considerations, were provided by [Daniel Lowrey][rdlowrey]. + + +[2616-511]: http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html#sec5.1.1 "RFC 2616 Section 5.1.1" +[blog_post]: http://nikic.github.io/2014/02/18/Fast-request-routing-using-regular-expressions.html +[levi]: https://github.com/morrisonlevi +[rdlowrey]: https://github.com/rdlowrey diff --git a/Sources/API/vendor/nikic/fast-route/composer.json b/Sources/API/vendor/nikic/fast-route/composer.json new file mode 100644 index 0000000..fb446a2 --- /dev/null +++ b/Sources/API/vendor/nikic/fast-route/composer.json @@ -0,0 +1,24 @@ +{ + "name": "nikic/fast-route", + "description": "Fast request router for PHP", + "keywords": ["routing", "router"], + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Nikita Popov", + "email": "nikic@php.net" + } + ], + "autoload": { + "psr-4": { + "FastRoute\\": "src/" + }, + "files": ["src/functions.php"] + }, + "require": { + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35|~5.7" + } +} diff --git a/Sources/API/vendor/nikic/fast-route/phpunit.xml b/Sources/API/vendor/nikic/fast-route/phpunit.xml new file mode 100644 index 0000000..3c807b6 --- /dev/null +++ b/Sources/API/vendor/nikic/fast-route/phpunit.xml @@ -0,0 +1,24 @@ + + + + + + ./test/ + + + + + + ./src/ + + + diff --git a/Sources/API/vendor/nikic/fast-route/psalm.xml b/Sources/API/vendor/nikic/fast-route/psalm.xml new file mode 100644 index 0000000..0dca5d7 --- /dev/null +++ b/Sources/API/vendor/nikic/fast-route/psalm.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/Sources/API/vendor/nikic/fast-route/src/BadRouteException.php b/Sources/API/vendor/nikic/fast-route/src/BadRouteException.php new file mode 100644 index 0000000..62262ec --- /dev/null +++ b/Sources/API/vendor/nikic/fast-route/src/BadRouteException.php @@ -0,0 +1,7 @@ + $route) { + $suffixLen++; + $suffix .= "\t"; + + $regexes[] = '(?:' . $regex . '/(\t{' . $suffixLen . '})\t{' . ($count - $suffixLen) . '})'; + $routeMap[$suffix] = [$route->handler, $route->variables]; + } + + $regex = '~^(?|' . implode('|', $regexes) . ')$~'; + return ['regex' => $regex, 'suffix' => '/' . $suffix, 'routeMap' => $routeMap]; + } +} diff --git a/Sources/API/vendor/nikic/fast-route/src/DataGenerator/GroupCountBased.php b/Sources/API/vendor/nikic/fast-route/src/DataGenerator/GroupCountBased.php new file mode 100644 index 0000000..54d9a05 --- /dev/null +++ b/Sources/API/vendor/nikic/fast-route/src/DataGenerator/GroupCountBased.php @@ -0,0 +1,30 @@ + $route) { + $numVariables = count($route->variables); + $numGroups = max($numGroups, $numVariables); + + $regexes[] = $regex . str_repeat('()', $numGroups - $numVariables); + $routeMap[$numGroups + 1] = [$route->handler, $route->variables]; + + ++$numGroups; + } + + $regex = '~^(?|' . implode('|', $regexes) . ')$~'; + return ['regex' => $regex, 'routeMap' => $routeMap]; + } +} diff --git a/Sources/API/vendor/nikic/fast-route/src/DataGenerator/GroupPosBased.php b/Sources/API/vendor/nikic/fast-route/src/DataGenerator/GroupPosBased.php new file mode 100644 index 0000000..fc4dc0a --- /dev/null +++ b/Sources/API/vendor/nikic/fast-route/src/DataGenerator/GroupPosBased.php @@ -0,0 +1,27 @@ + $route) { + $regexes[] = $regex; + $routeMap[$offset] = [$route->handler, $route->variables]; + + $offset += count($route->variables); + } + + $regex = '~^(?:' . implode('|', $regexes) . ')$~'; + return ['regex' => $regex, 'routeMap' => $routeMap]; + } +} diff --git a/Sources/API/vendor/nikic/fast-route/src/DataGenerator/MarkBased.php b/Sources/API/vendor/nikic/fast-route/src/DataGenerator/MarkBased.php new file mode 100644 index 0000000..0aebed9 --- /dev/null +++ b/Sources/API/vendor/nikic/fast-route/src/DataGenerator/MarkBased.php @@ -0,0 +1,27 @@ + $route) { + $regexes[] = $regex . '(*MARK:' . $markName . ')'; + $routeMap[$markName] = [$route->handler, $route->variables]; + + ++$markName; + } + + $regex = '~^(?|' . implode('|', $regexes) . ')$~'; + return ['regex' => $regex, 'routeMap' => $routeMap]; + } +} diff --git a/Sources/API/vendor/nikic/fast-route/src/DataGenerator/RegexBasedAbstract.php b/Sources/API/vendor/nikic/fast-route/src/DataGenerator/RegexBasedAbstract.php new file mode 100644 index 0000000..6457290 --- /dev/null +++ b/Sources/API/vendor/nikic/fast-route/src/DataGenerator/RegexBasedAbstract.php @@ -0,0 +1,186 @@ +isStaticRoute($routeData)) { + $this->addStaticRoute($httpMethod, $routeData, $handler); + } else { + $this->addVariableRoute($httpMethod, $routeData, $handler); + } + } + + /** + * @return mixed[] + */ + public function getData() + { + if (empty($this->methodToRegexToRoutesMap)) { + return [$this->staticRoutes, []]; + } + + return [$this->staticRoutes, $this->generateVariableRouteData()]; + } + + /** + * @return mixed[] + */ + private function generateVariableRouteData() + { + $data = []; + foreach ($this->methodToRegexToRoutesMap as $method => $regexToRoutesMap) { + $chunkSize = $this->computeChunkSize(count($regexToRoutesMap)); + $chunks = array_chunk($regexToRoutesMap, $chunkSize, true); + $data[$method] = array_map([$this, 'processChunk'], $chunks); + } + return $data; + } + + /** + * @param int + * @return int + */ + private function computeChunkSize($count) + { + $numParts = max(1, round($count / $this->getApproxChunkSize())); + return (int) ceil($count / $numParts); + } + + /** + * @param mixed[] + * @return bool + */ + private function isStaticRoute($routeData) + { + return count($routeData) === 1 && is_string($routeData[0]); + } + + private function addStaticRoute($httpMethod, $routeData, $handler) + { + $routeStr = $routeData[0]; + + if (isset($this->staticRoutes[$httpMethod][$routeStr])) { + throw new BadRouteException(sprintf( + 'Cannot register two routes matching "%s" for method "%s"', + $routeStr, $httpMethod + )); + } + + if (isset($this->methodToRegexToRoutesMap[$httpMethod])) { + foreach ($this->methodToRegexToRoutesMap[$httpMethod] as $route) { + if ($route->matches($routeStr)) { + throw new BadRouteException(sprintf( + 'Static route "%s" is shadowed by previously defined variable route "%s" for method "%s"', + $routeStr, $route->regex, $httpMethod + )); + } + } + } + + $this->staticRoutes[$httpMethod][$routeStr] = $handler; + } + + private function addVariableRoute($httpMethod, $routeData, $handler) + { + list($regex, $variables) = $this->buildRegexForRoute($routeData); + + if (isset($this->methodToRegexToRoutesMap[$httpMethod][$regex])) { + throw new BadRouteException(sprintf( + 'Cannot register two routes matching "%s" for method "%s"', + $regex, $httpMethod + )); + } + + $this->methodToRegexToRoutesMap[$httpMethod][$regex] = new Route( + $httpMethod, $handler, $regex, $variables + ); + } + + /** + * @param mixed[] + * @return mixed[] + */ + private function buildRegexForRoute($routeData) + { + $regex = ''; + $variables = []; + foreach ($routeData as $part) { + if (is_string($part)) { + $regex .= preg_quote($part, '~'); + continue; + } + + list($varName, $regexPart) = $part; + + if (isset($variables[$varName])) { + throw new BadRouteException(sprintf( + 'Cannot use the same placeholder "%s" twice', $varName + )); + } + + if ($this->regexHasCapturingGroups($regexPart)) { + throw new BadRouteException(sprintf( + 'Regex "%s" for parameter "%s" contains a capturing group', + $regexPart, $varName + )); + } + + $variables[$varName] = $varName; + $regex .= '(' . $regexPart . ')'; + } + + return [$regex, $variables]; + } + + /** + * @param string + * @return bool + */ + private function regexHasCapturingGroups($regex) + { + if (false === strpos($regex, '(')) { + // Needs to have at least a ( to contain a capturing group + return false; + } + + // Semi-accurate detection for capturing groups + return (bool) preg_match( + '~ + (?: + \(\?\( + | \[ [^\]\\\\]* (?: \\\\ . [^\]\\\\]* )* \] + | \\\\ . + ) (*SKIP)(*FAIL) | + \( + (?! + \? (?! <(?![!=]) | P< | \' ) + | \* + ) + ~x', + $regex + ); + } +} diff --git a/Sources/API/vendor/nikic/fast-route/src/Dispatcher.php b/Sources/API/vendor/nikic/fast-route/src/Dispatcher.php new file mode 100644 index 0000000..4ae72a3 --- /dev/null +++ b/Sources/API/vendor/nikic/fast-route/src/Dispatcher.php @@ -0,0 +1,26 @@ + 'value', ...]] + * + * @param string $httpMethod + * @param string $uri + * + * @return array + */ + public function dispatch($httpMethod, $uri); +} diff --git a/Sources/API/vendor/nikic/fast-route/src/Dispatcher/CharCountBased.php b/Sources/API/vendor/nikic/fast-route/src/Dispatcher/CharCountBased.php new file mode 100644 index 0000000..ef1eec1 --- /dev/null +++ b/Sources/API/vendor/nikic/fast-route/src/Dispatcher/CharCountBased.php @@ -0,0 +1,31 @@ +staticRouteMap, $this->variableRouteData) = $data; + } + + protected function dispatchVariableRoute($routeData, $uri) + { + foreach ($routeData as $data) { + if (!preg_match($data['regex'], $uri . $data['suffix'], $matches)) { + continue; + } + + list($handler, $varNames) = $data['routeMap'][end($matches)]; + + $vars = []; + $i = 0; + foreach ($varNames as $varName) { + $vars[$varName] = $matches[++$i]; + } + return [self::FOUND, $handler, $vars]; + } + + return [self::NOT_FOUND]; + } +} diff --git a/Sources/API/vendor/nikic/fast-route/src/Dispatcher/GroupCountBased.php b/Sources/API/vendor/nikic/fast-route/src/Dispatcher/GroupCountBased.php new file mode 100644 index 0000000..493e7a9 --- /dev/null +++ b/Sources/API/vendor/nikic/fast-route/src/Dispatcher/GroupCountBased.php @@ -0,0 +1,31 @@ +staticRouteMap, $this->variableRouteData) = $data; + } + + protected function dispatchVariableRoute($routeData, $uri) + { + foreach ($routeData as $data) { + if (!preg_match($data['regex'], $uri, $matches)) { + continue; + } + + list($handler, $varNames) = $data['routeMap'][count($matches)]; + + $vars = []; + $i = 0; + foreach ($varNames as $varName) { + $vars[$varName] = $matches[++$i]; + } + return [self::FOUND, $handler, $vars]; + } + + return [self::NOT_FOUND]; + } +} diff --git a/Sources/API/vendor/nikic/fast-route/src/Dispatcher/GroupPosBased.php b/Sources/API/vendor/nikic/fast-route/src/Dispatcher/GroupPosBased.php new file mode 100644 index 0000000..498220e --- /dev/null +++ b/Sources/API/vendor/nikic/fast-route/src/Dispatcher/GroupPosBased.php @@ -0,0 +1,33 @@ +staticRouteMap, $this->variableRouteData) = $data; + } + + protected function dispatchVariableRoute($routeData, $uri) + { + foreach ($routeData as $data) { + if (!preg_match($data['regex'], $uri, $matches)) { + continue; + } + + // find first non-empty match + for ($i = 1; '' === $matches[$i]; ++$i); + + list($handler, $varNames) = $data['routeMap'][$i]; + + $vars = []; + foreach ($varNames as $varName) { + $vars[$varName] = $matches[$i++]; + } + return [self::FOUND, $handler, $vars]; + } + + return [self::NOT_FOUND]; + } +} diff --git a/Sources/API/vendor/nikic/fast-route/src/Dispatcher/MarkBased.php b/Sources/API/vendor/nikic/fast-route/src/Dispatcher/MarkBased.php new file mode 100644 index 0000000..22eb09b --- /dev/null +++ b/Sources/API/vendor/nikic/fast-route/src/Dispatcher/MarkBased.php @@ -0,0 +1,31 @@ +staticRouteMap, $this->variableRouteData) = $data; + } + + protected function dispatchVariableRoute($routeData, $uri) + { + foreach ($routeData as $data) { + if (!preg_match($data['regex'], $uri, $matches)) { + continue; + } + + list($handler, $varNames) = $data['routeMap'][$matches['MARK']]; + + $vars = []; + $i = 0; + foreach ($varNames as $varName) { + $vars[$varName] = $matches[++$i]; + } + return [self::FOUND, $handler, $vars]; + } + + return [self::NOT_FOUND]; + } +} diff --git a/Sources/API/vendor/nikic/fast-route/src/Dispatcher/RegexBasedAbstract.php b/Sources/API/vendor/nikic/fast-route/src/Dispatcher/RegexBasedAbstract.php new file mode 100644 index 0000000..206e879 --- /dev/null +++ b/Sources/API/vendor/nikic/fast-route/src/Dispatcher/RegexBasedAbstract.php @@ -0,0 +1,88 @@ +staticRouteMap[$httpMethod][$uri])) { + $handler = $this->staticRouteMap[$httpMethod][$uri]; + return [self::FOUND, $handler, []]; + } + + $varRouteData = $this->variableRouteData; + if (isset($varRouteData[$httpMethod])) { + $result = $this->dispatchVariableRoute($varRouteData[$httpMethod], $uri); + if ($result[0] === self::FOUND) { + return $result; + } + } + + // For HEAD requests, attempt fallback to GET + if ($httpMethod === 'HEAD') { + if (isset($this->staticRouteMap['GET'][$uri])) { + $handler = $this->staticRouteMap['GET'][$uri]; + return [self::FOUND, $handler, []]; + } + if (isset($varRouteData['GET'])) { + $result = $this->dispatchVariableRoute($varRouteData['GET'], $uri); + if ($result[0] === self::FOUND) { + return $result; + } + } + } + + // If nothing else matches, try fallback routes + if (isset($this->staticRouteMap['*'][$uri])) { + $handler = $this->staticRouteMap['*'][$uri]; + return [self::FOUND, $handler, []]; + } + if (isset($varRouteData['*'])) { + $result = $this->dispatchVariableRoute($varRouteData['*'], $uri); + if ($result[0] === self::FOUND) { + return $result; + } + } + + // Find allowed methods for this URI by matching against all other HTTP methods as well + $allowedMethods = []; + + foreach ($this->staticRouteMap as $method => $uriMap) { + if ($method !== $httpMethod && isset($uriMap[$uri])) { + $allowedMethods[] = $method; + } + } + + foreach ($varRouteData as $method => $routeData) { + if ($method === $httpMethod) { + continue; + } + + $result = $this->dispatchVariableRoute($routeData, $uri); + if ($result[0] === self::FOUND) { + $allowedMethods[] = $method; + } + } + + // If there are no allowed methods the route simply does not exist + if ($allowedMethods) { + return [self::METHOD_NOT_ALLOWED, $allowedMethods]; + } + + return [self::NOT_FOUND]; + } +} diff --git a/Sources/API/vendor/nikic/fast-route/src/Route.php b/Sources/API/vendor/nikic/fast-route/src/Route.php new file mode 100644 index 0000000..e1bf7dd --- /dev/null +++ b/Sources/API/vendor/nikic/fast-route/src/Route.php @@ -0,0 +1,47 @@ +httpMethod = $httpMethod; + $this->handler = $handler; + $this->regex = $regex; + $this->variables = $variables; + } + + /** + * Tests whether this route matches the given string. + * + * @param string $str + * + * @return bool + */ + public function matches($str) + { + $regex = '~^' . $this->regex . '$~'; + return (bool) preg_match($regex, $str); + } +} diff --git a/Sources/API/vendor/nikic/fast-route/src/RouteCollector.php b/Sources/API/vendor/nikic/fast-route/src/RouteCollector.php new file mode 100644 index 0000000..c1c1762 --- /dev/null +++ b/Sources/API/vendor/nikic/fast-route/src/RouteCollector.php @@ -0,0 +1,152 @@ +routeParser = $routeParser; + $this->dataGenerator = $dataGenerator; + $this->currentGroupPrefix = ''; + } + + /** + * Adds a route to the collection. + * + * The syntax used in the $route string depends on the used route parser. + * + * @param string|string[] $httpMethod + * @param string $route + * @param mixed $handler + */ + public function addRoute($httpMethod, $route, $handler) + { + $route = $this->currentGroupPrefix . $route; + $routeDatas = $this->routeParser->parse($route); + foreach ((array) $httpMethod as $method) { + foreach ($routeDatas as $routeData) { + $this->dataGenerator->addRoute($method, $routeData, $handler); + } + } + } + + /** + * Create a route group with a common prefix. + * + * All routes created in the passed callback will have the given group prefix prepended. + * + * @param string $prefix + * @param callable $callback + */ + public function addGroup($prefix, callable $callback) + { + $previousGroupPrefix = $this->currentGroupPrefix; + $this->currentGroupPrefix = $previousGroupPrefix . $prefix; + $callback($this); + $this->currentGroupPrefix = $previousGroupPrefix; + } + + /** + * Adds a GET route to the collection + * + * This is simply an alias of $this->addRoute('GET', $route, $handler) + * + * @param string $route + * @param mixed $handler + */ + public function get($route, $handler) + { + $this->addRoute('GET', $route, $handler); + } + + /** + * Adds a POST route to the collection + * + * This is simply an alias of $this->addRoute('POST', $route, $handler) + * + * @param string $route + * @param mixed $handler + */ + public function post($route, $handler) + { + $this->addRoute('POST', $route, $handler); + } + + /** + * Adds a PUT route to the collection + * + * This is simply an alias of $this->addRoute('PUT', $route, $handler) + * + * @param string $route + * @param mixed $handler + */ + public function put($route, $handler) + { + $this->addRoute('PUT', $route, $handler); + } + + /** + * Adds a DELETE route to the collection + * + * This is simply an alias of $this->addRoute('DELETE', $route, $handler) + * + * @param string $route + * @param mixed $handler + */ + public function delete($route, $handler) + { + $this->addRoute('DELETE', $route, $handler); + } + + /** + * Adds a PATCH route to the collection + * + * This is simply an alias of $this->addRoute('PATCH', $route, $handler) + * + * @param string $route + * @param mixed $handler + */ + public function patch($route, $handler) + { + $this->addRoute('PATCH', $route, $handler); + } + + /** + * Adds a HEAD route to the collection + * + * This is simply an alias of $this->addRoute('HEAD', $route, $handler) + * + * @param string $route + * @param mixed $handler + */ + public function head($route, $handler) + { + $this->addRoute('HEAD', $route, $handler); + } + + /** + * Returns the collected route data, as provided by the data generator. + * + * @return array + */ + public function getData() + { + return $this->dataGenerator->getData(); + } +} diff --git a/Sources/API/vendor/nikic/fast-route/src/RouteParser.php b/Sources/API/vendor/nikic/fast-route/src/RouteParser.php new file mode 100644 index 0000000..6a7685c --- /dev/null +++ b/Sources/API/vendor/nikic/fast-route/src/RouteParser.php @@ -0,0 +1,37 @@ + $segment) { + if ($segment === '' && $n !== 0) { + throw new BadRouteException('Empty optional part'); + } + + $currentRoute .= $segment; + $routeDatas[] = $this->parsePlaceholders($currentRoute); + } + return $routeDatas; + } + + /** + * Parses a route string that does not contain optional segments. + * + * @param string + * @return mixed[] + */ + private function parsePlaceholders($route) + { + if (!preg_match_all( + '~' . self::VARIABLE_REGEX . '~x', $route, $matches, + PREG_OFFSET_CAPTURE | PREG_SET_ORDER + )) { + return [$route]; + } + + $offset = 0; + $routeData = []; + foreach ($matches as $set) { + if ($set[0][1] > $offset) { + $routeData[] = substr($route, $offset, $set[0][1] - $offset); + } + $routeData[] = [ + $set[1][0], + isset($set[2]) ? trim($set[2][0]) : self::DEFAULT_DISPATCH_REGEX + ]; + $offset = $set[0][1] + strlen($set[0][0]); + } + + if ($offset !== strlen($route)) { + $routeData[] = substr($route, $offset); + } + + return $routeData; + } +} diff --git a/Sources/API/vendor/nikic/fast-route/src/bootstrap.php b/Sources/API/vendor/nikic/fast-route/src/bootstrap.php new file mode 100644 index 0000000..0bce3a4 --- /dev/null +++ b/Sources/API/vendor/nikic/fast-route/src/bootstrap.php @@ -0,0 +1,12 @@ + 'FastRoute\\RouteParser\\Std', + 'dataGenerator' => 'FastRoute\\DataGenerator\\GroupCountBased', + 'dispatcher' => 'FastRoute\\Dispatcher\\GroupCountBased', + 'routeCollector' => 'FastRoute\\RouteCollector', + ]; + + /** @var RouteCollector $routeCollector */ + $routeCollector = new $options['routeCollector']( + new $options['routeParser'], new $options['dataGenerator'] + ); + $routeDefinitionCallback($routeCollector); + + return new $options['dispatcher']($routeCollector->getData()); + } + + /** + * @param callable $routeDefinitionCallback + * @param array $options + * + * @return Dispatcher + */ + function cachedDispatcher(callable $routeDefinitionCallback, array $options = []) + { + $options += [ + 'routeParser' => 'FastRoute\\RouteParser\\Std', + 'dataGenerator' => 'FastRoute\\DataGenerator\\GroupCountBased', + 'dispatcher' => 'FastRoute\\Dispatcher\\GroupCountBased', + 'routeCollector' => 'FastRoute\\RouteCollector', + 'cacheDisabled' => false, + ]; + + if (!isset($options['cacheFile'])) { + throw new \LogicException('Must specify "cacheFile" option'); + } + + if (!$options['cacheDisabled'] && file_exists($options['cacheFile'])) { + $dispatchData = require $options['cacheFile']; + if (!is_array($dispatchData)) { + throw new \RuntimeException('Invalid cache file "' . $options['cacheFile'] . '"'); + } + return new $options['dispatcher']($dispatchData); + } + + $routeCollector = new $options['routeCollector']( + new $options['routeParser'], new $options['dataGenerator'] + ); + $routeDefinitionCallback($routeCollector); + + /** @var RouteCollector $routeCollector */ + $dispatchData = $routeCollector->getData(); + if (!$options['cacheDisabled']) { + file_put_contents( + $options['cacheFile'], + ' $this->getDataGeneratorClass(), + 'dispatcher' => $this->getDispatcherClass() + ]; + } + + /** + * @dataProvider provideFoundDispatchCases + */ + public function testFoundDispatches($method, $uri, $callback, $handler, $argDict) + { + $dispatcher = \FastRoute\simpleDispatcher($callback, $this->generateDispatcherOptions()); + $info = $dispatcher->dispatch($method, $uri); + $this->assertSame($dispatcher::FOUND, $info[0]); + $this->assertSame($handler, $info[1]); + $this->assertSame($argDict, $info[2]); + } + + /** + * @dataProvider provideNotFoundDispatchCases + */ + public function testNotFoundDispatches($method, $uri, $callback) + { + $dispatcher = \FastRoute\simpleDispatcher($callback, $this->generateDispatcherOptions()); + $routeInfo = $dispatcher->dispatch($method, $uri); + $this->assertArrayNotHasKey(1, $routeInfo, + 'NOT_FOUND result must only contain a single element in the returned info array' + ); + $this->assertSame($dispatcher::NOT_FOUND, $routeInfo[0]); + } + + /** + * @dataProvider provideMethodNotAllowedDispatchCases + */ + public function testMethodNotAllowedDispatches($method, $uri, $callback, $availableMethods) + { + $dispatcher = \FastRoute\simpleDispatcher($callback, $this->generateDispatcherOptions()); + $routeInfo = $dispatcher->dispatch($method, $uri); + $this->assertArrayHasKey(1, $routeInfo, + 'METHOD_NOT_ALLOWED result must return an array of allowed methods at index 1' + ); + + list($routedStatus, $methodArray) = $dispatcher->dispatch($method, $uri); + $this->assertSame($dispatcher::METHOD_NOT_ALLOWED, $routedStatus); + $this->assertSame($availableMethods, $methodArray); + } + + /** + * @expectedException \FastRoute\BadRouteException + * @expectedExceptionMessage Cannot use the same placeholder "test" twice + */ + public function testDuplicateVariableNameError() + { + \FastRoute\simpleDispatcher(function (RouteCollector $r) { + $r->addRoute('GET', '/foo/{test}/{test:\d+}', 'handler0'); + }, $this->generateDispatcherOptions()); + } + + /** + * @expectedException \FastRoute\BadRouteException + * @expectedExceptionMessage Cannot register two routes matching "/user/([^/]+)" for method "GET" + */ + public function testDuplicateVariableRoute() + { + \FastRoute\simpleDispatcher(function (RouteCollector $r) { + $r->addRoute('GET', '/user/{id}', 'handler0'); // oops, forgot \d+ restriction ;) + $r->addRoute('GET', '/user/{name}', 'handler1'); + }, $this->generateDispatcherOptions()); + } + + /** + * @expectedException \FastRoute\BadRouteException + * @expectedExceptionMessage Cannot register two routes matching "/user" for method "GET" + */ + public function testDuplicateStaticRoute() + { + \FastRoute\simpleDispatcher(function (RouteCollector $r) { + $r->addRoute('GET', '/user', 'handler0'); + $r->addRoute('GET', '/user', 'handler1'); + }, $this->generateDispatcherOptions()); + } + + /** + * @expectedException \FastRoute\BadRouteException + * @expectedExceptionMessage Static route "/user/nikic" is shadowed by previously defined variable route "/user/([^/]+)" for method "GET" + */ + public function testShadowedStaticRoute() + { + \FastRoute\simpleDispatcher(function (RouteCollector $r) { + $r->addRoute('GET', '/user/{name}', 'handler0'); + $r->addRoute('GET', '/user/nikic', 'handler1'); + }, $this->generateDispatcherOptions()); + } + + /** + * @expectedException \FastRoute\BadRouteException + * @expectedExceptionMessage Regex "(en|de)" for parameter "lang" contains a capturing group + */ + public function testCapturing() + { + \FastRoute\simpleDispatcher(function (RouteCollector $r) { + $r->addRoute('GET', '/{lang:(en|de)}', 'handler0'); + }, $this->generateDispatcherOptions()); + } + + public function provideFoundDispatchCases() + { + $cases = []; + + // 0 --------------------------------------------------------------------------------------> + + $callback = function (RouteCollector $r) { + $r->addRoute('GET', '/resource/123/456', 'handler0'); + }; + + $method = 'GET'; + $uri = '/resource/123/456'; + $handler = 'handler0'; + $argDict = []; + + $cases[] = [$method, $uri, $callback, $handler, $argDict]; + + // 1 --------------------------------------------------------------------------------------> + + $callback = function (RouteCollector $r) { + $r->addRoute('GET', '/handler0', 'handler0'); + $r->addRoute('GET', '/handler1', 'handler1'); + $r->addRoute('GET', '/handler2', 'handler2'); + }; + + $method = 'GET'; + $uri = '/handler2'; + $handler = 'handler2'; + $argDict = []; + + $cases[] = [$method, $uri, $callback, $handler, $argDict]; + + // 2 --------------------------------------------------------------------------------------> + + $callback = function (RouteCollector $r) { + $r->addRoute('GET', '/user/{name}/{id:[0-9]+}', 'handler0'); + $r->addRoute('GET', '/user/{id:[0-9]+}', 'handler1'); + $r->addRoute('GET', '/user/{name}', 'handler2'); + }; + + $method = 'GET'; + $uri = '/user/rdlowrey'; + $handler = 'handler2'; + $argDict = ['name' => 'rdlowrey']; + + $cases[] = [$method, $uri, $callback, $handler, $argDict]; + + // 3 --------------------------------------------------------------------------------------> + + // reuse $callback from #2 + + $method = 'GET'; + $uri = '/user/12345'; + $handler = 'handler1'; + $argDict = ['id' => '12345']; + + $cases[] = [$method, $uri, $callback, $handler, $argDict]; + + // 4 --------------------------------------------------------------------------------------> + + // reuse $callback from #3 + + $method = 'GET'; + $uri = '/user/NaN'; + $handler = 'handler2'; + $argDict = ['name' => 'NaN']; + + $cases[] = [$method, $uri, $callback, $handler, $argDict]; + + // 5 --------------------------------------------------------------------------------------> + + // reuse $callback from #4 + + $method = 'GET'; + $uri = '/user/rdlowrey/12345'; + $handler = 'handler0'; + $argDict = ['name' => 'rdlowrey', 'id' => '12345']; + + $cases[] = [$method, $uri, $callback, $handler, $argDict]; + + // 6 --------------------------------------------------------------------------------------> + + $callback = function (RouteCollector $r) { + $r->addRoute('GET', '/user/{id:[0-9]+}', 'handler0'); + $r->addRoute('GET', '/user/12345/extension', 'handler1'); + $r->addRoute('GET', '/user/{id:[0-9]+}.{extension}', 'handler2'); + }; + + $method = 'GET'; + $uri = '/user/12345.svg'; + $handler = 'handler2'; + $argDict = ['id' => '12345', 'extension' => 'svg']; + + $cases[] = [$method, $uri, $callback, $handler, $argDict]; + + // 7 ----- Test GET method fallback on HEAD route miss ------------------------------------> + + $callback = function (RouteCollector $r) { + $r->addRoute('GET', '/user/{name}', 'handler0'); + $r->addRoute('GET', '/user/{name}/{id:[0-9]+}', 'handler1'); + $r->addRoute('GET', '/static0', 'handler2'); + $r->addRoute('GET', '/static1', 'handler3'); + $r->addRoute('HEAD', '/static1', 'handler4'); + }; + + $method = 'HEAD'; + $uri = '/user/rdlowrey'; + $handler = 'handler0'; + $argDict = ['name' => 'rdlowrey']; + + $cases[] = [$method, $uri, $callback, $handler, $argDict]; + + // 8 ----- Test GET method fallback on HEAD route miss ------------------------------------> + + // reuse $callback from #7 + + $method = 'HEAD'; + $uri = '/user/rdlowrey/1234'; + $handler = 'handler1'; + $argDict = ['name' => 'rdlowrey', 'id' => '1234']; + + $cases[] = [$method, $uri, $callback, $handler, $argDict]; + + // 9 ----- Test GET method fallback on HEAD route miss ------------------------------------> + + // reuse $callback from #8 + + $method = 'HEAD'; + $uri = '/static0'; + $handler = 'handler2'; + $argDict = []; + + $cases[] = [$method, $uri, $callback, $handler, $argDict]; + + // 10 ---- Test existing HEAD route used if available (no fallback) -----------------------> + + // reuse $callback from #9 + + $method = 'HEAD'; + $uri = '/static1'; + $handler = 'handler4'; + $argDict = []; + + $cases[] = [$method, $uri, $callback, $handler, $argDict]; + + // 11 ---- More specified routes are not shadowed by less specific of another method ------> + + $callback = function (RouteCollector $r) { + $r->addRoute('GET', '/user/{name}', 'handler0'); + $r->addRoute('POST', '/user/{name:[a-z]+}', 'handler1'); + }; + + $method = 'POST'; + $uri = '/user/rdlowrey'; + $handler = 'handler1'; + $argDict = ['name' => 'rdlowrey']; + + $cases[] = [$method, $uri, $callback, $handler, $argDict]; + + // 12 ---- Handler of more specific routes is used, if it occurs first --------------------> + + $callback = function (RouteCollector $r) { + $r->addRoute('GET', '/user/{name}', 'handler0'); + $r->addRoute('POST', '/user/{name:[a-z]+}', 'handler1'); + $r->addRoute('POST', '/user/{name}', 'handler2'); + }; + + $method = 'POST'; + $uri = '/user/rdlowrey'; + $handler = 'handler1'; + $argDict = ['name' => 'rdlowrey']; + + $cases[] = [$method, $uri, $callback, $handler, $argDict]; + + // 13 ---- Route with constant suffix -----------------------------------------------------> + + $callback = function (RouteCollector $r) { + $r->addRoute('GET', '/user/{name}', 'handler0'); + $r->addRoute('GET', '/user/{name}/edit', 'handler1'); + }; + + $method = 'GET'; + $uri = '/user/rdlowrey/edit'; + $handler = 'handler1'; + $argDict = ['name' => 'rdlowrey']; + + $cases[] = [$method, $uri, $callback, $handler, $argDict]; + + // 14 ---- Handle multiple methods with the same handler ----------------------------------> + + $callback = function (RouteCollector $r) { + $r->addRoute(['GET', 'POST'], '/user', 'handlerGetPost'); + $r->addRoute(['DELETE'], '/user', 'handlerDelete'); + $r->addRoute([], '/user', 'handlerNone'); + }; + + $argDict = []; + $cases[] = ['GET', '/user', $callback, 'handlerGetPost', $argDict]; + $cases[] = ['POST', '/user', $callback, 'handlerGetPost', $argDict]; + $cases[] = ['DELETE', '/user', $callback, 'handlerDelete', $argDict]; + + // 17 ---- + + $callback = function (RouteCollector $r) { + $r->addRoute('POST', '/user.json', 'handler0'); + $r->addRoute('GET', '/{entity}.json', 'handler1'); + }; + + $cases[] = ['GET', '/user.json', $callback, 'handler1', ['entity' => 'user']]; + + // 18 ---- + + $callback = function (RouteCollector $r) { + $r->addRoute('GET', '', 'handler0'); + }; + + $cases[] = ['GET', '', $callback, 'handler0', []]; + + // 19 ---- + + $callback = function (RouteCollector $r) { + $r->addRoute('HEAD', '/a/{foo}', 'handler0'); + $r->addRoute('GET', '/b/{foo}', 'handler1'); + }; + + $cases[] = ['HEAD', '/b/bar', $callback, 'handler1', ['foo' => 'bar']]; + + // 20 ---- + + $callback = function (RouteCollector $r) { + $r->addRoute('HEAD', '/a', 'handler0'); + $r->addRoute('GET', '/b', 'handler1'); + }; + + $cases[] = ['HEAD', '/b', $callback, 'handler1', []]; + + // 21 ---- + + $callback = function (RouteCollector $r) { + $r->addRoute('GET', '/foo', 'handler0'); + $r->addRoute('HEAD', '/{bar}', 'handler1'); + }; + + $cases[] = ['HEAD', '/foo', $callback, 'handler1', ['bar' => 'foo']]; + + // 22 ---- + + $callback = function (RouteCollector $r) { + $r->addRoute('*', '/user', 'handler0'); + $r->addRoute('*', '/{user}', 'handler1'); + $r->addRoute('GET', '/user', 'handler2'); + }; + + $cases[] = ['GET', '/user', $callback, 'handler2', []]; + + // 23 ---- + + $callback = function (RouteCollector $r) { + $r->addRoute('*', '/user', 'handler0'); + $r->addRoute('GET', '/user', 'handler1'); + }; + + $cases[] = ['POST', '/user', $callback, 'handler0', []]; + + // 24 ---- + + $cases[] = ['HEAD', '/user', $callback, 'handler1', []]; + + // 25 ---- + + $callback = function (RouteCollector $r) { + $r->addRoute('GET', '/{bar}', 'handler0'); + $r->addRoute('*', '/foo', 'handler1'); + }; + + $cases[] = ['GET', '/foo', $callback, 'handler0', ['bar' => 'foo']]; + + // 26 ---- + + $callback = function(RouteCollector $r) { + $r->addRoute('GET', '/user', 'handler0'); + $r->addRoute('*', '/{foo:.*}', 'handler1'); + }; + + $cases[] = ['POST', '/bar', $callback, 'handler1', ['foo' => 'bar']]; + + // x --------------------------------------------------------------------------------------> + + return $cases; + } + + public function provideNotFoundDispatchCases() + { + $cases = []; + + // 0 --------------------------------------------------------------------------------------> + + $callback = function (RouteCollector $r) { + $r->addRoute('GET', '/resource/123/456', 'handler0'); + }; + + $method = 'GET'; + $uri = '/not-found'; + + $cases[] = [$method, $uri, $callback]; + + // 1 --------------------------------------------------------------------------------------> + + // reuse callback from #0 + $method = 'POST'; + $uri = '/not-found'; + + $cases[] = [$method, $uri, $callback]; + + // 2 --------------------------------------------------------------------------------------> + + // reuse callback from #1 + $method = 'PUT'; + $uri = '/not-found'; + + $cases[] = [$method, $uri, $callback]; + + // 3 --------------------------------------------------------------------------------------> + + $callback = function (RouteCollector $r) { + $r->addRoute('GET', '/handler0', 'handler0'); + $r->addRoute('GET', '/handler1', 'handler1'); + $r->addRoute('GET', '/handler2', 'handler2'); + }; + + $method = 'GET'; + $uri = '/not-found'; + + $cases[] = [$method, $uri, $callback]; + + // 4 --------------------------------------------------------------------------------------> + + $callback = function (RouteCollector $r) { + $r->addRoute('GET', '/user/{name}/{id:[0-9]+}', 'handler0'); + $r->addRoute('GET', '/user/{id:[0-9]+}', 'handler1'); + $r->addRoute('GET', '/user/{name}', 'handler2'); + }; + + $method = 'GET'; + $uri = '/not-found'; + + $cases[] = [$method, $uri, $callback]; + + // 5 --------------------------------------------------------------------------------------> + + // reuse callback from #4 + $method = 'GET'; + $uri = '/user/rdlowrey/12345/not-found'; + + $cases[] = [$method, $uri, $callback]; + + // 6 --------------------------------------------------------------------------------------> + + // reuse callback from #5 + $method = 'HEAD'; + + $cases[] = [$method, $uri, $callback]; + + // x --------------------------------------------------------------------------------------> + + return $cases; + } + + public function provideMethodNotAllowedDispatchCases() + { + $cases = []; + + // 0 --------------------------------------------------------------------------------------> + + $callback = function (RouteCollector $r) { + $r->addRoute('GET', '/resource/123/456', 'handler0'); + }; + + $method = 'POST'; + $uri = '/resource/123/456'; + $allowedMethods = ['GET']; + + $cases[] = [$method, $uri, $callback, $allowedMethods]; + + // 1 --------------------------------------------------------------------------------------> + + $callback = function (RouteCollector $r) { + $r->addRoute('GET', '/resource/123/456', 'handler0'); + $r->addRoute('POST', '/resource/123/456', 'handler1'); + $r->addRoute('PUT', '/resource/123/456', 'handler2'); + $r->addRoute('*', '/', 'handler3'); + }; + + $method = 'DELETE'; + $uri = '/resource/123/456'; + $allowedMethods = ['GET', 'POST', 'PUT']; + + $cases[] = [$method, $uri, $callback, $allowedMethods]; + + // 2 --------------------------------------------------------------------------------------> + + $callback = function (RouteCollector $r) { + $r->addRoute('GET', '/user/{name}/{id:[0-9]+}', 'handler0'); + $r->addRoute('POST', '/user/{name}/{id:[0-9]+}', 'handler1'); + $r->addRoute('PUT', '/user/{name}/{id:[0-9]+}', 'handler2'); + $r->addRoute('PATCH', '/user/{name}/{id:[0-9]+}', 'handler3'); + }; + + $method = 'DELETE'; + $uri = '/user/rdlowrey/42'; + $allowedMethods = ['GET', 'POST', 'PUT', 'PATCH']; + + $cases[] = [$method, $uri, $callback, $allowedMethods]; + + // 3 --------------------------------------------------------------------------------------> + + $callback = function (RouteCollector $r) { + $r->addRoute('POST', '/user/{name}', 'handler1'); + $r->addRoute('PUT', '/user/{name:[a-z]+}', 'handler2'); + $r->addRoute('PATCH', '/user/{name:[a-z]+}', 'handler3'); + }; + + $method = 'GET'; + $uri = '/user/rdlowrey'; + $allowedMethods = ['POST', 'PUT', 'PATCH']; + + $cases[] = [$method, $uri, $callback, $allowedMethods]; + + // 4 --------------------------------------------------------------------------------------> + + $callback = function (RouteCollector $r) { + $r->addRoute(['GET', 'POST'], '/user', 'handlerGetPost'); + $r->addRoute(['DELETE'], '/user', 'handlerDelete'); + $r->addRoute([], '/user', 'handlerNone'); + }; + + $cases[] = ['PUT', '/user', $callback, ['GET', 'POST', 'DELETE']]; + + // 5 + + $callback = function (RouteCollector $r) { + $r->addRoute('POST', '/user.json', 'handler0'); + $r->addRoute('GET', '/{entity}.json', 'handler1'); + }; + + $cases[] = ['PUT', '/user.json', $callback, ['POST', 'GET']]; + + // x --------------------------------------------------------------------------------------> + + return $cases; + } +} diff --git a/Sources/API/vendor/nikic/fast-route/test/Dispatcher/GroupCountBasedTest.php b/Sources/API/vendor/nikic/fast-route/test/Dispatcher/GroupCountBasedTest.php new file mode 100644 index 0000000..f821ef5 --- /dev/null +++ b/Sources/API/vendor/nikic/fast-route/test/Dispatcher/GroupCountBasedTest.php @@ -0,0 +1,16 @@ +markTestSkipped('PHP 5.6 required for MARK support'); + } + } + + protected function getDispatcherClass() + { + return 'FastRoute\\Dispatcher\\MarkBased'; + } + + protected function getDataGeneratorClass() + { + return 'FastRoute\\DataGenerator\\MarkBased'; + } +} diff --git a/Sources/API/vendor/nikic/fast-route/test/HackTypechecker/HackTypecheckerTest.php b/Sources/API/vendor/nikic/fast-route/test/HackTypechecker/HackTypecheckerTest.php new file mode 100644 index 0000000..b6fc53f --- /dev/null +++ b/Sources/API/vendor/nikic/fast-route/test/HackTypechecker/HackTypecheckerTest.php @@ -0,0 +1,44 @@ +markTestSkipped('HHVM only'); + } + if (!version_compare(HHVM_VERSION, '3.9.0', '>=')) { + $this->markTestSkipped('classname requires HHVM 3.9+'); + } + + // The typechecker recurses the whole tree, so it makes sure + // that everything in fixtures/ is valid when this runs. + + $output = []; + $exit_code = null; + exec( + 'hh_server --check ' . escapeshellarg(__DIR__ . '/../../') . ' 2>&1', + $output, + $exit_code + ); + if ($exit_code === self::SERVER_ALREADY_RUNNING_CODE) { + $this->assertTrue( + $recurse, + 'Typechecker still running after running hh_client stop' + ); + // Server already running - 3.10 => 3.11 regression: + // https://github.com/facebook/hhvm/issues/6646 + exec('hh_client stop 2>/dev/null'); + $this->testTypechecks(/* recurse = */ false); + return; + + } + $this->assertSame(0, $exit_code, implode("\n", $output)); + } +} diff --git a/Sources/API/vendor/nikic/fast-route/test/HackTypechecker/fixtures/all_options.php b/Sources/API/vendor/nikic/fast-route/test/HackTypechecker/fixtures/all_options.php new file mode 100644 index 0000000..05a9af2 --- /dev/null +++ b/Sources/API/vendor/nikic/fast-route/test/HackTypechecker/fixtures/all_options.php @@ -0,0 +1,29 @@ + {}, + shape( + 'routeParser' => \FastRoute\RouteParser\Std::class, + 'dataGenerator' => \FastRoute\DataGenerator\GroupCountBased::class, + 'dispatcher' => \FastRoute\Dispatcher\GroupCountBased::class, + 'routeCollector' => \FastRoute\RouteCollector::class, + ), + ); +} + +function all_options_cached(): \FastRoute\Dispatcher { + return \FastRoute\cachedDispatcher( + $collector ==> {}, + shape( + 'routeParser' => \FastRoute\RouteParser\Std::class, + 'dataGenerator' => \FastRoute\DataGenerator\GroupCountBased::class, + 'dispatcher' => \FastRoute\Dispatcher\GroupCountBased::class, + 'routeCollector' => \FastRoute\RouteCollector::class, + 'cacheFile' => '/dev/null', + 'cacheDisabled' => false, + ), + ); +} diff --git a/Sources/API/vendor/nikic/fast-route/test/HackTypechecker/fixtures/empty_options.php b/Sources/API/vendor/nikic/fast-route/test/HackTypechecker/fixtures/empty_options.php new file mode 100644 index 0000000..61eb541 --- /dev/null +++ b/Sources/API/vendor/nikic/fast-route/test/HackTypechecker/fixtures/empty_options.php @@ -0,0 +1,11 @@ + {}, shape()); +} + +function empty_options_cached(): \FastRoute\Dispatcher { + return \FastRoute\cachedDispatcher($collector ==> {}, shape()); +} diff --git a/Sources/API/vendor/nikic/fast-route/test/HackTypechecker/fixtures/no_options.php b/Sources/API/vendor/nikic/fast-route/test/HackTypechecker/fixtures/no_options.php new file mode 100644 index 0000000..44b5422 --- /dev/null +++ b/Sources/API/vendor/nikic/fast-route/test/HackTypechecker/fixtures/no_options.php @@ -0,0 +1,11 @@ + {}); +} + +function no_options_cached(): \FastRoute\Dispatcher { + return \FastRoute\cachedDispatcher($collector ==> {}); +} diff --git a/Sources/API/vendor/nikic/fast-route/test/RouteCollectorTest.php b/Sources/API/vendor/nikic/fast-route/test/RouteCollectorTest.php new file mode 100644 index 0000000..cc54407 --- /dev/null +++ b/Sources/API/vendor/nikic/fast-route/test/RouteCollectorTest.php @@ -0,0 +1,108 @@ +delete('/delete', 'delete'); + $r->get('/get', 'get'); + $r->head('/head', 'head'); + $r->patch('/patch', 'patch'); + $r->post('/post', 'post'); + $r->put('/put', 'put'); + + $expected = [ + ['DELETE', '/delete', 'delete'], + ['GET', '/get', 'get'], + ['HEAD', '/head', 'head'], + ['PATCH', '/patch', 'patch'], + ['POST', '/post', 'post'], + ['PUT', '/put', 'put'], + ]; + + $this->assertSame($expected, $r->routes); + } + + public function testGroups() + { + $r = new DummyRouteCollector(); + + $r->delete('/delete', 'delete'); + $r->get('/get', 'get'); + $r->head('/head', 'head'); + $r->patch('/patch', 'patch'); + $r->post('/post', 'post'); + $r->put('/put', 'put'); + + $r->addGroup('/group-one', function (DummyRouteCollector $r) { + $r->delete('/delete', 'delete'); + $r->get('/get', 'get'); + $r->head('/head', 'head'); + $r->patch('/patch', 'patch'); + $r->post('/post', 'post'); + $r->put('/put', 'put'); + + $r->addGroup('/group-two', function (DummyRouteCollector $r) { + $r->delete('/delete', 'delete'); + $r->get('/get', 'get'); + $r->head('/head', 'head'); + $r->patch('/patch', 'patch'); + $r->post('/post', 'post'); + $r->put('/put', 'put'); + }); + }); + + $r->addGroup('/admin', function (DummyRouteCollector $r) { + $r->get('-some-info', 'admin-some-info'); + }); + $r->addGroup('/admin-', function (DummyRouteCollector $r) { + $r->get('more-info', 'admin-more-info'); + }); + + $expected = [ + ['DELETE', '/delete', 'delete'], + ['GET', '/get', 'get'], + ['HEAD', '/head', 'head'], + ['PATCH', '/patch', 'patch'], + ['POST', '/post', 'post'], + ['PUT', '/put', 'put'], + ['DELETE', '/group-one/delete', 'delete'], + ['GET', '/group-one/get', 'get'], + ['HEAD', '/group-one/head', 'head'], + ['PATCH', '/group-one/patch', 'patch'], + ['POST', '/group-one/post', 'post'], + ['PUT', '/group-one/put', 'put'], + ['DELETE', '/group-one/group-two/delete', 'delete'], + ['GET', '/group-one/group-two/get', 'get'], + ['HEAD', '/group-one/group-two/head', 'head'], + ['PATCH', '/group-one/group-two/patch', 'patch'], + ['POST', '/group-one/group-two/post', 'post'], + ['PUT', '/group-one/group-two/put', 'put'], + ['GET', '/admin-some-info', 'admin-some-info'], + ['GET', '/admin-more-info', 'admin-more-info'], + ]; + + $this->assertSame($expected, $r->routes); + } +} + +class DummyRouteCollector extends RouteCollector +{ + public $routes = []; + + public function __construct() + { + } + + public function addRoute($method, $route, $handler) + { + $route = $this->currentGroupPrefix . $route; + $this->routes[] = [$method, $route, $handler]; + } +} diff --git a/Sources/API/vendor/nikic/fast-route/test/RouteParser/StdTest.php b/Sources/API/vendor/nikic/fast-route/test/RouteParser/StdTest.php new file mode 100644 index 0000000..e13e4de --- /dev/null +++ b/Sources/API/vendor/nikic/fast-route/test/RouteParser/StdTest.php @@ -0,0 +1,154 @@ +parse($routeString); + $this->assertSame($expectedRouteDatas, $routeDatas); + } + + /** @dataProvider provideTestParseError */ + public function testParseError($routeString, $expectedExceptionMessage) + { + $parser = new Std(); + $this->setExpectedException('FastRoute\\BadRouteException', $expectedExceptionMessage); + $parser->parse($routeString); + } + + public function provideTestParse() + { + return [ + [ + '/test', + [ + ['/test'], + ] + ], + [ + '/test/{param}', + [ + ['/test/', ['param', '[^/]+']], + ] + ], + [ + '/te{ param }st', + [ + ['/te', ['param', '[^/]+'], 'st'] + ] + ], + [ + '/test/{param1}/test2/{param2}', + [ + ['/test/', ['param1', '[^/]+'], '/test2/', ['param2', '[^/]+']] + ] + ], + [ + '/test/{param:\d+}', + [ + ['/test/', ['param', '\d+']] + ] + ], + [ + '/test/{ param : \d{1,9} }', + [ + ['/test/', ['param', '\d{1,9}']] + ] + ], + [ + '/test[opt]', + [ + ['/test'], + ['/testopt'], + ] + ], + [ + '/test[/{param}]', + [ + ['/test'], + ['/test/', ['param', '[^/]+']], + ] + ], + [ + '/{param}[opt]', + [ + ['/', ['param', '[^/]+']], + ['/', ['param', '[^/]+'], 'opt'] + ] + ], + [ + '/test[/{name}[/{id:[0-9]+}]]', + [ + ['/test'], + ['/test/', ['name', '[^/]+']], + ['/test/', ['name', '[^/]+'], '/', ['id', '[0-9]+']], + ] + ], + [ + '', + [ + [''], + ] + ], + [ + '[test]', + [ + [''], + ['test'], + ] + ], + [ + '/{foo-bar}', + [ + ['/', ['foo-bar', '[^/]+']] + ] + ], + [ + '/{_foo:.*}', + [ + ['/', ['_foo', '.*']] + ] + ], + ]; + } + + public function provideTestParseError() + { + return [ + [ + '/test[opt', + "Number of opening '[' and closing ']' does not match" + ], + [ + '/test[opt[opt2]', + "Number of opening '[' and closing ']' does not match" + ], + [ + '/testopt]', + "Number of opening '[' and closing ']' does not match" + ], + [ + '/test[]', + 'Empty optional part' + ], + [ + '/test[[opt]]', + 'Empty optional part' + ], + [ + '[[test]]', + 'Empty optional part' + ], + [ + '/test[/opt]/required', + 'Optional segments can only occur at the end of a route' + ], + ]; + } +} diff --git a/Sources/API/vendor/nikic/fast-route/test/bootstrap.php b/Sources/API/vendor/nikic/fast-route/test/bootstrap.php new file mode 100644 index 0000000..3023f41 --- /dev/null +++ b/Sources/API/vendor/nikic/fast-route/test/bootstrap.php @@ -0,0 +1,11 @@ +=7.4.0" + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + } +} diff --git a/Sources/API/vendor/psr/container/src/ContainerExceptionInterface.php b/Sources/API/vendor/psr/container/src/ContainerExceptionInterface.php new file mode 100644 index 0000000..0f213f2 --- /dev/null +++ b/Sources/API/vendor/psr/container/src/ContainerExceptionInterface.php @@ -0,0 +1,12 @@ +=7.0.0", + "psr/http-message": "^1.0" + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + } +} diff --git a/Sources/API/vendor/psr/http-factory/src/RequestFactoryInterface.php b/Sources/API/vendor/psr/http-factory/src/RequestFactoryInterface.php new file mode 100644 index 0000000..cb39a08 --- /dev/null +++ b/Sources/API/vendor/psr/http-factory/src/RequestFactoryInterface.php @@ -0,0 +1,18 @@ +=5.3.0" + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + } +} diff --git a/Sources/API/vendor/psr/http-message/src/MessageInterface.php b/Sources/API/vendor/psr/http-message/src/MessageInterface.php new file mode 100644 index 0000000..dd46e5e --- /dev/null +++ b/Sources/API/vendor/psr/http-message/src/MessageInterface.php @@ -0,0 +1,187 @@ +getHeaders() as $name => $values) { + * echo $name . ": " . implode(", ", $values); + * } + * + * // Emit headers iteratively: + * foreach ($message->getHeaders() as $name => $values) { + * foreach ($values as $value) { + * header(sprintf('%s: %s', $name, $value), false); + * } + * } + * + * While header names are not case-sensitive, getHeaders() will preserve the + * exact case in which headers were originally specified. + * + * @return string[][] Returns an associative array of the message's headers. Each + * key MUST be a header name, and each value MUST be an array of strings + * for that header. + */ + public function getHeaders(); + + /** + * Checks if a header exists by the given case-insensitive name. + * + * @param string $name Case-insensitive header field name. + * @return bool Returns true if any header names match the given header + * name using a case-insensitive string comparison. Returns false if + * no matching header name is found in the message. + */ + public function hasHeader($name); + + /** + * Retrieves a message header value by the given case-insensitive name. + * + * This method returns an array of all the header values of the given + * case-insensitive header name. + * + * If the header does not appear in the message, this method MUST return an + * empty array. + * + * @param string $name Case-insensitive header field name. + * @return string[] An array of string values as provided for the given + * header. If the header does not appear in the message, this method MUST + * return an empty array. + */ + public function getHeader($name); + + /** + * Retrieves a comma-separated string of the values for a single header. + * + * This method returns all of the header values of the given + * case-insensitive header name as a string concatenated together using + * a comma. + * + * NOTE: Not all header values may be appropriately represented using + * comma concatenation. For such headers, use getHeader() instead + * and supply your own delimiter when concatenating. + * + * If the header does not appear in the message, this method MUST return + * an empty string. + * + * @param string $name Case-insensitive header field name. + * @return string A string of values as provided for the given header + * concatenated together using a comma. If the header does not appear in + * the message, this method MUST return an empty string. + */ + public function getHeaderLine($name); + + /** + * Return an instance with the provided value replacing the specified header. + * + * While header names are case-insensitive, the casing of the header will + * be preserved by this function, and returned from getHeaders(). + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * new and/or updated header and value. + * + * @param string $name Case-insensitive header field name. + * @param string|string[] $value Header value(s). + * @return static + * @throws \InvalidArgumentException for invalid header names or values. + */ + public function withHeader($name, $value); + + /** + * Return an instance with the specified header appended with the given value. + * + * Existing values for the specified header will be maintained. The new + * value(s) will be appended to the existing list. If the header did not + * exist previously, it will be added. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * new header and/or value. + * + * @param string $name Case-insensitive header field name to add. + * @param string|string[] $value Header value(s). + * @return static + * @throws \InvalidArgumentException for invalid header names or values. + */ + public function withAddedHeader($name, $value); + + /** + * Return an instance without the specified header. + * + * Header resolution MUST be done without case-sensitivity. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that removes + * the named header. + * + * @param string $name Case-insensitive header field name to remove. + * @return static + */ + public function withoutHeader($name); + + /** + * Gets the body of the message. + * + * @return StreamInterface Returns the body as a stream. + */ + public function getBody(); + + /** + * Return an instance with the specified message body. + * + * The body MUST be a StreamInterface object. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return a new instance that has the + * new body stream. + * + * @param StreamInterface $body Body. + * @return static + * @throws \InvalidArgumentException When the body is not valid. + */ + public function withBody(StreamInterface $body); +} diff --git a/Sources/API/vendor/psr/http-message/src/RequestInterface.php b/Sources/API/vendor/psr/http-message/src/RequestInterface.php new file mode 100644 index 0000000..a96d4fd --- /dev/null +++ b/Sources/API/vendor/psr/http-message/src/RequestInterface.php @@ -0,0 +1,129 @@ +getQuery()` + * or from the `QUERY_STRING` server param. + * + * @return array + */ + public function getQueryParams(); + + /** + * Return an instance with the specified query string arguments. + * + * These values SHOULD remain immutable over the course of the incoming + * request. They MAY be injected during instantiation, such as from PHP's + * $_GET superglobal, or MAY be derived from some other value such as the + * URI. In cases where the arguments are parsed from the URI, the data + * MUST be compatible with what PHP's parse_str() would return for + * purposes of how duplicate query parameters are handled, and how nested + * sets are handled. + * + * Setting query string arguments MUST NOT change the URI stored by the + * request, nor the values in the server params. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * updated query string arguments. + * + * @param array $query Array of query string arguments, typically from + * $_GET. + * @return static + */ + public function withQueryParams(array $query); + + /** + * Retrieve normalized file upload data. + * + * This method returns upload metadata in a normalized tree, with each leaf + * an instance of Psr\Http\Message\UploadedFileInterface. + * + * These values MAY be prepared from $_FILES or the message body during + * instantiation, or MAY be injected via withUploadedFiles(). + * + * @return array An array tree of UploadedFileInterface instances; an empty + * array MUST be returned if no data is present. + */ + public function getUploadedFiles(); + + /** + * Create a new instance with the specified uploaded files. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * updated body parameters. + * + * @param array $uploadedFiles An array tree of UploadedFileInterface instances. + * @return static + * @throws \InvalidArgumentException if an invalid structure is provided. + */ + public function withUploadedFiles(array $uploadedFiles); + + /** + * Retrieve any parameters provided in the request body. + * + * If the request Content-Type is either application/x-www-form-urlencoded + * or multipart/form-data, and the request method is POST, this method MUST + * return the contents of $_POST. + * + * Otherwise, this method may return any results of deserializing + * the request body content; as parsing returns structured content, the + * potential types MUST be arrays or objects only. A null value indicates + * the absence of body content. + * + * @return null|array|object The deserialized body parameters, if any. + * These will typically be an array or object. + */ + public function getParsedBody(); + + /** + * Return an instance with the specified body parameters. + * + * These MAY be injected during instantiation. + * + * If the request Content-Type is either application/x-www-form-urlencoded + * or multipart/form-data, and the request method is POST, use this method + * ONLY to inject the contents of $_POST. + * + * The data IS NOT REQUIRED to come from $_POST, but MUST be the results of + * deserializing the request body content. Deserialization/parsing returns + * structured data, and, as such, this method ONLY accepts arrays or objects, + * or a null value if nothing was available to parse. + * + * As an example, if content negotiation determines that the request data + * is a JSON payload, this method could be used to create a request + * instance with the deserialized parameters. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * updated body parameters. + * + * @param null|array|object $data The deserialized body data. This will + * typically be in an array or object. + * @return static + * @throws \InvalidArgumentException if an unsupported argument type is + * provided. + */ + public function withParsedBody($data); + + /** + * Retrieve attributes derived from the request. + * + * The request "attributes" may be used to allow injection of any + * parameters derived from the request: e.g., the results of path + * match operations; the results of decrypting cookies; the results of + * deserializing non-form-encoded message bodies; etc. Attributes + * will be application and request specific, and CAN be mutable. + * + * @return array Attributes derived from the request. + */ + public function getAttributes(); + + /** + * Retrieve a single derived request attribute. + * + * Retrieves a single derived request attribute as described in + * getAttributes(). If the attribute has not been previously set, returns + * the default value as provided. + * + * This method obviates the need for a hasAttribute() method, as it allows + * specifying a default value to return if the attribute is not found. + * + * @see getAttributes() + * @param string $name The attribute name. + * @param mixed $default Default value to return if the attribute does not exist. + * @return mixed + */ + public function getAttribute($name, $default = null); + + /** + * Return an instance with the specified derived request attribute. + * + * This method allows setting a single derived request attribute as + * described in getAttributes(). + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * updated attribute. + * + * @see getAttributes() + * @param string $name The attribute name. + * @param mixed $value The value of the attribute. + * @return static + */ + public function withAttribute($name, $value); + + /** + * Return an instance that removes the specified derived request attribute. + * + * This method allows removing a single derived request attribute as + * described in getAttributes(). + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that removes + * the attribute. + * + * @see getAttributes() + * @param string $name The attribute name. + * @return static + */ + public function withoutAttribute($name); +} diff --git a/Sources/API/vendor/psr/http-message/src/StreamInterface.php b/Sources/API/vendor/psr/http-message/src/StreamInterface.php new file mode 100644 index 0000000..f68f391 --- /dev/null +++ b/Sources/API/vendor/psr/http-message/src/StreamInterface.php @@ -0,0 +1,158 @@ + + * [user-info@]host[:port] + * + * + * If the port component is not set or is the standard port for the current + * scheme, it SHOULD NOT be included. + * + * @see https://tools.ietf.org/html/rfc3986#section-3.2 + * @return string The URI authority, in "[user-info@]host[:port]" format. + */ + public function getAuthority(); + + /** + * Retrieve the user information component of the URI. + * + * If no user information is present, this method MUST return an empty + * string. + * + * If a user is present in the URI, this will return that value; + * additionally, if the password is also present, it will be appended to the + * user value, with a colon (":") separating the values. + * + * The trailing "@" character is not part of the user information and MUST + * NOT be added. + * + * @return string The URI user information, in "username[:password]" format. + */ + public function getUserInfo(); + + /** + * Retrieve the host component of the URI. + * + * If no host is present, this method MUST return an empty string. + * + * The value returned MUST be normalized to lowercase, per RFC 3986 + * Section 3.2.2. + * + * @see http://tools.ietf.org/html/rfc3986#section-3.2.2 + * @return string The URI host. + */ + public function getHost(); + + /** + * Retrieve the port component of the URI. + * + * If a port is present, and it is non-standard for the current scheme, + * this method MUST return it as an integer. If the port is the standard port + * used with the current scheme, this method SHOULD return null. + * + * If no port is present, and no scheme is present, this method MUST return + * a null value. + * + * If no port is present, but a scheme is present, this method MAY return + * the standard port for that scheme, but SHOULD return null. + * + * @return null|int The URI port. + */ + public function getPort(); + + /** + * Retrieve the path component of the URI. + * + * The path can either be empty or absolute (starting with a slash) or + * rootless (not starting with a slash). Implementations MUST support all + * three syntaxes. + * + * Normally, the empty path "" and absolute path "/" are considered equal as + * defined in RFC 7230 Section 2.7.3. But this method MUST NOT automatically + * do this normalization because in contexts with a trimmed base path, e.g. + * the front controller, this difference becomes significant. It's the task + * of the user to handle both "" and "/". + * + * The value returned MUST be percent-encoded, but MUST NOT double-encode + * any characters. To determine what characters to encode, please refer to + * RFC 3986, Sections 2 and 3.3. + * + * As an example, if the value should include a slash ("/") not intended as + * delimiter between path segments, that value MUST be passed in encoded + * form (e.g., "%2F") to the instance. + * + * @see https://tools.ietf.org/html/rfc3986#section-2 + * @see https://tools.ietf.org/html/rfc3986#section-3.3 + * @return string The URI path. + */ + public function getPath(); + + /** + * Retrieve the query string of the URI. + * + * If no query string is present, this method MUST return an empty string. + * + * The leading "?" character is not part of the query and MUST NOT be + * added. + * + * The value returned MUST be percent-encoded, but MUST NOT double-encode + * any characters. To determine what characters to encode, please refer to + * RFC 3986, Sections 2 and 3.4. + * + * As an example, if a value in a key/value pair of the query string should + * include an ampersand ("&") not intended as a delimiter between values, + * that value MUST be passed in encoded form (e.g., "%26") to the instance. + * + * @see https://tools.ietf.org/html/rfc3986#section-2 + * @see https://tools.ietf.org/html/rfc3986#section-3.4 + * @return string The URI query string. + */ + public function getQuery(); + + /** + * Retrieve the fragment component of the URI. + * + * If no fragment is present, this method MUST return an empty string. + * + * The leading "#" character is not part of the fragment and MUST NOT be + * added. + * + * The value returned MUST be percent-encoded, but MUST NOT double-encode + * any characters. To determine what characters to encode, please refer to + * RFC 3986, Sections 2 and 3.5. + * + * @see https://tools.ietf.org/html/rfc3986#section-2 + * @see https://tools.ietf.org/html/rfc3986#section-3.5 + * @return string The URI fragment. + */ + public function getFragment(); + + /** + * Return an instance with the specified scheme. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified scheme. + * + * Implementations MUST support the schemes "http" and "https" case + * insensitively, and MAY accommodate other schemes if required. + * + * An empty scheme is equivalent to removing the scheme. + * + * @param string $scheme The scheme to use with the new instance. + * @return static A new instance with the specified scheme. + * @throws \InvalidArgumentException for invalid or unsupported schemes. + */ + public function withScheme($scheme); + + /** + * Return an instance with the specified user information. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified user information. + * + * Password is optional, but the user information MUST include the + * user; an empty string for the user is equivalent to removing user + * information. + * + * @param string $user The user name to use for authority. + * @param null|string $password The password associated with $user. + * @return static A new instance with the specified user information. + */ + public function withUserInfo($user, $password = null); + + /** + * Return an instance with the specified host. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified host. + * + * An empty host value is equivalent to removing the host. + * + * @param string $host The hostname to use with the new instance. + * @return static A new instance with the specified host. + * @throws \InvalidArgumentException for invalid hostnames. + */ + public function withHost($host); + + /** + * Return an instance with the specified port. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified port. + * + * Implementations MUST raise an exception for ports outside the + * established TCP and UDP port ranges. + * + * A null value provided for the port is equivalent to removing the port + * information. + * + * @param null|int $port The port to use with the new instance; a null value + * removes the port information. + * @return static A new instance with the specified port. + * @throws \InvalidArgumentException for invalid ports. + */ + public function withPort($port); + + /** + * Return an instance with the specified path. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified path. + * + * The path can either be empty or absolute (starting with a slash) or + * rootless (not starting with a slash). Implementations MUST support all + * three syntaxes. + * + * If the path is intended to be domain-relative rather than path relative then + * it must begin with a slash ("/"). Paths not starting with a slash ("/") + * are assumed to be relative to some base path known to the application or + * consumer. + * + * Users can provide both encoded and decoded path characters. + * Implementations ensure the correct encoding as outlined in getPath(). + * + * @param string $path The path to use with the new instance. + * @return static A new instance with the specified path. + * @throws \InvalidArgumentException for invalid paths. + */ + public function withPath($path); + + /** + * Return an instance with the specified query string. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified query string. + * + * Users can provide both encoded and decoded query characters. + * Implementations ensure the correct encoding as outlined in getQuery(). + * + * An empty query string value is equivalent to removing the query string. + * + * @param string $query The query string to use with the new instance. + * @return static A new instance with the specified query string. + * @throws \InvalidArgumentException for invalid query strings. + */ + public function withQuery($query); + + /** + * Return an instance with the specified URI fragment. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified URI fragment. + * + * Users can provide both encoded and decoded fragment characters. + * Implementations ensure the correct encoding as outlined in getFragment(). + * + * An empty fragment value is equivalent to removing the fragment. + * + * @param string $fragment The fragment to use with the new instance. + * @return static A new instance with the specified fragment. + */ + public function withFragment($fragment); + + /** + * Return the string representation as a URI reference. + * + * Depending on which components of the URI are present, the resulting + * string is either a full URI or relative reference according to RFC 3986, + * Section 4.1. The method concatenates the various components of the URI, + * using the appropriate delimiters: + * + * - If a scheme is present, it MUST be suffixed by ":". + * - If an authority is present, it MUST be prefixed by "//". + * - The path can be concatenated without delimiters. But there are two + * cases where the path has to be adjusted to make the URI reference + * valid as PHP does not allow to throw an exception in __toString(): + * - If the path is rootless and an authority is present, the path MUST + * be prefixed by "/". + * - If the path is starting with more than one "/" and no authority is + * present, the starting slashes MUST be reduced to one. + * - If a query is present, it MUST be prefixed by "?". + * - If a fragment is present, it MUST be prefixed by "#". + * + * @see http://tools.ietf.org/html/rfc3986#section-4.1 + * @return string + */ + public function __toString(); +} diff --git a/Sources/API/vendor/psr/http-server-handler/LICENSE b/Sources/API/vendor/psr/http-server-handler/LICENSE new file mode 100644 index 0000000..b71ec5d --- /dev/null +++ b/Sources/API/vendor/psr/http-server-handler/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 PHP Framework Interoperability Group + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Sources/API/vendor/psr/http-server-handler/README.md b/Sources/API/vendor/psr/http-server-handler/README.md new file mode 100644 index 0000000..1b7b486 --- /dev/null +++ b/Sources/API/vendor/psr/http-server-handler/README.md @@ -0,0 +1,6 @@ +HTTP Server Handler +=================== + +Provides the `RequestHandlerInterface` of [PSR-15][psr-15]. + +[psr-15]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-15-request-handlers.md diff --git a/Sources/API/vendor/psr/http-server-handler/composer.json b/Sources/API/vendor/psr/http-server-handler/composer.json new file mode 100644 index 0000000..9e8b51d --- /dev/null +++ b/Sources/API/vendor/psr/http-server-handler/composer.json @@ -0,0 +1,36 @@ +{ + "name": "psr/http-server-handler", + "description": "Common interface for HTTP server-side request handler", + "keywords": [ + "psr", + "psr-7", + "psr-15", + "http-interop", + "http", + "server", + "handler", + "request", + "response" + ], + "license": "MIT", + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "require": { + "php": ">=7.0", + "psr/http-message": "^1.0" + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Server\\": "src/" + } + }, + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + } +} diff --git a/Sources/API/vendor/psr/http-server-handler/src/RequestHandlerInterface.php b/Sources/API/vendor/psr/http-server-handler/src/RequestHandlerInterface.php new file mode 100644 index 0000000..83911e2 --- /dev/null +++ b/Sources/API/vendor/psr/http-server-handler/src/RequestHandlerInterface.php @@ -0,0 +1,22 @@ +=7.0", + "psr/http-message": "^1.0", + "psr/http-server-handler": "^1.0" + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Server\\": "src/" + } + }, + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + } +} diff --git a/Sources/API/vendor/psr/http-server-middleware/src/MiddlewareInterface.php b/Sources/API/vendor/psr/http-server-middleware/src/MiddlewareInterface.php new file mode 100644 index 0000000..a6c14f8 --- /dev/null +++ b/Sources/API/vendor/psr/http-server-middleware/src/MiddlewareInterface.php @@ -0,0 +1,25 @@ += 5.3. + +[![Build Status](https://travis-ci.org/ralouphie/getallheaders.svg?branch=master)](https://travis-ci.org/ralouphie/getallheaders) +[![Coverage Status](https://coveralls.io/repos/ralouphie/getallheaders/badge.png?branch=master)](https://coveralls.io/r/ralouphie/getallheaders?branch=master) +[![Latest Stable Version](https://poser.pugx.org/ralouphie/getallheaders/v/stable.png)](https://packagist.org/packages/ralouphie/getallheaders) +[![Latest Unstable Version](https://poser.pugx.org/ralouphie/getallheaders/v/unstable.png)](https://packagist.org/packages/ralouphie/getallheaders) +[![License](https://poser.pugx.org/ralouphie/getallheaders/license.png)](https://packagist.org/packages/ralouphie/getallheaders) + + +This is a simple polyfill for [`getallheaders()`](http://www.php.net/manual/en/function.getallheaders.php). + +## Install + +For PHP version **`>= 5.6`**: + +``` +composer require ralouphie/getallheaders +``` + +For PHP version **`< 5.6`**: + +``` +composer require ralouphie/getallheaders "^2" +``` diff --git a/Sources/API/vendor/ralouphie/getallheaders/composer.json b/Sources/API/vendor/ralouphie/getallheaders/composer.json new file mode 100644 index 0000000..de8ce62 --- /dev/null +++ b/Sources/API/vendor/ralouphie/getallheaders/composer.json @@ -0,0 +1,26 @@ +{ + "name": "ralouphie/getallheaders", + "description": "A polyfill for getallheaders.", + "license": "MIT", + "authors": [ + { + "name": "Ralph Khattar", + "email": "ralph.khattar@gmail.com" + } + ], + "require": { + "php": ">=5.6" + }, + "require-dev": { + "phpunit/phpunit": "^5 || ^6.5", + "php-coveralls/php-coveralls": "^2.1" + }, + "autoload": { + "files": ["src/getallheaders.php"] + }, + "autoload-dev": { + "psr-4": { + "getallheaders\\Tests\\": "tests/" + } + } +} diff --git a/Sources/API/vendor/ralouphie/getallheaders/src/getallheaders.php b/Sources/API/vendor/ralouphie/getallheaders/src/getallheaders.php new file mode 100644 index 0000000..c7285a5 --- /dev/null +++ b/Sources/API/vendor/ralouphie/getallheaders/src/getallheaders.php @@ -0,0 +1,46 @@ + 'Content-Type', + 'CONTENT_LENGTH' => 'Content-Length', + 'CONTENT_MD5' => 'Content-Md5', + ); + + foreach ($_SERVER as $key => $value) { + if (substr($key, 0, 5) === 'HTTP_') { + $key = substr($key, 5); + if (!isset($copy_server[$key]) || !isset($_SERVER[$key])) { + $key = str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', $key)))); + $headers[$key] = $value; + } + } elseif (isset($copy_server[$key])) { + $headers[$copy_server[$key]] = $value; + } + } + + if (!isset($headers['Authorization'])) { + if (isset($_SERVER['REDIRECT_HTTP_AUTHORIZATION'])) { + $headers['Authorization'] = $_SERVER['REDIRECT_HTTP_AUTHORIZATION']; + } elseif (isset($_SERVER['PHP_AUTH_USER'])) { + $basic_pass = isset($_SERVER['PHP_AUTH_PW']) ? $_SERVER['PHP_AUTH_PW'] : ''; + $headers['Authorization'] = 'Basic ' . base64_encode($_SERVER['PHP_AUTH_USER'] . ':' . $basic_pass); + } elseif (isset($_SERVER['PHP_AUTH_DIGEST'])) { + $headers['Authorization'] = $_SERVER['PHP_AUTH_DIGEST']; + } + } + + return $headers; + } + +} diff --git a/Sources/API/vendor/slim/psr7/LICENSE.md b/Sources/API/vendor/slim/psr7/LICENSE.md new file mode 100644 index 0000000..2bd2d5a --- /dev/null +++ b/Sources/API/vendor/slim/psr7/LICENSE.md @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2015 Slim Framework + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/Sources/API/vendor/slim/psr7/MAINTAINERS.md b/Sources/API/vendor/slim/psr7/MAINTAINERS.md new file mode 100644 index 0000000..5c2496e --- /dev/null +++ b/Sources/API/vendor/slim/psr7/MAINTAINERS.md @@ -0,0 +1,17 @@ +# Maintainers + +There aren't many rules for maintainers of Slim-Psr7 to remember; what we have is listed here. + +## We don't merge our own PRs + +Our code is better if more than one set of eyes looks at it. Therefore we do not merge our own pull requests unless there is an exceptional circumstance. This helps to spot errors in the patch and also enables us to share information about the project around the maintainer team. + +## PRs tagged `[WIP]` are not ready to be merged + +Sometimes it's helpful to collaborate on a patch before it's ready to be merged. We use the `[WIP]` tag (for _Work in Progress_) in the title to mark these PRs. + +If a PR has `[WIP]` in its title, then it is not to be merged. The person who raised the PR will remove the `[WIP]` tag when they are ready for a full review and merge. + +## Assign a merged PR to a milestone + +By ensuring that all merged PRs are assigned to a milestone, we can easily find which PRs were in which release. diff --git a/Sources/API/vendor/slim/psr7/composer.json b/Sources/API/vendor/slim/psr7/composer.json new file mode 100644 index 0000000..318f710 --- /dev/null +++ b/Sources/API/vendor/slim/psr7/composer.json @@ -0,0 +1,76 @@ +{ + "name": "slim/psr7", + "type": "library", + "description": "Strict PSR-7 implementation", + "keywords": ["psr7","psr-7","http"], + "homepage": "https://www.slimframework.com", + "license": "MIT", + "authors": [ + { + "name": "Josh Lockhart", + "email": "hello@joshlockhart.com", + "homepage": "http://joshlockhart.com" + }, + { + "name": "Andrew Smith", + "email": "a.smith@silentworks.co.uk", + "homepage": "http://silentworks.co.uk" + }, + { + "name": "Rob Allen", + "email": "rob@akrabat.com", + "homepage": "http://akrabat.com" + }, + { + "name": "Pierre Berube", + "email": "pierre@lgse.com", + "homepage": "http://www.lgse.com" + } + ], + "require": { + "php": "^7.4 || ^8.0", + "fig/http-message-util": "^1.1.5", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.0", + "ralouphie/getallheaders": "^3.0", + "symfony/polyfill-php80": "^1.26" + }, + "require-dev": { + "ext-json": "*", + "adriansuter/php-autoload-override": "^1.3", + "http-interop/http-factory-tests": "^0.9.0", + "php-http/psr7-integration-tests": "dev-master", + "phpspec/prophecy": "^1.15", + "phpspec/prophecy-phpunit": "^2.0", + "phpstan/phpstan": "^1.8", + "phpunit/phpunit": "^9.5", + "squizlabs/php_codesniffer": "^3.7" + }, + "provide": { + "psr/http-message-implementation": "1.0", + "psr/http-factory-implementation": "1.0" + }, + "autoload": { + "psr-4": { + "Slim\\Psr7\\": "src" + } + }, + "autoload-dev": { + "psr-4": { + "Slim\\Tests\\Psr7\\": "tests" + } + }, + "scripts": { + "test": [ + "@phpunit", + "@phpcs", + "@phpstan" + ], + "phpunit": "phpunit", + "phpcs": "phpcs", + "phpstan": "phpstan --memory-limit=-1" + }, + "config": { + "sort-packages": true + } +} diff --git a/Sources/API/vendor/slim/psr7/src/Cookies.php b/Sources/API/vendor/slim/psr7/src/Cookies.php new file mode 100644 index 0000000..044d438 --- /dev/null +++ b/Sources/API/vendor/slim/psr7/src/Cookies.php @@ -0,0 +1,218 @@ + '', + 'domain' => null, + 'hostonly' => null, + 'path' => null, + 'expires' => null, + 'secure' => false, + 'httponly' => false, + 'samesite' => null + ]; + + /** + * @param array $cookies + */ + public function __construct(array $cookies = []) + { + $this->requestCookies = $cookies; + } + + /** + * Set default cookie properties + * + * @param array $settings + * + * @return static + */ + public function setDefaults(array $settings): self + { + $this->defaults = array_replace($this->defaults, $settings); + + return $this; + } + + /** + * Get cookie + * + * @param string $name + * @param string|array|null $default + * @return mixed|null + */ + public function get(string $name, $default = null) + { + return array_key_exists($name, $this->requestCookies) ? $this->requestCookies[$name] : $default; + } + + /** + * Set cookie + * + * @param string $name + * @param string|array $value + * @return static + */ + public function set(string $name, $value): self + { + if (!is_array($value)) { + $value = ['value' => $value]; + } + + $this->responseCookies[$name] = array_replace($this->defaults, $value); + + return $this; + } + + /** + * Convert all response cookies into an associate array of header values + * + * @return array + */ + public function toHeaders(): array + { + $headers = []; + + foreach ($this->responseCookies as $name => $properties) { + $headers[] = $this->toHeader($name, $properties); + } + + return $headers; + } + + /** + * Convert to `Set-Cookie` header + * + * @param string $name Cookie name + * @param array $properties Cookie properties + * + * @return string + */ + protected function toHeader(string $name, array $properties): string + { + $result = urlencode($name) . '=' . urlencode($properties['value']); + + if (isset($properties['domain'])) { + $result .= '; domain=' . $properties['domain']; + } + + if (isset($properties['path'])) { + $result .= '; path=' . $properties['path']; + } + + if (isset($properties['expires'])) { + if (is_string($properties['expires'])) { + $timestamp = strtotime($properties['expires']); + } else { + $timestamp = (int) $properties['expires']; + } + if ($timestamp && $timestamp !== 0) { + $result .= '; expires=' . gmdate('D, d-M-Y H:i:s e', $timestamp); + } + } + + if (isset($properties['secure']) && $properties['secure']) { + $result .= '; secure'; + } + + if (isset($properties['hostonly']) && $properties['hostonly']) { + $result .= '; HostOnly'; + } + + if (isset($properties['httponly']) && $properties['httponly']) { + $result .= '; HttpOnly'; + } + + if ( + isset($properties['samesite']) + && in_array(strtolower($properties['samesite']), ['lax', 'strict', 'none'], true) + ) { + // While strtolower is needed for correct comparison, the RFC doesn't care about case + $result .= '; SameSite=' . $properties['samesite']; + } + + return $result; + } + + /** + * Parse cookie values from header value + * + * Returns an associative array of cookie names and values + * + * @param string|array $header + * + * @return array + */ + public static function parseHeader($header): array + { + if (is_array($header)) { + $header = $header[0] ?? ''; + } + + if (!is_string($header)) { + throw new InvalidArgumentException('Cannot parse Cookie data. Header value must be a string.'); + } + + $header = rtrim($header, "\r\n"); + $pieces = preg_split('@[;]\s*@', $header); + $cookies = []; + + if (is_array($pieces)) { + foreach ($pieces as $cookie) { + $cookie = explode('=', $cookie, 2); + + if (count($cookie) === 2) { + $key = urldecode($cookie[0]); + $value = urldecode($cookie[1]); + + if (!isset($cookies[$key])) { + $cookies[$key] = $value; + } + } + } + } + + return $cookies; + } +} diff --git a/Sources/API/vendor/slim/psr7/src/Environment.php b/Sources/API/vendor/slim/psr7/src/Environment.php new file mode 100644 index 0000000..55f187b --- /dev/null +++ b/Sources/API/vendor/slim/psr7/src/Environment.php @@ -0,0 +1,55 @@ + 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', + 'HTTP_ACCEPT_CHARSET' => 'ISO-8859-1,utf-8;q=0.7,*;q=0.3', + 'HTTP_ACCEPT_LANGUAGE' => 'en-US,en;q=0.8', + 'HTTP_USER_AGENT' => 'Slim Framework', + 'QUERY_STRING' => '', + 'REMOTE_ADDR' => '127.0.0.1', + 'REQUEST_METHOD' => 'GET', + 'REQUEST_SCHEME' => $scheme, + 'REQUEST_TIME' => time(), + 'REQUEST_TIME_FLOAT' => microtime(true), + 'REQUEST_URI' => '', + 'SCRIPT_NAME' => '', + 'SERVER_NAME' => 'localhost', + 'SERVER_PORT' => $port, + 'SERVER_PROTOCOL' => 'HTTP/1.1', + ], $data); + } +} diff --git a/Sources/API/vendor/slim/psr7/src/Factory/RequestFactory.php b/Sources/API/vendor/slim/psr7/src/Factory/RequestFactory.php new file mode 100644 index 0000000..e825ee3 --- /dev/null +++ b/Sources/API/vendor/slim/psr7/src/Factory/RequestFactory.php @@ -0,0 +1,59 @@ +streamFactory = $streamFactory ?? new StreamFactory(); + $this->uriFactory = $uriFactory ?? new UriFactory(); + } + + /** + * {@inheritdoc} + */ + public function createRequest(string $method, $uri): RequestInterface + { + if (is_string($uri)) { + $uri = $this->uriFactory->createUri($uri); + } + + if (!$uri instanceof UriInterface) { + throw new InvalidArgumentException( + 'Parameter 2 of RequestFactory::createRequest() must be a string or a compatible UriInterface.' + ); + } + + $body = $this->streamFactory->createStream(); + + return new Request($method, $uri, new Headers(), [], [], $body); + } +} diff --git a/Sources/API/vendor/slim/psr7/src/Factory/ResponseFactory.php b/Sources/API/vendor/slim/psr7/src/Factory/ResponseFactory.php new file mode 100644 index 0000000..c1a23a7 --- /dev/null +++ b/Sources/API/vendor/slim/psr7/src/Factory/ResponseFactory.php @@ -0,0 +1,35 @@ +withStatus($code, $reasonPhrase); + } + + return $res; + } +} diff --git a/Sources/API/vendor/slim/psr7/src/Factory/ServerRequestFactory.php b/Sources/API/vendor/slim/psr7/src/Factory/ServerRequestFactory.php new file mode 100644 index 0000000..5bc2447 --- /dev/null +++ b/Sources/API/vendor/slim/psr7/src/Factory/ServerRequestFactory.php @@ -0,0 +1,110 @@ +streamFactory = $streamFactory ?? new StreamFactory(); + $this->uriFactory = $uriFactory ?? new UriFactory(); + } + + /** + * {@inheritdoc} + */ + public function createServerRequest(string $method, $uri, array $serverParams = []): ServerRequestInterface + { + if (is_string($uri)) { + $uri = $this->uriFactory->createUri($uri); + } + + if (!$uri instanceof UriInterface) { + throw new InvalidArgumentException('URI must either be string or instance of ' . UriInterface::class); + } + + $body = $this->streamFactory->createStream(); + $headers = new Headers(); + $cookies = []; + + if (!empty($serverParams)) { + $headers = Headers::createFromGlobals(); + $cookies = Cookies::parseHeader($headers->getHeader('Cookie', [])); + } + + return new Request($method, $uri, $headers, $cookies, $serverParams, $body); + } + + /** + * Create new ServerRequest from environment. + * + * @internal This method is not part of PSR-17 + * + * @return Request + */ + public static function createFromGlobals(): Request + { + $method = $_SERVER['REQUEST_METHOD'] ?? 'GET'; + $uri = (new UriFactory())->createFromGlobals($_SERVER); + + $headers = Headers::createFromGlobals(); + $cookies = Cookies::parseHeader($headers->getHeader('Cookie', [])); + + // Cache the php://input stream as it cannot be re-read + $cacheResource = fopen('php://temp', 'wb+'); + $cache = $cacheResource ? new Stream($cacheResource) : null; + + $body = (new StreamFactory())->createStreamFromFile('php://input', 'r', $cache); + $uploadedFiles = UploadedFile::createFromGlobals($_SERVER); + + $request = new Request($method, $uri, $headers, $cookies, $_SERVER, $body, $uploadedFiles); + $contentTypes = $request->getHeader('Content-Type'); + + $parsedContentType = ''; + foreach ($contentTypes as $contentType) { + $fragments = explode(';', $contentType); + $parsedContentType = current($fragments); + } + + $contentTypesWithParsedBodies = ['application/x-www-form-urlencoded', 'multipart/form-data']; + if ($method === 'POST' && in_array($parsedContentType, $contentTypesWithParsedBodies)) { + return $request->withParsedBody($_POST); + } + + return $request; + } +} diff --git a/Sources/API/vendor/slim/psr7/src/Factory/StreamFactory.php b/Sources/API/vendor/slim/psr7/src/Factory/StreamFactory.php new file mode 100644 index 0000000..31d99b5 --- /dev/null +++ b/Sources/API/vendor/slim/psr7/src/Factory/StreamFactory.php @@ -0,0 +1,95 @@ +createStreamFromResource($resource); + } + + /** + * {@inheritdoc} + */ + public function createStreamFromFile( + string $filename, + string $mode = 'r', + StreamInterface $cache = null + ): StreamInterface { + set_error_handler( + static function (int $errno, string $errstr) use ($filename, $mode): void { + throw new RuntimeException( + "Unable to open $filename using mode $mode: $errstr", + $errno + ); + } + ); + + try { + $resource = fopen($filename, $mode); + } catch (ValueError $exception) { + throw new RuntimeException("Unable to open $filename using mode $mode: " . $exception->getMessage()); + } finally { + restore_error_handler(); + } + + if (!is_resource($resource)) { + throw new RuntimeException( + "StreamFactory::createStreamFromFile() could not create resource from file `$filename`" + ); + } + + return new Stream($resource, $cache); + } + + /** + * {@inheritdoc} + */ + public function createStreamFromResource($resource, StreamInterface $cache = null): StreamInterface + { + if (!is_resource($resource)) { + throw new InvalidArgumentException( + 'Parameter 1 of StreamFactory::createStreamFromResource() must be a resource.' + ); + } + + return new Stream($resource, $cache); + } +} diff --git a/Sources/API/vendor/slim/psr7/src/Factory/UploadedFileFactory.php b/Sources/API/vendor/slim/psr7/src/Factory/UploadedFileFactory.php new file mode 100644 index 0000000..5699e96 --- /dev/null +++ b/Sources/API/vendor/slim/psr7/src/Factory/UploadedFileFactory.php @@ -0,0 +1,47 @@ +getMetadata('uri'); + + if (!is_string($file) || !$stream->isReadable()) { + throw new InvalidArgumentException('File is not readable.'); + } + + if ($size === null) { + $size = $stream->getSize(); + } + + return new UploadedFile($stream, $clientFilename, $clientMediaType, $size, $error); + } +} diff --git a/Sources/API/vendor/slim/psr7/src/Factory/UriFactory.php b/Sources/API/vendor/slim/psr7/src/Factory/UriFactory.php new file mode 100644 index 0000000..74ab377 --- /dev/null +++ b/Sources/API/vendor/slim/psr7/src/Factory/UriFactory.php @@ -0,0 +1,113 @@ + 1) { + $queryString = parse_url('https://www.example.com' . $globals['REQUEST_URI'], PHP_URL_QUERY) ?? ''; + } + } + + // Build Uri and return + return new Uri($scheme, $host, $port, $requestUri, $queryString, '', $username, $password); + } +} diff --git a/Sources/API/vendor/slim/psr7/src/Header.php b/Sources/API/vendor/slim/psr7/src/Header.php new file mode 100644 index 0000000..ecdad32 --- /dev/null +++ b/Sources/API/vendor/slim/psr7/src/Header.php @@ -0,0 +1,96 @@ +originalName = $originalName; + $this->normalizedName = $normalizedName; + $this->values = $values; + } + + /** + * @return string + */ + public function getOriginalName(): string + { + return $this->originalName; + } + + /** + * @return string + */ + public function getNormalizedName(): string + { + return $this->normalizedName; + } + + /** + * @param string $value + * + * @return self + */ + public function addValue(string $value): self + { + $this->values[] = $value; + + return $this; + } + + /** + * @param array|string $values + * + * @return self + */ + public function addValues($values): self + { + if (is_string($values)) { + return $this->addValue($values); + } + + if (!is_array($values)) { + throw new InvalidArgumentException('Parameter 1 of Header::addValues() should be a string or an array.'); + } + + $this->values = array_merge($this->values, $values); + + return $this; + } + + /** + * @return array + */ + public function getValues(): array + { + return $this->values; + } +} diff --git a/Sources/API/vendor/slim/psr7/src/Headers.php b/Sources/API/vendor/slim/psr7/src/Headers.php new file mode 100644 index 0000000..038e792 --- /dev/null +++ b/Sources/API/vendor/slim/psr7/src/Headers.php @@ -0,0 +1,318 @@ +globals = $globals ?? $_SERVER; + $this->setHeaders($headers); + } + + /** + * {@inheritdoc} + */ + public function addHeader($name, $value): HeadersInterface + { + [$values, $originalName, $normalizedName] = $this->prepareHeader($name, $value); + + if (isset($this->headers[$normalizedName])) { + $header = $this->headers[$normalizedName]; + $header->addValues($values); + } else { + $this->headers[$normalizedName] = new Header($originalName, $normalizedName, $values); + } + + return $this; + } + + /** + * {@inheritdoc} + */ + public function removeHeader(string $name): HeadersInterface + { + $name = $this->normalizeHeaderName($name); + unset($this->headers[$name]); + return $this; + } + + /** + * {@inheritdoc} + */ + public function getHeader(string $name, $default = []): array + { + $name = $this->normalizeHeaderName($name); + + if (isset($this->headers[$name])) { + $header = $this->headers[$name]; + return $header->getValues(); + } + + if (empty($default)) { + return $default; + } + + $this->validateHeader($name, $default); + return $this->trimHeaderValue($default); + } + + /** + * {@inheritdoc} + */ + public function setHeader($name, $value): HeadersInterface + { + [$values, $originalName, $normalizedName] = $this->prepareHeader($name, $value); + + // Ensure we preserve original case if the header already exists in the stack + if (isset($this->headers[$normalizedName])) { + $existingHeader = $this->headers[$normalizedName]; + $originalName = $existingHeader->getOriginalName(); + } + + $this->headers[$normalizedName] = new Header($originalName, $normalizedName, $values); + + return $this; + } + + /** + * {@inheritdoc} + */ + public function setHeaders(array $headers): HeadersInterface + { + $this->headers = []; + + foreach ($this->parseAuthorizationHeader($headers) as $name => $value) { + $this->addHeader($name, $value); + } + + return $this; + } + + /** + * {@inheritdoc} + */ + public function hasHeader(string $name): bool + { + $name = $this->normalizeHeaderName($name); + return isset($this->headers[$name]); + } + + /** + * {@inheritdoc} + */ + public function getHeaders(bool $originalCase = false): array + { + $headers = []; + + foreach ($this->headers as $header) { + $name = $originalCase ? $header->getOriginalName() : $header->getNormalizedName(); + $headers[$name] = $header->getValues(); + } + + return $headers; + } + + /** + * @param string $name + * @param bool $preserveCase + * @return string + */ + protected function normalizeHeaderName(string $name, bool $preserveCase = false): string + { + $name = strtr($name, '_', '-'); + + if (!$preserveCase) { + $name = strtolower($name); + } + + if (strpos(strtolower($name), 'http-') === 0) { + $name = substr($name, 5); + } + + return $name; + } + + /** + * Parse incoming headers and determine Authorization header from original headers + * + * @param array $headers + * @return array + */ + protected function parseAuthorizationHeader(array $headers): array + { + $hasAuthorizationHeader = false; + foreach ($headers as $name => $value) { + if (strtolower((string) $name) === 'authorization') { + $hasAuthorizationHeader = true; + break; + } + } + + if (!$hasAuthorizationHeader) { + if (isset($this->globals['REDIRECT_HTTP_AUTHORIZATION'])) { + $headers['Authorization'] = $this->globals['REDIRECT_HTTP_AUTHORIZATION']; + } elseif (isset($this->globals['PHP_AUTH_USER'])) { + $pw = $this->globals['PHP_AUTH_PW'] ?? ''; + $headers['Authorization'] = 'Basic ' . base64_encode($this->globals['PHP_AUTH_USER'] . ':' . $pw); + } elseif (isset($this->globals['PHP_AUTH_DIGEST'])) { + $headers['Authorization'] = $this->globals['PHP_AUTH_DIGEST']; + } + } + + return $headers; + } + + /** + * @param array|string $value + * + * @return array + */ + protected function trimHeaderValue($value): array + { + $items = is_array($value) ? $value : [$value]; + $result = []; + foreach ($items as $item) { + $result[] = trim((string) $item, " \t"); + } + return $result; + } + + /** + * @param string $name + * @param array|string $value + * + * @throws InvalidArgumentException + * + * @return array + */ + protected function prepareHeader($name, $value): array + { + $this->validateHeader($name, $value); + $values = $this->trimHeaderValue($value); + $originalName = $this->normalizeHeaderName($name, true); + $normalizedName = $this->normalizeHeaderName($name); + return [$values, $originalName, $normalizedName]; + } + + /** + * Make sure the header complies with RFC 7230. + * + * Header names must be a non-empty string consisting of token characters. + * + * Header values must be strings consisting of visible characters with all optional + * leading and trailing whitespace stripped. This method will always strip such + * optional whitespace. Note that the method does not allow folding whitespace within + * the values as this was deprecated for almost all instances by the RFC. + * + * header-field = field-name ":" OWS field-value OWS + * field-name = 1*( "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "." / "^" + * / "_" / "`" / "|" / "~" / %x30-39 / ( %x41-5A / %x61-7A ) ) + * OWS = *( SP / HTAB ) + * field-value = *( ( %x21-7E / %x80-FF ) [ 1*( SP / HTAB ) ( %x21-7E / %x80-FF ) ] ) + * + * @see https://tools.ietf.org/html/rfc7230#section-3.2.4 + * + * @param string $name + * @param array|string $value + * + * @throws InvalidArgumentException; + */ + protected function validateHeader($name, $value): void + { + $this->validateHeaderName($name); + $this->validateHeaderValue($value); + } + + /** + * @param mixed $name + * + * @throws InvalidArgumentException + */ + protected function validateHeaderName($name): void + { + if (!is_string($name) || preg_match("@^[!#$%&'*+.^_`|~0-9A-Za-z-]+$@", $name) !== 1) { + throw new InvalidArgumentException('Header name must be an RFC 7230 compatible string.'); + } + } + + /** + * @param mixed $value + * + * @throws InvalidArgumentException + */ + protected function validateHeaderValue($value): void + { + $items = is_array($value) ? $value : [$value]; + + if (empty($items)) { + throw new InvalidArgumentException( + 'Header values must be a string or an array of strings, empty array given.' + ); + } + + $pattern = "@^[ \t\x21-\x7E\x80-\xFF]*$@"; + foreach ($items as $item) { + $hasInvalidType = !is_numeric($item) && !is_string($item); + $rejected = $hasInvalidType || preg_match($pattern, (string) $item) !== 1; + if ($rejected) { + throw new InvalidArgumentException( + 'Header values must be RFC 7230 compatible strings.' + ); + } + } + } + + /** + * @return static + */ + public static function createFromGlobals() + { + $headers = null; + + if (function_exists('getallheaders')) { + $headers = getallheaders(); + } + + if (!is_array($headers)) { + $headers = []; + } + + return new static($headers); + } +} diff --git a/Sources/API/vendor/slim/psr7/src/Interfaces/HeadersInterface.php b/Sources/API/vendor/slim/psr7/src/Interfaces/HeadersInterface.php new file mode 100644 index 0000000..3f486f1 --- /dev/null +++ b/Sources/API/vendor/slim/psr7/src/Interfaces/HeadersInterface.php @@ -0,0 +1,90 @@ + true, + '1.1' => true, + '2.0' => true, + '2' => true, + ]; + + /** + * @var HeadersInterface + */ + protected $headers; + + /** + * @var StreamInterface + */ + protected $body; + + /** + * Disable magic setter to ensure immutability + * + * @param string $name The property name + * @param mixed $value The property value + * + * @return void + */ + public function __set($name, $value): void + { + // Do nothing + } + + /** + * {@inheritdoc} + */ + public function getProtocolVersion(): string + { + return $this->protocolVersion; + } + + /** + * @return static + * {@inheritdoc} + */ + public function withProtocolVersion($version) + { + if (!isset(self::$validProtocolVersions[$version])) { + throw new InvalidArgumentException( + 'Invalid HTTP version. Must be one of: ' + . implode(', ', array_keys(self::$validProtocolVersions)) + ); + } + + $clone = clone $this; + $clone->protocolVersion = $version; + + return $clone; + } + + /** + * {@inheritdoc} + */ + public function getHeaders(): array + { + return $this->headers->getHeaders(true); + } + + /** + * {@inheritdoc} + */ + public function hasHeader($name): bool + { + return $this->headers->hasHeader($name); + } + + /** + * {@inheritdoc} + */ + public function getHeader($name): array + { + return $this->headers->getHeader($name); + } + + /** + * {@inheritdoc} + */ + public function getHeaderLine($name): string + { + $values = $this->headers->getHeader($name); + return implode(',', $values); + } + + /** + * @return static + * {@inheritdoc} + */ + public function withHeader($name, $value) + { + $clone = clone $this; + $clone->headers->setHeader($name, $value); + + if ($this instanceof Response && $this->body instanceof NonBufferedBody) { + header(sprintf('%s: %s', $name, $clone->getHeaderLine($name))); + } + + return $clone; + } + + /** + * @return static + * {@inheritdoc} + */ + public function withAddedHeader($name, $value) + { + $clone = clone $this; + $clone->headers->addHeader($name, $value); + + if ($this instanceof Response && $this->body instanceof NonBufferedBody) { + header(sprintf('%s: %s', $name, $clone->getHeaderLine($name))); + } + + return $clone; + } + + /** + * @return static + * {@inheritdoc} + */ + public function withoutHeader($name) + { + $clone = clone $this; + $clone->headers->removeHeader($name); + + if ($this instanceof Response && $this->body instanceof NonBufferedBody) { + header_remove($name); + } + + return $clone; + } + + /** + * {@inheritdoc} + */ + public function getBody(): StreamInterface + { + return $this->body; + } + + /** + * @return static + * {@inheritdoc} + */ + public function withBody(StreamInterface $body) + { + $clone = clone $this; + $clone->body = $body; + + return $clone; + } +} diff --git a/Sources/API/vendor/slim/psr7/src/NonBufferedBody.php b/Sources/API/vendor/slim/psr7/src/NonBufferedBody.php new file mode 100644 index 0000000..ad22c2d --- /dev/null +++ b/Sources/API/vendor/slim/psr7/src/NonBufferedBody.php @@ -0,0 +1,153 @@ +method = $this->filterMethod($method); + $this->uri = $uri; + $this->headers = $headers; + $this->cookies = $cookies; + $this->serverParams = $serverParams; + $this->attributes = []; + $this->body = $body; + $this->uploadedFiles = $uploadedFiles; + + if (isset($serverParams['SERVER_PROTOCOL'])) { + $this->protocolVersion = str_replace('HTTP/', '', $serverParams['SERVER_PROTOCOL']); + } + + if (!$this->headers->hasHeader('Host') || $this->uri->getHost() !== '') { + $this->headers->setHeader('Host', $this->uri->getHost()); + } + } + + /** + * This method is applied to the cloned object after PHP performs an initial shallow-copy. + * This method completes a deep-copy by creating new objects for the cloned object's internal reference pointers. + */ + public function __clone() + { + $this->headers = clone $this->headers; + $this->body = clone $this->body; + } + + /** + * {@inheritdoc} + */ + public function getMethod(): string + { + return $this->method; + } + + /** + * {@inheritdoc} + * @return static + */ + public function withMethod($method) + { + $method = $this->filterMethod($method); + $clone = clone $this; + $clone->method = $method; + + return $clone; + } + + /** + * Validate the HTTP method + * + * @param string $method + * + * @return string + * + * @throws InvalidArgumentException on invalid HTTP method. + */ + protected function filterMethod($method): string + { + /** @var mixed $method */ + if (!is_string($method)) { + throw new InvalidArgumentException(sprintf( + 'Unsupported HTTP method; must be a string, received %s', + (is_object($method) ? get_class($method) : gettype($method)) + )); + } + + if (preg_match("/^[!#$%&'*+.^_`|~0-9a-z-]+$/i", $method) !== 1) { + throw new InvalidArgumentException(sprintf( + 'Unsupported HTTP method "%s" provided', + $method + )); + } + + return $method; + } + + /** + * {@inheritdoc} + */ + public function getRequestTarget(): string + { + if ($this->requestTarget) { + return $this->requestTarget; + } + + if ($this->uri === null) { + return '/'; + } + + $path = $this->uri->getPath(); + $path = '/' . ltrim($path, '/'); + + $query = $this->uri->getQuery(); + if ($query) { + $path .= '?' . $query; + } + + return $path; + } + + /** + * {@inheritdoc} + * @return static + */ + public function withRequestTarget($requestTarget) + { + if (!is_string($requestTarget) || preg_match('#\s#', $requestTarget)) { + throw new InvalidArgumentException( + 'Invalid request target provided; must be a string and cannot contain whitespace' + ); + } + + $clone = clone $this; + $clone->requestTarget = $requestTarget; + + return $clone; + } + + /** + * {@inheritdoc} + */ + public function getUri(): UriInterface + { + return $this->uri; + } + + /** + * {@inheritdoc} + * @return static + */ + public function withUri(UriInterface $uri, $preserveHost = false) + { + $clone = clone $this; + $clone->uri = $uri; + + if (!$preserveHost && $uri->getHost() !== '') { + $clone->headers->setHeader('Host', $uri->getHost()); + return $clone; + } + + if (($uri->getHost() !== '' && !$this->hasHeader('Host') || $this->getHeaderLine('Host') === '')) { + $clone->headers->setHeader('Host', $uri->getHost()); + return $clone; + } + + return $clone; + } + + /** + * {@inheritdoc} + */ + public function getCookieParams(): array + { + return $this->cookies; + } + + /** + * {@inheritdoc} + * @return static + */ + public function withCookieParams(array $cookies) + { + $clone = clone $this; + $clone->cookies = $cookies; + + return $clone; + } + + /** + * {@inheritdoc} + */ + public function getQueryParams(): array + { + if (is_array($this->queryParams)) { + return $this->queryParams; + } + + if ($this->uri === null) { + return []; + } + + parse_str($this->uri->getQuery(), $this->queryParams); // <-- URL decodes data + assert(is_array($this->queryParams)); + + return $this->queryParams; + } + + /** + * {@inheritdoc} + * @return static + */ + public function withQueryParams(array $query) + { + $clone = clone $this; + $clone->queryParams = $query; + + return $clone; + } + + /** + * {@inheritdoc} + */ + public function getUploadedFiles(): array + { + return $this->uploadedFiles; + } + + /** + * {@inheritdoc} + * @return static + */ + public function withUploadedFiles(array $uploadedFiles) + { + $clone = clone $this; + $clone->uploadedFiles = $uploadedFiles; + + return $clone; + } + + /** + * {@inheritdoc} + */ + public function getServerParams(): array + { + return $this->serverParams; + } + + /** + * {@inheritdoc} + */ + public function getAttributes(): array + { + return $this->attributes; + } + + /** + * {@inheritdoc} + * @return mixed + */ + public function getAttribute($name, $default = null) + { + return $this->attributes[$name] ?? $default; + } + + /** + * {@inheritdoc} + * @return static + */ + public function withAttribute($name, $value) + { + $clone = clone $this; + $clone->attributes[$name] = $value; + + return $clone; + } + + /** + * {@inheritdoc} + * @return static + */ + public function withoutAttribute($name) + { + $clone = clone $this; + + unset($clone->attributes[$name]); + + return $clone; + } + + /** + * {@inheritdoc} + */ + public function getParsedBody() + { + return $this->parsedBody; + } + + /** + * {@inheritdoc} + * @return static + */ + public function withParsedBody($data) + { + /** @var mixed $data */ + if (!is_null($data) && !is_object($data) && !is_array($data)) { + throw new InvalidArgumentException('Parsed body value must be an array, an object, or null'); + } + + $clone = clone $this; + $clone->parsedBody = $data; + + return $clone; + } +} diff --git a/Sources/API/vendor/slim/psr7/src/Response.php b/Sources/API/vendor/slim/psr7/src/Response.php new file mode 100644 index 0000000..c6d4c6e --- /dev/null +++ b/Sources/API/vendor/slim/psr7/src/Response.php @@ -0,0 +1,216 @@ + 'Continue', + StatusCodeInterface::STATUS_SWITCHING_PROTOCOLS => 'Switching Protocols', + StatusCodeInterface::STATUS_PROCESSING => 'Processing', + + // Successful 2xx + StatusCodeInterface::STATUS_OK => 'OK', + StatusCodeInterface::STATUS_CREATED => 'Created', + StatusCodeInterface::STATUS_ACCEPTED => 'Accepted', + StatusCodeInterface::STATUS_NON_AUTHORITATIVE_INFORMATION => 'Non-Authoritative Information', + StatusCodeInterface::STATUS_NO_CONTENT => 'No Content', + StatusCodeInterface::STATUS_RESET_CONTENT => 'Reset Content', + StatusCodeInterface::STATUS_PARTIAL_CONTENT => 'Partial Content', + StatusCodeInterface::STATUS_MULTI_STATUS => 'Multi-Status', + StatusCodeInterface::STATUS_ALREADY_REPORTED => 'Already Reported', + StatusCodeInterface::STATUS_IM_USED => 'IM Used', + + // Redirection 3xx + StatusCodeInterface::STATUS_MULTIPLE_CHOICES => 'Multiple Choices', + StatusCodeInterface::STATUS_MOVED_PERMANENTLY => 'Moved Permanently', + StatusCodeInterface::STATUS_FOUND => 'Found', + StatusCodeInterface::STATUS_SEE_OTHER => 'See Other', + StatusCodeInterface::STATUS_NOT_MODIFIED => 'Not Modified', + StatusCodeInterface::STATUS_USE_PROXY => 'Use Proxy', + StatusCodeInterface::STATUS_RESERVED => '(Unused)', + StatusCodeInterface::STATUS_TEMPORARY_REDIRECT => 'Temporary Redirect', + StatusCodeInterface::STATUS_PERMANENT_REDIRECT => 'Permanent Redirect', + + // Client Error 4xx + StatusCodeInterface::STATUS_BAD_REQUEST => 'Bad Request', + StatusCodeInterface::STATUS_UNAUTHORIZED => 'Unauthorized', + StatusCodeInterface::STATUS_PAYMENT_REQUIRED => 'Payment Required', + StatusCodeInterface::STATUS_FORBIDDEN => 'Forbidden', + StatusCodeInterface::STATUS_NOT_FOUND => 'Not Found', + StatusCodeInterface::STATUS_METHOD_NOT_ALLOWED => 'Method Not Allowed', + StatusCodeInterface::STATUS_NOT_ACCEPTABLE => 'Not Acceptable', + StatusCodeInterface::STATUS_PROXY_AUTHENTICATION_REQUIRED => 'Proxy Authentication Required', + StatusCodeInterface::STATUS_REQUEST_TIMEOUT => 'Request Timeout', + StatusCodeInterface::STATUS_CONFLICT => 'Conflict', + StatusCodeInterface::STATUS_GONE => 'Gone', + StatusCodeInterface::STATUS_LENGTH_REQUIRED => 'Length Required', + StatusCodeInterface::STATUS_PRECONDITION_FAILED => 'Precondition Failed', + StatusCodeInterface::STATUS_PAYLOAD_TOO_LARGE => 'Request Entity Too Large', + StatusCodeInterface::STATUS_URI_TOO_LONG => 'Request-URI Too Long', + StatusCodeInterface::STATUS_UNSUPPORTED_MEDIA_TYPE => 'Unsupported Media Type', + StatusCodeInterface::STATUS_RANGE_NOT_SATISFIABLE => 'Requested Range Not Satisfiable', + StatusCodeInterface::STATUS_EXPECTATION_FAILED => 'Expectation Failed', + StatusCodeInterface::STATUS_IM_A_TEAPOT => 'I\'m a teapot', + StatusCodeInterface::STATUS_MISDIRECTED_REQUEST => 'Misdirected Request', + StatusCodeInterface::STATUS_UNPROCESSABLE_ENTITY => 'Unprocessable Entity', + StatusCodeInterface::STATUS_LOCKED => 'Locked', + StatusCodeInterface::STATUS_FAILED_DEPENDENCY => 'Failed Dependency', + StatusCodeInterface::STATUS_UPGRADE_REQUIRED => 'Upgrade Required', + StatusCodeInterface::STATUS_PRECONDITION_REQUIRED => 'Precondition Required', + StatusCodeInterface::STATUS_TOO_MANY_REQUESTS => 'Too Many Requests', + StatusCodeInterface::STATUS_REQUEST_HEADER_FIELDS_TOO_LARGE => 'Request Header Fields Too Large', + 444 => 'Connection Closed Without Response', + StatusCodeInterface::STATUS_UNAVAILABLE_FOR_LEGAL_REASONS => 'Unavailable For Legal Reasons', + 499 => 'Client Closed Request', + + // Server Error 5xx + StatusCodeInterface::STATUS_INTERNAL_SERVER_ERROR => 'Internal Server Error', + StatusCodeInterface::STATUS_NOT_IMPLEMENTED => 'Not Implemented', + StatusCodeInterface::STATUS_BAD_GATEWAY => 'Bad Gateway', + StatusCodeInterface::STATUS_SERVICE_UNAVAILABLE => 'Service Unavailable', + StatusCodeInterface::STATUS_GATEWAY_TIMEOUT => 'Gateway Timeout', + StatusCodeInterface::STATUS_VERSION_NOT_SUPPORTED => 'HTTP Version Not Supported', + StatusCodeInterface::STATUS_VARIANT_ALSO_NEGOTIATES => 'Variant Also Negotiates', + StatusCodeInterface::STATUS_INSUFFICIENT_STORAGE => 'Insufficient Storage', + StatusCodeInterface::STATUS_LOOP_DETECTED => 'Loop Detected', + StatusCodeInterface::STATUS_NOT_EXTENDED => 'Not Extended', + StatusCodeInterface::STATUS_NETWORK_AUTHENTICATION_REQUIRED => 'Network Authentication Required', + 599 => 'Network Connect Timeout Error', + ]; + + /** + * @param int $status The response status code. + * @param HeadersInterface|null $headers The response headers. + * @param StreamInterface|null $body The response body. + */ + public function __construct( + int $status = StatusCodeInterface::STATUS_OK, + ?HeadersInterface $headers = null, + ?StreamInterface $body = null + ) { + $this->status = $this->filterStatus($status); + $this->headers = $headers ?: new Headers([], []); + $this->body = $body ?: (new StreamFactory())->createStream(); + } + + /** + * This method is applied to the cloned object after PHP performs an initial shallow-copy. + * This method completes a deep-copy by creating new objects for the cloned object's internal reference pointers. + */ + public function __clone() + { + $this->headers = clone $this->headers; + } + + /** + * {@inheritdoc} + */ + public function getStatusCode(): int + { + return $this->status; + } + + /** + * {@inheritdoc} + * @return static + */ + public function withStatus($code, $reasonPhrase = '') + { + $code = $this->filterStatus($code); + $reasonPhrase = $this->filterReasonPhrase($reasonPhrase); + + $clone = clone $this; + $clone->status = $code; + $clone->reasonPhrase = $reasonPhrase; + + return $clone; + } + + /** + * {@inheritdoc} + */ + public function getReasonPhrase(): string + { + if ($this->reasonPhrase !== '') { + return $this->reasonPhrase; + } + + if (isset(static::$messages[$this->status])) { + return static::$messages[$this->status]; + } + + return ''; + } + + /** + * Filter HTTP status code. + * + * @param int $status HTTP status code. + * + * @return int + * + * @throws InvalidArgumentException If an invalid HTTP status code is provided. + */ + protected function filterStatus($status): int + { + if (!is_integer($status) || $status < StatusCodeInterface::STATUS_CONTINUE || $status > 599) { + throw new InvalidArgumentException('Invalid HTTP status code.'); + } + + return $status; + } + + /** + * Filter Reason Phrase + * + * @param mixed $reasonPhrase + * + * @return string + * + * @throws InvalidArgumentException + */ + protected function filterReasonPhrase($reasonPhrase = ''): string + { + if (is_object($reasonPhrase) && method_exists($reasonPhrase, '__toString')) { + $reasonPhrase = (string) $reasonPhrase; + } + + if (!is_string($reasonPhrase)) { + throw new InvalidArgumentException('Response reason phrase must be a string.'); + } + + if (strpos($reasonPhrase, "\r") !== false || strpos($reasonPhrase, "\n") !== false) { + throw new InvalidArgumentException( + 'Reason phrase contains one of the following prohibited characters: \r \n' + ); + } + + return $reasonPhrase; + } +} diff --git a/Sources/API/vendor/slim/psr7/src/Stream.php b/Sources/API/vendor/slim/psr7/src/Stream.php new file mode 100644 index 0000000..9de6685 --- /dev/null +++ b/Sources/API/vendor/slim/psr7/src/Stream.php @@ -0,0 +1,396 @@ +attach($stream); + + if ($cache && (!$cache->isSeekable() || !$cache->isWritable())) { + throw new RuntimeException('Cache stream must be seekable and writable'); + } + $this->cache = $cache; + } + + /** + * {@inheritdoc} + * @return array|mixed + */ + public function getMetadata($key = null) + { + if (!$this->stream) { + return null; + } + + $this->meta = stream_get_meta_data($this->stream); + + if (!$key) { + return $this->meta; + } + + return $this->meta[$key] ?? null; + } + + /** + * Attach new resource to this object. + * + * @internal This method is not part of the PSR-7 standard. + * + * @param resource $stream A PHP resource handle. + * + * @throws InvalidArgumentException If argument is not a valid PHP resource. + * + * @return void + */ + protected function attach($stream): void + { + if (!is_resource($stream)) { + throw new InvalidArgumentException(__METHOD__ . ' argument must be a valid PHP resource'); + } + + if ($this->stream) { + $this->detach(); + } + + $this->stream = $stream; + } + + /** + * {@inheritdoc} + */ + public function detach() + { + $oldResource = $this->stream; + $this->stream = null; + $this->meta = null; + $this->readable = null; + $this->writable = null; + $this->seekable = null; + $this->size = null; + $this->isPipe = null; + + $this->cache = null; + $this->finished = false; + + return $oldResource; + } + + /** + * {@inheritdoc} + */ + public function __toString(): string + { + if (!$this->stream) { + return ''; + } + if ($this->cache && $this->finished) { + $this->cache->rewind(); + return $this->cache->getContents(); + } + if ($this->isSeekable()) { + $this->rewind(); + } + return $this->getContents(); + } + + /** + * {@inheritdoc} + */ + public function close(): void + { + if ($this->stream) { + if ($this->isPipe()) { + pclose($this->stream); + } else { + fclose($this->stream); + } + } + + $this->detach(); + } + + /** + * {@inheritdoc} + */ + public function getSize(): ?int + { + if ($this->stream && !$this->size) { + $stats = fstat($this->stream); + + if ($stats) { + $this->size = !$this->isPipe() ? $stats['size'] : null; + } + } + + return $this->size; + } + + /** + * {@inheritdoc} + */ + public function tell(): int + { + $position = false; + + if ($this->stream) { + $position = ftell($this->stream); + } + + if ($position === false || $this->isPipe()) { + throw new RuntimeException('Could not get the position of the pointer in stream.'); + } + + return $position; + } + + /** + * {@inheritdoc} + */ + public function eof(): bool + { + return !$this->stream || feof($this->stream); + } + + /** + * {@inheritdoc} + */ + public function isReadable(): bool + { + if ($this->readable !== null) { + return $this->readable; + } + + $this->readable = false; + + if ($this->stream) { + $mode = $this->getMetadata('mode'); + + if (is_string($mode) && (strstr($mode, 'r') !== false || strstr($mode, '+') !== false)) { + $this->readable = true; + } + } + + return $this->readable; + } + + /** + * {@inheritdoc} + */ + public function isWritable(): bool + { + if ($this->writable === null) { + $this->writable = false; + + if ($this->stream) { + $mode = $this->getMetadata('mode'); + + if (is_string($mode) && (strstr($mode, 'w') !== false || strstr($mode, '+') !== false)) { + $this->writable = true; + } + } + } + + return $this->writable; + } + + /** + * {@inheritdoc} + */ + public function isSeekable(): bool + { + if ($this->seekable === null) { + $this->seekable = false; + + if ($this->stream) { + $this->seekable = !$this->isPipe() && $this->getMetadata('seekable'); + } + } + + return $this->seekable; + } + + /** + * {@inheritdoc} + */ + public function seek($offset, $whence = SEEK_SET): void + { + if (!$this->isSeekable() || $this->stream && fseek($this->stream, $offset, $whence) === -1) { + throw new RuntimeException('Could not seek in stream.'); + } + } + + /** + * {@inheritdoc} + */ + public function rewind(): void + { + if (!$this->isSeekable() || $this->stream && rewind($this->stream) === false) { + throw new RuntimeException('Could not rewind stream.'); + } + } + + /** + * {@inheritdoc} + */ + public function read($length): string + { + $data = false; + + if ($this->isReadable() && $this->stream && $length >= 0) { + $data = fread($this->stream, $length); + } + + if (is_string($data)) { + if ($this->cache) { + $this->cache->write($data); + } + if ($this->eof()) { + $this->finished = true; + } + return $data; + } + + throw new RuntimeException('Could not read from stream.'); + } + + /** + * {@inheritdoc} + * @return int + */ + public function write($string) + { + $written = false; + + if ($this->isWritable() && $this->stream) { + $written = fwrite($this->stream, $string); + } + + if ($written !== false) { + $this->size = null; + return $written; + } + + throw new RuntimeException('Could not write to stream.'); + } + + /** + * {@inheritdoc} + */ + public function getContents(): string + { + if ($this->cache && $this->finished) { + $this->cache->rewind(); + return $this->cache->getContents(); + } + + $contents = false; + + if ($this->stream) { + $contents = stream_get_contents($this->stream); + } + + if (is_string($contents)) { + if ($this->cache) { + $this->cache->write($contents); + } + if ($this->eof()) { + $this->finished = true; + } + return $contents; + } + + throw new RuntimeException('Could not get contents of stream.'); + } + + /** + * Returns whether or not the stream is a pipe. + * + * @internal This method is not part of the PSR-7 standard. + * + * @return bool + */ + public function isPipe(): bool + { + if ($this->isPipe === null) { + $this->isPipe = false; + + if ($this->stream) { + $stats = fstat($this->stream); + + if (is_array($stats)) { + $this->isPipe = ($stats['mode'] & self::FSTAT_MODE_S_IFIFO) !== 0; + } + } + } + + return $this->isPipe; + } +} diff --git a/Sources/API/vendor/slim/psr7/src/UploadedFile.php b/Sources/API/vendor/slim/psr7/src/UploadedFile.php new file mode 100644 index 0000000..b0c4df5 --- /dev/null +++ b/Sources/API/vendor/slim/psr7/src/UploadedFile.php @@ -0,0 +1,279 @@ +getMetadata('uri'); + if (!is_string($file)) { + throw new InvalidArgumentException('No URI associated with the stream.'); + } + $this->file = $file; + $this->stream = $fileNameOrStream; + } elseif (is_string($fileNameOrStream)) { + $this->file = $fileNameOrStream; + } else { + throw new InvalidArgumentException( + 'Please provide a string (full path to the uploaded file) or an instance of StreamInterface.' + ); + } + $this->name = $name; + $this->type = $type; + $this->size = $size; + $this->error = $error; + $this->sapi = $sapi; + } + + /** + * {@inheritdoc} + * @return StreamInterface + */ + public function getStream() + { + if ($this->moved) { + throw new RuntimeException(sprintf('Uploaded file %s has already been moved', $this->name)); + } + + if (!$this->stream) { + $this->stream = (new StreamFactory())->createStreamFromFile($this->file); + } + + return $this->stream; + } + + /** + * {@inheritdoc} + */ + public function moveTo($targetPath): void + { + if ($this->moved) { + throw new RuntimeException('Uploaded file already moved'); + } + + $targetIsStream = strpos($targetPath, '://') > 0; + if (!$targetIsStream && !is_writable(dirname($targetPath))) { + throw new InvalidArgumentException('Upload target path is not writable'); + } + + if ($targetIsStream) { + if (!copy($this->file, $targetPath)) { + throw new RuntimeException(sprintf('Error moving uploaded file %s to %s', $this->name, $targetPath)); + } + + if (!unlink($this->file)) { + throw new RuntimeException(sprintf('Error removing uploaded file %s', $this->name)); + } + } elseif ($this->sapi) { + if (!is_uploaded_file($this->file)) { + throw new RuntimeException(sprintf('%s is not a valid uploaded file', $this->file)); + } + + if (!move_uploaded_file($this->file, $targetPath)) { + throw new RuntimeException(sprintf('Error moving uploaded file %s to %s', $this->name, $targetPath)); + } + } else { + if (!rename($this->file, $targetPath)) { + throw new RuntimeException(sprintf('Error moving uploaded file %s to %s', $this->name, $targetPath)); + } + } + + $this->moved = true; + } + + /** + * {@inheritdoc} + */ + public function getError(): int + { + return $this->error; + } + + /** + * {@inheritdoc} + */ + public function getClientFilename(): ?string + { + return $this->name; + } + + /** + * {@inheritdoc} + */ + public function getClientMediaType(): ?string + { + return $this->type; + } + + /** + * {@inheritdoc} + */ + public function getSize(): ?int + { + return $this->size; + } + + /** + * Returns the client-provided full path to the file + * + * @internal This method is not part of the PSR-7 standard + * + * @return string + */ + public function getFilePath(): string + { + return $this->file; + } + + /** + * Create a normalized tree of UploadedFile instances from the Environment. + * + * @internal This method is not part of the PSR-7 standard. + * + * @param array $globals The global server variables. + * + * @return array A normalized tree of UploadedFile instances or null if none are provided. + */ + public static function createFromGlobals(array $globals): array + { + if (isset($globals['slim.files']) && is_array($globals['slim.files'])) { + return $globals['slim.files']; + } + + if (!empty($_FILES)) { + return self::parseUploadedFiles($_FILES); + } + + return []; + } + + /** + * Parse a non-normalized, i.e. $_FILES superglobal, tree of uploaded file data. + * + * @internal This method is not part of the PSR-7 standard. + * + * @param array $uploadedFiles The non-normalized tree of uploaded file data. + * + * @return array A normalized tree of UploadedFile instances. + */ + private static function parseUploadedFiles(array $uploadedFiles): array + { + $parsed = []; + foreach ($uploadedFiles as $field => $uploadedFile) { + if (!isset($uploadedFile['error'])) { + if (is_array($uploadedFile)) { + $parsed[$field] = self::parseUploadedFiles($uploadedFile); + } + continue; + } + + $parsed[$field] = []; + if (!is_array($uploadedFile['error'])) { + $parsed[$field] = new static( + $uploadedFile['tmp_name'], + $uploadedFile['name'] ?? null, + $uploadedFile['type'] ?? null, + $uploadedFile['size'] ?? null, + $uploadedFile['error'], + true + ); + } else { + $subArray = []; + foreach ($uploadedFile['error'] as $fileIdx => $error) { + // Normalize sub array and re-parse to move the input's key name up a level + $subArray[$fileIdx]['name'] = $uploadedFile['name'][$fileIdx]; + $subArray[$fileIdx]['type'] = $uploadedFile['type'][$fileIdx]; + $subArray[$fileIdx]['tmp_name'] = $uploadedFile['tmp_name'][$fileIdx]; + $subArray[$fileIdx]['error'] = $uploadedFile['error'][$fileIdx]; + $subArray[$fileIdx]['size'] = $uploadedFile['size'][$fileIdx]; + + $parsed[$field] = self::parseUploadedFiles($subArray); + } + } + } + + return $parsed; + } +} diff --git a/Sources/API/vendor/slim/psr7/src/Uri.php b/Sources/API/vendor/slim/psr7/src/Uri.php new file mode 100644 index 0000000..b43aa54 --- /dev/null +++ b/Sources/API/vendor/slim/psr7/src/Uri.php @@ -0,0 +1,494 @@ + null, + 'http' => 80, + 'https' => 443 + ]; + + /** + * Uri scheme (without "://" suffix) + */ + protected string $scheme = ''; + + protected string $user = ''; + + protected string $password = ''; + + protected string $host = ''; + + protected ?int $port; + + protected string $path = ''; + + /** + * Uri query string (without "?" prefix) + */ + protected string $query = ''; + + /** + * Uri fragment string (without "#" prefix) + */ + protected string $fragment = ''; + + /** + * @param string $scheme Uri scheme. + * @param string $host Uri host. + * @param int|null $port Uri port number. + * @param string $path Uri path. + * @param string $query Uri query string. + * @param string $fragment Uri fragment. + * @param string $user Uri user. + * @param string $password Uri password. + */ + public function __construct( + string $scheme, + string $host, + ?int $port = null, + string $path = '/', + string $query = '', + string $fragment = '', + string $user = '', + string $password = '' + ) { + $this->scheme = $this->filterScheme($scheme); + $this->host = $this->filterHost($host); + $this->port = $this->filterPort($port); + $this->path = $this->filterPath($path); + $this->query = $this->filterQuery($query); + $this->fragment = $this->filterFragment($fragment); + $this->user = $this->filterUserInfo($user); + $this->password = $this->filterUserInfo($password); + } + + /** + * {@inheritdoc} + */ + public function getScheme(): string + { + return $this->scheme; + } + + /** + * {@inheritdoc} + * @return static + */ + public function withScheme($scheme) + { + $scheme = $this->filterScheme($scheme); + $clone = clone $this; + $clone->scheme = $scheme; + + return $clone; + } + + /** + * Filter Uri scheme. + * + * @param mixed $scheme Raw Uri scheme. + * + * @return string + * + * @throws InvalidArgumentException If the Uri scheme is not a string. + * @throws InvalidArgumentException If Uri scheme is not exists in SUPPORTED_SCHEMES + */ + protected function filterScheme($scheme): string + { + if (!is_string($scheme)) { + throw new InvalidArgumentException('Uri scheme must be a string.'); + } + + $scheme = str_replace('://', '', strtolower($scheme)); + if (!key_exists($scheme, static::SUPPORTED_SCHEMES)) { + throw new InvalidArgumentException( + 'Uri scheme must be one of: "' . implode('", "', array_keys(static::SUPPORTED_SCHEMES)) . '"' + ); + } + + return $scheme; + } + + /** + * {@inheritdoc} + */ + public function getAuthority(): string + { + $userInfo = $this->getUserInfo(); + $host = $this->getHost(); + $port = $this->getPort(); + + return ($userInfo !== '' ? $userInfo . '@' : '') . $host . ($port !== null ? ':' . $port : ''); + } + + /** + * {@inheritdoc} + */ + public function getUserInfo(): string + { + $info = $this->user; + + if ($this->password !== '') { + $info .= ':' . $this->password; + } + + return $info; + } + + /** + * {@inheritdoc} + * @return static + */ + public function withUserInfo($user, $password = null) + { + $clone = clone $this; + $clone->user = $this->filterUserInfo($user); + + if ($clone->user !== '') { + $clone->password = $this->filterUserInfo($password); + } else { + $clone->password = ''; + } + + return $clone; + } + + /** + * Filters the user info string. + * + * Returns the percent-encoded query string. + * + * @param string|null $info The raw uri query string. + * + * @return string + */ + protected function filterUserInfo(?string $info = null): string + { + if (!is_string($info)) { + return ''; + } + + $match = preg_replace_callback( + '/(?:[^a-zA-Z0-9_\-\.~!\$&\'\(\)\*\+,;=]+|%(?![A-Fa-f0-9]{2}))/u', + function ($match) { + return rawurlencode($match[0]); + }, + $info + ); + + return is_string($match) ? $match : ''; + } + + /** + * {@inheritdoc} + */ + public function getHost(): string + { + return $this->host; + } + + /** + * {@inheritdoc} + * @return static + */ + public function withHost($host) + { + $clone = clone $this; + $clone->host = $this->filterHost($host); + + return $clone; + } + + /** + * Filter Uri host. + * + * If the supplied host is an IPv6 address, then it is converted to a reference + * as per RFC 2373. + * + * @param mixed $host The host to filter. + * + * @return string + * + * @throws InvalidArgumentException for invalid host names. + */ + protected function filterHost($host): string + { + if (is_object($host) && method_exists($host, '__toString')) { + $host = (string) $host; + } + + if (!is_string($host)) { + throw new InvalidArgumentException('Uri host must be a string'); + } + + if (filter_var($host, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) { + $host = '[' . $host . ']'; + } + + return strtolower($host); + } + + /** + * {@inheritdoc} + */ + public function getPort(): ?int + { + return $this->port && !$this->hasStandardPort() ? $this->port : null; + } + + /** + * {@inheritdoc} + * @return static + */ + public function withPort($port) + { + $port = $this->filterPort($port); + $clone = clone $this; + $clone->port = $port; + + return $clone; + } + + /** + * Does this Uri use a standard port? + * + * @return bool + */ + protected function hasStandardPort(): bool + { + return static::SUPPORTED_SCHEMES[$this->scheme] === $this->port; + } + + /** + * Filter Uri port. + * + * @param int|null $port The Uri port number. + * + * @return int|null + * + * @throws InvalidArgumentException If the port is invalid. + */ + protected function filterPort($port): ?int + { + if (is_null($port) || (is_integer($port) && ($port >= 1 && $port <= 65535))) { + return $port; + } + + throw new InvalidArgumentException('Uri port must be null or an integer between 1 and 65535 (inclusive)'); + } + + /** + * {@inheritdoc} + */ + public function getPath(): string + { + return $this->path; + } + + /** + * {@inheritdoc} + * @return static + */ + public function withPath($path) + { + if (!is_string($path)) { + throw new InvalidArgumentException('Uri path must be a string'); + } + + $clone = clone $this; + $clone->path = $this->filterPath($path); + + return $clone; + } + + /** + * Filter Uri path. + * + * This method percent-encodes all reserved characters in the provided path string. + * This method will NOT double-encode characters that are already percent-encoded. + * + * @param string $path The raw uri path. + * + * @return string The RFC 3986 percent-encoded uri path. + * + * @link http://www.faqs.org/rfcs/rfc3986.html + */ + protected function filterPath($path): string + { + $match = preg_replace_callback( + '/(?:[^a-zA-Z0-9_\-\.~:@&=\+\$,\/;%]+|%(?![A-Fa-f0-9]{2}))/', + function ($match) { + return rawurlencode($match[0]); + }, + $path + ); + + return is_string($match) ? $match : ''; + } + + /** + * {@inheritdoc} + */ + public function getQuery(): string + { + return $this->query; + } + + /** + * {@inheritdoc} + * @return static + */ + public function withQuery($query) + { + $query = ltrim($this->filterQuery($query), '?'); + $clone = clone $this; + $clone->query = $query; + + return $clone; + } + + /** + * Filters the query string of a URI. + * + * Returns the percent-encoded query string. + * + * @param mixed $query The raw uri query string. + * + * @return string + */ + protected function filterQuery($query): string + { + if (is_object($query) && method_exists($query, '__toString')) { + $query = (string) $query; + } + + if (!is_string($query)) { + throw new InvalidArgumentException('Uri query must be a string.'); + } + + $match = preg_replace_callback( + '/(?:[^a-zA-Z0-9_\-\.~!\$&\'\(\)\*\+,;=%:@\/\?]+|%(?![A-Fa-f0-9]{2}))/', + function ($match) { + return rawurlencode($match[0]); + }, + $query + ); + + return is_string($match) ? $match : ''; + } + + /** + * {@inheritdoc} + */ + public function getFragment(): string + { + return $this->fragment; + } + + /** + * {@inheritdoc} + * @return static + */ + public function withFragment($fragment) + { + $fragment = $this->filterFragment($fragment); + $clone = clone $this; + $clone->fragment = $fragment; + + return $clone; + } + + /** + * Filters fragment of a URI. + * + * Returns the percent-encoded fragment. + * + * @param mixed $fragment The raw uri query string. + * + * @return string + */ + protected function filterFragment($fragment): string + { + if (is_object($fragment) && method_exists($fragment, '__toString')) { + $fragment = (string) $fragment; + } + + if (!is_string($fragment)) { + throw new InvalidArgumentException('Uri fragment must be a string.'); + } + + $fragment = ltrim($fragment, '#'); + + $match = preg_replace_callback( + '/(?:[^a-zA-Z0-9_\-\.~!\$&\'\(\)\*\+,;=%:@\/\?]+|%(?![A-Fa-f0-9]{2}))/', + function ($match) { + return rawurlencode($match[0]); + }, + $fragment + ); + + return is_string($match) ? $match : ''; + } + + /** + * {@inheritdoc} + */ + public function __toString(): string + { + $scheme = $this->getScheme(); + $authority = $this->getAuthority(); + $path = $this->getPath(); + $query = $this->getQuery(); + $fragment = $this->getFragment(); + + if ($path !== '') { + if ($path[0] !== '/') { + if ($authority !== '') { + // If the path is rootless and an authority is present, the path MUST be prefixed by "/". + $path = '/' . $path; + } + } elseif (isset($path[1]) && $path[1] === '/') { + if ($authority === '') { + // If the path is starting with more than one "/" and no authority is present, + // the starting slashes MUST be reduced to one. + $path = '/' . ltrim($path, '/'); + } + } + } + + return ($scheme !== '' ? $scheme . ':' : '') + . ($authority !== '' ? '//' . $authority : '') + . $path + . ($query !== '' ? '?' . $query : '') + . ($fragment !== '' ? '#' . $fragment : ''); + } +} diff --git a/Sources/API/vendor/slim/slim/CHANGELOG.md b/Sources/API/vendor/slim/slim/CHANGELOG.md new file mode 100644 index 0000000..4953c3e --- /dev/null +++ b/Sources/API/vendor/slim/slim/CHANGELOG.md @@ -0,0 +1,208 @@ +# Changelog + +# 4.10.0 - 2022-03-14 +- [3120: Add a new PSR-17 factory to Psr17FactoryProvider](https://github.com/slimphp/Slim/pull/3120) thanks to @solventt +- [3123: Replace deprecated setMethods() in tests](https://github.com/slimphp/Slim/pull/3123) thanks to @solventt +- [3126: Update guzzlehttp/psr7 requirement from ^2.0 to ^2.1](https://github.com/slimphp/Slim/pull/3126) thanks to @dependabot[bot] +- [3127: PHPStan v1.0](https://github.com/slimphp/Slim/pull/3127) thanks to @t0mmy742 +- [3128: Update phpstan/phpstan requirement from ^1.0 to ^1.2](https://github.com/slimphp/Slim/pull/3128) thanks to @dependabot[bot] +- [3129: Deprecate PHP 7.3](https://github.com/slimphp/Slim/pull/3129) thanks to @l0gicgate +- [3130: Removed double defined PHP 7.4](https://github.com/slimphp/Slim/pull/3130) thanks to @flangofas +- [3132: Add new `RequestResponseNamedArgs` route strategy](https://github.com/slimphp/Slim/pull/3132) thanks to @adoy +- [3133: Improve typehinting for `RouteParserInterface`](https://github.com/slimphp/Slim/pull/3133) thanks to @jerowork +- [3135: Update phpstan/phpstan requirement from ^1.2 to ^1.3](https://github.com/slimphp/Slim/pull/3135) thanks to @dependabot[bot] +- [3137: Update phpspec/prophecy requirement from ^1.14 to ^1.15](https://github.com/slimphp/Slim/pull/3137) thanks to @dependabot[bot] +- [3138: Update license year](https://github.com/slimphp/Slim/pull/3138) thanks to @Awilum +- [3139: Fixed #1730 (reintroduced in 4.x)](https://github.com/slimphp/Slim/pull/3139) thanks to @adoy +- [3145: Update phpstan/phpstan requirement from ^1.3 to ^1.4](https://github.com/slimphp/Slim/pull/3145) thanks to @dependabot[bot] +- [3146: Inherit HttpException from RuntimeException](https://github.com/slimphp/Slim/pull/3146) thanks to @nbayramberdiyev +- [3148: Upgrade to HTML5](https://github.com/slimphp/Slim/pull/3148) thanks to @nbayramberdiyev +- [3172: Update nyholm/psr7 requirement from ^1.4 to ^1.5](https://github.com/slimphp/Slim/pull/3172) thanks to @dependabot[bot] + +# 4.9.0 - 2021-10-05 +- [3058: Implement exception class for Gone Http error](https://github.com/slimphp/Slim/pull/3058) thanks to @TheKernelPanic +- [3086: Update slim/psr7 requirement from ^1.3 to ^1.4](https://github.com/slimphp/Slim/pull/3086) thanks to @dependabot[bot] +- [3087: Update nyholm/psr7-server requirement from ^1.0.1 to ^1.0.2](https://github.com/slimphp/Slim/pull/3087) thanks to @dependabot[bot] +- [3093: Update phpstan/phpstan requirement from ^0.12.85 to ^0.12.90](https://github.com/slimphp/Slim/pull/3093) thanks to @dependabot[bot] +- [3099: Allow updated psr log](https://github.com/slimphp/Slim/pull/3099) thanks to @t0mmy742 +- [3104: Drop php7.2](https://github.com/slimphp/Slim/pull/3104) thanks to @t0mmy742 +- [3106: Use PSR-17 factory from Guzzle/psr7 2.0](https://github.com/slimphp/Slim/pull/3106) thanks to @t0mmy742 +- [3108: Update README file](https://github.com/slimphp/Slim/pull/3108) thanks to @t0mmy742 +- [3112: Update laminas/laminas-diactoros requirement from ^2.6 to ^2.8](https://github.com/slimphp/Slim/pull/3112) thanks to @dependabot[bot] +- [3114: Update slim/psr7 requirement from ^1.4 to ^1.5](https://github.com/slimphp/Slim/pull/3114) thanks to @dependabot[bot] +- [3115: Update phpstan/phpstan requirement from ^0.12.96 to ^0.12.99](https://github.com/slimphp/Slim/pull/3115) thanks to @dependabot[bot] +- [3116: Remove Zend Diactoros references](https://github.com/slimphp/Slim/pull/3116) thanks to @l0gicgate + +# 4.8.0 - 2021-05-19 +- [3034: Fix phpunit dependency version](https://github.com/slimphp/Slim/pull/3034) thanks to @l0gicgate +- [3037: Replace Travis by GitHub Actions](https://github.com/slimphp/Slim/pull/3037) thanks to @t0mmy742 +- [3043: Cover App creation from AppFactory with empty Container](https://github.com/slimphp/Slim/pull/3043) thanks to @t0mmy742 +- [3045: Update phpstan/phpstan requirement from ^0.12.58 to ^0.12.64](https://github.com/slimphp/Slim/pull/3045) thanks to @dependabot-preview[bot] +- [3047: documentation: min php 7.2 required](https://github.com/slimphp/Slim/pull/3047) thanks to @Rotzbua +- [3054: Update phpstan/phpstan requirement from ^0.12.64 to ^0.12.70](https://github.com/slimphp/Slim/pull/3054) thanks to @dependabot-preview[bot] +- [3056: Fix docblock in ErrorMiddleware](https://github.com/slimphp/Slim/pull/3056) thanks to @piotr-cz +- [3060: Update phpstan/phpstan requirement from ^0.12.70 to ^0.12.80](https://github.com/slimphp/Slim/pull/3060) thanks to @dependabot-preview[bot] +- [3061: Update nyholm/psr7 requirement from ^1.3 to ^1.4](https://github.com/slimphp/Slim/pull/3061) thanks to @dependabot-preview[bot] +- [3063: Allow ^1.0 || ^2.0 in psr/container](https://github.com/slimphp/Slim/pull/3063) thanks to @Ayesh +- [3069: Classname/Method Callable Arrays](https://github.com/slimphp/Slim/pull/3069) thanks to @ddrv +- [3078: Update squizlabs/php_codesniffer requirement from ^3.5 to ^3.6](https://github.com/slimphp/Slim/pull/3078) thanks to @dependabot[bot] +- [3079: Update phpspec/prophecy requirement from ^1.12 to ^1.13](https://github.com/slimphp/Slim/pull/3079) thanks to @dependabot[bot] +- [3080: Update guzzlehttp/psr7 requirement from ^1.7 to ^1.8](https://github.com/slimphp/Slim/pull/3080) thanks to @dependabot[bot] +- [3082: Update phpstan/phpstan requirement from ^0.12.80 to ^0.12.85](https://github.com/slimphp/Slim/pull/3082) thanks to @dependabot[bot] + +# 4.7.0 - 2020-11-30 + +### Fixed +- [3027: Fix: FastRoute dispatcher and data generator should match](https://github.com/slimphp/Slim/pull/3027) thanks to @edudobay + +### Added +- [3015: PHP 8 support](https://github.com/slimphp/Slim/pull/3015) thanks to @edudobay + +### Optimizations +- [3024: Randomize tests](https://github.com/slimphp/Slim/pull/3024) thanks to @pawel-slowik + +## 4.6.0 - 2020-11-15 + +### Fixed +- [2942: Fix PHPdoc for error handlers in ErrorMiddleware ](https://github.com/slimphp/Slim/pull/2942) thanks to @TiMESPLiNTER +- [2944: Remove unused function in ErrorHandler](https://github.com/slimphp/Slim/pull/2944) thanks to @l0gicgate +- [2960: Fix phpstan 0.12 errors](https://github.com/slimphp/Slim/pull/2960) thanks to @adriansuter +- [2982: Removing cloning statements in tests](https://github.com/slimphp/Slim/pull/2982) thanks to @l0gicgate +- [3017: Fix request creator factory test](https://github.com/slimphp/Slim/pull/3017) thanks to @pawel-slowik +- [3022: Ensure RouteParser Always Present After Routing](https://github.com/slimphp/Slim/pull/3022) thanks to @l0gicgate + +### Added +- [2949: Add the support in composer.json](https://github.com/slimphp/Slim/pull/2949) thanks to @ddrv +- [2958: Strict empty string content type checking in BodyParsingMiddleware::getMediaType](https://github.com/slimphp/Slim/pull/2958) thanks to @Ayesh +- [2997: Add hints to methods](https://github.com/slimphp/Slim/pull/2997) thanks to @evgsavosin - [3000: Fix route controller test](https://github.com/slimphp/Slim/pull/3000) thanks to @pawel-slowik +- [3001: Add missing `$strategy` parameter in a Route test](https://github.com/slimphp/Slim/pull/3001) thanks to @pawel-slowik + +### Optimizations +- [2951: Minor optimizations in if() blocks](https://github.com/slimphp/Slim/pull/2951) thanks to @Ayesh +- [2959: Micro optimization: Declare closures in BodyParsingMiddleware as static](https://github.com/slimphp/Slim/pull/2959) thanks to @Ayesh +- [2978: Split the routing results to its own function.](https://github.com/slimphp/Slim/pull/2978) thanks to @dlundgren + +### Dependencies Updated +- [2953: Update nyholm/psr7-server requirement from ^0.4.1](https://github.com/slimphp/Slim/pull/2953) thanks to @dependabot-preview[bot] +- [2954: Update laminas/laminas-diactoros requirement from ^2.1 to ^2.3](https://github.com/slimphp/Slim/pull/2954) thanks to @dependabot-preview[bot] +- [2955: Update guzzlehttp/psr7 requirement from ^1.5 to ^1.6](https://github.com/slimphp/Slim/pull/2955) thanks to @dependabot-preview[bot] +- [2956: Update slim/psr7 requirement from ^1.0 to ^1.1](https://github.com/slimphp/Slim/pull/2956) thanks to @dependabot-preview[bot] +- [2957: Update nyholm/psr7 requirement from ^1.1 to ^1.2](https://github.com/slimphp/Slim/pull/2957) thanks to @dependabot-preview[bot] +- [2963: Update phpstan/phpstan requirement from ^0.12.23 to ^0.12.25](https://github.com/slimphp/Slim/pull/2963) thanks to @dependabot-preview[bot] +- [2965: Update adriansuter/php-autoload-override requirement from ^1.0 to ^1.1](https://github.com/slimphp/Slim/pull/2965) thanks to @dependabot-preview[bot] +- [2967: Update nyholm/psr7 requirement from ^1.2 to ^1.3](https://github.com/slimphp/Slim/pull/2967) thanks to @dependabot-preview[bot] +- [2969: Update nyholm/psr7-server requirement from ^0.4.1 to ^1.0.0](https://github.com/slimphp/Slim/pull/2969) thanks to @dependabot-preview[bot] +- [2970: Update phpstan/phpstan requirement from ^0.12.25 to ^0.12.26](https://github.com/slimphp/Slim/pull/2970) thanks to @dependabot-preview[bot] +- [2971: Update phpstan/phpstan requirement from ^0.12.26 to ^0.12.27](https://github.com/slimphp/Slim/pull/2971) thanks to @dependabot-preview[bot] +- [2972: Update phpstan/phpstan requirement from ^0.12.27 to ^0.12.28](https://github.com/slimphp/Slim/pull/2972) thanks to @dependabot-preview[bot] +- [2973: Update phpstan/phpstan requirement from ^0.12.28 to ^0.12.29](https://github.com/slimphp/Slim/pull/2973) thanks to @dependabot-preview[bot] +- [2975: Update phpstan/phpstan requirement from ^0.12.29 to ^0.12.30](https://github.com/slimphp/Slim/pull/2975) thanks to @dependabot-preview[bot] +- [2976: Update phpstan/phpstan requirement from ^0.12.30 to ^0.12.31](https://github.com/slimphp/Slim/pull/2976) thanks to @dependabot-preview[bot] +- [2980: Update phpstan/phpstan requirement from ^0.12.31 to ^0.12.32](https://github.com/slimphp/Slim/pull/2980) thanks to @dependabot-preview[bot] +- [2981: Update phpspec/prophecy requirement from ^1.10 to ^1.11](https://github.com/slimphp/Slim/pull/2981) thanks to @dependabot-preview[bot] +- [2986: Update phpstan/phpstan requirement from ^0.12.32 to ^0.12.33](https://github.com/slimphp/Slim/pull/2986) thanks to @dependabot-preview[bot] +- [2990: Update phpstan/phpstan requirement from ^0.12.33 to ^0.12.34](https://github.com/slimphp/Slim/pull/2990) thanks to @dependabot-preview[bot] +- [2991: Update phpstan/phpstan requirement from ^0.12.34 to ^0.12.35](https://github.com/slimphp/Slim/pull/2991) thanks to @dependabot-preview[bot] +- [2993: Update phpstan/phpstan requirement from ^0.12.35 to ^0.12.36](https://github.com/slimphp/Slim/pull/2993) thanks to @dependabot-preview[bot] +- [2995: Update phpstan/phpstan requirement from ^0.12.36 to ^0.12.37](https://github.com/slimphp/Slim/pull/2995) thanks to @dependabot-preview[bot] +- [3010: Update guzzlehttp/psr7 requirement from ^1.6 to ^1.7](https://github.com/slimphp/Slim/pull/3010) thanks to @dependabot-preview[bot] +- [3011: Update phpspec/prophecy requirement from ^1.11 to ^1.12](https://github.com/slimphp/Slim/pull/3011) thanks to @dependabot-preview[bot] +- [3012: Update slim/http requirement from ^1.0 to ^1.1](https://github.com/slimphp/Slim/pull/3012) thanks to @dependabot-preview[bot] +- [3013: Update slim/psr7 requirement from ^1.1 to ^1.2](https://github.com/slimphp/Slim/pull/3013) thanks to @dependabot-preview[bot] +- [3014: Update laminas/laminas-diactoros requirement from ^2.3 to ^2.4](https://github.com/slimphp/Slim/pull/3014) thanks to @dependabot-preview[bot] +- [3018: Update phpstan/phpstan requirement from ^0.12.37 to ^0.12.54](https://github.com/slimphp/Slim/pull/3018) thanks to @dependabot-preview[bot] + +## 4.5.0 - 2020-04-14 + +### Added +- [2928](https://github.com/slimphp/Slim/pull/2928) Test against PHP 7.4 +- [2937](https://github.com/slimphp/Slim/pull/2937) Add support for PSR-3 + +### Fixed +- [2916](https://github.com/slimphp/Slim/pull/2916) Rename phpcs.xml to phpcs.xml.dist +- [2917](https://github.com/slimphp/Slim/pull/2917) Update .editorconfig +- [2925](https://github.com/slimphp/Slim/pull/2925) ResponseEmitter: Don't remove Content-Type and Content-Length when body is empt +- [2932](https://github.com/slimphp/Slim/pull/2932) Update the Tidelift enterprise language +- [2938](https://github.com/slimphp/Slim/pull/2938) Modify usage of deprecated expectExceptionMessageRegExp() method + +## 4.4.0 - 2020-01-04 + +### Added +- [2862](https://github.com/slimphp/Slim/pull/2862) Optionally handle subclasses of exceptions in custom error handler +- [2869](https://github.com/slimphp/Slim/pull/2869) php-di/php-di added in composer suggestion +- [2874](https://github.com/slimphp/Slim/pull/2874) Add `null` to param type-hints +- [2889](https://github.com/slimphp/Slim/pull/2889) Make `RouteContext` attributes customizable and change default to use private names +- [2907](https://github.com/slimphp/Slim/pull/2907) Migrate to PSR-12 convention +- [2910](https://github.com/slimphp/Slim/pull/2910) Migrate Zend to Laminas +- [2912](https://github.com/slimphp/Slim/pull/2912) Add Laminas PSR17 Factory +- [2913](https://github.com/slimphp/Slim/pull/2913) Update php-autoload-override version +- [2914](https://github.com/slimphp/Slim/pull/2914) Added ability to add handled exceptions as an array + +### Fixed +- [2864](https://github.com/slimphp/Slim/pull/2864) Optimize error message in error handling if displayErrorDetails was not set +- [2876](https://github.com/slimphp/Slim/pull/2876) Update links from http to https +- [2877](https://github.com/slimphp/Slim/pull/2877) Fix docblock for `Slim\Routing\RouteCollector::cacheFile` +- [2878](https://github.com/slimphp/Slim/pull/2878) check body is writable only on ouput buffering append +- [2896](https://github.com/slimphp/Slim/pull/2896) Render errors uniformly +- [2902](https://github.com/slimphp/Slim/pull/2902) Fix prophecies +- [2908](https://github.com/slimphp/Slim/pull/2908) Use autoload-dev for `Slim\Tests` namespace + +### Removed +- [2871](https://github.com/slimphp/Slim/pull/2871) Remove explicit type-hint +- [2872](https://github.com/slimphp/Slim/pull/2872) Remove type-hint + +## 4.3.0 - 2019-10-05 + +### Added +- [2819](https://github.com/slimphp/Slim/pull/2819) Added description to addRoutingMiddleware() +- [2820](https://github.com/slimphp/Slim/pull/2820) Update link to homepage in composer.json +- [2828](https://github.com/slimphp/Slim/pull/2828) Allow URIs with leading multi-slashes +- [2832](https://github.com/slimphp/Slim/pull/2832) Refactor `FastRouteDispatcher` +- [2835](https://github.com/slimphp/Slim/pull/2835) Rename `pathFor` to `urlFor` in docblock +- [2846](https://github.com/slimphp/Slim/pull/2846) Correcting the branch name as per issue-2843 +- [2849](https://github.com/slimphp/Slim/pull/2849) Create class alias for FastRoute\RouteCollector +- [2855](https://github.com/slimphp/Slim/pull/2855) Add list of allowed methods to HttpMethodNotAllowedException +- [2860](https://github.com/slimphp/Slim/pull/2860) Add base path to `$request` and use `RouteContext` to read + +### Fixed +- [2839](https://github.com/slimphp/Slim/pull/2839) Fix description for handler signature in phpdocs +- [2844](https://github.com/slimphp/Slim/pull/2844) Handle base path by routeCollector instead of RouteCollectorProxy +- [2845](https://github.com/slimphp/Slim/pull/2845) Fix composer scripts +- [2851](https://github.com/slimphp/Slim/pull/2851) Fix example of 'Hello World' app +- [2854](https://github.com/slimphp/Slim/pull/2854) Fix undefined property in tests + +### Removed +- [2853](https://github.com/slimphp/Slim/pull/2853) Remove unused classes + +## 4.2.0 - 2019-08-20 + +### Added +- [2787](https://github.com/slimphp/Slim/pull/2787) Add an advanced callable resolver +- [2791](https://github.com/slimphp/Slim/pull/2791) Add `inferPrivatePropertyTypeFromConstructor` to phpstan +- [2793](https://github.com/slimphp/Slim/pull/2793) Add ability to configure application via a container in `AppFactory` +- [2798](https://github.com/slimphp/Slim/pull/2798) Add PSR-7 Agnostic Body Parsing Middleware +- [2801](https://github.com/slimphp/Slim/pull/2801) Add `setLogErrorRenderer()` method to `ErrorHandler` +- [2807](https://github.com/slimphp/Slim/pull/2807) Add check for Slim callable notation if no resolver given +- [2803](https://github.com/slimphp/Slim/pull/2803) Add ability to emit non seekable streams in `ResponseEmitter` +- [2817](https://github.com/slimphp/Slim/pull/2817) Add the ability to pass in a custom `MiddlewareDispatcherInterface` to the `App` + +### Fixed +- [2789](https://github.com/slimphp/Slim/pull/2789) Fix Cookie header detection in `ResponseEmitter` +- [2796](https://github.com/slimphp/Slim/pull/2796) Fix http message format +- [2800](https://github.com/slimphp/Slim/pull/2800) Fix null comparisons more clear in `ErrorHandler` +- [2802](https://github.com/slimphp/Slim/pull/2802) Fix incorrect search of a header in stack +- [2806](https://github.com/slimphp/Slim/pull/2806) Simplify `Route::prepare()` method argument preparation +- [2809](https://github.com/slimphp/Slim/pull/2809) Eliminate a duplicate code via HOF in `MiddlewareDispatcher` +- [2816](https://github.com/slimphp/Slim/pull/2816) Fix RouteCollectorProxy::redirect() bug + +### Removed +- [2811](https://github.com/slimphp/Slim/pull/2811) Remove `DeferredCallable` + +## 4.1.0 - 2019-08-06 + +### Added +- [#2779](https://github.com/slimphp/Slim/pull/2774) Add support for Slim callables `Class:method` resolution & Container Closure auto-binding in `MiddlewareDispatcher` +- [#2774](https://github.com/slimphp/Slim/pull/2774) Add possibility for custom `RequestHandler` invocation strategies + +### Fixed +- [#2776](https://github.com/slimphp/Slim/pull/2774) Fix group middleware on multiple nested groups diff --git a/Sources/API/vendor/slim/slim/LICENSE.md b/Sources/API/vendor/slim/slim/LICENSE.md new file mode 100644 index 0000000..d6fd559 --- /dev/null +++ b/Sources/API/vendor/slim/slim/LICENSE.md @@ -0,0 +1,19 @@ +Copyright (c) 2011-2022 Josh Lockhart + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/Sources/API/vendor/slim/slim/MAINTAINERS.md b/Sources/API/vendor/slim/slim/MAINTAINERS.md new file mode 100644 index 0000000..2b8ad04 --- /dev/null +++ b/Sources/API/vendor/slim/slim/MAINTAINERS.md @@ -0,0 +1,17 @@ +# Maintainers + +There aren't many rules for maintainers of Slim to remember; what we have is listed here. + +## We don't merge our own PRs + +Our code is better if more than one set of eyes looks at it. Therefore we do not merge our own pull requests unless there is an exceptional circumstance. This helps to spot errors in the patch and also enables us to share information about the project around the maintainer team. + +## PRs tagged `WIP` are not ready to be merged + +Sometimes it's helpful to collaborate on a patch before it's ready to be merged. We use the text `WIP` (for _Work in Progress_) in the title to mark these PRs. + +If a PR has `WIP` in its title, then it is not to be merged. The person who raised the PR will remove the `WIP` text when they are ready for a full review and merge. + +## Assign a merged PR to a milestone + +By ensuring that all merged PRs are assigned to a milestone, we can easily find which PRs were in which release. diff --git a/Sources/API/vendor/slim/slim/SECURITY.md b/Sources/API/vendor/slim/slim/SECURITY.md new file mode 100644 index 0000000..a5b6df0 --- /dev/null +++ b/Sources/API/vendor/slim/slim/SECURITY.md @@ -0,0 +1,14 @@ +# Security Policy + +### Supported Versions + + +| Version | Supported | +| ------- | ------------------ | +| 3.x.x | :white_check_mark: | +| 4.x.x | :white_check_mark: | + + +### Reporting a Vulnerability + +To report a vulnerability please send an email to security@slimframework.com diff --git a/Sources/API/vendor/slim/slim/Slim/App.php b/Sources/API/vendor/slim/slim/Slim/App.php new file mode 100644 index 0000000..1374d6f --- /dev/null +++ b/Sources/API/vendor/slim/slim/Slim/App.php @@ -0,0 +1,216 @@ +routeResolver = $routeResolver ?? new RouteResolver($this->routeCollector); + $routeRunner = new RouteRunner($this->routeResolver, $this->routeCollector->getRouteParser(), $this); + + if (!$middlewareDispatcher) { + $middlewareDispatcher = new MiddlewareDispatcher($routeRunner, $this->callableResolver, $container); + } else { + $middlewareDispatcher->seedMiddlewareStack($routeRunner); + } + + $this->middlewareDispatcher = $middlewareDispatcher; + } + + /** + * @return RouteResolverInterface + */ + public function getRouteResolver(): RouteResolverInterface + { + return $this->routeResolver; + } + + /** + * @return MiddlewareDispatcherInterface + */ + public function getMiddlewareDispatcher(): MiddlewareDispatcherInterface + { + return $this->middlewareDispatcher; + } + + /** + * @param MiddlewareInterface|string|callable $middleware + */ + public function add($middleware): self + { + $this->middlewareDispatcher->add($middleware); + return $this; + } + + /** + * @param MiddlewareInterface $middleware + */ + public function addMiddleware(MiddlewareInterface $middleware): self + { + $this->middlewareDispatcher->addMiddleware($middleware); + return $this; + } + + /** + * Add the Slim built-in routing middleware to the app middleware stack + * + * This method can be used to control middleware order and is not required for default routing operation. + * + * @return RoutingMiddleware + */ + public function addRoutingMiddleware(): RoutingMiddleware + { + $routingMiddleware = new RoutingMiddleware( + $this->getRouteResolver(), + $this->getRouteCollector()->getRouteParser() + ); + $this->add($routingMiddleware); + return $routingMiddleware; + } + + /** + * Add the Slim built-in error middleware to the app middleware stack + * + * @param bool $displayErrorDetails + * @param bool $logErrors + * @param bool $logErrorDetails + * @param LoggerInterface|null $logger + * + * @return ErrorMiddleware + */ + public function addErrorMiddleware( + bool $displayErrorDetails, + bool $logErrors, + bool $logErrorDetails, + ?LoggerInterface $logger = null + ): ErrorMiddleware { + $errorMiddleware = new ErrorMiddleware( + $this->getCallableResolver(), + $this->getResponseFactory(), + $displayErrorDetails, + $logErrors, + $logErrorDetails, + $logger + ); + $this->add($errorMiddleware); + return $errorMiddleware; + } + + /** + * Add the Slim body parsing middleware to the app middleware stack + * + * @param callable[] $bodyParsers + * + * @return BodyParsingMiddleware + */ + public function addBodyParsingMiddleware(array $bodyParsers = []): BodyParsingMiddleware + { + $bodyParsingMiddleware = new BodyParsingMiddleware($bodyParsers); + $this->add($bodyParsingMiddleware); + return $bodyParsingMiddleware; + } + + /** + * Run application + * + * This method traverses the application middleware stack and then sends the + * resultant Response object to the HTTP client. + * + * @param ServerRequestInterface|null $request + * @return void + */ + public function run(?ServerRequestInterface $request = null): void + { + if (!$request) { + $serverRequestCreator = ServerRequestCreatorFactory::create(); + $request = $serverRequestCreator->createServerRequestFromGlobals(); + } + + $response = $this->handle($request); + $responseEmitter = new ResponseEmitter(); + $responseEmitter->emit($response); + } + + /** + * Handle a request + * + * This method traverses the application middleware stack and then returns the + * resultant Response object. + * + * @param ServerRequestInterface $request + * @return ResponseInterface + */ + public function handle(ServerRequestInterface $request): ResponseInterface + { + $response = $this->middlewareDispatcher->handle($request); + + /** + * This is to be in compliance with RFC 2616, Section 9. + * If the incoming request method is HEAD, we need to ensure that the response body + * is empty as the request may fall back on a GET route handler due to FastRoute's + * routing logic which could potentially append content to the response body + * https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.4 + */ + $method = strtoupper($request->getMethod()); + if ($method === 'HEAD') { + $emptyBody = $this->responseFactory->createResponse()->getBody(); + return $response->withBody($emptyBody); + } + + return $response; + } +} diff --git a/Sources/API/vendor/slim/slim/Slim/CallableResolver.php b/Sources/API/vendor/slim/slim/Slim/CallableResolver.php new file mode 100644 index 0000000..66f225d --- /dev/null +++ b/Sources/API/vendor/slim/slim/Slim/CallableResolver.php @@ -0,0 +1,193 @@ +container = $container; + } + + /** + * {@inheritdoc} + */ + public function resolve($toResolve): callable + { + $toResolve = $this->prepareToResolve($toResolve); + if (is_callable($toResolve)) { + return $this->bindToContainer($toResolve); + } + $resolved = $toResolve; + if (is_string($toResolve)) { + $resolved = $this->resolveSlimNotation($toResolve); + $resolved[1] ??= '__invoke'; + } + $callable = $this->assertCallable($resolved, $toResolve); + return $this->bindToContainer($callable); + } + + /** + * {@inheritdoc} + */ + public function resolveRoute($toResolve): callable + { + return $this->resolveByPredicate($toResolve, [$this, 'isRoute'], 'handle'); + } + + /** + * {@inheritdoc} + */ + public function resolveMiddleware($toResolve): callable + { + return $this->resolveByPredicate($toResolve, [$this, 'isMiddleware'], 'process'); + } + + /** + * @param string|callable $toResolve + * + * @throws RuntimeException + */ + private function resolveByPredicate($toResolve, callable $predicate, string $defaultMethod): callable + { + $toResolve = $this->prepareToResolve($toResolve); + if (is_callable($toResolve)) { + return $this->bindToContainer($toResolve); + } + $resolved = $toResolve; + if ($predicate($toResolve)) { + $resolved = [$toResolve, $defaultMethod]; + } + if (is_string($toResolve)) { + [$instance, $method] = $this->resolveSlimNotation($toResolve); + if ($method === null && $predicate($instance)) { + $method = $defaultMethod; + } + $resolved = [$instance, $method ?? '__invoke']; + } + $callable = $this->assertCallable($resolved, $toResolve); + return $this->bindToContainer($callable); + } + + /** + * @param mixed $toResolve + */ + private function isRoute($toResolve): bool + { + return $toResolve instanceof RequestHandlerInterface; + } + + /** + * @param mixed $toResolve + */ + private function isMiddleware($toResolve): bool + { + return $toResolve instanceof MiddlewareInterface; + } + + /** + * @throws RuntimeException + * + * @return array{object, string|null} [Instance, Method Name] + */ + private function resolveSlimNotation(string $toResolve): array + { + preg_match(CallableResolver::$callablePattern, $toResolve, $matches); + [$class, $method] = $matches ? [$matches[1], $matches[2]] : [$toResolve, null]; + + /** @var string $class */ + /** @var string|null $method */ + if ($this->container && $this->container->has($class)) { + $instance = $this->container->get($class); + if (!is_object($instance)) { + throw new RuntimeException(sprintf('%s container entry is not an object', $class)); + } + } else { + if (!class_exists($class)) { + if ($method) { + $class .= '::' . $method . '()'; + } + throw new RuntimeException(sprintf('Callable %s does not exist', $class)); + } + $instance = new $class($this->container); + } + return [$instance, $method]; + } + + /** + * @param mixed $resolved + * @param mixed $toResolve + * + * @throws RuntimeException + */ + private function assertCallable($resolved, $toResolve): callable + { + if (!is_callable($resolved)) { + if (is_callable($toResolve) || is_object($toResolve) || is_array($toResolve)) { + $formatedToResolve = ($toResolveJson = json_encode($toResolve)) !== false ? $toResolveJson : ''; + } else { + $formatedToResolve = is_string($toResolve) ? $toResolve : ''; + } + throw new RuntimeException(sprintf('%s is not resolvable', $formatedToResolve)); + } + return $resolved; + } + + private function bindToContainer(callable $callable): callable + { + if (is_array($callable) && $callable[0] instanceof Closure) { + $callable = $callable[0]; + } + if ($this->container && $callable instanceof Closure) { + /** @var Closure $callable */ + $callable = $callable->bindTo($this->container); + } + return $callable; + } + + /** + * @param string|callable $toResolve + * @return string|callable + */ + private function prepareToResolve($toResolve) + { + if (!is_array($toResolve)) { + return $toResolve; + } + $candidate = $toResolve; + $class = array_shift($candidate); + $method = array_shift($candidate); + if (is_string($class) && is_string($method)) { + return $class . ':' . $method; + } + return $toResolve; + } +} diff --git a/Sources/API/vendor/slim/slim/Slim/Error/AbstractErrorRenderer.php b/Sources/API/vendor/slim/slim/Slim/Error/AbstractErrorRenderer.php new file mode 100644 index 0000000..90b290d --- /dev/null +++ b/Sources/API/vendor/slim/slim/Slim/Error/AbstractErrorRenderer.php @@ -0,0 +1,46 @@ +getTitle(); + } + + return $this->defaultErrorTitle; + } + + protected function getErrorDescription(Throwable $exception): string + { + if ($exception instanceof HttpException) { + return $exception->getDescription(); + } + + return $this->defaultErrorDescription; + } +} diff --git a/Sources/API/vendor/slim/slim/Slim/Error/Renderers/HtmlErrorRenderer.php b/Sources/API/vendor/slim/slim/Slim/Error/Renderers/HtmlErrorRenderer.php new file mode 100644 index 0000000..e030522 --- /dev/null +++ b/Sources/API/vendor/slim/slim/Slim/Error/Renderers/HtmlErrorRenderer.php @@ -0,0 +1,84 @@ +The application could not run because of the following error:

'; + $html .= '

Details

'; + $html .= $this->renderExceptionFragment($exception); + } else { + $html = "

{$this->getErrorDescription($exception)}

"; + } + + return $this->renderHtmlBody($this->getErrorTitle($exception), $html); + } + + private function renderExceptionFragment(Throwable $exception): string + { + $html = sprintf('
Type: %s
', get_class($exception)); + + /** @var int|string $code */ + $code = $exception->getCode(); + $html .= sprintf('
Code: %s
', $code); + + $html .= sprintf('
Message: %s
', htmlentities($exception->getMessage())); + + $html .= sprintf('
File: %s
', $exception->getFile()); + + $html .= sprintf('
Line: %s
', $exception->getLine()); + + $html .= '

Trace

'; + $html .= sprintf('
%s
', htmlentities($exception->getTraceAsString())); + + return $html; + } + + public function renderHtmlBody(string $title = '', string $html = ''): string + { + return sprintf( + '' . + '' . + ' ' . + ' ' . + ' ' . + ' %s' . + ' ' . + ' ' . + ' ' . + '

%s

' . + '
%s
' . + ' Go Back' . + ' ' . + '', + $title, + $title, + $html + ); + } +} diff --git a/Sources/API/vendor/slim/slim/Slim/Error/Renderers/JsonErrorRenderer.php b/Sources/API/vendor/slim/slim/Slim/Error/Renderers/JsonErrorRenderer.php new file mode 100644 index 0000000..63d905b --- /dev/null +++ b/Sources/API/vendor/slim/slim/Slim/Error/Renderers/JsonErrorRenderer.php @@ -0,0 +1,56 @@ + $this->getErrorTitle($exception)]; + + if ($displayErrorDetails) { + $error['exception'] = []; + do { + $error['exception'][] = $this->formatExceptionFragment($exception); + } while ($exception = $exception->getPrevious()); + } + + return (string) json_encode($error, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES); + } + + /** + * @return array + */ + private function formatExceptionFragment(Throwable $exception): array + { + /** @var int|string $code */ + $code = $exception->getCode(); + return [ + 'type' => get_class($exception), + 'code' => $code, + 'message' => $exception->getMessage(), + 'file' => $exception->getFile(), + 'line' => $exception->getLine(), + ]; + } +} diff --git a/Sources/API/vendor/slim/slim/Slim/Error/Renderers/PlainTextErrorRenderer.php b/Sources/API/vendor/slim/slim/Slim/Error/Renderers/PlainTextErrorRenderer.php new file mode 100644 index 0000000..3d80c74 --- /dev/null +++ b/Sources/API/vendor/slim/slim/Slim/Error/Renderers/PlainTextErrorRenderer.php @@ -0,0 +1,59 @@ +getErrorTitle($exception)}\n"; + + if ($displayErrorDetails) { + $text .= $this->formatExceptionFragment($exception); + + while ($exception = $exception->getPrevious()) { + $text .= "\nPrevious Error:\n"; + $text .= $this->formatExceptionFragment($exception); + } + } + + return $text; + } + + private function formatExceptionFragment(Throwable $exception): string + { + $text = sprintf("Type: %s\n", get_class($exception)); + + $code = $exception->getCode(); + /** @var int|string $code */ + $text .= sprintf("Code: %s\n", $code); + + $text .= sprintf("Message: %s\n", htmlentities($exception->getMessage())); + + $text .= sprintf("File: %s\n", $exception->getFile()); + + $text .= sprintf("Line: %s\n", $exception->getLine()); + + $text .= sprintf('Trace: %s', $exception->getTraceAsString()); + + return $text; + } +} diff --git a/Sources/API/vendor/slim/slim/Slim/Error/Renderers/XmlErrorRenderer.php b/Sources/API/vendor/slim/slim/Slim/Error/Renderers/XmlErrorRenderer.php new file mode 100644 index 0000000..1171b79 --- /dev/null +++ b/Sources/API/vendor/slim/slim/Slim/Error/Renderers/XmlErrorRenderer.php @@ -0,0 +1,54 @@ +\n"; + $xml .= "\n " . $this->createCdataSection($this->getErrorTitle($exception)) . "\n"; + + if ($displayErrorDetails) { + do { + $xml .= " \n"; + $xml .= ' ' . get_class($exception) . "\n"; + $xml .= ' ' . $exception->getCode() . "\n"; + $xml .= ' ' . $this->createCdataSection($exception->getMessage()) . "\n"; + $xml .= ' ' . $exception->getFile() . "\n"; + $xml .= ' ' . $exception->getLine() . "\n"; + $xml .= " \n"; + } while ($exception = $exception->getPrevious()); + } + + $xml .= ''; + + return $xml; + } + + /** + * Returns a CDATA section with the given content. + */ + private function createCdataSection(string $content): string + { + return sprintf('', str_replace(']]>', ']]]]>', $content)); + } +} diff --git a/Sources/API/vendor/slim/slim/Slim/Exception/HttpBadRequestException.php b/Sources/API/vendor/slim/slim/Slim/Exception/HttpBadRequestException.php new file mode 100644 index 0000000..caea20f --- /dev/null +++ b/Sources/API/vendor/slim/slim/Slim/Exception/HttpBadRequestException.php @@ -0,0 +1,28 @@ +request = $request; + } + + public function getRequest(): ServerRequestInterface + { + return $this->request; + } + + public function getTitle(): string + { + return $this->title; + } + + public function setTitle(string $title): self + { + $this->title = $title; + return $this; + } + + public function getDescription(): string + { + return $this->description; + } + + public function setDescription(string $description): self + { + $this->description = $description; + return $this; + } +} diff --git a/Sources/API/vendor/slim/slim/Slim/Exception/HttpForbiddenException.php b/Sources/API/vendor/slim/slim/Slim/Exception/HttpForbiddenException.php new file mode 100644 index 0000000..dd3bb23 --- /dev/null +++ b/Sources/API/vendor/slim/slim/Slim/Exception/HttpForbiddenException.php @@ -0,0 +1,27 @@ +allowedMethods; + } + + /** + * @param string[] $methods + */ + public function setAllowedMethods(array $methods): self + { + $this->allowedMethods = $methods; + $this->message = 'Method not allowed. Must be one of: ' . implode(', ', $methods); + return $this; + } +} diff --git a/Sources/API/vendor/slim/slim/Slim/Exception/HttpNotFoundException.php b/Sources/API/vendor/slim/slim/Slim/Exception/HttpNotFoundException.php new file mode 100644 index 0000000..865146d --- /dev/null +++ b/Sources/API/vendor/slim/slim/Slim/Exception/HttpNotFoundException.php @@ -0,0 +1,27 @@ +message = $message; + } + + parent::__construct($request, $this->message, $this->code, $previous); + } +} diff --git a/Sources/API/vendor/slim/slim/Slim/Exception/HttpUnauthorizedException.php b/Sources/API/vendor/slim/slim/Slim/Exception/HttpUnauthorizedException.php new file mode 100644 index 0000000..07bd70d --- /dev/null +++ b/Sources/API/vendor/slim/slim/Slim/Exception/HttpUnauthorizedException.php @@ -0,0 +1,27 @@ +has(ResponseFactoryInterface::class) + && ( + $responseFactoryFromContainer = $container->get(ResponseFactoryInterface::class) + ) instanceof ResponseFactoryInterface + ? $responseFactoryFromContainer + : self::determineResponseFactory(); + + $callableResolver = $container->has(CallableResolverInterface::class) + && ( + $callableResolverFromContainer = $container->get(CallableResolverInterface::class) + ) instanceof CallableResolverInterface + ? $callableResolverFromContainer + : null; + + $routeCollector = $container->has(RouteCollectorInterface::class) + && ( + $routeCollectorFromContainer = $container->get(RouteCollectorInterface::class) + ) instanceof RouteCollectorInterface + ? $routeCollectorFromContainer + : null; + + $routeResolver = $container->has(RouteResolverInterface::class) + && ( + $routeResolverFromContainer = $container->get(RouteResolverInterface::class) + ) instanceof RouteResolverInterface + ? $routeResolverFromContainer + : null; + + $middlewareDispatcher = $container->has(MiddlewareDispatcherInterface::class) + && ( + $middlewareDispatcherFromContainer = $container->get(MiddlewareDispatcherInterface::class) + ) instanceof MiddlewareDispatcherInterface + ? $middlewareDispatcherFromContainer + : null; + + return new App( + $responseFactory, + $container, + $callableResolver, + $routeCollector, + $routeResolver, + $middlewareDispatcher + ); + } + + /** + * @throws RuntimeException + */ + public static function determineResponseFactory(): ResponseFactoryInterface + { + if (static::$responseFactory) { + if (static::$streamFactory) { + return static::attemptResponseFactoryDecoration(static::$responseFactory, static::$streamFactory); + } + return static::$responseFactory; + } + + $psr17FactoryProvider = static::$psr17FactoryProvider ?? new Psr17FactoryProvider(); + + /** @var Psr17Factory $psr17factory */ + foreach ($psr17FactoryProvider->getFactories() as $psr17factory) { + if ($psr17factory::isResponseFactoryAvailable()) { + $responseFactory = $psr17factory::getResponseFactory(); + + if (static::$streamFactory || $psr17factory::isStreamFactoryAvailable()) { + $streamFactory = static::$streamFactory ?? $psr17factory::getStreamFactory(); + return static::attemptResponseFactoryDecoration($responseFactory, $streamFactory); + } + + return $responseFactory; + } + } + + throw new RuntimeException( + "Could not detect any PSR-17 ResponseFactory implementations. " . + "Please install a supported implementation in order to use `AppFactory::create()`. " . + "See https://github.com/slimphp/Slim/blob/4.x/README.md for a list of supported implementations." + ); + } + + protected static function attemptResponseFactoryDecoration( + ResponseFactoryInterface $responseFactory, + StreamFactoryInterface $streamFactory + ): ResponseFactoryInterface { + if ( + static::$slimHttpDecoratorsAutomaticDetectionEnabled + && SlimHttpPsr17Factory::isResponseFactoryAvailable() + ) { + return SlimHttpPsr17Factory::createDecoratedResponseFactory($responseFactory, $streamFactory); + } + + return $responseFactory; + } + + public static function setPsr17FactoryProvider(Psr17FactoryProviderInterface $psr17FactoryProvider): void + { + static::$psr17FactoryProvider = $psr17FactoryProvider; + } + + public static function setResponseFactory(ResponseFactoryInterface $responseFactory): void + { + static::$responseFactory = $responseFactory; + } + + public static function setStreamFactory(StreamFactoryInterface $streamFactory): void + { + static::$streamFactory = $streamFactory; + } + + public static function setContainer(ContainerInterface $container): void + { + static::$container = $container; + } + + public static function setCallableResolver(CallableResolverInterface $callableResolver): void + { + static::$callableResolver = $callableResolver; + } + + public static function setRouteCollector(RouteCollectorInterface $routeCollector): void + { + static::$routeCollector = $routeCollector; + } + + public static function setRouteResolver(RouteResolverInterface $routeResolver): void + { + static::$routeResolver = $routeResolver; + } + + public static function setMiddlewareDispatcher(MiddlewareDispatcherInterface $middlewareDispatcher): void + { + static::$middlewareDispatcher = $middlewareDispatcher; + } + + public static function setSlimHttpDecoratorsAutomaticDetection(bool $enabled): void + { + static::$slimHttpDecoratorsAutomaticDetectionEnabled = $enabled; + } +} diff --git a/Sources/API/vendor/slim/slim/Slim/Factory/Psr17/GuzzlePsr17Factory.php b/Sources/API/vendor/slim/slim/Slim/Factory/Psr17/GuzzlePsr17Factory.php new file mode 100644 index 0000000..32a548a --- /dev/null +++ b/Sources/API/vendor/slim/slim/Slim/Factory/Psr17/GuzzlePsr17Factory.php @@ -0,0 +1,19 @@ +serverRequestCreator = $serverRequestCreator; + $this->serverRequestCreatorMethod = $serverRequestCreatorMethod; + } + + /** + * {@inheritdoc} + */ + public function createServerRequestFromGlobals(): ServerRequestInterface + { + /** @var callable $callable */ + $callable = [$this->serverRequestCreator, $this->serverRequestCreatorMethod]; + return (Closure::fromCallable($callable))(); + } +} diff --git a/Sources/API/vendor/slim/slim/Slim/Factory/Psr17/SlimHttpPsr17Factory.php b/Sources/API/vendor/slim/slim/Slim/Factory/Psr17/SlimHttpPsr17Factory.php new file mode 100644 index 0000000..5d63631 --- /dev/null +++ b/Sources/API/vendor/slim/slim/Slim/Factory/Psr17/SlimHttpPsr17Factory.php @@ -0,0 +1,39 @@ +serverRequestCreator = $serverRequestCreator; + } + + /** + * {@inheritdoc} + */ + public function createServerRequestFromGlobals(): ServerRequestInterface + { + if (!static::isServerRequestDecoratorAvailable()) { + throw new RuntimeException('The Slim-Http ServerRequest decorator is not available.'); + } + + $request = $this->serverRequestCreator->createServerRequestFromGlobals(); + + if ( + !(( + $decoratedServerRequest = new static::$serverRequestDecoratorClass($request) + ) instanceof ServerRequestInterface) + ) { + throw new RuntimeException(get_called_class() . ' could not instantiate a decorated server request.'); + } + + return $decoratedServerRequest; + } + + public static function isServerRequestDecoratorAvailable(): bool + { + return class_exists(static::$serverRequestDecoratorClass); + } +} diff --git a/Sources/API/vendor/slim/slim/Slim/Factory/Psr17/SlimPsr17Factory.php b/Sources/API/vendor/slim/slim/Slim/Factory/Psr17/SlimPsr17Factory.php new file mode 100644 index 0000000..46c46f9 --- /dev/null +++ b/Sources/API/vendor/slim/slim/Slim/Factory/Psr17/SlimPsr17Factory.php @@ -0,0 +1,19 @@ +getFactories() as $psr17Factory) { + if ($psr17Factory::isServerRequestCreatorAvailable()) { + $serverRequestCreator = $psr17Factory::getServerRequestCreator(); + return static::attemptServerRequestCreatorDecoration($serverRequestCreator); + } + } + + throw new RuntimeException( + "Could not detect any ServerRequest creator implementations. " . + "Please install a supported implementation in order to use `App::run()` " . + "without having to pass in a `ServerRequest` object. " . + "See https://github.com/slimphp/Slim/blob/4.x/README.md for a list of supported implementations." + ); + } + + protected static function attemptServerRequestCreatorDecoration( + ServerRequestCreatorInterface $serverRequestCreator + ): ServerRequestCreatorInterface { + if ( + static::$slimHttpDecoratorsAutomaticDetectionEnabled + && SlimHttpServerRequestCreator::isServerRequestDecoratorAvailable() + ) { + return new SlimHttpServerRequestCreator($serverRequestCreator); + } + + return $serverRequestCreator; + } + + public static function setPsr17FactoryProvider(Psr17FactoryProviderInterface $psr17FactoryProvider): void + { + static::$psr17FactoryProvider = $psr17FactoryProvider; + } + + public static function setServerRequestCreator(ServerRequestCreatorInterface $serverRequestCreator): void + { + self::$serverRequestCreator = $serverRequestCreator; + } + + public static function setSlimHttpDecoratorsAutomaticDetection(bool $enabled): void + { + static::$slimHttpDecoratorsAutomaticDetectionEnabled = $enabled; + } +} diff --git a/Sources/API/vendor/slim/slim/Slim/Handlers/ErrorHandler.php b/Sources/API/vendor/slim/slim/Slim/Handlers/ErrorHandler.php new file mode 100644 index 0000000..f9606e3 --- /dev/null +++ b/Sources/API/vendor/slim/slim/Slim/Handlers/ErrorHandler.php @@ -0,0 +1,308 @@ + + */ + protected array $errorRenderers = [ + 'application/json' => JsonErrorRenderer::class, + 'application/xml' => XmlErrorRenderer::class, + 'text/xml' => XmlErrorRenderer::class, + 'text/html' => HtmlErrorRenderer::class, + 'text/plain' => PlainTextErrorRenderer::class, + ]; + + protected bool $displayErrorDetails = false; + + protected bool $logErrors; + + protected bool $logErrorDetails = false; + + protected ?string $contentType = null; + + protected ?string $method = null; + + protected ServerRequestInterface $request; + + protected Throwable $exception; + + protected int $statusCode; + + protected CallableResolverInterface $callableResolver; + + protected ResponseFactoryInterface $responseFactory; + + protected LoggerInterface $logger; + + public function __construct( + CallableResolverInterface $callableResolver, + ResponseFactoryInterface $responseFactory, + ?LoggerInterface $logger = null + ) { + $this->callableResolver = $callableResolver; + $this->responseFactory = $responseFactory; + $this->logger = $logger ?: $this->getDefaultLogger(); + } + + /** + * Invoke error handler + * + * @param ServerRequestInterface $request The most recent Request object + * @param Throwable $exception The caught Exception object + * @param bool $displayErrorDetails Whether or not to display the error details + * @param bool $logErrors Whether or not to log errors + * @param bool $logErrorDetails Whether or not to log error details + */ + public function __invoke( + ServerRequestInterface $request, + Throwable $exception, + bool $displayErrorDetails, + bool $logErrors, + bool $logErrorDetails + ): ResponseInterface { + $this->displayErrorDetails = $displayErrorDetails; + $this->logErrors = $logErrors; + $this->logErrorDetails = $logErrorDetails; + $this->request = $request; + $this->exception = $exception; + $this->method = $request->getMethod(); + $this->statusCode = $this->determineStatusCode(); + if ($this->contentType === null) { + $this->contentType = $this->determineContentType($request); + } + + if ($logErrors) { + $this->writeToErrorLog(); + } + + return $this->respond(); + } + + /** + * Force the content type for all error handler responses. + * + * @param string|null $contentType The content type + */ + public function forceContentType(?string $contentType): void + { + $this->contentType = $contentType; + } + + protected function determineStatusCode(): int + { + if ($this->method === 'OPTIONS') { + return 200; + } + + if ($this->exception instanceof HttpException) { + return $this->exception->getCode(); + } + + return 500; + } + + /** + * Determine which content type we know about is wanted using Accept header + * + * Note: This method is a bare-bones implementation designed specifically for + * Slim's error handling requirements. Consider a fully-feature solution such + * as willdurand/negotiation for any other situation. + */ + protected function determineContentType(ServerRequestInterface $request): ?string + { + $acceptHeader = $request->getHeaderLine('Accept'); + $selectedContentTypes = array_intersect( + explode(',', $acceptHeader), + array_keys($this->errorRenderers) + ); + $count = count($selectedContentTypes); + + if ($count) { + $current = current($selectedContentTypes); + + /** + * Ensure other supported content types take precedence over text/plain + * when multiple content types are provided via Accept header. + */ + if ($current === 'text/plain' && $count > 1) { + $next = next($selectedContentTypes); + if (is_string($next)) { + return $next; + } + } + + if (is_string($current)) { + return $current; + } + } + + if (preg_match('/\+(json|xml)/', $acceptHeader, $matches)) { + $mediaType = 'application/' . $matches[1]; + if (array_key_exists($mediaType, $this->errorRenderers)) { + return $mediaType; + } + } + + return null; + } + + /** + * Determine which renderer to use based on content type + * + * @throws RuntimeException + */ + protected function determineRenderer(): callable + { + if ($this->contentType !== null && array_key_exists($this->contentType, $this->errorRenderers)) { + $renderer = $this->errorRenderers[$this->contentType]; + } else { + $renderer = $this->defaultErrorRenderer; + } + + return $this->callableResolver->resolve($renderer); + } + + /** + * Register an error renderer for a specific content-type + * + * @param string $contentType The content-type this renderer should be registered to + * @param ErrorRendererInterface|string|callable $errorRenderer The error renderer + */ + public function registerErrorRenderer(string $contentType, $errorRenderer): void + { + $this->errorRenderers[$contentType] = $errorRenderer; + } + + /** + * Set the default error renderer + * + * @param string $contentType The content type of the default error renderer + * @param ErrorRendererInterface|string|callable $errorRenderer The default error renderer + */ + public function setDefaultErrorRenderer(string $contentType, $errorRenderer): void + { + $this->defaultErrorRendererContentType = $contentType; + $this->defaultErrorRenderer = $errorRenderer; + } + + /** + * Set the renderer for the error logger + * + * @param ErrorRendererInterface|string|callable $logErrorRenderer + */ + public function setLogErrorRenderer($logErrorRenderer): void + { + $this->logErrorRenderer = $logErrorRenderer; + } + + /** + * Write to the error log if $logErrors has been set to true + */ + protected function writeToErrorLog(): void + { + $renderer = $this->callableResolver->resolve($this->logErrorRenderer); + $error = $renderer($this->exception, $this->logErrorDetails); + if (!$this->displayErrorDetails) { + $error .= "\nTips: To display error details in HTTP response "; + $error .= 'set "displayErrorDetails" to true in the ErrorHandler constructor.'; + } + $this->logError($error); + } + + /** + * Wraps the error_log function so that this can be easily tested + */ + protected function logError(string $error): void + { + $this->logger->error($error); + } + + /** + * Returns a default logger implementation. + */ + protected function getDefaultLogger(): LoggerInterface + { + return new Logger(); + } + + protected function respond(): ResponseInterface + { + $response = $this->responseFactory->createResponse($this->statusCode); + if ($this->contentType !== null && array_key_exists($this->contentType, $this->errorRenderers)) { + $response = $response->withHeader('Content-type', $this->contentType); + } else { + $response = $response->withHeader('Content-type', $this->defaultErrorRendererContentType); + } + + if ($this->exception instanceof HttpMethodNotAllowedException) { + $allowedMethods = implode(', ', $this->exception->getAllowedMethods()); + $response = $response->withHeader('Allow', $allowedMethods); + } + + $renderer = $this->determineRenderer(); + $body = call_user_func($renderer, $this->exception, $this->displayErrorDetails); + if ($body !== false) { + /** @var string $body */ + $response->getBody()->write($body); + } + + return $response; + } +} diff --git a/Sources/API/vendor/slim/slim/Slim/Handlers/Strategies/RequestHandler.php b/Sources/API/vendor/slim/slim/Slim/Handlers/Strategies/RequestHandler.php new file mode 100644 index 0000000..ea88a5f --- /dev/null +++ b/Sources/API/vendor/slim/slim/Slim/Handlers/Strategies/RequestHandler.php @@ -0,0 +1,48 @@ +appendRouteArgumentsToRequestAttributes = $appendRouteArgumentsToRequestAttributes; + } + + /** + * Invoke a route callable that implements RequestHandlerInterface + * + * @param array $routeArguments + */ + public function __invoke( + callable $callable, + ServerRequestInterface $request, + ResponseInterface $response, + array $routeArguments + ): ResponseInterface { + if ($this->appendRouteArgumentsToRequestAttributes) { + foreach ($routeArguments as $k => $v) { + $request = $request->withAttribute($k, $v); + } + } + + return $callable($request); + } +} diff --git a/Sources/API/vendor/slim/slim/Slim/Handlers/Strategies/RequestResponse.php b/Sources/API/vendor/slim/slim/Slim/Handlers/Strategies/RequestResponse.php new file mode 100644 index 0000000..45b2c05 --- /dev/null +++ b/Sources/API/vendor/slim/slim/Slim/Handlers/Strategies/RequestResponse.php @@ -0,0 +1,40 @@ + $routeArguments + */ + public function __invoke( + callable $callable, + ServerRequestInterface $request, + ResponseInterface $response, + array $routeArguments + ): ResponseInterface { + foreach ($routeArguments as $k => $v) { + $request = $request->withAttribute($k, $v); + } + + return $callable($request, $response, $routeArguments); + } +} diff --git a/Sources/API/vendor/slim/slim/Slim/Handlers/Strategies/RequestResponseArgs.php b/Sources/API/vendor/slim/slim/Slim/Handlers/Strategies/RequestResponseArgs.php new file mode 100644 index 0000000..c4ab16d --- /dev/null +++ b/Sources/API/vendor/slim/slim/Slim/Handlers/Strategies/RequestResponseArgs.php @@ -0,0 +1,38 @@ + $routeArguments + */ + public function __invoke( + callable $callable, + ServerRequestInterface $request, + ResponseInterface $response, + array $routeArguments + ): ResponseInterface { + return $callable($request, $response, ...array_values($routeArguments)); + } +} diff --git a/Sources/API/vendor/slim/slim/Slim/Handlers/Strategies/RequestResponseNamedArgs.php b/Sources/API/vendor/slim/slim/Slim/Handlers/Strategies/RequestResponseNamedArgs.php new file mode 100644 index 0000000..651111d --- /dev/null +++ b/Sources/API/vendor/slim/slim/Slim/Handlers/Strategies/RequestResponseNamedArgs.php @@ -0,0 +1,44 @@ += 8.0.0'); + } + } + + /** + * Invoke a route callable with request, response and all route parameters + * as individual arguments. + * + * @param array $routeArguments + */ + public function __invoke( + callable $callable, + ServerRequestInterface $request, + ResponseInterface $response, + array $routeArguments + ): ResponseInterface { + return $callable($request, $response, ...$routeArguments); + } +} diff --git a/Sources/API/vendor/slim/slim/Slim/Interfaces/AdvancedCallableResolverInterface.php b/Sources/API/vendor/slim/slim/Slim/Interfaces/AdvancedCallableResolverInterface.php new file mode 100644 index 0000000..aa1d897 --- /dev/null +++ b/Sources/API/vendor/slim/slim/Slim/Interfaces/AdvancedCallableResolverInterface.php @@ -0,0 +1,28 @@ + $routeArguments The route's placeholder arguments + * + * @return ResponseInterface The response from the callable. + */ + public function __invoke( + callable $callable, + ServerRequestInterface $request, + ResponseInterface $response, + array $routeArguments + ): ResponseInterface; +} diff --git a/Sources/API/vendor/slim/slim/Slim/Interfaces/MiddlewareDispatcherInterface.php b/Sources/API/vendor/slim/slim/Slim/Interfaces/MiddlewareDispatcherInterface.php new file mode 100644 index 0000000..aa7a26a --- /dev/null +++ b/Sources/API/vendor/slim/slim/Slim/Interfaces/MiddlewareDispatcherInterface.php @@ -0,0 +1,42 @@ + + */ + public function getArguments(): array; + + /** + * Set a route argument + */ + public function setArgument(string $name, string $value): RouteInterface; + + /** + * Replace route arguments + * + * @param array $arguments + */ + public function setArguments(array $arguments): self; + + /** + * @param MiddlewareInterface|string|callable $middleware + */ + public function add($middleware): self; + + public function addMiddleware(MiddlewareInterface $middleware): self; + + /** + * Prepare the route for use + * + * @param array $arguments + */ + public function prepare(array $arguments): self; + + /** + * Run route + * + * This method traverses the middleware stack, including the route's callable + * and captures the resultant HTTP response object. It then sends the response + * back to the Application. + */ + public function run(ServerRequestInterface $request): ResponseInterface; +} diff --git a/Sources/API/vendor/slim/slim/Slim/Interfaces/RouteParserInterface.php b/Sources/API/vendor/slim/slim/Slim/Interfaces/RouteParserInterface.php new file mode 100644 index 0000000..03d9326 --- /dev/null +++ b/Sources/API/vendor/slim/slim/Slim/Interfaces/RouteParserInterface.php @@ -0,0 +1,52 @@ + $data Named argument replacement data + * @param array $queryParams Optional query string parameters + * + * @throws RuntimeException If named route does not exist + * @throws InvalidArgumentException If required data not provided + */ + public function relativeUrlFor(string $routeName, array $data = [], array $queryParams = []): string; + + /** + * Build the path for a named route including the base path + * + * @param string $routeName Route name + * @param array $data Named argument replacement data + * @param array $queryParams Optional query string parameters + * + * @throws RuntimeException If named route does not exist + * @throws InvalidArgumentException If required data not provided + */ + public function urlFor(string $routeName, array $data = [], array $queryParams = []): string; + + /** + * Get fully qualified URL for named route + * + * @param UriInterface $uri + * @param string $routeName Route name + * @param array $data Named argument replacement data + * @param array $queryParams Optional query string parameters + */ + public function fullUrlFor(UriInterface $uri, string $routeName, array $data = [], array $queryParams = []): string; +} diff --git a/Sources/API/vendor/slim/slim/Slim/Interfaces/RouteResolverInterface.php b/Sources/API/vendor/slim/slim/Slim/Interfaces/RouteResolverInterface.php new file mode 100644 index 0000000..256a359 --- /dev/null +++ b/Sources/API/vendor/slim/slim/Slim/Interfaces/RouteResolverInterface.php @@ -0,0 +1,17 @@ +getPath() + */ + public function computeRoutingResults(string $uri, string $method): RoutingResults; + + public function resolveRoute(string $identifier): RouteInterface; +} diff --git a/Sources/API/vendor/slim/slim/Slim/Interfaces/ServerRequestCreatorInterface.php b/Sources/API/vendor/slim/slim/Slim/Interfaces/ServerRequestCreatorInterface.php new file mode 100644 index 0000000..54d231e --- /dev/null +++ b/Sources/API/vendor/slim/slim/Slim/Interfaces/ServerRequestCreatorInterface.php @@ -0,0 +1,18 @@ + $context + * + * @throws InvalidArgumentException + */ + public function log($level, $message, array $context = []): void + { + error_log((string) $message); + } +} diff --git a/Sources/API/vendor/slim/slim/Slim/Middleware/BodyParsingMiddleware.php b/Sources/API/vendor/slim/slim/Slim/Middleware/BodyParsingMiddleware.php new file mode 100644 index 0000000..9a90f30 --- /dev/null +++ b/Sources/API/vendor/slim/slim/Slim/Middleware/BodyParsingMiddleware.php @@ -0,0 +1,196 @@ + callable + */ + public function __construct(array $bodyParsers = []) + { + $this->registerDefaultBodyParsers(); + + foreach ($bodyParsers as $mediaType => $parser) { + $this->registerBodyParser($mediaType, $parser); + } + } + + public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface + { + $parsedBody = $request->getParsedBody(); + + if (empty($parsedBody)) { + $parsedBody = $this->parseBody($request); + $request = $request->withParsedBody($parsedBody); + } + + return $handler->handle($request); + } + + /** + * @param string $mediaType A HTTP media type (excluding content-type params). + * @param callable $callable A callable that returns parsed contents for media type. + */ + public function registerBodyParser(string $mediaType, callable $callable): self + { + $this->bodyParsers[$mediaType] = $callable; + return $this; + } + + /** + * @param string $mediaType A HTTP media type (excluding content-type params). + */ + public function hasBodyParser(string $mediaType): bool + { + return isset($this->bodyParsers[$mediaType]); + } + + /** + * @param string $mediaType A HTTP media type (excluding content-type params). + * @throws RuntimeException + */ + public function getBodyParser(string $mediaType): callable + { + if (!isset($this->bodyParsers[$mediaType])) { + throw new RuntimeException('No parser for type ' . $mediaType); + } + return $this->bodyParsers[$mediaType]; + } + + protected function registerDefaultBodyParsers(): void + { + $this->registerBodyParser('application/json', static function ($input) { + $result = json_decode($input, true); + + if (!is_array($result)) { + return null; + } + + return $result; + }); + + $this->registerBodyParser('application/x-www-form-urlencoded', static function ($input) { + parse_str($input, $data); + return $data; + }); + + $xmlCallable = static function ($input) { + $backup = self::disableXmlEntityLoader(true); + $backup_errors = libxml_use_internal_errors(true); + $result = simplexml_load_string($input); + + self::disableXmlEntityLoader($backup); + libxml_clear_errors(); + libxml_use_internal_errors($backup_errors); + + if ($result === false) { + return null; + } + + return $result; + }; + + $this->registerBodyParser('application/xml', $xmlCallable); + $this->registerBodyParser('text/xml', $xmlCallable); + } + + /** + * @return null|array|object + */ + protected function parseBody(ServerRequestInterface $request) + { + $mediaType = $this->getMediaType($request); + if ($mediaType === null) { + return null; + } + + // Check if this specific media type has a parser registered first + if (!isset($this->bodyParsers[$mediaType])) { + // If not, look for a media type with a structured syntax suffix (RFC 6839) + $parts = explode('+', $mediaType); + if (count($parts) >= 2) { + $mediaType = 'application/' . $parts[count($parts) - 1]; + } + } + + if (isset($this->bodyParsers[$mediaType])) { + $body = (string)$request->getBody(); + $parsed = $this->bodyParsers[$mediaType]($body); + + if ($parsed !== null && !is_object($parsed) && !is_array($parsed)) { + throw new RuntimeException( + 'Request body media type parser return value must be an array, an object, or null' + ); + } + + return $parsed; + } + + return null; + } + + /** + * @return string|null The serverRequest media type, minus content-type params + */ + protected function getMediaType(ServerRequestInterface $request): ?string + { + $contentType = $request->getHeader('Content-Type')[0] ?? null; + + if (is_string($contentType) && trim($contentType) !== '') { + $contentTypeParts = explode(';', $contentType); + return strtolower(trim($contentTypeParts[0])); + } + + return null; + } + + protected static function disableXmlEntityLoader(bool $disable): bool + { + if (LIBXML_VERSION >= 20900) { + // libxml >= 2.9.0 disables entity loading by default, so it is + // safe to skip the real call (deprecated in PHP 8). + return true; + } + + // @codeCoverageIgnoreStart + return libxml_disable_entity_loader($disable); + // @codeCoverageIgnoreEnd + } +} diff --git a/Sources/API/vendor/slim/slim/Slim/Middleware/ContentLengthMiddleware.php b/Sources/API/vendor/slim/slim/Slim/Middleware/ContentLengthMiddleware.php new file mode 100644 index 0000000..8fa13bc --- /dev/null +++ b/Sources/API/vendor/slim/slim/Slim/Middleware/ContentLengthMiddleware.php @@ -0,0 +1,32 @@ +handle($request); + + // Add Content-Length header if not already added + $size = $response->getBody()->getSize(); + if ($size !== null && !$response->hasHeader('Content-Length')) { + $response = $response->withHeader('Content-Length', (string) $size); + } + + return $response; + } +} diff --git a/Sources/API/vendor/slim/slim/Slim/Middleware/ErrorMiddleware.php b/Sources/API/vendor/slim/slim/Slim/Middleware/ErrorMiddleware.php new file mode 100644 index 0000000..2eb5cc9 --- /dev/null +++ b/Sources/API/vendor/slim/slim/Slim/Middleware/ErrorMiddleware.php @@ -0,0 +1,212 @@ +callableResolver = $callableResolver; + $this->responseFactory = $responseFactory; + $this->displayErrorDetails = $displayErrorDetails; + $this->logErrors = $logErrors; + $this->logErrorDetails = $logErrorDetails; + $this->logger = $logger; + } + + public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface + { + try { + return $handler->handle($request); + } catch (Throwable $e) { + return $this->handleException($request, $e); + } + } + + public function handleException(ServerRequestInterface $request, Throwable $exception): ResponseInterface + { + if ($exception instanceof HttpException) { + $request = $exception->getRequest(); + } + + $exceptionType = get_class($exception); + $handler = $this->getErrorHandler($exceptionType); + + return $handler($request, $exception, $this->displayErrorDetails, $this->logErrors, $this->logErrorDetails); + } + + /** + * Get callable to handle scenarios where an error + * occurs when processing the current request. + * + * @param string $type Exception/Throwable name. ie: RuntimeException::class + * @return callable|ErrorHandler + */ + public function getErrorHandler(string $type) + { + if (isset($this->handlers[$type])) { + return $this->callableResolver->resolve($this->handlers[$type]); + } + + if (isset($this->subClassHandlers[$type])) { + return $this->callableResolver->resolve($this->subClassHandlers[$type]); + } + + foreach ($this->subClassHandlers as $class => $handler) { + if (is_subclass_of($type, $class)) { + return $this->callableResolver->resolve($handler); + } + } + + return $this->getDefaultErrorHandler(); + } + + /** + * Get default error handler + * + * @return ErrorHandler|callable + */ + public function getDefaultErrorHandler() + { + if ($this->defaultErrorHandler === null) { + $this->defaultErrorHandler = new ErrorHandler( + $this->callableResolver, + $this->responseFactory, + $this->logger + ); + } + + return $this->callableResolver->resolve($this->defaultErrorHandler); + } + + /** + * Set callable as the default Slim application error handler. + * + * The callable signature MUST match the ErrorHandlerInterface + * + * @see \Slim\Interfaces\ErrorHandlerInterface + * + * 1. Instance of \Psr\Http\Message\ServerRequestInterface + * 2. Instance of \Throwable + * 3. Boolean $displayErrorDetails + * 4. Boolean $logErrors + * 5. Boolean $logErrorDetails + * + * The callable MUST return an instance of + * \Psr\Http\Message\ResponseInterface. + * + * @param string|callable|ErrorHandler $handler + */ + public function setDefaultErrorHandler($handler): self + { + $this->defaultErrorHandler = $handler; + return $this; + } + + /** + * Set callable to handle scenarios where an error + * occurs when processing the current request. + * + * The callable signature MUST match the ErrorHandlerInterface + * + * Pass true to $handleSubclasses to make the handler handle all subclasses of + * the type as well. Pass an array of classes to make the same function handle multiple exceptions. + * + * @see \Slim\Interfaces\ErrorHandlerInterface + * + * 1. Instance of \Psr\Http\Message\ServerRequestInterface + * 2. Instance of \Throwable + * 3. Boolean $displayErrorDetails + * 4. Boolean $logErrors + * 5. Boolean $logErrorDetails + * + * The callable MUST return an instance of + * \Psr\Http\Message\ResponseInterface. + * + * @param string|string[] $typeOrTypes Exception/Throwable name. + * ie: RuntimeException::class or an array of classes + * ie: [HttpNotFoundException::class, HttpMethodNotAllowedException::class] + * @param string|callable|ErrorHandlerInterface $handler + */ + public function setErrorHandler($typeOrTypes, $handler, bool $handleSubclasses = false): self + { + if (is_array($typeOrTypes)) { + foreach ($typeOrTypes as $type) { + $this->addErrorHandler($type, $handler, $handleSubclasses); + } + } else { + $this->addErrorHandler($typeOrTypes, $handler, $handleSubclasses); + } + + return $this; + } + + /** + * Used internally to avoid code repetition when passing multiple exceptions to setErrorHandler(). + * @param string|callable|ErrorHandlerInterface $handler + */ + private function addErrorHandler(string $type, $handler, bool $handleSubclasses): void + { + if ($handleSubclasses) { + $this->subClassHandlers[$type] = $handler; + } else { + $this->handlers[$type] = $handler; + } + } +} diff --git a/Sources/API/vendor/slim/slim/Slim/Middleware/MethodOverrideMiddleware.php b/Sources/API/vendor/slim/slim/Slim/Middleware/MethodOverrideMiddleware.php new file mode 100644 index 0000000..079a1f1 --- /dev/null +++ b/Sources/API/vendor/slim/slim/Slim/Middleware/MethodOverrideMiddleware.php @@ -0,0 +1,43 @@ +getHeaderLine('X-Http-Method-Override'); + + if ($methodHeader) { + $request = $request->withMethod($methodHeader); + } elseif (strtoupper($request->getMethod()) === 'POST') { + $body = $request->getParsedBody(); + + if (is_array($body) && !empty($body['_METHOD'])) { + $request = $request->withMethod($body['_METHOD']); + } + + if ($request->getBody()->eof()) { + $request->getBody()->rewind(); + } + } + + return $handler->handle($request); + } +} diff --git a/Sources/API/vendor/slim/slim/Slim/Middleware/OutputBufferingMiddleware.php b/Sources/API/vendor/slim/slim/Slim/Middleware/OutputBufferingMiddleware.php new file mode 100644 index 0000000..69ee1f6 --- /dev/null +++ b/Sources/API/vendor/slim/slim/Slim/Middleware/OutputBufferingMiddleware.php @@ -0,0 +1,74 @@ +streamFactory = $streamFactory; + $this->style = $style; + + if (!in_array($style, [static::APPEND, static::PREPEND], true)) { + throw new InvalidArgumentException("Invalid style `{$style}`. Must be `append` or `prepend`"); + } + } + + /** + * @throws Throwable + */ + public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface + { + try { + ob_start(); + $response = $handler->handle($request); + $output = ob_get_clean(); + } catch (Throwable $e) { + ob_end_clean(); + throw $e; + } + + if (!empty($output)) { + if ($this->style === static::PREPEND) { + $body = $this->streamFactory->createStream(); + $body->write($output . $response->getBody()); + $response = $response->withBody($body); + } elseif ($this->style === static::APPEND && $response->getBody()->isWritable()) { + $response->getBody()->write($output); + } + } + + return $response; + } +} diff --git a/Sources/API/vendor/slim/slim/Slim/Middleware/RoutingMiddleware.php b/Sources/API/vendor/slim/slim/Slim/Middleware/RoutingMiddleware.php new file mode 100644 index 0000000..a3d3085 --- /dev/null +++ b/Sources/API/vendor/slim/slim/Slim/Middleware/RoutingMiddleware.php @@ -0,0 +1,98 @@ +routeResolver = $routeResolver; + $this->routeParser = $routeParser; + } + + /** + * @throws HttpNotFoundException + * @throws HttpMethodNotAllowedException + * @throws RuntimeException + */ + public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface + { + $request = $this->performRouting($request); + return $handler->handle($request); + } + + /** + * Perform routing + * + * @param ServerRequestInterface $request PSR7 Server Request + * + * @throws HttpNotFoundException + * @throws HttpMethodNotAllowedException + * @throws RuntimeException + */ + public function performRouting(ServerRequestInterface $request): ServerRequestInterface + { + $request = $request->withAttribute(RouteContext::ROUTE_PARSER, $this->routeParser); + + $routingResults = $this->resolveRoutingResultsFromRequest($request); + $routeStatus = $routingResults->getRouteStatus(); + + $request = $request->withAttribute(RouteContext::ROUTING_RESULTS, $routingResults); + + switch ($routeStatus) { + case RoutingResults::FOUND: + $routeArguments = $routingResults->getRouteArguments(); + $routeIdentifier = $routingResults->getRouteIdentifier() ?? ''; + $route = $this->routeResolver + ->resolveRoute($routeIdentifier) + ->prepare($routeArguments); + return $request->withAttribute(RouteContext::ROUTE, $route); + + case RoutingResults::NOT_FOUND: + throw new HttpNotFoundException($request); + + case RoutingResults::METHOD_NOT_ALLOWED: + $exception = new HttpMethodNotAllowedException($request); + $exception->setAllowedMethods($routingResults->getAllowedMethods()); + throw $exception; + + default: + throw new RuntimeException('An unexpected error occurred while performing routing.'); + } + } + + /** + * Resolves the route from the given request + */ + protected function resolveRoutingResultsFromRequest(ServerRequestInterface $request): RoutingResults + { + return $this->routeResolver->computeRoutingResults( + $request->getUri()->getPath(), + $request->getMethod() + ); + } +} diff --git a/Sources/API/vendor/slim/slim/Slim/MiddlewareDispatcher.php b/Sources/API/vendor/slim/slim/Slim/MiddlewareDispatcher.php new file mode 100644 index 0000000..7e05644 --- /dev/null +++ b/Sources/API/vendor/slim/slim/Slim/MiddlewareDispatcher.php @@ -0,0 +1,275 @@ +seedMiddlewareStack($kernel); + $this->callableResolver = $callableResolver; + $this->container = $container; + } + + /** + * {@inheritdoc} + */ + public function seedMiddlewareStack(RequestHandlerInterface $kernel): void + { + $this->tip = $kernel; + } + + /** + * Invoke the middleware stack + */ + public function handle(ServerRequestInterface $request): ResponseInterface + { + return $this->tip->handle($request); + } + + /** + * Add a new middleware to the stack + * + * Middleware are organized as a stack. That means middleware + * that have been added before will be executed after the newly + * added one (last in, first out). + * + * @param MiddlewareInterface|string|callable $middleware + */ + public function add($middleware): MiddlewareDispatcherInterface + { + if ($middleware instanceof MiddlewareInterface) { + return $this->addMiddleware($middleware); + } + + if (is_string($middleware)) { + return $this->addDeferred($middleware); + } + + if (is_callable($middleware)) { + return $this->addCallable($middleware); + } + + /** @phpstan-ignore-next-line */ + throw new RuntimeException( + 'A middleware must be an object/class name referencing an implementation of ' . + 'MiddlewareInterface or a callable with a matching signature.' + ); + } + + /** + * Add a new middleware to the stack + * + * Middleware are organized as a stack. That means middleware + * that have been added before will be executed after the newly + * added one (last in, first out). + */ + public function addMiddleware(MiddlewareInterface $middleware): MiddlewareDispatcherInterface + { + $next = $this->tip; + $this->tip = new class ($middleware, $next) implements RequestHandlerInterface { + private MiddlewareInterface $middleware; + + private RequestHandlerInterface $next; + + public function __construct(MiddlewareInterface $middleware, RequestHandlerInterface $next) + { + $this->middleware = $middleware; + $this->next = $next; + } + + public function handle(ServerRequestInterface $request): ResponseInterface + { + return $this->middleware->process($request, $this->next); + } + }; + + return $this; + } + + /** + * Add a new middleware by class name + * + * Middleware are organized as a stack. That means middleware + * that have been added before will be executed after the newly + * added one (last in, first out). + */ + public function addDeferred(string $middleware): self + { + $next = $this->tip; + $this->tip = new class ( + $middleware, + $next, + $this->container, + $this->callableResolver + ) implements RequestHandlerInterface { + private string $middleware; + + private RequestHandlerInterface $next; + + private ?ContainerInterface $container; + + private ?CallableResolverInterface $callableResolver; + + public function __construct( + string $middleware, + RequestHandlerInterface $next, + ?ContainerInterface $container = null, + ?CallableResolverInterface $callableResolver = null + ) { + $this->middleware = $middleware; + $this->next = $next; + $this->container = $container; + $this->callableResolver = $callableResolver; + } + + public function handle(ServerRequestInterface $request): ResponseInterface + { + if ($this->callableResolver instanceof AdvancedCallableResolverInterface) { + $callable = $this->callableResolver->resolveMiddleware($this->middleware); + return $callable($request, $this->next); + } + + $callable = null; + + if ($this->callableResolver instanceof CallableResolverInterface) { + try { + $callable = $this->callableResolver->resolve($this->middleware); + } catch (RuntimeException $e) { + // Do Nothing + } + } + + if (!$callable) { + $resolved = $this->middleware; + $instance = null; + $method = null; + + // Check for Slim callable as `class:method` + if (preg_match(CallableResolver::$callablePattern, $resolved, $matches)) { + $resolved = $matches[1]; + $method = $matches[2]; + } + + if ($this->container && $this->container->has($resolved)) { + $instance = $this->container->get($resolved); + if ($instance instanceof MiddlewareInterface) { + return $instance->process($request, $this->next); + } + } elseif (!function_exists($resolved)) { + if (!class_exists($resolved)) { + throw new RuntimeException(sprintf('Middleware %s does not exist', $resolved)); + } + $instance = new $resolved($this->container); + } + + if ($instance && $instance instanceof MiddlewareInterface) { + return $instance->process($request, $this->next); + } + + $callable = $instance ?? $resolved; + if ($instance && $method) { + $callable = [$instance, $method]; + } + + if ($this->container && $callable instanceof Closure) { + $callable = $callable->bindTo($this->container); + } + } + + if (!is_callable($callable)) { + throw new RuntimeException( + sprintf( + 'Middleware %s is not resolvable', + $this->middleware + ) + ); + } + + return $callable($request, $this->next); + } + }; + + return $this; + } + + /** + * Add a (non-standard) callable middleware to the stack + * + * Middleware are organized as a stack. That means middleware + * that have been added before will be executed after the newly + * added one (last in, first out). + */ + public function addCallable(callable $middleware): self + { + $next = $this->tip; + + if ($this->container && $middleware instanceof Closure) { + /** @var Closure $middleware */ + $middleware = $middleware->bindTo($this->container); + } + + $this->tip = new class ($middleware, $next) implements RequestHandlerInterface { + /** + * @var callable + */ + private $middleware; + + /** + * @var RequestHandlerInterface + */ + private $next; + + public function __construct(callable $middleware, RequestHandlerInterface $next) + { + $this->middleware = $middleware; + $this->next = $next; + } + + public function handle(ServerRequestInterface $request): ResponseInterface + { + return ($this->middleware)($request, $this->next); + } + }; + + return $this; + } +} diff --git a/Sources/API/vendor/slim/slim/Slim/ResponseEmitter.php b/Sources/API/vendor/slim/slim/Slim/ResponseEmitter.php new file mode 100644 index 0000000..fac36e9 --- /dev/null +++ b/Sources/API/vendor/slim/slim/Slim/ResponseEmitter.php @@ -0,0 +1,136 @@ +responseChunkSize = $responseChunkSize; + } + + /** + * Send the response the client + */ + public function emit(ResponseInterface $response): void + { + $isEmpty = $this->isResponseEmpty($response); + if (headers_sent() === false) { + $this->emitHeaders($response); + + // Set the status _after_ the headers, because of PHP's "helpful" behavior with location headers. + // See https://github.com/slimphp/Slim/issues/1730 + + $this->emitStatusLine($response); + } + + if (!$isEmpty) { + $this->emitBody($response); + } + } + + /** + * Emit Response Headers + */ + private function emitHeaders(ResponseInterface $response): void + { + foreach ($response->getHeaders() as $name => $values) { + $first = strtolower($name) !== 'set-cookie'; + foreach ($values as $value) { + $header = sprintf('%s: %s', $name, $value); + header($header, $first); + $first = false; + } + } + } + + /** + * Emit Status Line + */ + private function emitStatusLine(ResponseInterface $response): void + { + $statusLine = sprintf( + 'HTTP/%s %s %s', + $response->getProtocolVersion(), + $response->getStatusCode(), + $response->getReasonPhrase() + ); + header($statusLine, true, $response->getStatusCode()); + } + + /** + * Emit Body + */ + private function emitBody(ResponseInterface $response): void + { + $body = $response->getBody(); + if ($body->isSeekable()) { + $body->rewind(); + } + + $amountToRead = (int) $response->getHeaderLine('Content-Length'); + if (!$amountToRead) { + $amountToRead = $body->getSize(); + } + + if ($amountToRead) { + while ($amountToRead > 0 && !$body->eof()) { + $length = min($this->responseChunkSize, $amountToRead); + $data = $body->read($length); + echo $data; + + $amountToRead -= strlen($data); + + if (connection_status() !== CONNECTION_NORMAL) { + break; + } + } + } else { + while (!$body->eof()) { + echo $body->read($this->responseChunkSize); + if (connection_status() !== CONNECTION_NORMAL) { + break; + } + } + } + } + + /** + * Asserts response body is empty or status code is 204, 205 or 304 + */ + public function isResponseEmpty(ResponseInterface $response): bool + { + if (in_array($response->getStatusCode(), [204, 205, 304], true)) { + return true; + } + $stream = $response->getBody(); + $seekable = $stream->isSeekable(); + if ($seekable) { + $stream->rewind(); + } + return $seekable ? $stream->read(1) === '' : $stream->eof(); + } +} diff --git a/Sources/API/vendor/slim/slim/Slim/Routing/Dispatcher.php b/Sources/API/vendor/slim/slim/Slim/Routing/Dispatcher.php new file mode 100644 index 0000000..e33eac3 --- /dev/null +++ b/Sources/API/vendor/slim/slim/Slim/Routing/Dispatcher.php @@ -0,0 +1,78 @@ +routeCollector = $routeCollector; + } + + protected function createDispatcher(): FastRouteDispatcher + { + if ($this->dispatcher) { + return $this->dispatcher; + } + + $routeDefinitionCallback = function (FastRouteCollector $r): void { + $basePath = $this->routeCollector->getBasePath(); + + foreach ($this->routeCollector->getRoutes() as $route) { + $r->addRoute($route->getMethods(), $basePath . $route->getPattern(), $route->getIdentifier()); + } + }; + + $cacheFile = $this->routeCollector->getCacheFile(); + if ($cacheFile) { + /** @var FastRouteDispatcher $dispatcher */ + $dispatcher = \FastRoute\cachedDispatcher($routeDefinitionCallback, [ + 'dataGenerator' => GroupCountBased::class, + 'dispatcher' => FastRouteDispatcher::class, + 'routeParser' => new Std(), + 'cacheFile' => $cacheFile, + ]); + } else { + /** @var FastRouteDispatcher $dispatcher */ + $dispatcher = \FastRoute\simpleDispatcher($routeDefinitionCallback, [ + 'dataGenerator' => GroupCountBased::class, + 'dispatcher' => FastRouteDispatcher::class, + 'routeParser' => new Std(), + ]); + } + + $this->dispatcher = $dispatcher; + return $this->dispatcher; + } + + /** + * {@inheritdoc} + */ + public function dispatch(string $method, string $uri): RoutingResults + { + $dispatcher = $this->createDispatcher(); + $results = $dispatcher->dispatch($method, $uri); + return new RoutingResults($this, $method, $uri, $results[0], $results[1], $results[2]); + } + + /** + * {@inheritdoc} + */ + public function getAllowedMethods(string $uri): array + { + $dispatcher = $this->createDispatcher(); + return $dispatcher->getAllowedMethods($uri); + } +} diff --git a/Sources/API/vendor/slim/slim/Slim/Routing/FastRouteDispatcher.php b/Sources/API/vendor/slim/slim/Slim/Routing/FastRouteDispatcher.php new file mode 100644 index 0000000..1f567b5 --- /dev/null +++ b/Sources/API/vendor/slim/slim/Slim/Routing/FastRouteDispatcher.php @@ -0,0 +1,109 @@ +} + */ + public function dispatch($httpMethod, $uri): array + { + $routingResults = $this->routingResults($httpMethod, $uri); + if ($routingResults[0] === self::FOUND) { + return $routingResults; + } + + // For HEAD requests, attempt fallback to GET + if ($httpMethod === 'HEAD') { + $routingResults = $this->routingResults('GET', $uri); + if ($routingResults[0] === self::FOUND) { + return $routingResults; + } + } + + // If nothing else matches, try fallback routes + $routingResults = $this->routingResults('*', $uri); + if ($routingResults[0] === self::FOUND) { + return $routingResults; + } + + if (!empty($this->getAllowedMethods($uri))) { + return [self::METHOD_NOT_ALLOWED, null, []]; + } + + return [self::NOT_FOUND, null, []]; + } + + /** + * @param string $httpMethod + * @param string $uri + * + * @return array{int, string|null, array} + */ + private function routingResults(string $httpMethod, string $uri): array + { + if (isset($this->staticRouteMap[$httpMethod][$uri])) { + /** @var string $routeIdentifier */ + $routeIdentifier = $this->staticRouteMap[$httpMethod][$uri]; + return [self::FOUND, $routeIdentifier, []]; + } + + if (isset($this->variableRouteData[$httpMethod])) { + /** @var array{0: int, 1?: string, 2?: array} $result */ + $result = $this->dispatchVariableRoute($this->variableRouteData[$httpMethod], $uri); + if ($result[0] === self::FOUND) { + /** @var array{int, string, array} $result */ + return [self::FOUND, $result[1], $result[2]]; + } + } + + return [self::NOT_FOUND, null, []]; + } + + /** + * @param string $uri + * + * @return string[] + */ + public function getAllowedMethods(string $uri): array + { + if (isset($this->allowedMethods[$uri])) { + return $this->allowedMethods[$uri]; + } + + $this->allowedMethods[$uri] = []; + foreach ($this->staticRouteMap as $method => $uriMap) { + if (isset($uriMap[$uri])) { + $this->allowedMethods[$uri][] = $method; + } + } + + foreach ($this->variableRouteData as $method => $routeData) { + $result = $this->dispatchVariableRoute($routeData, $uri); + if ($result[0] === self::FOUND) { + $this->allowedMethods[$uri][] = $method; + } + } + + return $this->allowedMethods[$uri]; + } +} diff --git a/Sources/API/vendor/slim/slim/Slim/Routing/Route.php b/Sources/API/vendor/slim/slim/Slim/Routing/Route.php new file mode 100644 index 0000000..c498423 --- /dev/null +++ b/Sources/API/vendor/slim/slim/Slim/Routing/Route.php @@ -0,0 +1,360 @@ + + */ + protected array $arguments = []; + + /** + * Route arguments parameters + * + * @var string[] + */ + protected array $savedArguments = []; + + /** + * Container + */ + protected ?ContainerInterface $container = null; + + protected MiddlewareDispatcher $middlewareDispatcher; + + /** + * Route callable + * + * @var callable|string + */ + protected $callable; + + protected CallableResolverInterface $callableResolver; + + protected ResponseFactoryInterface $responseFactory; + + /** + * Route pattern + */ + protected string $pattern; + + protected bool $groupMiddlewareAppended = false; + + /** + * @param string[] $methods The route HTTP methods + * @param string $pattern The route pattern + * @param callable|string $callable The route callable + * @param ResponseFactoryInterface $responseFactory + * @param CallableResolverInterface $callableResolver + * @param ContainerInterface|null $container + * @param InvocationStrategyInterface|null $invocationStrategy + * @param RouteGroup[] $groups The parent route groups + * @param int $identifier The route identifier + */ + public function __construct( + array $methods, + string $pattern, + $callable, + ResponseFactoryInterface $responseFactory, + CallableResolverInterface $callableResolver, + ?ContainerInterface $container = null, + ?InvocationStrategyInterface $invocationStrategy = null, + array $groups = [], + int $identifier = 0 + ) { + $this->methods = $methods; + $this->pattern = $pattern; + $this->callable = $callable; + $this->responseFactory = $responseFactory; + $this->callableResolver = $callableResolver; + $this->container = $container; + $this->invocationStrategy = $invocationStrategy ?? new RequestResponse(); + $this->groups = $groups; + $this->identifier = 'route' . $identifier; + $this->middlewareDispatcher = new MiddlewareDispatcher($this, $callableResolver, $container); + } + + public function getCallableResolver(): CallableResolverInterface + { + return $this->callableResolver; + } + + /** + * {@inheritdoc} + */ + public function getInvocationStrategy(): InvocationStrategyInterface + { + return $this->invocationStrategy; + } + + /** + * {@inheritdoc} + */ + public function setInvocationStrategy(InvocationStrategyInterface $invocationStrategy): RouteInterface + { + $this->invocationStrategy = $invocationStrategy; + return $this; + } + + /** + * {@inheritdoc} + */ + public function getMethods(): array + { + return $this->methods; + } + + /** + * {@inheritdoc} + */ + public function getPattern(): string + { + return $this->pattern; + } + + /** + * {@inheritdoc} + */ + public function setPattern(string $pattern): RouteInterface + { + $this->pattern = $pattern; + return $this; + } + + /** + * {@inheritdoc} + */ + public function getCallable() + { + return $this->callable; + } + + /** + * {@inheritdoc} + */ + public function setCallable($callable): RouteInterface + { + $this->callable = $callable; + return $this; + } + + /** + * {@inheritdoc} + */ + public function getName(): ?string + { + return $this->name; + } + + /** + * {@inheritdoc} + */ + public function setName(string $name): RouteInterface + { + $this->name = $name; + return $this; + } + + /** + * {@inheritdoc} + */ + public function getIdentifier(): string + { + return $this->identifier; + } + + /** + * {@inheritdoc} + */ + public function getArgument(string $name, ?string $default = null): ?string + { + if (array_key_exists($name, $this->arguments)) { + return $this->arguments[$name]; + } + return $default; + } + + /** + * {@inheritdoc} + */ + public function getArguments(): array + { + return $this->arguments; + } + + /** + * {@inheritdoc} + */ + public function setArguments(array $arguments, bool $includeInSavedArguments = true): RouteInterface + { + if ($includeInSavedArguments) { + $this->savedArguments = $arguments; + } + + $this->arguments = $arguments; + return $this; + } + + /** + * @return RouteGroupInterface[] + */ + public function getGroups(): array + { + return $this->groups; + } + + /** + * {@inheritdoc} + */ + public function add($middleware): RouteInterface + { + $this->middlewareDispatcher->add($middleware); + return $this; + } + + /** + * {@inheritdoc} + */ + public function addMiddleware(MiddlewareInterface $middleware): RouteInterface + { + $this->middlewareDispatcher->addMiddleware($middleware); + return $this; + } + + /** + * {@inheritdoc} + */ + public function prepare(array $arguments): RouteInterface + { + $this->arguments = array_replace($this->savedArguments, $arguments); + return $this; + } + + /** + * {@inheritdoc} + */ + public function setArgument(string $name, string $value, bool $includeInSavedArguments = true): RouteInterface + { + if ($includeInSavedArguments) { + $this->savedArguments[$name] = $value; + } + + $this->arguments[$name] = $value; + return $this; + } + + /** + * {@inheritdoc} + */ + public function run(ServerRequestInterface $request): ResponseInterface + { + if (!$this->groupMiddlewareAppended) { + $this->appendGroupMiddlewareToRoute(); + } + + return $this->middlewareDispatcher->handle($request); + } + + /** + * @return void + */ + protected function appendGroupMiddlewareToRoute(): void + { + $inner = $this->middlewareDispatcher; + $this->middlewareDispatcher = new MiddlewareDispatcher($inner, $this->callableResolver, $this->container); + + /** @var RouteGroupInterface $group */ + foreach (array_reverse($this->groups) as $group) { + $group->appendMiddlewareToDispatcher($this->middlewareDispatcher); + } + + $this->groupMiddlewareAppended = true; + } + + /** + * {@inheritdoc} + */ + public function handle(ServerRequestInterface $request): ResponseInterface + { + if ($this->callableResolver instanceof AdvancedCallableResolverInterface) { + $callable = $this->callableResolver->resolveRoute($this->callable); + } else { + $callable = $this->callableResolver->resolve($this->callable); + } + $strategy = $this->invocationStrategy; + + /** @var string[] $strategyImplements */ + $strategyImplements = class_implements($strategy); + + if ( + is_array($callable) + && $callable[0] instanceof RequestHandlerInterface + && !in_array(RequestHandlerInvocationStrategyInterface::class, $strategyImplements) + ) { + $strategy = new RequestHandler(); + } + + $response = $this->responseFactory->createResponse(); + return $strategy($callable, $request, $response, $this->arguments); + } +} diff --git a/Sources/API/vendor/slim/slim/Slim/Routing/RouteCollector.php b/Sources/API/vendor/slim/slim/Slim/Routing/RouteCollector.php new file mode 100644 index 0000000..4a74285 --- /dev/null +++ b/Sources/API/vendor/slim/slim/Slim/Routing/RouteCollector.php @@ -0,0 +1,280 @@ +responseFactory = $responseFactory; + $this->callableResolver = $callableResolver; + $this->container = $container; + $this->defaultInvocationStrategy = $defaultInvocationStrategy ?? new RequestResponse(); + $this->routeParser = $routeParser ?? new RouteParser($this); + + if ($cacheFile) { + $this->setCacheFile($cacheFile); + } + } + + public function getRouteParser(): RouteParserInterface + { + return $this->routeParser; + } + + /** + * Get default route invocation strategy + */ + public function getDefaultInvocationStrategy(): InvocationStrategyInterface + { + return $this->defaultInvocationStrategy; + } + + public function setDefaultInvocationStrategy(InvocationStrategyInterface $strategy): RouteCollectorInterface + { + $this->defaultInvocationStrategy = $strategy; + return $this; + } + + /** + * {@inheritdoc} + */ + public function getCacheFile(): ?string + { + return $this->cacheFile; + } + + /** + * {@inheritdoc} + */ + public function setCacheFile(string $cacheFile): RouteCollectorInterface + { + if (file_exists($cacheFile) && !is_readable($cacheFile)) { + throw new RuntimeException( + sprintf('Route collector cache file `%s` is not readable', $cacheFile) + ); + } + + if (!file_exists($cacheFile) && !is_writable(dirname($cacheFile))) { + throw new RuntimeException( + sprintf('Route collector cache file directory `%s` is not writable', dirname($cacheFile)) + ); + } + + $this->cacheFile = $cacheFile; + return $this; + } + + /** + * {@inheritdoc} + */ + public function getBasePath(): string + { + return $this->basePath; + } + + /** + * Set the base path used in urlFor() + */ + public function setBasePath(string $basePath): RouteCollectorInterface + { + $this->basePath = $basePath; + + return $this; + } + + /** + * {@inheritdoc} + */ + public function getRoutes(): array + { + return $this->routes; + } + + /** + * {@inheritdoc} + */ + public function removeNamedRoute(string $name): RouteCollectorInterface + { + $route = $this->getNamedRoute($name); + + unset($this->routesByName[$route->getName()], $this->routes[$route->getIdentifier()]); + return $this; + } + + /** + * {@inheritdoc} + */ + public function getNamedRoute(string $name): RouteInterface + { + if (isset($this->routesByName[$name])) { + $route = $this->routesByName[$name]; + if ($route->getName() === $name) { + return $route; + } + + unset($this->routesByName[$name]); + } + + foreach ($this->routes as $route) { + if ($name === $route->getName()) { + $this->routesByName[$name] = $route; + return $route; + } + } + + throw new RuntimeException('Named route does not exist for name: ' . $name); + } + + /** + * {@inheritdoc} + */ + public function lookupRoute(string $identifier): RouteInterface + { + if (!isset($this->routes[$identifier])) { + throw new RuntimeException('Route not found, looks like your route cache is stale.'); + } + return $this->routes[$identifier]; + } + + /** + * {@inheritdoc} + */ + public function group(string $pattern, $callable): RouteGroupInterface + { + $routeCollectorProxy = new RouteCollectorProxy( + $this->responseFactory, + $this->callableResolver, + $this->container, + $this, + $pattern + ); + + $routeGroup = new RouteGroup($pattern, $callable, $this->callableResolver, $routeCollectorProxy); + $this->routeGroups[] = $routeGroup; + + $routeGroup->collectRoutes(); + array_pop($this->routeGroups); + + return $routeGroup; + } + + /** + * {@inheritdoc} + */ + public function map(array $methods, string $pattern, $handler): RouteInterface + { + $route = $this->createRoute($methods, $pattern, $handler); + $this->routes[$route->getIdentifier()] = $route; + + $routeName = $route->getName(); + if ($routeName !== null && !isset($this->routesByName[$routeName])) { + $this->routesByName[$routeName] = $route; + } + + $this->routeCounter++; + + return $route; + } + + /** + * @param string[] $methods + * @param callable|string $callable + */ + protected function createRoute(array $methods, string $pattern, $callable): RouteInterface + { + return new Route( + $methods, + $pattern, + $callable, + $this->responseFactory, + $this->callableResolver, + $this->container, + $this->defaultInvocationStrategy, + $this->routeGroups, + $this->routeCounter + ); + } +} diff --git a/Sources/API/vendor/slim/slim/Slim/Routing/RouteCollectorProxy.php b/Sources/API/vendor/slim/slim/Slim/Routing/RouteCollectorProxy.php new file mode 100644 index 0000000..f8bc232 --- /dev/null +++ b/Sources/API/vendor/slim/slim/Slim/Routing/RouteCollectorProxy.php @@ -0,0 +1,187 @@ +responseFactory = $responseFactory; + $this->callableResolver = $callableResolver; + $this->container = $container; + $this->routeCollector = $routeCollector ?? new RouteCollector($responseFactory, $callableResolver, $container); + $this->groupPattern = $groupPattern; + } + + /** + * {@inheritdoc} + */ + public function getResponseFactory(): ResponseFactoryInterface + { + return $this->responseFactory; + } + + /** + * {@inheritdoc} + */ + public function getCallableResolver(): CallableResolverInterface + { + return $this->callableResolver; + } + + /** + * {@inheritdoc} + */ + public function getContainer(): ?ContainerInterface + { + return $this->container; + } + + /** + * {@inheritdoc} + */ + public function getRouteCollector(): RouteCollectorInterface + { + return $this->routeCollector; + } + + /** + * {@inheritdoc} + */ + public function getBasePath(): string + { + return $this->routeCollector->getBasePath(); + } + + /** + * {@inheritdoc} + */ + public function setBasePath(string $basePath): RouteCollectorProxyInterface + { + $this->routeCollector->setBasePath($basePath); + + return $this; + } + + /** + * {@inheritdoc} + */ + public function get(string $pattern, $callable): RouteInterface + { + return $this->map(['GET'], $pattern, $callable); + } + + /** + * {@inheritdoc} + */ + public function post(string $pattern, $callable): RouteInterface + { + return $this->map(['POST'], $pattern, $callable); + } + + /** + * {@inheritdoc} + */ + public function put(string $pattern, $callable): RouteInterface + { + return $this->map(['PUT'], $pattern, $callable); + } + + /** + * {@inheritdoc} + */ + public function patch(string $pattern, $callable): RouteInterface + { + return $this->map(['PATCH'], $pattern, $callable); + } + + /** + * {@inheritdoc} + */ + public function delete(string $pattern, $callable): RouteInterface + { + return $this->map(['DELETE'], $pattern, $callable); + } + + /** + * {@inheritdoc} + */ + public function options(string $pattern, $callable): RouteInterface + { + return $this->map(['OPTIONS'], $pattern, $callable); + } + + /** + * {@inheritdoc} + */ + public function any(string $pattern, $callable): RouteInterface + { + return $this->map(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'], $pattern, $callable); + } + + /** + * {@inheritdoc} + */ + public function map(array $methods, string $pattern, $callable): RouteInterface + { + $pattern = $this->groupPattern . $pattern; + + return $this->routeCollector->map($methods, $pattern, $callable); + } + + /** + * {@inheritdoc} + */ + public function group(string $pattern, $callable): RouteGroupInterface + { + $pattern = $this->groupPattern . $pattern; + + return $this->routeCollector->group($pattern, $callable); + } + + /** + * {@inheritdoc} + */ + public function redirect(string $from, $to, int $status = 302): RouteInterface + { + $responseFactory = $this->responseFactory; + + $handler = function () use ($to, $status, $responseFactory) { + $response = $responseFactory->createResponse($status); + return $response->withHeader('Location', (string) $to); + }; + + return $this->get($from, $handler); + } +} diff --git a/Sources/API/vendor/slim/slim/Slim/Routing/RouteContext.php b/Sources/API/vendor/slim/slim/Slim/Routing/RouteContext.php new file mode 100644 index 0000000..3ba5e23 --- /dev/null +++ b/Sources/API/vendor/slim/slim/Slim/Routing/RouteContext.php @@ -0,0 +1,88 @@ +getAttribute(self::ROUTE); + $routeParser = $serverRequest->getAttribute(self::ROUTE_PARSER); + $routingResults = $serverRequest->getAttribute(self::ROUTING_RESULTS); + $basePath = $serverRequest->getAttribute(self::BASE_PATH); + + if ($routeParser === null || $routingResults === null) { + throw new RuntimeException('Cannot create RouteContext before routing has been completed'); + } + + /** @var RouteInterface|null $route */ + /** @var RouteParserInterface $routeParser */ + /** @var RoutingResults $routingResults */ + /** @var string|null $basePath */ + return new self($route, $routeParser, $routingResults, $basePath); + } + + private ?RouteInterface $route; + + private RouteParserInterface $routeParser; + + private RoutingResults $routingResults; + + private ?string $basePath; + + private function __construct( + ?RouteInterface $route, + RouteParserInterface $routeParser, + RoutingResults $routingResults, + ?string $basePath = null + ) { + $this->route = $route; + $this->routeParser = $routeParser; + $this->routingResults = $routingResults; + $this->basePath = $basePath; + } + + public function getRoute(): ?RouteInterface + { + return $this->route; + } + + public function getRouteParser(): RouteParserInterface + { + return $this->routeParser; + } + + public function getRoutingResults(): RoutingResults + { + return $this->routingResults; + } + + public function getBasePath(): string + { + if ($this->basePath === null) { + throw new RuntimeException('No base path defined.'); + } + return $this->basePath; + } +} diff --git a/Sources/API/vendor/slim/slim/Slim/Routing/RouteGroup.php b/Sources/API/vendor/slim/slim/Slim/Routing/RouteGroup.php new file mode 100644 index 0000000..cd2f4e7 --- /dev/null +++ b/Sources/API/vendor/slim/slim/Slim/Routing/RouteGroup.php @@ -0,0 +1,104 @@ +pattern = $pattern; + $this->callable = $callable; + $this->callableResolver = $callableResolver; + $this->routeCollectorProxy = $routeCollectorProxy; + } + + /** + * {@inheritdoc} + */ + public function collectRoutes(): RouteGroupInterface + { + if ($this->callableResolver instanceof AdvancedCallableResolverInterface) { + $callable = $this->callableResolver->resolveRoute($this->callable); + } else { + $callable = $this->callableResolver->resolve($this->callable); + } + $callable($this->routeCollectorProxy); + return $this; + } + + /** + * {@inheritdoc} + */ + public function add($middleware): RouteGroupInterface + { + $this->middleware[] = $middleware; + return $this; + } + + /** + * {@inheritdoc} + */ + public function addMiddleware(MiddlewareInterface $middleware): RouteGroupInterface + { + $this->middleware[] = $middleware; + return $this; + } + + /** + * {@inheritdoc} + */ + public function appendMiddlewareToDispatcher(MiddlewareDispatcher $dispatcher): RouteGroupInterface + { + foreach ($this->middleware as $middleware) { + $dispatcher->add($middleware); + } + + return $this; + } + + /** + * {@inheritdoc} + */ + public function getPattern(): string + { + return $this->pattern; + } +} diff --git a/Sources/API/vendor/slim/slim/Slim/Routing/RouteParser.php b/Sources/API/vendor/slim/slim/Slim/Routing/RouteParser.php new file mode 100644 index 0000000..afb533c --- /dev/null +++ b/Sources/API/vendor/slim/slim/Slim/Routing/RouteParser.php @@ -0,0 +1,127 @@ +routeCollector = $routeCollector; + $this->routeParser = new Std(); + } + + /** + * {@inheritdoc} + */ + public function relativeUrlFor(string $routeName, array $data = [], array $queryParams = []): string + { + $route = $this->routeCollector->getNamedRoute($routeName); + $pattern = $route->getPattern(); + + $segments = []; + $segmentName = ''; + + /* + * $routes is an associative array of expressions representing a route as multiple segments + * There is an expression for each optional parameter plus one without the optional parameters + * The most specific is last, hence why we reverse the array before iterating over it + */ + $expressions = array_reverse($this->routeParser->parse($pattern)); + foreach ($expressions as $expression) { + foreach ($expression as $segment) { + /* + * Each $segment is either a string or an array of strings + * containing optional parameters of an expression + */ + if (is_string($segment)) { + $segments[] = $segment; + continue; + } + + /** @var string[] $segment */ + /* + * If we don't have a data element for this segment in the provided $data + * we cancel testing to move onto the next expression with a less specific item + */ + if (!array_key_exists($segment[0], $data)) { + $segments = []; + $segmentName = $segment[0]; + break; + } + + $segments[] = $data[$segment[0]]; + } + + /* + * If we get to this logic block we have found all the parameters + * for the provided $data which means we don't need to continue testing + * less specific expressions + */ + if (!empty($segments)) { + break; + } + } + + if (empty($segments)) { + throw new InvalidArgumentException('Missing data for URL segment: ' . $segmentName); + } + + $url = implode('', $segments); + if ($queryParams) { + $url .= '?' . http_build_query($queryParams); + } + + return $url; + } + + /** + * {@inheritdoc} + */ + public function urlFor(string $routeName, array $data = [], array $queryParams = []): string + { + $basePath = $this->routeCollector->getBasePath(); + $url = $this->relativeUrlFor($routeName, $data, $queryParams); + + if ($basePath) { + $url = $basePath . $url; + } + + return $url; + } + + /** + * {@inheritdoc} + */ + public function fullUrlFor(UriInterface $uri, string $routeName, array $data = [], array $queryParams = []): string + { + $path = $this->urlFor($routeName, $data, $queryParams); + $scheme = $uri->getScheme(); + $authority = $uri->getAuthority(); + $protocol = ($scheme ? $scheme . ':' : '') . ($authority ? '//' . $authority : ''); + return $protocol . $path; + } +} diff --git a/Sources/API/vendor/slim/slim/Slim/Routing/RouteResolver.php b/Sources/API/vendor/slim/slim/Slim/Routing/RouteResolver.php new file mode 100644 index 0000000..d4f4eaf --- /dev/null +++ b/Sources/API/vendor/slim/slim/Slim/Routing/RouteResolver.php @@ -0,0 +1,56 @@ +routeCollector = $routeCollector; + $this->dispatcher = $dispatcher ?? new Dispatcher($routeCollector); + } + + /** + * @param string $uri Should be $request->getUri()->getPath() + */ + public function computeRoutingResults(string $uri, string $method): RoutingResults + { + $uri = rawurldecode($uri); + if ($uri === '' || $uri[0] !== '/') { + $uri = '/' . $uri; + } + return $this->dispatcher->dispatch($method, $uri); + } + + /** + * @throws RuntimeException + */ + public function resolveRoute(string $identifier): RouteInterface + { + return $this->routeCollector->lookupRoute($identifier); + } +} diff --git a/Sources/API/vendor/slim/slim/Slim/Routing/RouteRunner.php b/Sources/API/vendor/slim/slim/Slim/Routing/RouteRunner.php new file mode 100644 index 0000000..40946af --- /dev/null +++ b/Sources/API/vendor/slim/slim/Slim/Routing/RouteRunner.php @@ -0,0 +1,70 @@ +routeResolver = $routeResolver; + $this->routeParser = $routeParser; + $this->routeCollectorProxy = $routeCollectorProxy; + } + + /** + * This request handler is instantiated automatically in App::__construct() + * It is at the very tip of the middleware queue meaning it will be executed + * last and it detects whether or not routing has been performed in the user + * defined middleware stack. In the event that the user did not perform routing + * it is done here + * + * @throws HttpNotFoundException + * @throws HttpMethodNotAllowedException + */ + public function handle(ServerRequestInterface $request): ResponseInterface + { + // If routing hasn't been done, then do it now so we can dispatch + if ($request->getAttribute(RouteContext::ROUTING_RESULTS) === null) { + $routingMiddleware = new RoutingMiddleware($this->routeResolver, $this->routeParser); + $request = $routingMiddleware->performRouting($request); + } + + if ($this->routeCollectorProxy !== null) { + $request = $request->withAttribute( + RouteContext::BASE_PATH, + $this->routeCollectorProxy->getBasePath() + ); + } + + /** @var Route $route */ + $route = $request->getAttribute(RouteContext::ROUTE); + return $route->run($request); + } +} diff --git a/Sources/API/vendor/slim/slim/Slim/Routing/RoutingResults.php b/Sources/API/vendor/slim/slim/Slim/Routing/RoutingResults.php new file mode 100644 index 0000000..ac2fa64 --- /dev/null +++ b/Sources/API/vendor/slim/slim/Slim/Routing/RoutingResults.php @@ -0,0 +1,112 @@ + + */ + protected array $routeArguments; + + /** + * @param array $routeArguments + */ + public function __construct( + DispatcherInterface $dispatcher, + string $method, + string $uri, + int $routeStatus, + ?string $routeIdentifier = null, + array $routeArguments = [] + ) { + $this->dispatcher = $dispatcher; + $this->method = $method; + $this->uri = $uri; + $this->routeStatus = $routeStatus; + $this->routeIdentifier = $routeIdentifier; + $this->routeArguments = $routeArguments; + } + + public function getDispatcher(): DispatcherInterface + { + return $this->dispatcher; + } + + public function getMethod(): string + { + return $this->method; + } + + public function getUri(): string + { + return $this->uri; + } + + public function getRouteStatus(): int + { + return $this->routeStatus; + } + + public function getRouteIdentifier(): ?string + { + return $this->routeIdentifier; + } + + /** + * @return array + */ + public function getRouteArguments(bool $urlDecode = true): array + { + if (!$urlDecode) { + return $this->routeArguments; + } + + $routeArguments = []; + foreach ($this->routeArguments as $key => $value) { + $routeArguments[$key] = rawurldecode($value); + } + + return $routeArguments; + } + + /** + * @return string[] + */ + public function getAllowedMethods(): array + { + return $this->dispatcher->getAllowedMethods($this->uri); + } +} diff --git a/Sources/API/vendor/slim/slim/composer.json b/Sources/API/vendor/slim/slim/composer.json new file mode 100644 index 0000000..31e8b55 --- /dev/null +++ b/Sources/API/vendor/slim/slim/composer.json @@ -0,0 +1,102 @@ +{ + "name": "slim/slim", + "type": "library", + "description": "Slim is a PHP micro framework that helps you quickly write simple yet powerful web applications and APIs", + "keywords": ["framework","micro","api","router"], + "homepage": "https://www.slimframework.com", + "license": "MIT", + "authors": [ + { + "name": "Josh Lockhart", + "email": "hello@joshlockhart.com", + "homepage": "https://joshlockhart.com" + }, + { + "name": "Andrew Smith", + "email": "a.smith@silentworks.co.uk", + "homepage": "http://silentworks.co.uk" + }, + { + "name": "Rob Allen", + "email": "rob@akrabat.com", + "homepage": "http://akrabat.com" + }, + { + "name": "Pierre Berube", + "email": "pierre@lgse.com", + "homepage": "http://www.lgse.com" + }, + { + "name": "Gabriel Manricks", + "email": "gmanricks@me.com", + "homepage": "http://gabrielmanricks.com" + } + ], + "support": { + "docs": "https://www.slimframework.com/docs/v4/", + "forum": "https://discourse.slimframework.com/", + "irc": "irc://irc.freenode.net:6667/slimphp", + "issues": "https://github.com/slimphp/Slim/issues", + "rss": "https://www.slimframework.com/blog/feed.rss", + "slack": "https://slimphp.slack.com/", + "source": "https://github.com/slimphp/Slim", + "wiki": "https://github.com/slimphp/Slim/wiki" + }, + "require": { + "php": "^7.4 || ^8.0", + "ext-json": "*", + "nikic/fast-route": "^1.3", + "psr/container": "^1.0 || ^2.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.0", + "psr/http-server-handler": "^1.0", + "psr/http-server-middleware": "^1.0", + "psr/log": "^1.1 || ^2.0 || ^3.0" + }, + "require-dev": { + "ext-simplexml": "*", + "adriansuter/php-autoload-override": "^1.3", + "guzzlehttp/psr7": "^2.4", + "httpsoft/http-message": "^1.0", + "httpsoft/http-server-request": "^1.0", + "laminas/laminas-diactoros": "^2.17", + "nyholm/psr7": "^1.5", + "nyholm/psr7-server": "^1.0", + "phpspec/prophecy": "^1.15", + "phpspec/prophecy-phpunit": "^2.0", + "phpstan/phpstan": "^1.8", + "phpunit/phpunit": "^9.5", + "slim/http": "^1.2", + "slim/psr7": "^1.5", + "squizlabs/php_codesniffer": "^3.7" + }, + "autoload": { + "psr-4": { + "Slim\\": "Slim" + } + }, + "autoload-dev": { + "psr-4": { + "Slim\\Tests\\": "tests" + } + }, + "scripts": { + "test": [ + "@phpunit", + "@phpcs", + "@phpstan" + ], + "phpunit": "phpunit", + "phpcs": "phpcs", + "phpstan": "phpstan --memory-limit=-1" + }, + "suggest": { + "ext-simplexml": "Needed to support XML format in BodyParsingMiddleware", + "ext-xml": "Needed to support XML format in BodyParsingMiddleware", + "slim/psr7": "Slim PSR-7 implementation. See https://www.slimframework.com/docs/v4/start/installation.html for more information.", + "php-di/php-di": "PHP-DI is the recommended container library to be used with Slim" + }, + "config": { + "sort-packages": true + } +} diff --git a/Sources/API/vendor/symfony/polyfill-php80/LICENSE b/Sources/API/vendor/symfony/polyfill-php80/LICENSE new file mode 100644 index 0000000..5593b1d --- /dev/null +++ b/Sources/API/vendor/symfony/polyfill-php80/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2020 Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/Sources/API/vendor/symfony/polyfill-php80/Php80.php b/Sources/API/vendor/symfony/polyfill-php80/Php80.php new file mode 100644 index 0000000..362dd1a --- /dev/null +++ b/Sources/API/vendor/symfony/polyfill-php80/Php80.php @@ -0,0 +1,115 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Polyfill\Php80; + +/** + * @author Ion Bazan + * @author Nico Oelgart + * @author Nicolas Grekas + * + * @internal + */ +final class Php80 +{ + public static function fdiv(float $dividend, float $divisor): float + { + return @($dividend / $divisor); + } + + public static function get_debug_type($value): string + { + switch (true) { + case null === $value: return 'null'; + case \is_bool($value): return 'bool'; + case \is_string($value): return 'string'; + case \is_array($value): return 'array'; + case \is_int($value): return 'int'; + case \is_float($value): return 'float'; + case \is_object($value): break; + case $value instanceof \__PHP_Incomplete_Class: return '__PHP_Incomplete_Class'; + default: + if (null === $type = @get_resource_type($value)) { + return 'unknown'; + } + + if ('Unknown' === $type) { + $type = 'closed'; + } + + return "resource ($type)"; + } + + $class = \get_class($value); + + if (false === strpos($class, '@')) { + return $class; + } + + return (get_parent_class($class) ?: key(class_implements($class)) ?: 'class').'@anonymous'; + } + + public static function get_resource_id($res): int + { + if (!\is_resource($res) && null === @get_resource_type($res)) { + throw new \TypeError(sprintf('Argument 1 passed to get_resource_id() must be of the type resource, %s given', get_debug_type($res))); + } + + return (int) $res; + } + + public static function preg_last_error_msg(): string + { + switch (preg_last_error()) { + case \PREG_INTERNAL_ERROR: + return 'Internal error'; + case \PREG_BAD_UTF8_ERROR: + return 'Malformed UTF-8 characters, possibly incorrectly encoded'; + case \PREG_BAD_UTF8_OFFSET_ERROR: + return 'The offset did not correspond to the beginning of a valid UTF-8 code point'; + case \PREG_BACKTRACK_LIMIT_ERROR: + return 'Backtrack limit exhausted'; + case \PREG_RECURSION_LIMIT_ERROR: + return 'Recursion limit exhausted'; + case \PREG_JIT_STACKLIMIT_ERROR: + return 'JIT stack limit exhausted'; + case \PREG_NO_ERROR: + return 'No error'; + default: + return 'Unknown error'; + } + } + + public static function str_contains(string $haystack, string $needle): bool + { + return '' === $needle || false !== strpos($haystack, $needle); + } + + public static function str_starts_with(string $haystack, string $needle): bool + { + return 0 === strncmp($haystack, $needle, \strlen($needle)); + } + + public static function str_ends_with(string $haystack, string $needle): bool + { + if ('' === $needle || $needle === $haystack) { + return true; + } + + if ('' === $haystack) { + return false; + } + + $needleLength = \strlen($needle); + + return $needleLength <= \strlen($haystack) && 0 === substr_compare($haystack, $needle, -$needleLength); + } +} diff --git a/Sources/API/vendor/symfony/polyfill-php80/PhpToken.php b/Sources/API/vendor/symfony/polyfill-php80/PhpToken.php new file mode 100644 index 0000000..fe6e691 --- /dev/null +++ b/Sources/API/vendor/symfony/polyfill-php80/PhpToken.php @@ -0,0 +1,103 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Polyfill\Php80; + +/** + * @author Fedonyuk Anton + * + * @internal + */ +class PhpToken implements \Stringable +{ + /** + * @var int + */ + public $id; + + /** + * @var string + */ + public $text; + + /** + * @var int + */ + public $line; + + /** + * @var int + */ + public $pos; + + public function __construct(int $id, string $text, int $line = -1, int $position = -1) + { + $this->id = $id; + $this->text = $text; + $this->line = $line; + $this->pos = $position; + } + + public function getTokenName(): ?string + { + if ('UNKNOWN' === $name = token_name($this->id)) { + $name = \strlen($this->text) > 1 || \ord($this->text) < 32 ? null : $this->text; + } + + return $name; + } + + /** + * @param int|string|array $kind + */ + public function is($kind): bool + { + foreach ((array) $kind as $value) { + if (\in_array($value, [$this->id, $this->text], true)) { + return true; + } + } + + return false; + } + + public function isIgnorable(): bool + { + return \in_array($this->id, [\T_WHITESPACE, \T_COMMENT, \T_DOC_COMMENT, \T_OPEN_TAG], true); + } + + public function __toString(): string + { + return (string) $this->text; + } + + /** + * @return static[] + */ + public static function tokenize(string $code, int $flags = 0): array + { + $line = 1; + $position = 0; + $tokens = token_get_all($code, $flags); + foreach ($tokens as $index => $token) { + if (\is_string($token)) { + $id = \ord($token); + $text = $token; + } else { + [$id, $text, $line] = $token; + } + $tokens[$index] = new static($id, $text, $line, $position); + $position += \strlen($text); + } + + return $tokens; + } +} diff --git a/Sources/API/vendor/symfony/polyfill-php80/README.md b/Sources/API/vendor/symfony/polyfill-php80/README.md new file mode 100644 index 0000000..3816c55 --- /dev/null +++ b/Sources/API/vendor/symfony/polyfill-php80/README.md @@ -0,0 +1,25 @@ +Symfony Polyfill / Php80 +======================== + +This component provides features added to PHP 8.0 core: + +- [`Stringable`](https://php.net/stringable) interface +- [`fdiv`](https://php.net/fdiv) +- [`ValueError`](https://php.net/valueerror) class +- [`UnhandledMatchError`](https://php.net/unhandledmatcherror) class +- `FILTER_VALIDATE_BOOL` constant +- [`get_debug_type`](https://php.net/get_debug_type) +- [`PhpToken`](https://php.net/phptoken) class +- [`preg_last_error_msg`](https://php.net/preg_last_error_msg) +- [`str_contains`](https://php.net/str_contains) +- [`str_starts_with`](https://php.net/str_starts_with) +- [`str_ends_with`](https://php.net/str_ends_with) +- [`get_resource_id`](https://php.net/get_resource_id) + +More information can be found in the +[main Polyfill README](https://github.com/symfony/polyfill/blob/main/README.md). + +License +======= + +This library is released under the [MIT license](LICENSE). diff --git a/Sources/API/vendor/symfony/polyfill-php80/Resources/stubs/Attribute.php b/Sources/API/vendor/symfony/polyfill-php80/Resources/stubs/Attribute.php new file mode 100644 index 0000000..2b95542 --- /dev/null +++ b/Sources/API/vendor/symfony/polyfill-php80/Resources/stubs/Attribute.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +#[Attribute(Attribute::TARGET_CLASS)] +final class Attribute +{ + public const TARGET_CLASS = 1; + public const TARGET_FUNCTION = 2; + public const TARGET_METHOD = 4; + public const TARGET_PROPERTY = 8; + public const TARGET_CLASS_CONSTANT = 16; + public const TARGET_PARAMETER = 32; + public const TARGET_ALL = 63; + public const IS_REPEATABLE = 64; + + /** @var int */ + public $flags; + + public function __construct(int $flags = self::TARGET_ALL) + { + $this->flags = $flags; + } +} diff --git a/Sources/API/vendor/symfony/polyfill-php80/Resources/stubs/PhpToken.php b/Sources/API/vendor/symfony/polyfill-php80/Resources/stubs/PhpToken.php new file mode 100644 index 0000000..bd1212f --- /dev/null +++ b/Sources/API/vendor/symfony/polyfill-php80/Resources/stubs/PhpToken.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +if (\PHP_VERSION_ID < 80000 && extension_loaded('tokenizer')) { + class PhpToken extends Symfony\Polyfill\Php80\PhpToken + { + } +} diff --git a/Sources/API/vendor/symfony/polyfill-php80/Resources/stubs/Stringable.php b/Sources/API/vendor/symfony/polyfill-php80/Resources/stubs/Stringable.php new file mode 100644 index 0000000..7c62d75 --- /dev/null +++ b/Sources/API/vendor/symfony/polyfill-php80/Resources/stubs/Stringable.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +if (\PHP_VERSION_ID < 80000) { + interface Stringable + { + /** + * @return string + */ + public function __toString(); + } +} diff --git a/Sources/API/vendor/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php b/Sources/API/vendor/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php new file mode 100644 index 0000000..01c6c6c --- /dev/null +++ b/Sources/API/vendor/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +if (\PHP_VERSION_ID < 80000) { + class UnhandledMatchError extends Error + { + } +} diff --git a/Sources/API/vendor/symfony/polyfill-php80/Resources/stubs/ValueError.php b/Sources/API/vendor/symfony/polyfill-php80/Resources/stubs/ValueError.php new file mode 100644 index 0000000..783dbc2 --- /dev/null +++ b/Sources/API/vendor/symfony/polyfill-php80/Resources/stubs/ValueError.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +if (\PHP_VERSION_ID < 80000) { + class ValueError extends Error + { + } +} diff --git a/Sources/API/vendor/symfony/polyfill-php80/bootstrap.php b/Sources/API/vendor/symfony/polyfill-php80/bootstrap.php new file mode 100644 index 0000000..e5f7dbc --- /dev/null +++ b/Sources/API/vendor/symfony/polyfill-php80/bootstrap.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Polyfill\Php80 as p; + +if (\PHP_VERSION_ID >= 80000) { + return; +} + +if (!defined('FILTER_VALIDATE_BOOL') && defined('FILTER_VALIDATE_BOOLEAN')) { + define('FILTER_VALIDATE_BOOL', \FILTER_VALIDATE_BOOLEAN); +} + +if (!function_exists('fdiv')) { + function fdiv(float $num1, float $num2): float { return p\Php80::fdiv($num1, $num2); } +} +if (!function_exists('preg_last_error_msg')) { + function preg_last_error_msg(): string { return p\Php80::preg_last_error_msg(); } +} +if (!function_exists('str_contains')) { + function str_contains(?string $haystack, ?string $needle): bool { return p\Php80::str_contains($haystack ?? '', $needle ?? ''); } +} +if (!function_exists('str_starts_with')) { + function str_starts_with(?string $haystack, ?string $needle): bool { return p\Php80::str_starts_with($haystack ?? '', $needle ?? ''); } +} +if (!function_exists('str_ends_with')) { + function str_ends_with(?string $haystack, ?string $needle): bool { return p\Php80::str_ends_with($haystack ?? '', $needle ?? ''); } +} +if (!function_exists('get_debug_type')) { + function get_debug_type($value): string { return p\Php80::get_debug_type($value); } +} +if (!function_exists('get_resource_id')) { + function get_resource_id($resource): int { return p\Php80::get_resource_id($resource); } +} diff --git a/Sources/API/vendor/symfony/polyfill-php80/composer.json b/Sources/API/vendor/symfony/polyfill-php80/composer.json new file mode 100644 index 0000000..bd9a326 --- /dev/null +++ b/Sources/API/vendor/symfony/polyfill-php80/composer.json @@ -0,0 +1,40 @@ +{ + "name": "symfony/polyfill-php80", + "type": "library", + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "keywords": ["polyfill", "shim", "compatibility", "portable"], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": ">=7.1" + }, + "autoload": { + "psr-4": { "Symfony\\Polyfill\\Php80\\": "" }, + "files": [ "bootstrap.php" ], + "classmap": [ "Resources/stubs" ] + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + } +}