diff --git a/.htaccess b/.htaccess
new file mode 100644
index 00000000..5624e80a
--- /dev/null
+++ b/.htaccess
@@ -0,0 +1,12 @@
+
+ Options -MultiViews
+
+ RewriteEngine On
+ #RewriteBase /test/
+ RewriteCond %{REQUEST_FILENAME} !-d
+ RewriteCond %{REQUEST_FILENAME} !-f
+ RewriteRule ^ index.php [QSA,L]
+
+
+
+#FallbackResource /index.php
\ No newline at end of file
diff --git a/BD.txt b/BD.txt
new file mode 100644
index 00000000..25919f9f
--- /dev/null
+++ b/BD.txt
@@ -0,0 +1,15 @@
+
+### Criar Base
+CREATE DATABASE `test` /*!40100 DEFAULT CHARACTER SET latin1 */;
+
+### criar tabela de clientes
+CREATE TABLE `tb_customers` (
+ `id_customer` int(11) NOT NULL AUTO_INCREMENT,
+ `name` varchar(150) NOT NULL,
+ `cpf` int(11) NOT NULL,
+ `birth_date` date NOT NULL,
+ `email` varchar(150) NOT NULL,
+ `dt_register` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `dt_change` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ PRIMARY KEY (`id_customer`)
+) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;
diff --git a/composer.json b/composer.json
new file mode 100644
index 00000000..fd5e19ef
--- /dev/null
+++ b/composer.json
@@ -0,0 +1,5 @@
+{
+ "require": {
+ "silex/silex": "~2.0"
+ }
+}
\ No newline at end of file
diff --git a/composer.lock b/composer.lock
new file mode 100644
index 00000000..cc2f631d
--- /dev/null
+++ b/composer.lock
@@ -0,0 +1,648 @@
+{
+ "_readme": [
+ "This file locks the dependencies of your project to a known state",
+ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
+ "This file is @generated automatically"
+ ],
+ "content-hash": "85677501dca45c0b473c524c2f1a82b0",
+ "packages": [
+ {
+ "name": "pimple/pimple",
+ "version": "v3.2.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/silexphp/Pimple.git",
+ "reference": "4d45fb62d96418396ec58ba76e6f065bca16e10a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/silexphp/Pimple/zipball/4d45fb62d96418396ec58ba76e6f065bca16e10a",
+ "reference": "4d45fb62d96418396ec58ba76e6f065bca16e10a",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0",
+ "psr/container": "^1.0"
+ },
+ "require-dev": {
+ "symfony/phpunit-bridge": "^3.2"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.2.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Pimple": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ }
+ ],
+ "description": "Pimple, a simple Dependency Injection Container",
+ "homepage": "http://pimple.sensiolabs.org",
+ "keywords": [
+ "container",
+ "dependency injection"
+ ],
+ "time": "2017-07-23T07:32:15+00:00"
+ },
+ {
+ "name": "psr/container",
+ "version": "1.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/container.git",
+ "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
+ "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Container\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "http://www.php-fig.org/"
+ }
+ ],
+ "description": "Common Container Interface (PHP FIG PSR-11)",
+ "homepage": "https://github.com/php-fig/container",
+ "keywords": [
+ "PSR-11",
+ "container",
+ "container-interface",
+ "container-interop",
+ "psr"
+ ],
+ "time": "2017-02-14T16:28:37+00:00"
+ },
+ {
+ "name": "psr/log",
+ "version": "1.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/log.git",
+ "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
+ "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Log\\": "Psr/Log/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "http://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for logging libraries",
+ "homepage": "https://github.com/php-fig/log",
+ "keywords": [
+ "log",
+ "psr",
+ "psr-3"
+ ],
+ "time": "2016-10-10T12:19:37+00:00"
+ },
+ {
+ "name": "silex/silex",
+ "version": "v2.2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/silexphp/Silex.git",
+ "reference": "ec7d5b5334465414952d4b2e935e73bd085dbbbb"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/silexphp/Silex/zipball/ec7d5b5334465414952d4b2e935e73bd085dbbbb",
+ "reference": "ec7d5b5334465414952d4b2e935e73bd085dbbbb",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.5.9",
+ "pimple/pimple": "~3.0",
+ "symfony/event-dispatcher": "~2.8|^3.0",
+ "symfony/http-foundation": "~2.8|^3.0",
+ "symfony/http-kernel": "~2.8|^3.0",
+ "symfony/routing": "~2.8|^3.0"
+ },
+ "conflict": {
+ "phpunit/phpunit": "<4.8.35 || >= 5.0, <5.4.3"
+ },
+ "replace": {
+ "silex/api": "self.version",
+ "silex/providers": "self.version"
+ },
+ "require-dev": {
+ "doctrine/dbal": "~2.2",
+ "monolog/monolog": "^1.4.1",
+ "swiftmailer/swiftmailer": "~5",
+ "symfony/asset": "~2.8|^3.0",
+ "symfony/browser-kit": "~2.8|^3.0",
+ "symfony/config": "~2.8|^3.0",
+ "symfony/css-selector": "~2.8|^3.0",
+ "symfony/debug": "~2.8|^3.0",
+ "symfony/doctrine-bridge": "~2.8|^3.0",
+ "symfony/dom-crawler": "~2.8|^3.0",
+ "symfony/expression-language": "~2.8|^3.0",
+ "symfony/finder": "~2.8|^3.0",
+ "symfony/form": "~2.8|^3.0",
+ "symfony/intl": "~2.8|^3.0",
+ "symfony/monolog-bridge": "~2.8|^3.0",
+ "symfony/options-resolver": "~2.8|^3.0",
+ "symfony/phpunit-bridge": "^3.2",
+ "symfony/process": "~2.8|^3.0",
+ "symfony/security": "~2.8|^3.0",
+ "symfony/serializer": "~2.8|^3.0",
+ "symfony/translation": "~2.8|^3.0",
+ "symfony/twig-bridge": "~2.8|^3.0",
+ "symfony/validator": "~2.8|^3.0",
+ "symfony/var-dumper": "~2.8|^3.0",
+ "symfony/web-link": "^3.3",
+ "twig/twig": "~1.28|~2.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.2.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Silex\\": "src/Silex"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Igor Wiedler",
+ "email": "igor@wiedler.ch"
+ }
+ ],
+ "description": "The PHP micro-framework based on the Symfony Components",
+ "homepage": "http://silex.sensiolabs.org",
+ "keywords": [
+ "microframework"
+ ],
+ "time": "2017-07-23T07:40:14+00:00"
+ },
+ {
+ "name": "symfony/debug",
+ "version": "v3.3.9",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/debug.git",
+ "reference": "8beb24eec70b345c313640962df933499373a944"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/debug/zipball/8beb24eec70b345c313640962df933499373a944",
+ "reference": "8beb24eec70b345c313640962df933499373a944",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.5.9|>=7.0.8",
+ "psr/log": "~1.0"
+ },
+ "conflict": {
+ "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2"
+ },
+ "require-dev": {
+ "symfony/http-kernel": "~2.8|~3.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.3-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Debug\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony Debug Component",
+ "homepage": "https://symfony.com",
+ "time": "2017-09-01T13:23:39+00:00"
+ },
+ {
+ "name": "symfony/event-dispatcher",
+ "version": "v3.3.9",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/event-dispatcher.git",
+ "reference": "54ca9520a00386f83bca145819ad3b619aaa2485"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/54ca9520a00386f83bca145819ad3b619aaa2485",
+ "reference": "54ca9520a00386f83bca145819ad3b619aaa2485",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.5.9|>=7.0.8"
+ },
+ "conflict": {
+ "symfony/dependency-injection": "<3.3"
+ },
+ "require-dev": {
+ "psr/log": "~1.0",
+ "symfony/config": "~2.8|~3.0",
+ "symfony/dependency-injection": "~3.3",
+ "symfony/expression-language": "~2.8|~3.0",
+ "symfony/stopwatch": "~2.8|~3.0"
+ },
+ "suggest": {
+ "symfony/dependency-injection": "",
+ "symfony/http-kernel": ""
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.3-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\EventDispatcher\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony EventDispatcher Component",
+ "homepage": "https://symfony.com",
+ "time": "2017-07-29T21:54:42+00:00"
+ },
+ {
+ "name": "symfony/http-foundation",
+ "version": "v3.3.9",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/http-foundation.git",
+ "reference": "2cdc7de1921d1a1c805a13dc05e44a2cd58f5ad3"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/http-foundation/zipball/2cdc7de1921d1a1c805a13dc05e44a2cd58f5ad3",
+ "reference": "2cdc7de1921d1a1c805a13dc05e44a2cd58f5ad3",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.5.9|>=7.0.8",
+ "symfony/polyfill-mbstring": "~1.1"
+ },
+ "require-dev": {
+ "symfony/expression-language": "~2.8|~3.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.3-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\HttpFoundation\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony HttpFoundation Component",
+ "homepage": "https://symfony.com",
+ "time": "2017-09-06T17:07:39+00:00"
+ },
+ {
+ "name": "symfony/http-kernel",
+ "version": "v3.3.9",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/http-kernel.git",
+ "reference": "70f5bb3cdd737624249953b61023411e26be5db7"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/http-kernel/zipball/70f5bb3cdd737624249953b61023411e26be5db7",
+ "reference": "70f5bb3cdd737624249953b61023411e26be5db7",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.5.9|>=7.0.8",
+ "psr/log": "~1.0",
+ "symfony/debug": "~2.8|~3.0",
+ "symfony/event-dispatcher": "~2.8|~3.0",
+ "symfony/http-foundation": "~3.3"
+ },
+ "conflict": {
+ "symfony/config": "<2.8",
+ "symfony/dependency-injection": "<3.3",
+ "symfony/var-dumper": "<3.3",
+ "twig/twig": "<1.34|<2.4,>=2"
+ },
+ "require-dev": {
+ "psr/cache": "~1.0",
+ "symfony/browser-kit": "~2.8|~3.0",
+ "symfony/class-loader": "~2.8|~3.0",
+ "symfony/config": "~2.8|~3.0",
+ "symfony/console": "~2.8|~3.0",
+ "symfony/css-selector": "~2.8|~3.0",
+ "symfony/dependency-injection": "~3.3",
+ "symfony/dom-crawler": "~2.8|~3.0",
+ "symfony/expression-language": "~2.8|~3.0",
+ "symfony/finder": "~2.8|~3.0",
+ "symfony/process": "~2.8|~3.0",
+ "symfony/routing": "~2.8|~3.0",
+ "symfony/stopwatch": "~2.8|~3.0",
+ "symfony/templating": "~2.8|~3.0",
+ "symfony/translation": "~2.8|~3.0",
+ "symfony/var-dumper": "~3.3"
+ },
+ "suggest": {
+ "symfony/browser-kit": "",
+ "symfony/class-loader": "",
+ "symfony/config": "",
+ "symfony/console": "",
+ "symfony/dependency-injection": "",
+ "symfony/finder": "",
+ "symfony/var-dumper": ""
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.3-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\HttpKernel\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony HttpKernel Component",
+ "homepage": "https://symfony.com",
+ "time": "2017-09-11T16:13:23+00:00"
+ },
+ {
+ "name": "symfony/polyfill-mbstring",
+ "version": "v1.5.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-mbstring.git",
+ "reference": "7c8fae0ac1d216eb54349e6a8baa57d515fe8803"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/7c8fae0ac1d216eb54349e6a8baa57d515fe8803",
+ "reference": "7c8fae0ac1d216eb54349e6a8baa57d515fe8803",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "suggest": {
+ "ext-mbstring": "For best performance"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.5-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Polyfill\\Mbstring\\": ""
+ },
+ "files": [
+ "bootstrap.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill for the Mbstring extension",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "mbstring",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "time": "2017-06-14T15:44:48+00:00"
+ },
+ {
+ "name": "symfony/routing",
+ "version": "v3.3.9",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/routing.git",
+ "reference": "970326dcd04522e1cd1fe128abaee54c225e27f9"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/routing/zipball/970326dcd04522e1cd1fe128abaee54c225e27f9",
+ "reference": "970326dcd04522e1cd1fe128abaee54c225e27f9",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.5.9|>=7.0.8"
+ },
+ "conflict": {
+ "symfony/config": "<2.8",
+ "symfony/dependency-injection": "<3.3",
+ "symfony/yaml": "<3.3"
+ },
+ "require-dev": {
+ "doctrine/annotations": "~1.0",
+ "doctrine/common": "~2.2",
+ "psr/log": "~1.0",
+ "symfony/config": "~2.8|~3.0",
+ "symfony/dependency-injection": "~3.3",
+ "symfony/expression-language": "~2.8|~3.0",
+ "symfony/http-foundation": "~2.8|~3.0",
+ "symfony/yaml": "~3.3"
+ },
+ "suggest": {
+ "doctrine/annotations": "For using the annotation loader",
+ "symfony/config": "For using the all-in-one router or any loader",
+ "symfony/dependency-injection": "For loading routes from a service",
+ "symfony/expression-language": "For using expression matching",
+ "symfony/http-foundation": "For using a Symfony Request object",
+ "symfony/yaml": "For using the YAML loader"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.3-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Routing\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony Routing Component",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "router",
+ "routing",
+ "uri",
+ "url"
+ ],
+ "time": "2017-07-29T21:54:42+00:00"
+ }
+ ],
+ "packages-dev": [],
+ "aliases": [],
+ "minimum-stability": "stable",
+ "stability-flags": [],
+ "prefer-stable": false,
+ "prefer-lowest": false,
+ "platform": [],
+ "platform-dev": []
+}
diff --git a/composer.phar b/composer.phar
new file mode 100644
index 00000000..508f9cf2
Binary files /dev/null and b/composer.phar differ
diff --git a/index.php b/index.php
new file mode 100644
index 00000000..cbe00588
--- /dev/null
+++ b/index.php
@@ -0,0 +1,103 @@
+getMessage();
+ }
+
+ ### listar clientes
+ $app->get('/customers', function () use ($app, $dbh) {
+ // consulta todos clientes
+ $sth = $dbh->prepare('SELECT name, cpf, birth_date, email FROM tb_customers');
+ $sth->execute();
+ $customers = $sth->fetchAll(PDO::FETCH_ASSOC);
+
+ return $app->json($customers);
+ });
+
+ ### listar cliente conforme id
+ $app->get('/customers/{id}', function ($id) use ($app, $dbh) {
+ // consulta todos clientes
+ $sth = $dbh->prepare('SELECT name, cpf, birth_date, email FROM tb_customers WHERE id_customer = ?');
+ $sth->execute([ $id ]);
+ $customers = $sth->fetchAll(PDO::FETCH_ASSOC);
+
+ echo __LINE__ . "
";
+
+ return $app->json($customers);
+ });
+
+ ### incluir cliente
+ $app->post('/customers', function(Request $request) use ($app, $dbh) {
+ $dados = array(
+ 'name' => $request->get('name'),
+ 'cpf' => $request->get('cpf'),
+ 'birth_date' => $request->get('birth_date'),
+ 'email' => $request->get('email'),
+ );
+
+ $sth = $dbh->prepare("
+ INSERT INTO tb_customers (name, cpf, birth_date, email)
+ VALUES(:name, :cpf, :birth_date, :email)
+ ");
+
+ $sth->execute($dados);
+ $id = $dbh->lastInsertId();
+
+ ### response, 201 created
+ $response = new Response('Ok', 201);
+ $response->headers->set('Location', "/customers/$id");
+ return $response;
+ });
+
+ // editar cliente
+ $app->put('/customers/{id}', function(Request $request, $id) use ($app, $dbh) {
+ $dados = array(
+ 'name' => $request->get('name'),
+ 'cpf' => $request->get('cpf'),
+ 'birth_date' => $request->get('birth_date'),
+ 'email' => $request->get('email'),
+ 'id' => $id,
+ );
+ $sth = $dbh->prepare("
+ UPDATE tb_customers
+ SET name = :name, cpf = :cpf, birth_date = :birth_date, email = :email
+ WHERE id_customer = :id
+ ");
+
+ $sth->execute($dados);
+ return $app->json($dados, 200);
+ })->assert('id', '\d+');
+
+ ### excluir cliente
+ $app->delete('/customers/{id}', function($id) use ($app, $dbh) {
+ $sth = $dbh->prepare('DELETE FROM tb_customers WHERE id_customer = ?');
+ $sth->execute([ $id ]);
+
+ if($sth->rowCount() < 1) {
+ return new Response("Cliente com id {$id} não encontrado para exclusão!", 404);
+ }
+
+ ### registro foi excluido, retornar 204 - no content
+ return new Response(null, 204);
+ })->assert('id', '\d+');
+
+ $app->run();
\ No newline at end of file
diff --git a/vendor/autoload.php b/vendor/autoload.php
new file mode 100644
index 00000000..fa1a3675
--- /dev/null
+++ b/vendor/autoload.php
@@ -0,0 +1,7 @@
+
+ * Jordi Boggiano
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Composer\Autoload;
+
+/**
+ * ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
+ *
+ * $loader = new \Composer\Autoload\ClassLoader();
+ *
+ * // register classes with namespaces
+ * $loader->add('Symfony\Component', __DIR__.'/component');
+ * $loader->add('Symfony', __DIR__.'/framework');
+ *
+ * // activate the autoloader
+ * $loader->register();
+ *
+ * // to enable searching the include path (eg. for PEAR packages)
+ * $loader->setUseIncludePath(true);
+ *
+ * In this example, if you try to use a class in the Symfony\Component
+ * namespace or one of its children (Symfony\Component\Console for instance),
+ * the autoloader will first look for the class under the component/
+ * directory, and it will then fallback to the framework/ directory if not
+ * found before giving up.
+ *
+ * This class is loosely based on the Symfony UniversalClassLoader.
+ *
+ * @author Fabien Potencier
+ * @author Jordi Boggiano
+ * @see http://www.php-fig.org/psr/psr-0/
+ * @see http://www.php-fig.org/psr/psr-4/
+ */
+class ClassLoader
+{
+ // PSR-4
+ private $prefixLengthsPsr4 = array();
+ private $prefixDirsPsr4 = array();
+ private $fallbackDirsPsr4 = array();
+
+ // PSR-0
+ private $prefixesPsr0 = array();
+ private $fallbackDirsPsr0 = array();
+
+ private $useIncludePath = false;
+ private $classMap = array();
+ private $classMapAuthoritative = false;
+ private $missingClasses = array();
+ private $apcuPrefix;
+
+ public function getPrefixes()
+ {
+ if (!empty($this->prefixesPsr0)) {
+ return call_user_func_array('array_merge', $this->prefixesPsr0);
+ }
+
+ return array();
+ }
+
+ public function getPrefixesPsr4()
+ {
+ return $this->prefixDirsPsr4;
+ }
+
+ public function getFallbackDirs()
+ {
+ return $this->fallbackDirsPsr0;
+ }
+
+ public function getFallbackDirsPsr4()
+ {
+ return $this->fallbackDirsPsr4;
+ }
+
+ public function getClassMap()
+ {
+ return $this->classMap;
+ }
+
+ /**
+ * @param array $classMap Class to filename map
+ */
+ public function addClassMap(array $classMap)
+ {
+ if ($this->classMap) {
+ $this->classMap = array_merge($this->classMap, $classMap);
+ } else {
+ $this->classMap = $classMap;
+ }
+ }
+
+ /**
+ * Registers a set of PSR-0 directories for a given prefix, either
+ * appending or prepending to the ones previously set for this prefix.
+ *
+ * @param string $prefix The prefix
+ * @param array|string $paths The PSR-0 root directories
+ * @param bool $prepend Whether to prepend the directories
+ */
+ public function add($prefix, $paths, $prepend = false)
+ {
+ if (!$prefix) {
+ if ($prepend) {
+ $this->fallbackDirsPsr0 = array_merge(
+ (array) $paths,
+ $this->fallbackDirsPsr0
+ );
+ } else {
+ $this->fallbackDirsPsr0 = array_merge(
+ $this->fallbackDirsPsr0,
+ (array) $paths
+ );
+ }
+
+ return;
+ }
+
+ $first = $prefix[0];
+ if (!isset($this->prefixesPsr0[$first][$prefix])) {
+ $this->prefixesPsr0[$first][$prefix] = (array) $paths;
+
+ return;
+ }
+ if ($prepend) {
+ $this->prefixesPsr0[$first][$prefix] = array_merge(
+ (array) $paths,
+ $this->prefixesPsr0[$first][$prefix]
+ );
+ } else {
+ $this->prefixesPsr0[$first][$prefix] = array_merge(
+ $this->prefixesPsr0[$first][$prefix],
+ (array) $paths
+ );
+ }
+ }
+
+ /**
+ * Registers a set of PSR-4 directories for a given namespace, either
+ * appending or prepending to the ones previously set for this namespace.
+ *
+ * @param string $prefix The prefix/namespace, with trailing '\\'
+ * @param array|string $paths The PSR-4 base directories
+ * @param bool $prepend Whether to prepend the directories
+ *
+ * @throws \InvalidArgumentException
+ */
+ public function addPsr4($prefix, $paths, $prepend = false)
+ {
+ if (!$prefix) {
+ // Register directories for the root namespace.
+ if ($prepend) {
+ $this->fallbackDirsPsr4 = array_merge(
+ (array) $paths,
+ $this->fallbackDirsPsr4
+ );
+ } else {
+ $this->fallbackDirsPsr4 = array_merge(
+ $this->fallbackDirsPsr4,
+ (array) $paths
+ );
+ }
+ } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
+ // Register directories for a new namespace.
+ $length = strlen($prefix);
+ if ('\\' !== $prefix[$length - 1]) {
+ throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
+ }
+ $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
+ $this->prefixDirsPsr4[$prefix] = (array) $paths;
+ } elseif ($prepend) {
+ // Prepend directories for an already registered namespace.
+ $this->prefixDirsPsr4[$prefix] = array_merge(
+ (array) $paths,
+ $this->prefixDirsPsr4[$prefix]
+ );
+ } else {
+ // Append directories for an already registered namespace.
+ $this->prefixDirsPsr4[$prefix] = array_merge(
+ $this->prefixDirsPsr4[$prefix],
+ (array) $paths
+ );
+ }
+ }
+
+ /**
+ * Registers a set of PSR-0 directories for a given prefix,
+ * replacing any others previously set for this prefix.
+ *
+ * @param string $prefix The prefix
+ * @param array|string $paths The PSR-0 base directories
+ */
+ public function set($prefix, $paths)
+ {
+ if (!$prefix) {
+ $this->fallbackDirsPsr0 = (array) $paths;
+ } else {
+ $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
+ }
+ }
+
+ /**
+ * Registers a set of PSR-4 directories for a given namespace,
+ * replacing any others previously set for this namespace.
+ *
+ * @param string $prefix The prefix/namespace, with trailing '\\'
+ * @param array|string $paths The PSR-4 base directories
+ *
+ * @throws \InvalidArgumentException
+ */
+ public function setPsr4($prefix, $paths)
+ {
+ if (!$prefix) {
+ $this->fallbackDirsPsr4 = (array) $paths;
+ } else {
+ $length = strlen($prefix);
+ if ('\\' !== $prefix[$length - 1]) {
+ throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
+ }
+ $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
+ $this->prefixDirsPsr4[$prefix] = (array) $paths;
+ }
+ }
+
+ /**
+ * Turns on searching the include path for class files.
+ *
+ * @param bool $useIncludePath
+ */
+ public function setUseIncludePath($useIncludePath)
+ {
+ $this->useIncludePath = $useIncludePath;
+ }
+
+ /**
+ * Can be used to check if the autoloader uses the include path to check
+ * for classes.
+ *
+ * @return bool
+ */
+ public function getUseIncludePath()
+ {
+ return $this->useIncludePath;
+ }
+
+ /**
+ * Turns off searching the prefix and fallback directories for classes
+ * that have not been registered with the class map.
+ *
+ * @param bool $classMapAuthoritative
+ */
+ public function setClassMapAuthoritative($classMapAuthoritative)
+ {
+ $this->classMapAuthoritative = $classMapAuthoritative;
+ }
+
+ /**
+ * Should class lookup fail if not found in the current class map?
+ *
+ * @return bool
+ */
+ public function isClassMapAuthoritative()
+ {
+ return $this->classMapAuthoritative;
+ }
+
+ /**
+ * APCu prefix to use to cache found/not-found classes, if the extension is enabled.
+ *
+ * @param string|null $apcuPrefix
+ */
+ public function setApcuPrefix($apcuPrefix)
+ {
+ $this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null;
+ }
+
+ /**
+ * The APCu prefix in use, or null if APCu caching is not enabled.
+ *
+ * @return string|null
+ */
+ public function getApcuPrefix()
+ {
+ return $this->apcuPrefix;
+ }
+
+ /**
+ * Registers this instance as an autoloader.
+ *
+ * @param bool $prepend Whether to prepend the autoloader or not
+ */
+ public function register($prepend = false)
+ {
+ spl_autoload_register(array($this, 'loadClass'), true, $prepend);
+ }
+
+ /**
+ * Unregisters this instance as an autoloader.
+ */
+ public function unregister()
+ {
+ spl_autoload_unregister(array($this, 'loadClass'));
+ }
+
+ /**
+ * Loads the given class or interface.
+ *
+ * @param string $class The name of the class
+ * @return bool|null True if loaded, null otherwise
+ */
+ public function loadClass($class)
+ {
+ if ($file = $this->findFile($class)) {
+ includeFile($file);
+
+ return true;
+ }
+ }
+
+ /**
+ * Finds the path to the file where the class is defined.
+ *
+ * @param string $class The name of the class
+ *
+ * @return string|false The path if found, false otherwise
+ */
+ public function findFile($class)
+ {
+ // class map lookup
+ if (isset($this->classMap[$class])) {
+ return $this->classMap[$class];
+ }
+ if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
+ return false;
+ }
+ if (null !== $this->apcuPrefix) {
+ $file = apcu_fetch($this->apcuPrefix.$class, $hit);
+ if ($hit) {
+ return $file;
+ }
+ }
+
+ $file = $this->findFileWithExtension($class, '.php');
+
+ // Search for Hack files if we are running on HHVM
+ if (false === $file && defined('HHVM_VERSION')) {
+ $file = $this->findFileWithExtension($class, '.hh');
+ }
+
+ if (null !== $this->apcuPrefix) {
+ apcu_add($this->apcuPrefix.$class, $file);
+ }
+
+ if (false === $file) {
+ // Remember that this class does not exist.
+ $this->missingClasses[$class] = true;
+ }
+
+ return $file;
+ }
+
+ private function findFileWithExtension($class, $ext)
+ {
+ // PSR-4 lookup
+ $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
+
+ $first = $class[0];
+ if (isset($this->prefixLengthsPsr4[$first])) {
+ $subPath = $class;
+ while (false !== $lastPos = strrpos($subPath, '\\')) {
+ $subPath = substr($subPath, 0, $lastPos);
+ $search = $subPath.'\\';
+ if (isset($this->prefixDirsPsr4[$search])) {
+ foreach ($this->prefixDirsPsr4[$search] as $dir) {
+ $length = $this->prefixLengthsPsr4[$first][$search];
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) {
+ return $file;
+ }
+ }
+ }
+ }
+ }
+
+ // PSR-4 fallback dirs
+ foreach ($this->fallbackDirsPsr4 as $dir) {
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
+ return $file;
+ }
+ }
+
+ // PSR-0 lookup
+ if (false !== $pos = strrpos($class, '\\')) {
+ // namespaced class name
+ $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
+ . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
+ } else {
+ // PEAR-like class name
+ $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
+ }
+
+ if (isset($this->prefixesPsr0[$first])) {
+ foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
+ if (0 === strpos($class, $prefix)) {
+ foreach ($dirs as $dir) {
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
+ return $file;
+ }
+ }
+ }
+ }
+ }
+
+ // PSR-0 fallback dirs
+ foreach ($this->fallbackDirsPsr0 as $dir) {
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
+ return $file;
+ }
+ }
+
+ // PSR-0 include paths.
+ if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
+ return $file;
+ }
+
+ return false;
+ }
+}
+
+/**
+ * Scope isolated include.
+ *
+ * Prevents access to $this/self from included files.
+ */
+function includeFile($file)
+{
+ include $file;
+}
diff --git a/vendor/composer/LICENSE b/vendor/composer/LICENSE
new file mode 100644
index 00000000..f27399a0
--- /dev/null
+++ b/vendor/composer/LICENSE
@@ -0,0 +1,21 @@
+
+Copyright (c) Nils Adermann, Jordi Boggiano
+
+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/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php
new file mode 100644
index 00000000..7a91153b
--- /dev/null
+++ b/vendor/composer/autoload_classmap.php
@@ -0,0 +1,9 @@
+ $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
+);
diff --git a/vendor/composer/autoload_namespaces.php b/vendor/composer/autoload_namespaces.php
new file mode 100644
index 00000000..c3cd0229
--- /dev/null
+++ b/vendor/composer/autoload_namespaces.php
@@ -0,0 +1,10 @@
+ array($vendorDir . '/pimple/pimple/src'),
+);
diff --git a/vendor/composer/autoload_psr4.php b/vendor/composer/autoload_psr4.php
new file mode 100644
index 00000000..845ad2e3
--- /dev/null
+++ b/vendor/composer/autoload_psr4.php
@@ -0,0 +1,18 @@
+ array($vendorDir . '/symfony/polyfill-mbstring'),
+ 'Symfony\\Component\\Routing\\' => array($vendorDir . '/symfony/routing'),
+ 'Symfony\\Component\\HttpKernel\\' => array($vendorDir . '/symfony/http-kernel'),
+ 'Symfony\\Component\\HttpFoundation\\' => array($vendorDir . '/symfony/http-foundation'),
+ 'Symfony\\Component\\EventDispatcher\\' => array($vendorDir . '/symfony/event-dispatcher'),
+ 'Symfony\\Component\\Debug\\' => array($vendorDir . '/symfony/debug'),
+ 'Silex\\' => array($vendorDir . '/silex/silex/src/Silex'),
+ 'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
+ 'Psr\\Container\\' => array($vendorDir . '/psr/container/src'),
+);
diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php
new file mode 100644
index 00000000..06d14708
--- /dev/null
+++ b/vendor/composer/autoload_real.php
@@ -0,0 +1,70 @@
+= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
+ if ($useStaticLoader) {
+ require_once __DIR__ . '/autoload_static.php';
+
+ call_user_func(\Composer\Autoload\ComposerStaticInit55d0196e4984142c4bf289e9cf5a13bd::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\ComposerStaticInit55d0196e4984142c4bf289e9cf5a13bd::$files;
+ } else {
+ $includeFiles = require __DIR__ . '/autoload_files.php';
+ }
+ foreach ($includeFiles as $fileIdentifier => $file) {
+ composerRequire55d0196e4984142c4bf289e9cf5a13bd($fileIdentifier, $file);
+ }
+
+ return $loader;
+ }
+}
+
+function composerRequire55d0196e4984142c4bf289e9cf5a13bd($fileIdentifier, $file)
+{
+ if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
+ require $file;
+
+ $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
+ }
+}
diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php
new file mode 100644
index 00000000..f96d6030
--- /dev/null
+++ b/vendor/composer/autoload_static.php
@@ -0,0 +1,89 @@
+ __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
+ );
+
+ public static $prefixLengthsPsr4 = array (
+ 'S' =>
+ array (
+ 'Symfony\\Polyfill\\Mbstring\\' => 26,
+ 'Symfony\\Component\\Routing\\' => 26,
+ 'Symfony\\Component\\HttpKernel\\' => 29,
+ 'Symfony\\Component\\HttpFoundation\\' => 33,
+ 'Symfony\\Component\\EventDispatcher\\' => 34,
+ 'Symfony\\Component\\Debug\\' => 24,
+ 'Silex\\' => 6,
+ ),
+ 'P' =>
+ array (
+ 'Psr\\Log\\' => 8,
+ 'Psr\\Container\\' => 14,
+ ),
+ );
+
+ public static $prefixDirsPsr4 = array (
+ 'Symfony\\Polyfill\\Mbstring\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring',
+ ),
+ 'Symfony\\Component\\Routing\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/symfony/routing',
+ ),
+ 'Symfony\\Component\\HttpKernel\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/symfony/http-kernel',
+ ),
+ 'Symfony\\Component\\HttpFoundation\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/symfony/http-foundation',
+ ),
+ 'Symfony\\Component\\EventDispatcher\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/symfony/event-dispatcher',
+ ),
+ 'Symfony\\Component\\Debug\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/symfony/debug',
+ ),
+ 'Silex\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/silex/silex/src/Silex',
+ ),
+ 'Psr\\Log\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/psr/log/Psr/Log',
+ ),
+ 'Psr\\Container\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/psr/container/src',
+ ),
+ );
+
+ public static $prefixesPsr0 = array (
+ 'P' =>
+ array (
+ 'Pimple' =>
+ array (
+ 0 => __DIR__ . '/..' . '/pimple/pimple/src',
+ ),
+ ),
+ );
+
+ public static function getInitializer(ClassLoader $loader)
+ {
+ return \Closure::bind(function () use ($loader) {
+ $loader->prefixLengthsPsr4 = ComposerStaticInit55d0196e4984142c4bf289e9cf5a13bd::$prefixLengthsPsr4;
+ $loader->prefixDirsPsr4 = ComposerStaticInit55d0196e4984142c4bf289e9cf5a13bd::$prefixDirsPsr4;
+ $loader->prefixesPsr0 = ComposerStaticInit55d0196e4984142c4bf289e9cf5a13bd::$prefixesPsr0;
+
+ }, null, ClassLoader::class);
+ }
+}
diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json
new file mode 100644
index 00000000..d92f025a
--- /dev/null
+++ b/vendor/composer/installed.json
@@ -0,0 +1,652 @@
+[
+ {
+ "name": "psr/container",
+ "version": "1.0.0",
+ "version_normalized": "1.0.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/container.git",
+ "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
+ "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "time": "2017-02-14T16:28:37+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.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": "http://www.php-fig.org/"
+ }
+ ],
+ "description": "Common Container Interface (PHP FIG PSR-11)",
+ "homepage": "https://github.com/php-fig/container",
+ "keywords": [
+ "PSR-11",
+ "container",
+ "container-interface",
+ "container-interop",
+ "psr"
+ ]
+ },
+ {
+ "name": "symfony/routing",
+ "version": "v3.3.9",
+ "version_normalized": "3.3.9.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/routing.git",
+ "reference": "970326dcd04522e1cd1fe128abaee54c225e27f9"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/routing/zipball/970326dcd04522e1cd1fe128abaee54c225e27f9",
+ "reference": "970326dcd04522e1cd1fe128abaee54c225e27f9",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.5.9|>=7.0.8"
+ },
+ "conflict": {
+ "symfony/config": "<2.8",
+ "symfony/dependency-injection": "<3.3",
+ "symfony/yaml": "<3.3"
+ },
+ "require-dev": {
+ "doctrine/annotations": "~1.0",
+ "doctrine/common": "~2.2",
+ "psr/log": "~1.0",
+ "symfony/config": "~2.8|~3.0",
+ "symfony/dependency-injection": "~3.3",
+ "symfony/expression-language": "~2.8|~3.0",
+ "symfony/http-foundation": "~2.8|~3.0",
+ "symfony/yaml": "~3.3"
+ },
+ "suggest": {
+ "doctrine/annotations": "For using the annotation loader",
+ "symfony/config": "For using the all-in-one router or any loader",
+ "symfony/dependency-injection": "For loading routes from a service",
+ "symfony/expression-language": "For using expression matching",
+ "symfony/http-foundation": "For using a Symfony Request object",
+ "symfony/yaml": "For using the YAML loader"
+ },
+ "time": "2017-07-29T21:54:42+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.3-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Routing\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony Routing Component",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "router",
+ "routing",
+ "uri",
+ "url"
+ ]
+ },
+ {
+ "name": "symfony/polyfill-mbstring",
+ "version": "v1.5.0",
+ "version_normalized": "1.5.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-mbstring.git",
+ "reference": "7c8fae0ac1d216eb54349e6a8baa57d515fe8803"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/7c8fae0ac1d216eb54349e6a8baa57d515fe8803",
+ "reference": "7c8fae0ac1d216eb54349e6a8baa57d515fe8803",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "suggest": {
+ "ext-mbstring": "For best performance"
+ },
+ "time": "2017-06-14T15:44:48+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.5-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Polyfill\\Mbstring\\": ""
+ },
+ "files": [
+ "bootstrap.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill for the Mbstring extension",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "mbstring",
+ "polyfill",
+ "portable",
+ "shim"
+ ]
+ },
+ {
+ "name": "symfony/http-foundation",
+ "version": "v3.3.9",
+ "version_normalized": "3.3.9.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/http-foundation.git",
+ "reference": "2cdc7de1921d1a1c805a13dc05e44a2cd58f5ad3"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/http-foundation/zipball/2cdc7de1921d1a1c805a13dc05e44a2cd58f5ad3",
+ "reference": "2cdc7de1921d1a1c805a13dc05e44a2cd58f5ad3",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.5.9|>=7.0.8",
+ "symfony/polyfill-mbstring": "~1.1"
+ },
+ "require-dev": {
+ "symfony/expression-language": "~2.8|~3.0"
+ },
+ "time": "2017-09-06T17:07:39+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.3-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\HttpFoundation\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony HttpFoundation Component",
+ "homepage": "https://symfony.com"
+ },
+ {
+ "name": "symfony/event-dispatcher",
+ "version": "v3.3.9",
+ "version_normalized": "3.3.9.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/event-dispatcher.git",
+ "reference": "54ca9520a00386f83bca145819ad3b619aaa2485"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/54ca9520a00386f83bca145819ad3b619aaa2485",
+ "reference": "54ca9520a00386f83bca145819ad3b619aaa2485",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.5.9|>=7.0.8"
+ },
+ "conflict": {
+ "symfony/dependency-injection": "<3.3"
+ },
+ "require-dev": {
+ "psr/log": "~1.0",
+ "symfony/config": "~2.8|~3.0",
+ "symfony/dependency-injection": "~3.3",
+ "symfony/expression-language": "~2.8|~3.0",
+ "symfony/stopwatch": "~2.8|~3.0"
+ },
+ "suggest": {
+ "symfony/dependency-injection": "",
+ "symfony/http-kernel": ""
+ },
+ "time": "2017-07-29T21:54:42+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.3-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\EventDispatcher\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony EventDispatcher Component",
+ "homepage": "https://symfony.com"
+ },
+ {
+ "name": "psr/log",
+ "version": "1.0.2",
+ "version_normalized": "1.0.2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/log.git",
+ "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
+ "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "time": "2016-10-10T12:19:37+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Psr\\Log\\": "Psr/Log/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "http://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for logging libraries",
+ "homepage": "https://github.com/php-fig/log",
+ "keywords": [
+ "log",
+ "psr",
+ "psr-3"
+ ]
+ },
+ {
+ "name": "symfony/debug",
+ "version": "v3.3.9",
+ "version_normalized": "3.3.9.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/debug.git",
+ "reference": "8beb24eec70b345c313640962df933499373a944"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/debug/zipball/8beb24eec70b345c313640962df933499373a944",
+ "reference": "8beb24eec70b345c313640962df933499373a944",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.5.9|>=7.0.8",
+ "psr/log": "~1.0"
+ },
+ "conflict": {
+ "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2"
+ },
+ "require-dev": {
+ "symfony/http-kernel": "~2.8|~3.0"
+ },
+ "time": "2017-09-01T13:23:39+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.3-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Debug\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony Debug Component",
+ "homepage": "https://symfony.com"
+ },
+ {
+ "name": "symfony/http-kernel",
+ "version": "v3.3.9",
+ "version_normalized": "3.3.9.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/http-kernel.git",
+ "reference": "70f5bb3cdd737624249953b61023411e26be5db7"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/http-kernel/zipball/70f5bb3cdd737624249953b61023411e26be5db7",
+ "reference": "70f5bb3cdd737624249953b61023411e26be5db7",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.5.9|>=7.0.8",
+ "psr/log": "~1.0",
+ "symfony/debug": "~2.8|~3.0",
+ "symfony/event-dispatcher": "~2.8|~3.0",
+ "symfony/http-foundation": "~3.3"
+ },
+ "conflict": {
+ "symfony/config": "<2.8",
+ "symfony/dependency-injection": "<3.3",
+ "symfony/var-dumper": "<3.3",
+ "twig/twig": "<1.34|<2.4,>=2"
+ },
+ "require-dev": {
+ "psr/cache": "~1.0",
+ "symfony/browser-kit": "~2.8|~3.0",
+ "symfony/class-loader": "~2.8|~3.0",
+ "symfony/config": "~2.8|~3.0",
+ "symfony/console": "~2.8|~3.0",
+ "symfony/css-selector": "~2.8|~3.0",
+ "symfony/dependency-injection": "~3.3",
+ "symfony/dom-crawler": "~2.8|~3.0",
+ "symfony/expression-language": "~2.8|~3.0",
+ "symfony/finder": "~2.8|~3.0",
+ "symfony/process": "~2.8|~3.0",
+ "symfony/routing": "~2.8|~3.0",
+ "symfony/stopwatch": "~2.8|~3.0",
+ "symfony/templating": "~2.8|~3.0",
+ "symfony/translation": "~2.8|~3.0",
+ "symfony/var-dumper": "~3.3"
+ },
+ "suggest": {
+ "symfony/browser-kit": "",
+ "symfony/class-loader": "",
+ "symfony/config": "",
+ "symfony/console": "",
+ "symfony/dependency-injection": "",
+ "symfony/finder": "",
+ "symfony/var-dumper": ""
+ },
+ "time": "2017-09-11T16:13:23+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.3-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\HttpKernel\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony HttpKernel Component",
+ "homepage": "https://symfony.com"
+ },
+ {
+ "name": "pimple/pimple",
+ "version": "v3.2.2",
+ "version_normalized": "3.2.2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/silexphp/Pimple.git",
+ "reference": "4d45fb62d96418396ec58ba76e6f065bca16e10a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/silexphp/Pimple/zipball/4d45fb62d96418396ec58ba76e6f065bca16e10a",
+ "reference": "4d45fb62d96418396ec58ba76e6f065bca16e10a",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0",
+ "psr/container": "^1.0"
+ },
+ "require-dev": {
+ "symfony/phpunit-bridge": "^3.2"
+ },
+ "time": "2017-07-23T07:32:15+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.2.x-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-0": {
+ "Pimple": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ }
+ ],
+ "description": "Pimple, a simple Dependency Injection Container",
+ "homepage": "http://pimple.sensiolabs.org",
+ "keywords": [
+ "container",
+ "dependency injection"
+ ]
+ },
+ {
+ "name": "silex/silex",
+ "version": "v2.2.0",
+ "version_normalized": "2.2.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/silexphp/Silex.git",
+ "reference": "ec7d5b5334465414952d4b2e935e73bd085dbbbb"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/silexphp/Silex/zipball/ec7d5b5334465414952d4b2e935e73bd085dbbbb",
+ "reference": "ec7d5b5334465414952d4b2e935e73bd085dbbbb",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.5.9",
+ "pimple/pimple": "~3.0",
+ "symfony/event-dispatcher": "~2.8|^3.0",
+ "symfony/http-foundation": "~2.8|^3.0",
+ "symfony/http-kernel": "~2.8|^3.0",
+ "symfony/routing": "~2.8|^3.0"
+ },
+ "conflict": {
+ "phpunit/phpunit": "<4.8.35 || >= 5.0, <5.4.3"
+ },
+ "replace": {
+ "silex/api": "self.version",
+ "silex/providers": "self.version"
+ },
+ "require-dev": {
+ "doctrine/dbal": "~2.2",
+ "monolog/monolog": "^1.4.1",
+ "swiftmailer/swiftmailer": "~5",
+ "symfony/asset": "~2.8|^3.0",
+ "symfony/browser-kit": "~2.8|^3.0",
+ "symfony/config": "~2.8|^3.0",
+ "symfony/css-selector": "~2.8|^3.0",
+ "symfony/debug": "~2.8|^3.0",
+ "symfony/doctrine-bridge": "~2.8|^3.0",
+ "symfony/dom-crawler": "~2.8|^3.0",
+ "symfony/expression-language": "~2.8|^3.0",
+ "symfony/finder": "~2.8|^3.0",
+ "symfony/form": "~2.8|^3.0",
+ "symfony/intl": "~2.8|^3.0",
+ "symfony/monolog-bridge": "~2.8|^3.0",
+ "symfony/options-resolver": "~2.8|^3.0",
+ "symfony/phpunit-bridge": "^3.2",
+ "symfony/process": "~2.8|^3.0",
+ "symfony/security": "~2.8|^3.0",
+ "symfony/serializer": "~2.8|^3.0",
+ "symfony/translation": "~2.8|^3.0",
+ "symfony/twig-bridge": "~2.8|^3.0",
+ "symfony/validator": "~2.8|^3.0",
+ "symfony/var-dumper": "~2.8|^3.0",
+ "symfony/web-link": "^3.3",
+ "twig/twig": "~1.28|~2.0"
+ },
+ "time": "2017-07-23T07:40:14+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.2.x-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Silex\\": "src/Silex"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Igor Wiedler",
+ "email": "igor@wiedler.ch"
+ }
+ ],
+ "description": "The PHP micro-framework based on the Symfony Components",
+ "homepage": "http://silex.sensiolabs.org",
+ "keywords": [
+ "microframework"
+ ]
+ }
+]
diff --git a/vendor/pimple/pimple/.gitignore b/vendor/pimple/pimple/.gitignore
new file mode 100644
index 00000000..c089b095
--- /dev/null
+++ b/vendor/pimple/pimple/.gitignore
@@ -0,0 +1,3 @@
+phpunit.xml
+composer.lock
+/vendor/
diff --git a/vendor/pimple/pimple/.travis.yml b/vendor/pimple/pimple/.travis.yml
new file mode 100644
index 00000000..196f7fc1
--- /dev/null
+++ b/vendor/pimple/pimple/.travis.yml
@@ -0,0 +1,40 @@
+language: php
+
+env:
+ matrix:
+ - PIMPLE_EXT=no
+ - PIMPLE_EXT=yes
+ global:
+ - REPORT_EXIT_STATUS=1
+
+php:
+ - 5.3
+ - 5.4
+ - 5.5
+ - 5.6
+ - 7.0
+ - 7.1
+
+before_script:
+ - composer self-update
+ - COMPOSER_ROOT_VERSION=dev-master composer install
+ - if [ "$PIMPLE_EXT" == "yes" ]; then sh -c "cd ext/pimple && phpize && ./configure && make && sudo make install"; fi
+ - if [ "$PIMPLE_EXT" == "yes" ]; then echo "extension=pimple.so" >> `php --ini | grep "Loaded Configuration" | sed -e "s|.*:\s*||"`; fi
+
+script:
+ - cd ext/pimple
+ - if [ "$PIMPLE_EXT" == "yes" ]; then yes n | make test | tee output ; grep -E 'Tests failed +. +0' output; fi
+ - if [ "$PIMPLE_EXT" == "yes" ]; then export SYMFONY_DEPRECATIONS_HELPER=weak; fi
+ - cd ../..
+ - ./vendor/bin/simple-phpunit
+
+matrix:
+ include:
+ - php: hhvm
+ dist: trusty
+ env: PIMPLE_EXT=no
+ exclude:
+ - php: 7.0
+ env: PIMPLE_EXT=yes
+ - php: 7.1
+ env: PIMPLE_EXT=yes
diff --git a/vendor/pimple/pimple/CHANGELOG b/vendor/pimple/pimple/CHANGELOG
new file mode 100644
index 00000000..f277b969
--- /dev/null
+++ b/vendor/pimple/pimple/CHANGELOG
@@ -0,0 +1,55 @@
+* 3.2.2 (2017-07-23)
+
+ * reverted extending a protected closure throws an exception (deprecated it instead)
+
+* 3.2.1 (2017-07-17)
+
+ * fixed PHP error
+
+* 3.2.0 (2017-07-17)
+
+ * added a PSR-11 service locator
+ * added a PSR-11 wrapper
+ * added ServiceIterator
+ * fixed extending a protected closure (now throws InvalidServiceIdentifierException)
+
+* 3.1.0 (2017-07-03)
+
+ * deprecated the C extension
+ * added support for PSR-11 exceptions
+
+* 3.0.2 (2015-09-11)
+
+ * refactored the C extension
+ * minor non-significant changes
+
+* 3.0.1 (2015-07-30)
+
+ * simplified some code
+ * fixed a segfault in the C extension
+
+* 3.0.0 (2014-07-24)
+
+ * removed the Pimple class alias (use Pimple\Container instead)
+
+* 2.1.1 (2014-07-24)
+
+ * fixed compiler warnings for the C extension
+ * fixed code when dealing with circular references
+
+* 2.1.0 (2014-06-24)
+
+ * moved the Pimple to Pimple\Container (with a BC layer -- Pimple is now a
+ deprecated alias which will be removed in Pimple 3.0)
+ * added Pimple\ServiceProviderInterface (and Pimple::register())
+
+* 2.0.0 (2014-02-10)
+
+ * changed extend to automatically re-assign the extended service and keep it as shared or factory
+ (to keep BC, extend still returns the extended service)
+ * changed services to be shared by default (use factory() for factory
+ services)
+
+* 1.0.0
+
+ * initial version
diff --git a/vendor/pimple/pimple/LICENSE b/vendor/pimple/pimple/LICENSE
new file mode 100644
index 00000000..e02dc5a7
--- /dev/null
+++ b/vendor/pimple/pimple/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2009-2017 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/vendor/pimple/pimple/README.rst b/vendor/pimple/pimple/README.rst
new file mode 100644
index 00000000..d27d8aa3
--- /dev/null
+++ b/vendor/pimple/pimple/README.rst
@@ -0,0 +1,326 @@
+Pimple
+======
+
+.. caution::
+
+ This is the documentation for Pimple 3.x. If you are using Pimple 1.x, read
+ the `Pimple 1.x documentation`_. Reading the Pimple 1.x code is also a good
+ way to learn more about how to create a simple Dependency Injection
+ Container (recent versions of Pimple are more focused on performance).
+
+Pimple is a small Dependency Injection Container for PHP.
+
+Installation
+------------
+
+Before using Pimple in your project, add it to your ``composer.json`` file:
+
+.. code-block:: bash
+
+ $ ./composer.phar require pimple/pimple "^3.0"
+
+Usage
+-----
+
+Creating a container is a matter of creating a ``Container`` instance:
+
+.. code-block:: php
+
+ use Pimple\Container;
+
+ $container = new Container();
+
+As many other dependency injection containers, Pimple manages two different
+kind of data: **services** and **parameters**.
+
+Defining Services
+~~~~~~~~~~~~~~~~~
+
+A service is an object that does something as part of a larger system. Examples
+of services: a database connection, a templating engine, or a mailer. Almost
+any **global** object can be a service.
+
+Services are defined by **anonymous functions** that return an instance of an
+object:
+
+.. code-block:: php
+
+ // define some services
+ $container['session_storage'] = function ($c) {
+ return new SessionStorage('SESSION_ID');
+ };
+
+ $container['session'] = function ($c) {
+ return new Session($c['session_storage']);
+ };
+
+Notice that the anonymous function has access to the current container
+instance, allowing references to other services or parameters.
+
+As objects are only created when you get them, the order of the definitions
+does not matter.
+
+Using the defined services is also very easy:
+
+.. code-block:: php
+
+ // get the session object
+ $session = $container['session'];
+
+ // the above call is roughly equivalent to the following code:
+ // $storage = new SessionStorage('SESSION_ID');
+ // $session = new Session($storage);
+
+Defining Factory Services
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+By default, each time you get a service, Pimple returns the **same instance**
+of it. If you want a different instance to be returned for all calls, wrap your
+anonymous function with the ``factory()`` method
+
+.. code-block:: php
+
+ $container['session'] = $container->factory(function ($c) {
+ return new Session($c['session_storage']);
+ });
+
+Now, each call to ``$container['session']`` returns a new instance of the
+session.
+
+Defining Parameters
+~~~~~~~~~~~~~~~~~~~
+
+Defining a parameter allows to ease the configuration of your container from
+the outside and to store global values:
+
+.. code-block:: php
+
+ // define some parameters
+ $container['cookie_name'] = 'SESSION_ID';
+ $container['session_storage_class'] = 'SessionStorage';
+
+If you change the ``session_storage`` service definition like below:
+
+.. code-block:: php
+
+ $container['session_storage'] = function ($c) {
+ return new $c['session_storage_class']($c['cookie_name']);
+ };
+
+You can now easily change the cookie name by overriding the
+``session_storage_class`` parameter instead of redefining the service
+definition.
+
+Protecting Parameters
+~~~~~~~~~~~~~~~~~~~~~
+
+Because Pimple sees anonymous functions as service definitions, you need to
+wrap anonymous functions with the ``protect()`` method to store them as
+parameters:
+
+.. code-block:: php
+
+ $container['random_func'] = $container->protect(function () {
+ return rand();
+ });
+
+Modifying Services after Definition
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In some cases you may want to modify a service definition after it has been
+defined. You can use the ``extend()`` method to define additional code to be
+run on your service just after it is created:
+
+.. code-block:: php
+
+ $container['session_storage'] = function ($c) {
+ return new $c['session_storage_class']($c['cookie_name']);
+ };
+
+ $container->extend('session_storage', function ($storage, $c) {
+ $storage->...();
+
+ return $storage;
+ });
+
+The first argument is the name of the service to extend, the second a function
+that gets access to the object instance and the container.
+
+Extending a Container
+~~~~~~~~~~~~~~~~~~~~~
+
+If you use the same libraries over and over, you might want to reuse some
+services from one project to the next one; package your services into a
+**provider** by implementing ``Pimple\ServiceProviderInterface``:
+
+.. code-block:: php
+
+ use Pimple\Container;
+
+ class FooProvider implements Pimple\ServiceProviderInterface
+ {
+ public function register(Container $pimple)
+ {
+ // register some services and parameters
+ // on $pimple
+ }
+ }
+
+Then, register the provider on a Container:
+
+.. code-block:: php
+
+ $pimple->register(new FooProvider());
+
+Fetching the Service Creation Function
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+When you access an object, Pimple automatically calls the anonymous function
+that you defined, which creates the service object for you. If you want to get
+raw access to this function, you can use the ``raw()`` method:
+
+.. code-block:: php
+
+ $container['session'] = function ($c) {
+ return new Session($c['session_storage']);
+ };
+
+ $sessionFunction = $container->raw('session');
+
+PSR-11 compatibility
+--------------------
+
+For historical reasons, the ``Container`` class does not implement the PSR-11
+``ContainerInterface``. However, Pimple provides a helper class that will let
+you decouple your code from the Pimple container class.
+
+The PSR-11 container class
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The ``Pimple\Psr11\Container`` class lets you access the content of an
+underlying Pimple container using ``Psr\Container\ContainerInterface``
+methods:
+
+.. code-block:: php
+
+ use Pimple\Container;
+ use Pimple\Psr11\Container as PsrContainer;
+
+ $container = new Container();
+ $container['service'] = function ($c) {
+ return new Service();
+ };
+ $psr11 = new PsrContainer($container);
+
+ $controller = function (PsrContainer $container) {
+ $service = $container->get('service');
+ };
+ $controller($psr11);
+
+Using the PSR-11 ServiceLocator
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Sometimes, a service needs access to several other services without being sure
+that all of them will actually be used. In those cases, you may want the
+instantiation of the services to be lazy.
+
+The traditional solution is to inject the entire service container to get only
+the services really needed. However, this is not recommended because it gives
+services a too broad access to the rest of the application and it hides their
+actual dependencies.
+
+The ``ServiceLocator`` is intended to solve this problem by giving access to a
+set of predefined services while instantiating them only when actually needed.
+
+It also allows you to make your services available under a different name than
+the one used to register them. For instance, you may want to use an object
+that expects an instance of ``EventDispatcherInterface`` to be available under
+the name ``event_dispatcher`` while your event dispatcher has been
+registered under the name ``dispatcher``:
+
+.. code-block:: php
+
+ use Monolog\Logger;
+ use Pimple\Psr11\ServiceLocator;
+ use Psr\Container\ContainerInterface;
+ use Symfony\Component\EventDispatcher\EventDispatcher;
+
+ class MyService
+ {
+ /**
+ * "logger" must be an instance of Psr\Log\LoggerInterface
+ * "event_dispatcher" must be an instance of Symfony\Component\EventDispatcher\EventDispatcherInterface
+ */
+ private $services;
+
+ public function __construct(ContainerInterface $services)
+ {
+ $this->services = $services;
+ }
+ }
+
+ $container['logger'] = function ($c) {
+ return new Monolog\Logger();
+ };
+ $container['dispatcher'] = function () {
+ return new EventDispatcher();
+ };
+
+ $container['service'] = function ($c) {
+ $locator = new ServiceLocator($c, array('logger', 'event_dispatcher' => 'dispatcher'));
+
+ return new MyService($locator);
+ };
+
+Referencing a Collection of Services Lazily
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Passing a collection of services instances in an array may prove inefficient
+if the class that consumes the collection only needs to iterate over it at a
+later stage, when one of its method is called. It can also lead to problems
+if there is a circular dependency between one of the services stored in the
+collection and the class that consumes it.
+
+The ``ServiceIterator`` class helps you solve these issues. It receives a
+list of service names during instantiation and will retrieve the services
+when iterated over:
+
+.. code-block:: php
+
+ use Pimple\Container;
+ use Pimple\ServiceIterator;
+
+ class AuthorizationService
+ {
+ private $voters;
+
+ public function __construct($voters)
+ {
+ $this->voters = $voters;
+ }
+
+ public function canAccess($resource)
+ {
+ foreach ($this->voters as $voter) {
+ if (true === $voter->canAccess($resource) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+ }
+
+ $container = new Container();
+
+ $container['voter1'] = function ($c) {
+ return new SomeVoter();
+ }
+ $container['voter2'] = function ($c) {
+ return new SomeOtherVoter($c['auth']);
+ }
+ $container['auth'] = function ($c) {
+ return new AuthorizationService(new ServiceIterator($c, array('voter1', 'voter2'));
+ }
+
+.. _Pimple 1.x documentation: https://github.com/silexphp/Pimple/tree/1.1
diff --git a/vendor/pimple/pimple/composer.json b/vendor/pimple/pimple/composer.json
new file mode 100644
index 00000000..dabf190a
--- /dev/null
+++ b/vendor/pimple/pimple/composer.json
@@ -0,0 +1,29 @@
+{
+ "name": "pimple/pimple",
+ "type": "library",
+ "description": "Pimple, a simple Dependency Injection Container",
+ "keywords": ["dependency injection", "container"],
+ "homepage": "http://pimple.sensiolabs.org",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ }
+ ],
+ "require": {
+ "php": ">=5.3.0",
+ "psr/container": "^1.0"
+ },
+ "require-dev": {
+ "symfony/phpunit-bridge": "^3.2"
+ },
+ "autoload": {
+ "psr-0": { "Pimple": "src/" }
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.2.x-dev"
+ }
+ }
+}
diff --git a/vendor/pimple/pimple/ext/pimple/.gitignore b/vendor/pimple/pimple/ext/pimple/.gitignore
new file mode 100644
index 00000000..1861088a
--- /dev/null
+++ b/vendor/pimple/pimple/ext/pimple/.gitignore
@@ -0,0 +1,30 @@
+*.sw*
+.deps
+Makefile
+Makefile.fragments
+Makefile.global
+Makefile.objects
+acinclude.m4
+aclocal.m4
+build/
+config.cache
+config.guess
+config.h
+config.h.in
+config.log
+config.nice
+config.status
+config.sub
+configure
+configure.in
+install-sh
+libtool
+ltmain.sh
+missing
+mkinstalldirs
+run-tests.php
+*.loT
+.libs/
+modules/
+*.la
+*.lo
diff --git a/vendor/pimple/pimple/ext/pimple/README.md b/vendor/pimple/pimple/ext/pimple/README.md
new file mode 100644
index 00000000..7b39eb29
--- /dev/null
+++ b/vendor/pimple/pimple/ext/pimple/README.md
@@ -0,0 +1,12 @@
+This is Pimple 2 implemented in C
+
+* PHP >= 5.3
+* Not tested under Windows, might work
+
+Install
+=======
+
+ > phpize
+ > ./configure
+ > make
+ > make install
diff --git a/vendor/pimple/pimple/ext/pimple/config.m4 b/vendor/pimple/pimple/ext/pimple/config.m4
new file mode 100644
index 00000000..3a6e9aae
--- /dev/null
+++ b/vendor/pimple/pimple/ext/pimple/config.m4
@@ -0,0 +1,63 @@
+dnl $Id$
+dnl config.m4 for extension pimple
+
+dnl Comments in this file start with the string 'dnl'.
+dnl Remove where necessary. This file will not work
+dnl without editing.
+
+dnl If your extension references something external, use with:
+
+dnl PHP_ARG_WITH(pimple, for pimple support,
+dnl Make sure that the comment is aligned:
+dnl [ --with-pimple Include pimple support])
+
+dnl Otherwise use enable:
+
+PHP_ARG_ENABLE(pimple, whether to enable pimple support,
+dnl Make sure that the comment is aligned:
+[ --enable-pimple Enable pimple support])
+
+if test "$PHP_PIMPLE" != "no"; then
+ dnl Write more examples of tests here...
+
+ dnl # --with-pimple -> check with-path
+ dnl SEARCH_PATH="/usr/local /usr" # you might want to change this
+ dnl SEARCH_FOR="/include/pimple.h" # you most likely want to change this
+ dnl if test -r $PHP_PIMPLE/$SEARCH_FOR; then # path given as parameter
+ dnl PIMPLE_DIR=$PHP_PIMPLE
+ dnl else # search default path list
+ dnl AC_MSG_CHECKING([for pimple files in default path])
+ dnl for i in $SEARCH_PATH ; do
+ dnl if test -r $i/$SEARCH_FOR; then
+ dnl PIMPLE_DIR=$i
+ dnl AC_MSG_RESULT(found in $i)
+ dnl fi
+ dnl done
+ dnl fi
+ dnl
+ dnl if test -z "$PIMPLE_DIR"; then
+ dnl AC_MSG_RESULT([not found])
+ dnl AC_MSG_ERROR([Please reinstall the pimple distribution])
+ dnl fi
+
+ dnl # --with-pimple -> add include path
+ dnl PHP_ADD_INCLUDE($PIMPLE_DIR/include)
+
+ dnl # --with-pimple -> check for lib and symbol presence
+ dnl LIBNAME=pimple # you may want to change this
+ dnl LIBSYMBOL=pimple # you most likely want to change this
+
+ dnl PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL,
+ dnl [
+ dnl PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $PIMPLE_DIR/lib, PIMPLE_SHARED_LIBADD)
+ dnl AC_DEFINE(HAVE_PIMPLELIB,1,[ ])
+ dnl ],[
+ dnl AC_MSG_ERROR([wrong pimple lib version or lib not found])
+ dnl ],[
+ dnl -L$PIMPLE_DIR/lib -lm
+ dnl ])
+ dnl
+ dnl PHP_SUBST(PIMPLE_SHARED_LIBADD)
+
+ PHP_NEW_EXTENSION(pimple, pimple.c, $ext_shared)
+fi
diff --git a/vendor/pimple/pimple/ext/pimple/config.w32 b/vendor/pimple/pimple/ext/pimple/config.w32
new file mode 100644
index 00000000..39857b32
--- /dev/null
+++ b/vendor/pimple/pimple/ext/pimple/config.w32
@@ -0,0 +1,13 @@
+// $Id$
+// vim:ft=javascript
+
+// If your extension references something external, use ARG_WITH
+// ARG_WITH("pimple", "for pimple support", "no");
+
+// Otherwise, use ARG_ENABLE
+// ARG_ENABLE("pimple", "enable pimple support", "no");
+
+if (PHP_PIMPLE != "no") {
+ EXTENSION("pimple", "pimple.c");
+}
+
diff --git a/vendor/pimple/pimple/ext/pimple/php_pimple.h b/vendor/pimple/pimple/ext/pimple/php_pimple.h
new file mode 100644
index 00000000..258f3eea
--- /dev/null
+++ b/vendor/pimple/pimple/ext/pimple/php_pimple.h
@@ -0,0 +1,137 @@
+
+/*
+ * This file is part of Pimple.
+ *
+ * Copyright (c) 2014 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.
+ */
+
+#ifndef PHP_PIMPLE_H
+#define PHP_PIMPLE_H
+
+extern zend_module_entry pimple_module_entry;
+#define phpext_pimple_ptr &pimple_module_entry
+
+#ifdef PHP_WIN32
+# define PHP_PIMPLE_API __declspec(dllexport)
+#elif defined(__GNUC__) && __GNUC__ >= 4
+# define PHP_PIMPLE_API __attribute__ ((visibility("default")))
+#else
+# define PHP_PIMPLE_API
+#endif
+
+#ifdef ZTS
+#include "TSRM.h"
+#endif
+
+#define PIMPLE_VERSION "3.2.2-DEV"
+
+#define PIMPLE_NS "Pimple"
+#define PSR_CONTAINER_NS "Psr\\Container"
+#define PIMPLE_EXCEPTION_NS "Pimple\\Exception"
+
+#define PIMPLE_DEFAULT_ZVAL_CACHE_NUM 5
+#define PIMPLE_DEFAULT_ZVAL_VALUES_NUM 10
+
+#define PIMPLE_DEPRECATE do { \
+ int er = EG(error_reporting); \
+ EG(error_reporting) = 0;\
+ php_error(E_DEPRECATED, "The Pimple C extension is deprecated since version 3.1 and will be removed in 4.0."); \
+ EG(error_reporting) = er; \
+} while (0);
+
+zend_module_entry *get_module(void);
+
+PHP_MINIT_FUNCTION(pimple);
+PHP_MINFO_FUNCTION(pimple);
+
+PHP_METHOD(FrozenServiceException, __construct);
+PHP_METHOD(InvalidServiceIdentifierException, __construct);
+PHP_METHOD(UnknownIdentifierException, __construct);
+
+PHP_METHOD(Pimple, __construct);
+PHP_METHOD(Pimple, factory);
+PHP_METHOD(Pimple, protect);
+PHP_METHOD(Pimple, raw);
+PHP_METHOD(Pimple, extend);
+PHP_METHOD(Pimple, keys);
+PHP_METHOD(Pimple, register);
+PHP_METHOD(Pimple, offsetSet);
+PHP_METHOD(Pimple, offsetUnset);
+PHP_METHOD(Pimple, offsetGet);
+PHP_METHOD(Pimple, offsetExists);
+
+PHP_METHOD(PimpleClosure, invoker);
+
+typedef struct _pimple_bucket_value {
+ zval *value; /* Must be the first element */
+ zval *raw;
+ zend_object_handle handle_num;
+ enum {
+ PIMPLE_IS_PARAM = 0,
+ PIMPLE_IS_SERVICE = 2
+ } type;
+ zend_bool initialized;
+ zend_fcall_info_cache fcc;
+} pimple_bucket_value;
+
+typedef struct _pimple_object {
+ zend_object zobj;
+ HashTable values;
+ HashTable factories;
+ HashTable protected;
+} pimple_object;
+
+typedef struct _pimple_closure_object {
+ zend_object zobj;
+ zval *callable;
+ zval *factory;
+} pimple_closure_object;
+
+static const char sensiolabs_logo[] = "
";
+
+static void pimple_exception_call_parent_constructor(zval *this_ptr, const char *format, const char *arg1 TSRMLS_DC);
+
+static int pimple_zval_to_pimpleval(zval *_zval, pimple_bucket_value *_pimple_bucket_value TSRMLS_DC);
+static int pimple_zval_is_valid_callback(zval *_zval, pimple_bucket_value *_pimple_bucket_value TSRMLS_DC);
+
+static void pimple_bucket_dtor(pimple_bucket_value *bucket);
+static void pimple_free_bucket(pimple_bucket_value *bucket);
+
+static zval *pimple_object_read_dimension(zval *object, zval *offset, int type TSRMLS_DC);
+static void pimple_object_write_dimension(zval *object, zval *offset, zval *value TSRMLS_DC);
+static int pimple_object_has_dimension(zval *object, zval *offset, int check_empty TSRMLS_DC);
+static void pimple_object_unset_dimension(zval *object, zval *offset TSRMLS_DC);
+static zend_object_value pimple_object_create(zend_class_entry *ce TSRMLS_DC);
+static void pimple_free_object_storage(pimple_object *obj TSRMLS_DC);
+
+static void pimple_closure_free_object_storage(pimple_closure_object *obj TSRMLS_DC);
+static zend_object_value pimple_closure_object_create(zend_class_entry *ce TSRMLS_DC);
+static zend_function *pimple_closure_get_constructor(zval * TSRMLS_DC);
+static int pimple_closure_get_closure(zval *obj, zend_class_entry **ce_ptr, union _zend_function **fptr_ptr, zval **zobj_ptr TSRMLS_DC);
+
+#ifdef ZTS
+#define PIMPLE_G(v) TSRMG(pimple_globals_id, zend_pimple_globals *, v)
+#else
+#define PIMPLE_G(v) (pimple_globals.v)
+#endif
+
+#endif /* PHP_PIMPLE_H */
+
diff --git a/vendor/pimple/pimple/ext/pimple/pimple.c b/vendor/pimple/pimple/ext/pimple/pimple.c
new file mode 100644
index 00000000..c80499b3
--- /dev/null
+++ b/vendor/pimple/pimple/ext/pimple/pimple.c
@@ -0,0 +1,1114 @@
+
+/*
+ * This file is part of Pimple.
+ *
+ * Copyright (c) 2014 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php.h"
+#include "php_ini.h"
+#include "ext/standard/info.h"
+#include "php_pimple.h"
+#include "pimple_compat.h"
+#include "zend_interfaces.h"
+#include "zend.h"
+#include "Zend/zend_closures.h"
+#include "ext/spl/spl_exceptions.h"
+#include "Zend/zend_exceptions.h"
+#include "main/php_output.h"
+#include "SAPI.h"
+
+static zend_class_entry *pimple_ce_PsrContainerInterface;
+static zend_class_entry *pimple_ce_PsrContainerExceptionInterface;
+static zend_class_entry *pimple_ce_PsrNotFoundExceptionInterface;
+
+static zend_class_entry *pimple_ce_ExpectedInvokableException;
+static zend_class_entry *pimple_ce_FrozenServiceException;
+static zend_class_entry *pimple_ce_InvalidServiceIdentifierException;
+static zend_class_entry *pimple_ce_UnknownIdentifierException;
+
+static zend_class_entry *pimple_ce;
+static zend_object_handlers pimple_object_handlers;
+static zend_class_entry *pimple_closure_ce;
+static zend_class_entry *pimple_serviceprovider_ce;
+static zend_object_handlers pimple_closure_object_handlers;
+static zend_internal_function pimple_closure_invoker_function;
+
+#define FETCH_DIM_HANDLERS_VARS pimple_object *pimple_obj = NULL; \
+ ulong index; \
+ pimple_obj = (pimple_object *)zend_object_store_get_object(object TSRMLS_CC); \
+
+#define PIMPLE_OBJECT_HANDLE_INHERITANCE_OBJECT_HANDLERS do { \
+ if (ce != pimple_ce) { \
+ zend_hash_find(&ce->function_table, ZEND_STRS("offsetget"), (void **)&function); \
+ if (function->common.scope != ce) { /* if the function is not defined in this actual class */ \
+ pimple_object_handlers.read_dimension = pimple_object_read_dimension; /* then overwrite the handler to use custom one */ \
+ } \
+ zend_hash_find(&ce->function_table, ZEND_STRS("offsetset"), (void **)&function); \
+ if (function->common.scope != ce) { \
+ pimple_object_handlers.write_dimension = pimple_object_write_dimension; \
+ } \
+ zend_hash_find(&ce->function_table, ZEND_STRS("offsetexists"), (void **)&function); \
+ if (function->common.scope != ce) { \
+ pimple_object_handlers.has_dimension = pimple_object_has_dimension; \
+ } \
+ zend_hash_find(&ce->function_table, ZEND_STRS("offsetunset"), (void **)&function); \
+ if (function->common.scope != ce) { \
+ pimple_object_handlers.unset_dimension = pimple_object_unset_dimension; \
+ } \
+ } else { \
+ pimple_object_handlers.read_dimension = pimple_object_read_dimension; \
+ pimple_object_handlers.write_dimension = pimple_object_write_dimension; \
+ pimple_object_handlers.has_dimension = pimple_object_has_dimension; \
+ pimple_object_handlers.unset_dimension = pimple_object_unset_dimension; \
+ }\
+ } while(0);
+
+#define PIMPLE_CALL_CB do { \
+ zend_fcall_info_argn(&fci TSRMLS_CC, 1, &object); \
+ fci.size = sizeof(fci); \
+ fci.object_ptr = retval->fcc.object_ptr; \
+ fci.function_name = retval->value; \
+ fci.no_separation = 1; \
+ fci.retval_ptr_ptr = &retval_ptr_ptr; \
+\
+ zend_call_function(&fci, &retval->fcc TSRMLS_CC); \
+ efree(fci.params); \
+ if (EG(exception)) { \
+ return EG(uninitialized_zval_ptr); \
+ } \
+ } while(0);
+
+
+/* Psr\Container\ContainerInterface */
+ZEND_BEGIN_ARG_INFO_EX(arginfo_pimple_PsrContainerInterface_get, 0, 0, 1)
+ZEND_ARG_INFO(0, id)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_pimple_PsrContainerInterface_has, 0, 0, 1)
+ZEND_ARG_INFO(0, id)
+ZEND_END_ARG_INFO()
+
+static const zend_function_entry pimple_ce_PsrContainerInterface_functions[] = {
+ PHP_ABSTRACT_ME(ContainerInterface, get, arginfo_pimple_PsrContainerInterface_get)
+ PHP_ABSTRACT_ME(ContainerInterface, has, arginfo_pimple_PsrContainerInterface_has)
+ PHP_FE_END
+};
+
+/* Psr\Container\ContainerExceptionInterface */
+static const zend_function_entry pimple_ce_PsrContainerExceptionInterface_functions[] = {
+ PHP_FE_END
+};
+
+/* Psr\Container\NotFoundExceptionInterface */
+static const zend_function_entry pimple_ce_PsrNotFoundExceptionInterface_functions[] = {
+ PHP_FE_END
+};
+
+/* Pimple\Exception\FrozenServiceException */
+ZEND_BEGIN_ARG_INFO_EX(arginfo_FrozenServiceException___construct, 0, 0, 1)
+ZEND_ARG_INFO(0, id)
+ZEND_END_ARG_INFO()
+
+static const zend_function_entry pimple_ce_FrozenServiceException_functions[] = {
+ PHP_ME(FrozenServiceException, __construct, arginfo_FrozenServiceException___construct, ZEND_ACC_PUBLIC)
+ PHP_FE_END
+};
+
+/* Pimple\Exception\InvalidServiceIdentifierException */
+ZEND_BEGIN_ARG_INFO_EX(arginfo_InvalidServiceIdentifierException___construct, 0, 0, 1)
+ZEND_ARG_INFO(0, id)
+ZEND_END_ARG_INFO()
+
+static const zend_function_entry pimple_ce_InvalidServiceIdentifierException_functions[] = {
+ PHP_ME(InvalidServiceIdentifierException, __construct, arginfo_InvalidServiceIdentifierException___construct, ZEND_ACC_PUBLIC)
+ PHP_FE_END
+};
+
+/* Pimple\Exception\UnknownIdentifierException */
+ZEND_BEGIN_ARG_INFO_EX(arginfo_UnknownIdentifierException___construct, 0, 0, 1)
+ZEND_ARG_INFO(0, id)
+ZEND_END_ARG_INFO()
+
+static const zend_function_entry pimple_ce_UnknownIdentifierException_functions[] = {
+ PHP_ME(UnknownIdentifierException, __construct, arginfo_UnknownIdentifierException___construct, ZEND_ACC_PUBLIC)
+ PHP_FE_END
+};
+
+/* Pimple\Container */
+ZEND_BEGIN_ARG_INFO_EX(arginfo___construct, 0, 0, 0)
+ZEND_ARG_ARRAY_INFO(0, value, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetset, 0, 0, 2)
+ZEND_ARG_INFO(0, offset)
+ZEND_ARG_INFO(0, value)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetget, 0, 0, 1)
+ZEND_ARG_INFO(0, offset)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetexists, 0, 0, 1)
+ZEND_ARG_INFO(0, offset)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetunset, 0, 0, 1)
+ZEND_ARG_INFO(0, offset)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_factory, 0, 0, 1)
+ZEND_ARG_INFO(0, callable)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_protect, 0, 0, 1)
+ZEND_ARG_INFO(0, callable)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_raw, 0, 0, 1)
+ZEND_ARG_INFO(0, id)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_extend, 0, 0, 2)
+ZEND_ARG_INFO(0, id)
+ZEND_ARG_INFO(0, callable)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_keys, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_register, 0, 0, 1)
+ZEND_ARG_OBJ_INFO(0, provider, Pimple\\ServiceProviderInterface, 0)
+ZEND_ARG_ARRAY_INFO(0, values, 1)
+ZEND_END_ARG_INFO()
+
+static const zend_function_entry pimple_ce_functions[] = {
+ PHP_ME(Pimple, __construct, arginfo___construct, ZEND_ACC_PUBLIC)
+ PHP_ME(Pimple, factory, arginfo_factory, ZEND_ACC_PUBLIC)
+ PHP_ME(Pimple, protect, arginfo_protect, ZEND_ACC_PUBLIC)
+ PHP_ME(Pimple, raw, arginfo_raw, ZEND_ACC_PUBLIC)
+ PHP_ME(Pimple, extend, arginfo_extend, ZEND_ACC_PUBLIC)
+ PHP_ME(Pimple, keys, arginfo_keys, ZEND_ACC_PUBLIC)
+ PHP_ME(Pimple, register, arginfo_register, ZEND_ACC_PUBLIC)
+
+ PHP_ME(Pimple, offsetSet, arginfo_offsetset, ZEND_ACC_PUBLIC)
+ PHP_ME(Pimple, offsetGet, arginfo_offsetget, ZEND_ACC_PUBLIC)
+ PHP_ME(Pimple, offsetExists, arginfo_offsetexists, ZEND_ACC_PUBLIC)
+ PHP_ME(Pimple, offsetUnset, arginfo_offsetunset, ZEND_ACC_PUBLIC)
+ PHP_FE_END
+};
+
+/* Pimple\ServiceProviderInterface */
+ZEND_BEGIN_ARG_INFO_EX(arginfo_serviceprovider_register, 0, 0, 1)
+ZEND_ARG_OBJ_INFO(0, pimple, Pimple\\Container, 0)
+ZEND_END_ARG_INFO()
+
+static const zend_function_entry pimple_serviceprovider_iface_ce_functions[] = {
+ PHP_ABSTRACT_ME(ServiceProviderInterface, register, arginfo_serviceprovider_register)
+ PHP_FE_END
+};
+
+/* parent::__construct(sprintf("Something with %s", $arg1)) */
+static void pimple_exception_call_parent_constructor(zval *this_ptr, const char *format, const char *arg1 TSRMLS_DC)
+{
+ zend_class_entry *ce = Z_OBJCE_P(this_ptr);
+ char *message = NULL;
+ int message_len;
+ zval *constructor_arg;
+
+ message_len = spprintf(&message, 0, format, arg1);
+ ALLOC_INIT_ZVAL(constructor_arg);
+ ZVAL_STRINGL(constructor_arg, message, message_len, 1);
+
+ zend_call_method_with_1_params(&this_ptr, ce, &ce->parent->constructor, "__construct", NULL, constructor_arg);
+
+ efree(message);
+ zval_ptr_dtor(&constructor_arg);
+}
+
+/**
+ * Pass a single string parameter to exception constructor and throw
+ */
+static void pimple_throw_exception_string(zend_class_entry *ce, const char *message, zend_uint message_len TSRMLS_DC)
+{
+ zval *exception, *param;
+
+ ALLOC_INIT_ZVAL(exception);
+ object_init_ex(exception, ce);
+
+ ALLOC_INIT_ZVAL(param);
+ ZVAL_STRINGL(param, message, message_len, 1);
+
+ zend_call_method_with_1_params(&exception, ce, &ce->constructor, "__construct", NULL, param);
+
+ zend_throw_exception_object(exception TSRMLS_CC);
+
+ zval_ptr_dtor(¶m);
+}
+
+static void pimple_closure_free_object_storage(pimple_closure_object *obj TSRMLS_DC)
+{
+ zend_object_std_dtor(&obj->zobj TSRMLS_CC);
+ if (obj->factory) {
+ zval_ptr_dtor(&obj->factory);
+ }
+ if (obj->callable) {
+ zval_ptr_dtor(&obj->callable);
+ }
+ efree(obj);
+}
+
+static void pimple_free_object_storage(pimple_object *obj TSRMLS_DC)
+{
+ zend_hash_destroy(&obj->factories);
+ zend_hash_destroy(&obj->protected);
+ zend_hash_destroy(&obj->values);
+ zend_object_std_dtor(&obj->zobj TSRMLS_CC);
+ efree(obj);
+}
+
+static void pimple_free_bucket(pimple_bucket_value *bucket)
+{
+ if (bucket->raw) {
+ zval_ptr_dtor(&bucket->raw);
+ }
+}
+
+static zend_object_value pimple_closure_object_create(zend_class_entry *ce TSRMLS_DC)
+{
+ zend_object_value retval;
+ pimple_closure_object *pimple_closure_obj = NULL;
+
+ pimple_closure_obj = ecalloc(1, sizeof(pimple_closure_object));
+ ZEND_OBJ_INIT(&pimple_closure_obj->zobj, ce);
+
+ pimple_closure_object_handlers.get_constructor = pimple_closure_get_constructor;
+ retval.handlers = &pimple_closure_object_handlers;
+ retval.handle = zend_objects_store_put(pimple_closure_obj, (zend_objects_store_dtor_t) zend_objects_destroy_object, (zend_objects_free_object_storage_t) pimple_closure_free_object_storage, NULL TSRMLS_CC);
+
+ return retval;
+}
+
+static zend_function *pimple_closure_get_constructor(zval *obj TSRMLS_DC)
+{
+ zend_error(E_ERROR, "Pimple\\ContainerClosure is an internal class and cannot be instantiated");
+
+ return NULL;
+}
+
+static int pimple_closure_get_closure(zval *obj, zend_class_entry **ce_ptr, union _zend_function **fptr_ptr, zval **zobj_ptr TSRMLS_DC)
+{
+ *zobj_ptr = obj;
+ *ce_ptr = Z_OBJCE_P(obj);
+ *fptr_ptr = (zend_function *)&pimple_closure_invoker_function;
+
+ return SUCCESS;
+}
+
+static zend_object_value pimple_object_create(zend_class_entry *ce TSRMLS_DC)
+{
+ zend_object_value retval;
+ pimple_object *pimple_obj = NULL;
+ zend_function *function = NULL;
+
+ pimple_obj = emalloc(sizeof(pimple_object));
+ ZEND_OBJ_INIT(&pimple_obj->zobj, ce);
+
+ PIMPLE_OBJECT_HANDLE_INHERITANCE_OBJECT_HANDLERS
+
+ retval.handlers = &pimple_object_handlers;
+ retval.handle = zend_objects_store_put(pimple_obj, (zend_objects_store_dtor_t) zend_objects_destroy_object, (zend_objects_free_object_storage_t) pimple_free_object_storage, NULL TSRMLS_CC);
+
+ zend_hash_init(&pimple_obj->factories, PIMPLE_DEFAULT_ZVAL_CACHE_NUM, NULL, (dtor_func_t)pimple_bucket_dtor, 0);
+ zend_hash_init(&pimple_obj->protected, PIMPLE_DEFAULT_ZVAL_CACHE_NUM, NULL, (dtor_func_t)pimple_bucket_dtor, 0);
+ zend_hash_init(&pimple_obj->values, PIMPLE_DEFAULT_ZVAL_VALUES_NUM, NULL, (dtor_func_t)pimple_bucket_dtor, 0);
+
+ return retval;
+}
+
+static void pimple_object_write_dimension(zval *object, zval *offset, zval *value TSRMLS_DC)
+{
+ FETCH_DIM_HANDLERS_VARS
+
+ pimple_bucket_value pimple_value = {0}, *found_value = NULL;
+ ulong hash;
+
+ pimple_zval_to_pimpleval(value, &pimple_value TSRMLS_CC);
+
+ if (!offset) {/* $p[] = 'foo' when not overloaded */
+ zend_hash_next_index_insert(&pimple_obj->values, (void *)&pimple_value, sizeof(pimple_bucket_value), NULL);
+ Z_ADDREF_P(value);
+ return;
+ }
+
+ switch (Z_TYPE_P(offset)) {
+ case IS_STRING:
+ hash = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ zend_hash_quick_find(&pimple_obj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hash, (void **)&found_value);
+ if (found_value && found_value->type == PIMPLE_IS_SERVICE && found_value->initialized == 1) {
+ pimple_free_bucket(&pimple_value);
+ pimple_throw_exception_string(pimple_ce_FrozenServiceException, Z_STRVAL_P(offset), Z_STRLEN_P(offset) TSRMLS_CC);
+ return;
+ }
+ if (zend_hash_quick_update(&pimple_obj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hash, (void *)&pimple_value, sizeof(pimple_bucket_value), NULL) == FAILURE) {
+ pimple_free_bucket(&pimple_value);
+ return;
+ }
+ Z_ADDREF_P(value);
+ break;
+ case IS_DOUBLE:
+ case IS_BOOL:
+ case IS_LONG:
+ if (Z_TYPE_P(offset) == IS_DOUBLE) {
+ index = (ulong)Z_DVAL_P(offset);
+ } else {
+ index = Z_LVAL_P(offset);
+ }
+ zend_hash_index_find(&pimple_obj->values, index, (void **)&found_value);
+ if (found_value && found_value->type == PIMPLE_IS_SERVICE && found_value->initialized == 1) {
+ pimple_free_bucket(&pimple_value);
+ convert_to_string(offset);
+ pimple_throw_exception_string(pimple_ce_FrozenServiceException, Z_STRVAL_P(offset), Z_STRLEN_P(offset) TSRMLS_CC);
+ return;
+ }
+ if (zend_hash_index_update(&pimple_obj->values, index, (void *)&pimple_value, sizeof(pimple_bucket_value), NULL) == FAILURE) {
+ pimple_free_bucket(&pimple_value);
+ return;
+ }
+ Z_ADDREF_P(value);
+ break;
+ case IS_NULL: /* $p[] = 'foo' when overloaded */
+ zend_hash_next_index_insert(&pimple_obj->values, (void *)&pimple_value, sizeof(pimple_bucket_value), NULL);
+ Z_ADDREF_P(value);
+ break;
+ default:
+ pimple_free_bucket(&pimple_value);
+ zend_error(E_WARNING, "Unsupported offset type");
+ }
+}
+
+static void pimple_object_unset_dimension(zval *object, zval *offset TSRMLS_DC)
+{
+ FETCH_DIM_HANDLERS_VARS
+
+ switch (Z_TYPE_P(offset)) {
+ case IS_STRING:
+ zend_symtable_del(&pimple_obj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ zend_symtable_del(&pimple_obj->factories, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ zend_symtable_del(&pimple_obj->protected, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ break;
+ case IS_DOUBLE:
+ case IS_BOOL:
+ case IS_LONG:
+ if (Z_TYPE_P(offset) == IS_DOUBLE) {
+ index = (ulong)Z_DVAL_P(offset);
+ } else {
+ index = Z_LVAL_P(offset);
+ }
+ zend_hash_index_del(&pimple_obj->values, index);
+ zend_hash_index_del(&pimple_obj->factories, index);
+ zend_hash_index_del(&pimple_obj->protected, index);
+ break;
+ default:
+ zend_error(E_WARNING, "Unsupported offset type");
+ }
+}
+
+static int pimple_object_has_dimension(zval *object, zval *offset, int check_empty TSRMLS_DC)
+{
+ FETCH_DIM_HANDLERS_VARS
+
+ pimple_bucket_value *retval = NULL;
+
+ switch (Z_TYPE_P(offset)) {
+ case IS_STRING:
+ if (zend_symtable_find(&pimple_obj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void **)&retval) == SUCCESS) {
+ switch (check_empty) {
+ case 0: /* isset */
+ return 1; /* Differs from PHP behavior (Z_TYPE_P(retval->value) != IS_NULL;) */
+ case 1: /* empty */
+ default:
+ return zend_is_true(retval->value);
+ }
+ }
+ return 0;
+ break;
+ case IS_DOUBLE:
+ case IS_BOOL:
+ case IS_LONG:
+ if (Z_TYPE_P(offset) == IS_DOUBLE) {
+ index = (ulong)Z_DVAL_P(offset);
+ } else {
+ index = Z_LVAL_P(offset);
+ }
+ if (zend_hash_index_find(&pimple_obj->values, index, (void **)&retval) == SUCCESS) {
+ switch (check_empty) {
+ case 0: /* isset */
+ return 1; /* Differs from PHP behavior (Z_TYPE_P(retval->value) != IS_NULL;)*/
+ case 1: /* empty */
+ default:
+ return zend_is_true(retval->value);
+ }
+ }
+ return 0;
+ break;
+ default:
+ zend_error(E_WARNING, "Unsupported offset type");
+ return 0;
+ }
+}
+
+static zval *pimple_object_read_dimension(zval *object, zval *offset, int type TSRMLS_DC)
+{
+ FETCH_DIM_HANDLERS_VARS
+
+ pimple_bucket_value *retval = NULL;
+ zend_fcall_info fci = {0};
+ zval *retval_ptr_ptr = NULL;
+
+ switch (Z_TYPE_P(offset)) {
+ case IS_STRING:
+ if (zend_symtable_find(&pimple_obj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void **)&retval) == FAILURE) {
+ pimple_throw_exception_string(pimple_ce_UnknownIdentifierException, Z_STRVAL_P(offset), Z_STRLEN_P(offset) TSRMLS_CC);
+
+ return EG(uninitialized_zval_ptr);
+ }
+ break;
+ case IS_DOUBLE:
+ case IS_BOOL:
+ case IS_LONG:
+ if (Z_TYPE_P(offset) == IS_DOUBLE) {
+ index = (ulong)Z_DVAL_P(offset);
+ } else {
+ index = Z_LVAL_P(offset);
+ }
+ if (zend_hash_index_find(&pimple_obj->values, index, (void **)&retval) == FAILURE) {
+ return EG(uninitialized_zval_ptr);
+ }
+ break;
+ case IS_NULL: /* $p[][3] = 'foo' first dim access */
+ return EG(uninitialized_zval_ptr);
+ break;
+ default:
+ zend_error(E_WARNING, "Unsupported offset type");
+ return EG(uninitialized_zval_ptr);
+ }
+
+ if(retval->type == PIMPLE_IS_PARAM) {
+ return retval->value;
+ }
+
+ if (zend_hash_index_exists(&pimple_obj->protected, retval->handle_num)) {
+ /* Service is protected, return the value every time */
+ return retval->value;
+ }
+
+ if (zend_hash_index_exists(&pimple_obj->factories, retval->handle_num)) {
+ /* Service is a factory, call it every time and never cache its result */
+ PIMPLE_CALL_CB
+ Z_DELREF_P(retval_ptr_ptr); /* fetch dim addr will increment refcount */
+ return retval_ptr_ptr;
+ }
+
+ if (retval->initialized == 1) {
+ /* Service has already been called, return its cached value */
+ return retval->value;
+ }
+
+ ALLOC_INIT_ZVAL(retval->raw);
+ MAKE_COPY_ZVAL(&retval->value, retval->raw);
+
+ PIMPLE_CALL_CB
+
+ retval->initialized = 1;
+ zval_ptr_dtor(&retval->value);
+ retval->value = retval_ptr_ptr;
+
+ return retval->value;
+}
+
+static int pimple_zval_is_valid_callback(zval *_zval, pimple_bucket_value *_pimple_bucket_value TSRMLS_DC)
+{
+ if (Z_TYPE_P(_zval) != IS_OBJECT) {
+ return FAILURE;
+ }
+
+ if (_pimple_bucket_value->fcc.called_scope) {
+ return SUCCESS;
+ }
+
+ if (Z_OBJ_HANDLER_P(_zval, get_closure) && Z_OBJ_HANDLER_P(_zval, get_closure)(_zval, &_pimple_bucket_value->fcc.calling_scope, &_pimple_bucket_value->fcc.function_handler, &_pimple_bucket_value->fcc.object_ptr TSRMLS_CC) == SUCCESS) {
+ _pimple_bucket_value->fcc.called_scope = _pimple_bucket_value->fcc.calling_scope;
+ return SUCCESS;
+ } else {
+ return FAILURE;
+ }
+}
+
+static int pimple_zval_to_pimpleval(zval *_zval, pimple_bucket_value *_pimple_bucket_value TSRMLS_DC)
+{
+ _pimple_bucket_value->value = _zval;
+
+ if (Z_TYPE_P(_zval) != IS_OBJECT) {
+ return PIMPLE_IS_PARAM;
+ }
+
+ if (pimple_zval_is_valid_callback(_zval, _pimple_bucket_value TSRMLS_CC) == SUCCESS) {
+ _pimple_bucket_value->type = PIMPLE_IS_SERVICE;
+ _pimple_bucket_value->handle_num = Z_OBJ_HANDLE_P(_zval);
+ }
+
+ return PIMPLE_IS_SERVICE;
+}
+
+static void pimple_bucket_dtor(pimple_bucket_value *bucket)
+{
+ zval_ptr_dtor(&bucket->value);
+ pimple_free_bucket(bucket);
+}
+
+PHP_METHOD(FrozenServiceException, __construct)
+{
+ char *id = NULL;
+ int id_len;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &id, &id_len) == FAILURE) {
+ return;
+ }
+ pimple_exception_call_parent_constructor(getThis(), "Cannot override frozen service \"%s\".", id TSRMLS_CC);
+}
+
+PHP_METHOD(InvalidServiceIdentifierException, __construct)
+{
+ char *id = NULL;
+ int id_len;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &id, &id_len) == FAILURE) {
+ return;
+ }
+ pimple_exception_call_parent_constructor(getThis(), "Identifier \"%s\" does not contain an object definition.", id TSRMLS_CC);
+}
+
+PHP_METHOD(UnknownIdentifierException, __construct)
+{
+ char *id = NULL;
+ int id_len;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &id, &id_len) == FAILURE) {
+ return;
+ }
+ pimple_exception_call_parent_constructor(getThis(), "Identifier \"%s\" is not defined.", id TSRMLS_CC);
+}
+
+PHP_METHOD(Pimple, protect)
+{
+ zval *protected = NULL;
+ pimple_object *pobj = NULL;
+ pimple_bucket_value bucket = {0};
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &protected) == FAILURE) {
+ return;
+ }
+
+ if (pimple_zval_is_valid_callback(protected, &bucket TSRMLS_CC) == FAILURE) {
+ pimple_free_bucket(&bucket);
+ zend_throw_exception(pimple_ce_ExpectedInvokableException, "Callable is not a Closure or invokable object.", 0 TSRMLS_CC);
+ return;
+ }
+
+ pimple_zval_to_pimpleval(protected, &bucket TSRMLS_CC);
+ pobj = (pimple_object *)zend_object_store_get_object(getThis() TSRMLS_CC);
+
+ if (zend_hash_index_update(&pobj->protected, bucket.handle_num, (void *)&bucket, sizeof(pimple_bucket_value), NULL) == SUCCESS) {
+ Z_ADDREF_P(protected);
+ RETURN_ZVAL(protected, 1 , 0);
+ } else {
+ pimple_free_bucket(&bucket);
+ }
+ RETURN_FALSE;
+}
+
+PHP_METHOD(Pimple, raw)
+{
+ zval *offset = NULL;
+ pimple_object *pobj = NULL;
+ pimple_bucket_value *value = NULL;
+ ulong index;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &offset) == FAILURE) {
+ return;
+ }
+
+ pobj = zend_object_store_get_object(getThis() TSRMLS_CC);
+
+ switch (Z_TYPE_P(offset)) {
+ case IS_STRING:
+ if (zend_symtable_find(&pobj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void *)&value) == FAILURE) {
+ pimple_throw_exception_string(pimple_ce_UnknownIdentifierException, Z_STRVAL_P(offset), Z_STRLEN_P(offset) TSRMLS_CC);
+ RETURN_NULL();
+ }
+ break;
+ case IS_DOUBLE:
+ case IS_BOOL:
+ case IS_LONG:
+ if (Z_TYPE_P(offset) == IS_DOUBLE) {
+ index = (ulong)Z_DVAL_P(offset);
+ } else {
+ index = Z_LVAL_P(offset);
+ }
+ if (zend_hash_index_find(&pobj->values, index, (void *)&value) == FAILURE) {
+ RETURN_NULL();
+ }
+ break;
+ case IS_NULL:
+ default:
+ zend_error(E_WARNING, "Unsupported offset type");
+ }
+
+ if (value->raw) {
+ RETVAL_ZVAL(value->raw, 1, 0);
+ } else {
+ RETVAL_ZVAL(value->value, 1, 0);
+ }
+}
+
+PHP_METHOD(Pimple, extend)
+{
+ zval *offset = NULL, *callable = NULL, *pimple_closure_obj = NULL;
+ pimple_bucket_value bucket = {0}, *value = NULL;
+ pimple_object *pobj = NULL;
+ pimple_closure_object *pcobj = NULL;
+ ulong index;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &offset, &callable) == FAILURE) {
+ return;
+ }
+
+ pobj = zend_object_store_get_object(getThis() TSRMLS_CC);
+
+ switch (Z_TYPE_P(offset)) {
+ case IS_STRING:
+ if (zend_symtable_find(&pobj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void *)&value) == FAILURE) {
+ pimple_throw_exception_string(pimple_ce_UnknownIdentifierException, Z_STRVAL_P(offset), Z_STRLEN_P(offset) TSRMLS_CC);
+ RETURN_NULL();
+ }
+
+ if (value->type != PIMPLE_IS_SERVICE) {
+ pimple_throw_exception_string(pimple_ce_InvalidServiceIdentifierException, Z_STRVAL_P(offset), Z_STRLEN_P(offset) TSRMLS_CC);
+ RETURN_NULL();
+ }
+ if (zend_hash_index_exists(&pobj->protected, value->handle_num)) {
+ int er = EG(error_reporting);
+ EG(error_reporting) = 0;
+ php_error(E_DEPRECATED, "How Pimple behaves when extending protected closures will be fixed in Pimple 4. Are you sure \"%s\" should be protected?", Z_STRVAL_P(offset));
+ EG(error_reporting) = er;
+ }
+ break;
+ case IS_DOUBLE:
+ case IS_BOOL:
+ case IS_LONG:
+ if (Z_TYPE_P(offset) == IS_DOUBLE) {
+ index = (ulong)Z_DVAL_P(offset);
+ } else {
+ index = Z_LVAL_P(offset);
+ }
+ if (zend_hash_index_find(&pobj->values, index, (void *)&value) == FAILURE) {
+ convert_to_string(offset);
+ pimple_throw_exception_string(pimple_ce_UnknownIdentifierException, Z_STRVAL_P(offset), Z_STRLEN_P(offset) TSRMLS_CC);
+ RETURN_NULL();
+ }
+ if (value->type != PIMPLE_IS_SERVICE) {
+ convert_to_string(offset);
+ pimple_throw_exception_string(pimple_ce_InvalidServiceIdentifierException, Z_STRVAL_P(offset), Z_STRLEN_P(offset) TSRMLS_CC);
+ RETURN_NULL();
+ }
+ if (zend_hash_index_exists(&pobj->protected, value->handle_num)) {
+ int er = EG(error_reporting);
+ EG(error_reporting) = 0;
+ php_error(E_DEPRECATED, "How Pimple behaves when extending protected closures will be fixed in Pimple 4. Are you sure \"%ld\" should be protected?", index);
+ EG(error_reporting) = er;
+ }
+ break;
+ case IS_NULL:
+ default:
+ zend_error(E_WARNING, "Unsupported offset type");
+ }
+
+ if (pimple_zval_is_valid_callback(callable, &bucket TSRMLS_CC) == FAILURE) {
+ pimple_free_bucket(&bucket);
+ zend_throw_exception(pimple_ce_ExpectedInvokableException, "Extension service definition is not a Closure or invokable object.", 0 TSRMLS_CC);
+ RETURN_NULL();
+ }
+ pimple_free_bucket(&bucket);
+
+ ALLOC_INIT_ZVAL(pimple_closure_obj);
+ object_init_ex(pimple_closure_obj, pimple_closure_ce);
+
+ pcobj = zend_object_store_get_object(pimple_closure_obj TSRMLS_CC);
+ pcobj->callable = callable;
+ pcobj->factory = value->value;
+ Z_ADDREF_P(callable);
+ Z_ADDREF_P(value->value);
+
+ if (zend_hash_index_exists(&pobj->factories, value->handle_num)) {
+ pimple_zval_to_pimpleval(pimple_closure_obj, &bucket TSRMLS_CC);
+ zend_hash_index_del(&pobj->factories, value->handle_num);
+ zend_hash_index_update(&pobj->factories, bucket.handle_num, (void *)&bucket, sizeof(pimple_bucket_value), NULL);
+ Z_ADDREF_P(pimple_closure_obj);
+ }
+
+ pimple_object_write_dimension(getThis(), offset, pimple_closure_obj TSRMLS_CC);
+
+ RETVAL_ZVAL(pimple_closure_obj, 1, 1);
+}
+
+PHP_METHOD(Pimple, keys)
+{
+ HashPosition pos;
+ pimple_object *pobj = NULL;
+ zval **value = NULL;
+ zval *endval = NULL;
+ char *str_index = NULL;
+ int str_len;
+ ulong num_index;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+
+ pobj = zend_object_store_get_object(getThis() TSRMLS_CC);
+ array_init_size(return_value, zend_hash_num_elements(&pobj->values));
+
+ zend_hash_internal_pointer_reset_ex(&pobj->values, &pos);
+
+ while(zend_hash_get_current_data_ex(&pobj->values, (void **)&value, &pos) == SUCCESS) {
+ MAKE_STD_ZVAL(endval);
+ switch (zend_hash_get_current_key_ex(&pobj->values, &str_index, (uint *)&str_len, &num_index, 0, &pos)) {
+ case HASH_KEY_IS_STRING:
+ ZVAL_STRINGL(endval, str_index, str_len - 1, 1);
+ zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &endval, sizeof(zval *), NULL);
+ break;
+ case HASH_KEY_IS_LONG:
+ ZVAL_LONG(endval, num_index);
+ zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &endval, sizeof(zval *), NULL);
+ break;
+ }
+ zend_hash_move_forward_ex(&pobj->values, &pos);
+ }
+}
+
+PHP_METHOD(Pimple, factory)
+{
+ zval *factory = NULL;
+ pimple_object *pobj = NULL;
+ pimple_bucket_value bucket = {0};
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &factory) == FAILURE) {
+ return;
+ }
+
+ if (pimple_zval_is_valid_callback(factory, &bucket TSRMLS_CC) == FAILURE) {
+ pimple_free_bucket(&bucket);
+ zend_throw_exception(pimple_ce_ExpectedInvokableException, "Service definition is not a Closure or invokable object.", 0 TSRMLS_CC);
+ return;
+ }
+
+ pimple_zval_to_pimpleval(factory, &bucket TSRMLS_CC);
+ pobj = (pimple_object *)zend_object_store_get_object(getThis() TSRMLS_CC);
+
+ if (zend_hash_index_update(&pobj->factories, bucket.handle_num, (void *)&bucket, sizeof(pimple_bucket_value), NULL) == SUCCESS) {
+ Z_ADDREF_P(factory);
+ RETURN_ZVAL(factory, 1 , 0);
+ } else {
+ pimple_free_bucket(&bucket);
+ }
+
+ RETURN_FALSE;
+}
+
+PHP_METHOD(Pimple, offsetSet)
+{
+ zval *offset = NULL, *value = NULL;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &offset, &value) == FAILURE) {
+ return;
+ }
+
+ pimple_object_write_dimension(getThis(), offset, value TSRMLS_CC);
+}
+
+PHP_METHOD(Pimple, offsetGet)
+{
+ zval *offset = NULL, *retval = NULL;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &offset) == FAILURE) {
+ return;
+ }
+
+ retval = pimple_object_read_dimension(getThis(), offset, 0 TSRMLS_CC);
+
+ RETVAL_ZVAL(retval, 1, 0);
+}
+
+PHP_METHOD(Pimple, offsetUnset)
+{
+ zval *offset = NULL;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &offset) == FAILURE) {
+ return;
+ }
+
+ pimple_object_unset_dimension(getThis(), offset TSRMLS_CC);
+}
+
+PHP_METHOD(Pimple, offsetExists)
+{
+ zval *offset = NULL;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &offset) == FAILURE) {
+ return;
+ }
+
+ RETVAL_BOOL(pimple_object_has_dimension(getThis(), offset, 1 TSRMLS_CC));
+}
+
+PHP_METHOD(Pimple, register)
+{
+ zval *provider;
+ zval **data;
+ zval *retval = NULL;
+ zval key;
+
+ HashTable *array = NULL;
+ HashPosition pos;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|h", &provider, pimple_serviceprovider_ce, &array) == FAILURE) {
+ return;
+ }
+
+ RETVAL_ZVAL(getThis(), 1, 0);
+
+ zend_call_method_with_1_params(&provider, Z_OBJCE_P(provider), NULL, "register", &retval, getThis());
+
+ if (retval) {
+ zval_ptr_dtor(&retval);
+ }
+
+ if (!array) {
+ return;
+ }
+
+ zend_hash_internal_pointer_reset_ex(array, &pos);
+
+ while(zend_hash_get_current_data_ex(array, (void **)&data, &pos) == SUCCESS) {
+ zend_hash_get_current_key_zval_ex(array, &key, &pos);
+ pimple_object_write_dimension(getThis(), &key, *data TSRMLS_CC);
+ zend_hash_move_forward_ex(array, &pos);
+ }
+}
+
+PHP_METHOD(Pimple, __construct)
+{
+ zval *values = NULL, **pData = NULL, offset;
+ HashPosition pos;
+ char *str_index = NULL;
+ zend_uint str_length;
+ ulong num_index;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a!", &values) == FAILURE) {
+ return;
+ }
+
+ PIMPLE_DEPRECATE
+
+ if (!values) {
+ return;
+ }
+
+ zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(values), &pos);
+ while (zend_hash_has_more_elements_ex(Z_ARRVAL_P(values), &pos) == SUCCESS) {
+ zend_hash_get_current_data_ex(Z_ARRVAL_P(values), (void **)&pData, &pos);
+ zend_hash_get_current_key_ex(Z_ARRVAL_P(values), &str_index, &str_length, &num_index, 0, &pos);
+ INIT_ZVAL(offset);
+ if (zend_hash_get_current_key_type_ex(Z_ARRVAL_P(values), &pos) == HASH_KEY_IS_LONG) {
+ ZVAL_LONG(&offset, num_index);
+ } else {
+ ZVAL_STRINGL(&offset, str_index, (str_length - 1), 0);
+ }
+ pimple_object_write_dimension(getThis(), &offset, *pData TSRMLS_CC);
+ zend_hash_move_forward_ex(Z_ARRVAL_P(values), &pos);
+ }
+}
+
+/*
+ * This is PHP code snippet handling extend()s calls :
+
+ $extended = function ($c) use ($callable, $factory) {
+ return $callable($factory($c), $c);
+ };
+
+ */
+PHP_METHOD(PimpleClosure, invoker)
+{
+ pimple_closure_object *pcobj = NULL;
+ zval *arg = NULL, *retval = NULL, *newretval = NULL;
+ zend_fcall_info fci = {0};
+ zval **args[2];
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &arg) == FAILURE) {
+ return;
+ }
+
+ pcobj = zend_object_store_get_object(getThis() TSRMLS_CC);
+
+ fci.function_name = pcobj->factory;
+ args[0] = &arg;
+ zend_fcall_info_argp(&fci TSRMLS_CC, 1, args);
+ fci.retval_ptr_ptr = &retval;
+ fci.size = sizeof(fci);
+
+ if (zend_call_function(&fci, NULL TSRMLS_CC) == FAILURE || EG(exception)) {
+ efree(fci.params);
+ return; /* Should here return default zval */
+ }
+
+ efree(fci.params);
+ memset(&fci, 0, sizeof(fci));
+ fci.size = sizeof(fci);
+
+ fci.function_name = pcobj->callable;
+ args[0] = &retval;
+ args[1] = &arg;
+ zend_fcall_info_argp(&fci TSRMLS_CC, 2, args);
+ fci.retval_ptr_ptr = &newretval;
+
+ if (zend_call_function(&fci, NULL TSRMLS_CC) == FAILURE || EG(exception)) {
+ efree(fci.params);
+ zval_ptr_dtor(&retval);
+ return;
+ }
+
+ efree(fci.params);
+ zval_ptr_dtor(&retval);
+
+ RETVAL_ZVAL(newretval, 1 ,1);
+}
+
+PHP_MINIT_FUNCTION(pimple)
+{
+ zend_class_entry tmp_ce_PsrContainerInterface, tmp_ce_PsrContainerExceptionInterface, tmp_ce_PsrNotFoundExceptionInterface;
+ zend_class_entry tmp_ce_ExpectedInvokableException, tmp_ce_FrozenServiceException, tmp_ce_InvalidServiceIdentifierException, tmp_ce_UnknownIdentifierException;
+ zend_class_entry tmp_pimple_ce, tmp_pimple_closure_ce, tmp_pimple_serviceprovider_iface_ce;
+
+ /* Psr\Container namespace */
+ INIT_NS_CLASS_ENTRY(tmp_ce_PsrContainerInterface, PSR_CONTAINER_NS, "ContainerInterface", pimple_ce_PsrContainerInterface_functions);
+ INIT_NS_CLASS_ENTRY(tmp_ce_PsrContainerExceptionInterface, PSR_CONTAINER_NS, "ContainerExceptionInterface", pimple_ce_PsrContainerExceptionInterface_functions);
+ INIT_NS_CLASS_ENTRY(tmp_ce_PsrNotFoundExceptionInterface, PSR_CONTAINER_NS, "NotFoundExceptionInterface", pimple_ce_PsrNotFoundExceptionInterface_functions);
+
+ pimple_ce_PsrContainerInterface = zend_register_internal_interface(&tmp_ce_PsrContainerInterface TSRMLS_CC);
+ pimple_ce_PsrContainerExceptionInterface = zend_register_internal_interface(&tmp_ce_PsrContainerExceptionInterface TSRMLS_CC);
+ pimple_ce_PsrNotFoundExceptionInterface = zend_register_internal_interface(&tmp_ce_PsrNotFoundExceptionInterface TSRMLS_CC);
+
+ zend_class_implements(pimple_ce_PsrNotFoundExceptionInterface TSRMLS_CC, 1, pimple_ce_PsrContainerExceptionInterface);
+
+ /* Pimple\Exception namespace */
+ INIT_NS_CLASS_ENTRY(tmp_ce_ExpectedInvokableException, PIMPLE_EXCEPTION_NS, "ExpectedInvokableException", NULL);
+ INIT_NS_CLASS_ENTRY(tmp_ce_FrozenServiceException, PIMPLE_EXCEPTION_NS, "FrozenServiceException", pimple_ce_FrozenServiceException_functions);
+ INIT_NS_CLASS_ENTRY(tmp_ce_InvalidServiceIdentifierException, PIMPLE_EXCEPTION_NS, "InvalidServiceIdentifierException", pimple_ce_InvalidServiceIdentifierException_functions);
+ INIT_NS_CLASS_ENTRY(tmp_ce_UnknownIdentifierException, PIMPLE_EXCEPTION_NS, "UnknownIdentifierException", pimple_ce_UnknownIdentifierException_functions);
+
+ pimple_ce_ExpectedInvokableException = zend_register_internal_class_ex(&tmp_ce_ExpectedInvokableException, spl_ce_InvalidArgumentException, NULL TSRMLS_CC);
+ pimple_ce_FrozenServiceException = zend_register_internal_class_ex(&tmp_ce_FrozenServiceException, spl_ce_RuntimeException, NULL TSRMLS_CC);
+ pimple_ce_InvalidServiceIdentifierException = zend_register_internal_class_ex(&tmp_ce_InvalidServiceIdentifierException, spl_ce_InvalidArgumentException, NULL TSRMLS_CC);
+ pimple_ce_UnknownIdentifierException = zend_register_internal_class_ex(&tmp_ce_UnknownIdentifierException, spl_ce_InvalidArgumentException, NULL TSRMLS_CC);
+
+ zend_class_implements(pimple_ce_ExpectedInvokableException TSRMLS_CC, 1, pimple_ce_PsrContainerExceptionInterface);
+ zend_class_implements(pimple_ce_FrozenServiceException TSRMLS_CC, 1, pimple_ce_PsrContainerExceptionInterface);
+ zend_class_implements(pimple_ce_InvalidServiceIdentifierException TSRMLS_CC, 1, pimple_ce_PsrContainerExceptionInterface);
+ zend_class_implements(pimple_ce_UnknownIdentifierException TSRMLS_CC, 1, pimple_ce_PsrNotFoundExceptionInterface);
+
+ /* Pimple namespace */
+ INIT_NS_CLASS_ENTRY(tmp_pimple_ce, PIMPLE_NS, "Container", pimple_ce_functions);
+ INIT_NS_CLASS_ENTRY(tmp_pimple_closure_ce, PIMPLE_NS, "ContainerClosure", NULL);
+ INIT_NS_CLASS_ENTRY(tmp_pimple_serviceprovider_iface_ce, PIMPLE_NS, "ServiceProviderInterface", pimple_serviceprovider_iface_ce_functions);
+
+ tmp_pimple_ce.create_object = pimple_object_create;
+ tmp_pimple_closure_ce.create_object = pimple_closure_object_create;
+
+ pimple_ce = zend_register_internal_class(&tmp_pimple_ce TSRMLS_CC);
+ zend_class_implements(pimple_ce TSRMLS_CC, 1, zend_ce_arrayaccess);
+
+ pimple_closure_ce = zend_register_internal_class(&tmp_pimple_closure_ce TSRMLS_CC);
+ pimple_closure_ce->ce_flags |= ZEND_ACC_FINAL_CLASS;
+
+ pimple_serviceprovider_ce = zend_register_internal_interface(&tmp_pimple_serviceprovider_iface_ce TSRMLS_CC);
+
+ memcpy(&pimple_closure_object_handlers, zend_get_std_object_handlers(), sizeof(*zend_get_std_object_handlers()));
+ pimple_object_handlers = std_object_handlers;
+ pimple_closure_object_handlers.get_closure = pimple_closure_get_closure;
+
+ pimple_closure_invoker_function.function_name = "Pimple closure internal invoker";
+ pimple_closure_invoker_function.fn_flags |= ZEND_ACC_CLOSURE;
+ pimple_closure_invoker_function.handler = ZEND_MN(PimpleClosure_invoker);
+ pimple_closure_invoker_function.num_args = 1;
+ pimple_closure_invoker_function.required_num_args = 1;
+ pimple_closure_invoker_function.scope = pimple_closure_ce;
+ pimple_closure_invoker_function.type = ZEND_INTERNAL_FUNCTION;
+ pimple_closure_invoker_function.module = &pimple_module_entry;
+
+ return SUCCESS;
+}
+
+PHP_MINFO_FUNCTION(pimple)
+{
+ php_info_print_table_start();
+ php_info_print_table_header(2, "SensioLabs Pimple C support", "enabled");
+ php_info_print_table_row(2, "Pimple supported version", PIMPLE_VERSION);
+ php_info_print_table_end();
+
+ php_info_print_box_start(0);
+ php_write((void *)ZEND_STRL("SensioLabs Pimple C support developed by Julien Pauli") TSRMLS_CC);
+ if (!sapi_module.phpinfo_as_text) {
+ php_write((void *)ZEND_STRL(sensiolabs_logo) TSRMLS_CC);
+ }
+ php_info_print_box_end();
+}
+
+zend_module_entry pimple_module_entry = {
+ STANDARD_MODULE_HEADER,
+ "pimple",
+ NULL,
+ PHP_MINIT(pimple),
+ NULL,
+ NULL,
+ NULL,
+ PHP_MINFO(pimple),
+ PIMPLE_VERSION,
+ STANDARD_MODULE_PROPERTIES
+};
+
+#ifdef COMPILE_DL_PIMPLE
+ZEND_GET_MODULE(pimple)
+#endif
diff --git a/vendor/pimple/pimple/ext/pimple/pimple_compat.h b/vendor/pimple/pimple/ext/pimple/pimple_compat.h
new file mode 100644
index 00000000..d234e174
--- /dev/null
+++ b/vendor/pimple/pimple/ext/pimple/pimple_compat.h
@@ -0,0 +1,81 @@
+
+/*
+ * This file is part of Pimple.
+ *
+ * Copyright (c) 2014 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.
+ */
+
+#ifndef PIMPLE_COMPAT_H_
+#define PIMPLE_COMPAT_H_
+
+#include "Zend/zend_extensions.h" /* for ZEND_EXTENSION_API_NO */
+
+#define PHP_5_0_X_API_NO 220040412
+#define PHP_5_1_X_API_NO 220051025
+#define PHP_5_2_X_API_NO 220060519
+#define PHP_5_3_X_API_NO 220090626
+#define PHP_5_4_X_API_NO 220100525
+#define PHP_5_5_X_API_NO 220121212
+#define PHP_5_6_X_API_NO 220131226
+
+#define IS_PHP_56 ZEND_EXTENSION_API_NO == PHP_5_6_X_API_NO
+#define IS_AT_LEAST_PHP_56 ZEND_EXTENSION_API_NO >= PHP_5_6_X_API_NO
+
+#define IS_PHP_55 ZEND_EXTENSION_API_NO == PHP_5_5_X_API_NO
+#define IS_AT_LEAST_PHP_55 ZEND_EXTENSION_API_NO >= PHP_5_5_X_API_NO
+
+#define IS_PHP_54 ZEND_EXTENSION_API_NO == PHP_5_4_X_API_NO
+#define IS_AT_LEAST_PHP_54 ZEND_EXTENSION_API_NO >= PHP_5_4_X_API_NO
+
+#define IS_PHP_53 ZEND_EXTENSION_API_NO == PHP_5_3_X_API_NO
+#define IS_AT_LEAST_PHP_53 ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
+
+#if IS_PHP_53
+#define object_properties_init(obj, ce) do { \
+ zend_hash_copy(obj->properties, &ce->default_properties, zval_copy_property_ctor(ce), NULL, sizeof(zval *)); \
+ } while (0);
+#endif
+
+#define ZEND_OBJ_INIT(obj, ce) do { \
+ zend_object_std_init(obj, ce TSRMLS_CC); \
+ object_properties_init((obj), (ce)); \
+ } while(0);
+
+#if IS_PHP_53 || IS_PHP_54
+static void zend_hash_get_current_key_zval_ex(const HashTable *ht, zval *key, HashPosition *pos) {
+ Bucket *p;
+
+ p = pos ? (*pos) : ht->pInternalPointer;
+
+ if (!p) {
+ Z_TYPE_P(key) = IS_NULL;
+ } else if (p->nKeyLength) {
+ Z_TYPE_P(key) = IS_STRING;
+ Z_STRVAL_P(key) = estrndup(p->arKey, p->nKeyLength - 1);
+ Z_STRLEN_P(key) = p->nKeyLength - 1;
+ } else {
+ Z_TYPE_P(key) = IS_LONG;
+ Z_LVAL_P(key) = p->h;
+ }
+}
+#endif
+
+#endif /* PIMPLE_COMPAT_H_ */
diff --git a/vendor/pimple/pimple/ext/pimple/tests/001.phpt b/vendor/pimple/pimple/ext/pimple/tests/001.phpt
new file mode 100644
index 00000000..0809ea23
--- /dev/null
+++ b/vendor/pimple/pimple/ext/pimple/tests/001.phpt
@@ -0,0 +1,45 @@
+--TEST--
+Test for read_dim/write_dim handlers
+--SKIPIF--
+
+--FILE--
+
+
+--EXPECTF--
+foo
+42
+foo2
+foo99
+baz
+strstr
\ No newline at end of file
diff --git a/vendor/pimple/pimple/ext/pimple/tests/002.phpt b/vendor/pimple/pimple/ext/pimple/tests/002.phpt
new file mode 100644
index 00000000..7b56d2c1
--- /dev/null
+++ b/vendor/pimple/pimple/ext/pimple/tests/002.phpt
@@ -0,0 +1,15 @@
+--TEST--
+Test for constructor
+--SKIPIF--
+
+--FILE--
+'foo'));
+var_dump($p[42]);
+?>
+--EXPECT--
+NULL
+string(3) "foo"
diff --git a/vendor/pimple/pimple/ext/pimple/tests/003.phpt b/vendor/pimple/pimple/ext/pimple/tests/003.phpt
new file mode 100644
index 00000000..a22cfa35
--- /dev/null
+++ b/vendor/pimple/pimple/ext/pimple/tests/003.phpt
@@ -0,0 +1,16 @@
+--TEST--
+Test empty dimensions
+--SKIPIF--
+
+--FILE--
+
+--EXPECT--
+int(42)
+string(3) "bar"
\ No newline at end of file
diff --git a/vendor/pimple/pimple/ext/pimple/tests/004.phpt b/vendor/pimple/pimple/ext/pimple/tests/004.phpt
new file mode 100644
index 00000000..1e1d2513
--- /dev/null
+++ b/vendor/pimple/pimple/ext/pimple/tests/004.phpt
@@ -0,0 +1,30 @@
+--TEST--
+Test has/unset dim handlers
+--SKIPIF--
+
+--FILE--
+
+--EXPECT--
+int(42)
+NULL
+bool(true)
+bool(false)
+bool(true)
+bool(true)
\ No newline at end of file
diff --git a/vendor/pimple/pimple/ext/pimple/tests/005.phpt b/vendor/pimple/pimple/ext/pimple/tests/005.phpt
new file mode 100644
index 00000000..0479ee05
--- /dev/null
+++ b/vendor/pimple/pimple/ext/pimple/tests/005.phpt
@@ -0,0 +1,27 @@
+--TEST--
+Test simple class inheritance
+--SKIPIF--
+
+--FILE--
+someAttr;
+?>
+--EXPECT--
+string(3) "hit"
+foo
+fooAttr
\ No newline at end of file
diff --git a/vendor/pimple/pimple/ext/pimple/tests/006.phpt b/vendor/pimple/pimple/ext/pimple/tests/006.phpt
new file mode 100644
index 00000000..cfe8a119
--- /dev/null
+++ b/vendor/pimple/pimple/ext/pimple/tests/006.phpt
@@ -0,0 +1,51 @@
+--TEST--
+Test complex class inheritance
+--SKIPIF--
+
+--FILE--
+ 'bar', 88 => 'baz');
+
+$p = new TestPimple($defaultValues);
+$p[42] = 'foo';
+var_dump($p[42]);
+var_dump($p[0]);
+?>
+--EXPECT--
+string(13) "hit offsetset"
+string(27) "hit offsetget in TestPimple"
+string(25) "hit offsetget in MyPimple"
+string(3) "foo"
+string(27) "hit offsetget in TestPimple"
+string(25) "hit offsetget in MyPimple"
+string(3) "baz"
\ No newline at end of file
diff --git a/vendor/pimple/pimple/ext/pimple/tests/007.phpt b/vendor/pimple/pimple/ext/pimple/tests/007.phpt
new file mode 100644
index 00000000..5aac6838
--- /dev/null
+++ b/vendor/pimple/pimple/ext/pimple/tests/007.phpt
@@ -0,0 +1,22 @@
+--TEST--
+Test for read_dim/write_dim handlers
+--SKIPIF--
+
+--FILE--
+
+--EXPECTF--
+foo
+42
\ No newline at end of file
diff --git a/vendor/pimple/pimple/ext/pimple/tests/008.phpt b/vendor/pimple/pimple/ext/pimple/tests/008.phpt
new file mode 100644
index 00000000..db7eeec4
--- /dev/null
+++ b/vendor/pimple/pimple/ext/pimple/tests/008.phpt
@@ -0,0 +1,29 @@
+--TEST--
+Test frozen services
+--SKIPIF--
+
+--FILE--
+
+--EXPECTF--
diff --git a/vendor/pimple/pimple/ext/pimple/tests/009.phpt b/vendor/pimple/pimple/ext/pimple/tests/009.phpt
new file mode 100644
index 00000000..bb05ea29
--- /dev/null
+++ b/vendor/pimple/pimple/ext/pimple/tests/009.phpt
@@ -0,0 +1,13 @@
+--TEST--
+Test service is called as callback, and only once
+--SKIPIF--
+
+--FILE--
+
+--EXPECTF--
+bool(true)
\ No newline at end of file
diff --git a/vendor/pimple/pimple/ext/pimple/tests/010.phpt b/vendor/pimple/pimple/ext/pimple/tests/010.phpt
new file mode 100644
index 00000000..badce014
--- /dev/null
+++ b/vendor/pimple/pimple/ext/pimple/tests/010.phpt
@@ -0,0 +1,45 @@
+--TEST--
+Test service is called as callback for every callback type
+--SKIPIF--
+
+--FILE--
+
+--EXPECTF--
+callme
+called
+Foo::bar
+array(2) {
+ [0]=>
+ string(3) "Foo"
+ [1]=>
+ string(3) "bar"
+}
\ No newline at end of file
diff --git a/vendor/pimple/pimple/ext/pimple/tests/011.phpt b/vendor/pimple/pimple/ext/pimple/tests/011.phpt
new file mode 100644
index 00000000..6682ab8e
--- /dev/null
+++ b/vendor/pimple/pimple/ext/pimple/tests/011.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Test service callback throwing an exception
+--SKIPIF--
+
+--FILE--
+
+--EXPECTF--
+all right!
\ No newline at end of file
diff --git a/vendor/pimple/pimple/ext/pimple/tests/012.phpt b/vendor/pimple/pimple/ext/pimple/tests/012.phpt
new file mode 100644
index 00000000..4c6ac486
--- /dev/null
+++ b/vendor/pimple/pimple/ext/pimple/tests/012.phpt
@@ -0,0 +1,28 @@
+--TEST--
+Test service factory
+--SKIPIF--
+
+--FILE--
+factory($f = function() { var_dump('called-1'); return 'ret-1';});
+
+$p[] = $f;
+
+$p[] = function () { var_dump('called-2'); return 'ret-2'; };
+
+var_dump($p[0]);
+var_dump($p[0]);
+var_dump($p[1]);
+var_dump($p[1]);
+?>
+--EXPECTF--
+string(8) "called-1"
+string(5) "ret-1"
+string(8) "called-1"
+string(5) "ret-1"
+string(8) "called-2"
+string(5) "ret-2"
+string(5) "ret-2"
\ No newline at end of file
diff --git a/vendor/pimple/pimple/ext/pimple/tests/013.phpt b/vendor/pimple/pimple/ext/pimple/tests/013.phpt
new file mode 100644
index 00000000..f419958c
--- /dev/null
+++ b/vendor/pimple/pimple/ext/pimple/tests/013.phpt
@@ -0,0 +1,33 @@
+--TEST--
+Test keys()
+--SKIPIF--
+
+--FILE--
+keys());
+
+$p['foo'] = 'bar';
+$p[] = 'foo';
+
+var_dump($p->keys());
+
+unset($p['foo']);
+
+var_dump($p->keys());
+?>
+--EXPECTF--
+array(0) {
+}
+array(2) {
+ [0]=>
+ string(3) "foo"
+ [1]=>
+ int(0)
+}
+array(1) {
+ [0]=>
+ int(0)
+}
\ No newline at end of file
diff --git a/vendor/pimple/pimple/ext/pimple/tests/014.phpt b/vendor/pimple/pimple/ext/pimple/tests/014.phpt
new file mode 100644
index 00000000..ac937213
--- /dev/null
+++ b/vendor/pimple/pimple/ext/pimple/tests/014.phpt
@@ -0,0 +1,30 @@
+--TEST--
+Test raw()
+--SKIPIF--
+
+--FILE--
+raw('foo'));
+var_dump($p[42]);
+
+unset($p['foo']);
+
+try {
+ $p->raw('foo');
+ echo "expected exception";
+} catch (InvalidArgumentException $e) { }
+--EXPECTF--
+string(8) "called-2"
+string(5) "ret-2"
+object(Closure)#%i (0) {
+}
+string(8) "called-2"
+string(5) "ret-2"
\ No newline at end of file
diff --git a/vendor/pimple/pimple/ext/pimple/tests/015.phpt b/vendor/pimple/pimple/ext/pimple/tests/015.phpt
new file mode 100644
index 00000000..314f008a
--- /dev/null
+++ b/vendor/pimple/pimple/ext/pimple/tests/015.phpt
@@ -0,0 +1,17 @@
+--TEST--
+Test protect()
+--SKIPIF--
+
+--FILE--
+protect($f);
+
+var_dump($p['foo']);
+--EXPECTF--
+object(Closure)#%i (0) {
+}
\ No newline at end of file
diff --git a/vendor/pimple/pimple/ext/pimple/tests/016.phpt b/vendor/pimple/pimple/ext/pimple/tests/016.phpt
new file mode 100644
index 00000000..e55edb0a
--- /dev/null
+++ b/vendor/pimple/pimple/ext/pimple/tests/016.phpt
@@ -0,0 +1,24 @@
+--TEST--
+Test extend()
+--SKIPIF--
+
+--FILE--
+extend(12, function ($w) { var_dump($w); return 'bar'; }); /* $callable in code above */
+
+var_dump($c('param'));
+--EXPECTF--
+string(5) "param"
+string(3) "foo"
+string(3) "bar"
\ No newline at end of file
diff --git a/vendor/pimple/pimple/ext/pimple/tests/017.phpt b/vendor/pimple/pimple/ext/pimple/tests/017.phpt
new file mode 100644
index 00000000..bac23ce0
--- /dev/null
+++ b/vendor/pimple/pimple/ext/pimple/tests/017.phpt
@@ -0,0 +1,17 @@
+--TEST--
+Test extend() with exception in service extension
+--SKIPIF--
+
+--FILE--
+extend(12, function ($w) { throw new BadMethodCallException; });
+
+try {
+ $p[12];
+ echo "Exception expected";
+} catch (BadMethodCallException $e) { }
+--EXPECTF--
diff --git a/vendor/pimple/pimple/ext/pimple/tests/017_1.phpt b/vendor/pimple/pimple/ext/pimple/tests/017_1.phpt
new file mode 100644
index 00000000..8f881d6e
--- /dev/null
+++ b/vendor/pimple/pimple/ext/pimple/tests/017_1.phpt
@@ -0,0 +1,17 @@
+--TEST--
+Test extend() with exception in service factory
+--SKIPIF--
+
+--FILE--
+extend(12, function ($w) { return 'foobar'; });
+
+try {
+ $p[12];
+ echo "Exception expected";
+} catch (BadMethodCallException $e) { }
+--EXPECTF--
diff --git a/vendor/pimple/pimple/ext/pimple/tests/018.phpt b/vendor/pimple/pimple/ext/pimple/tests/018.phpt
new file mode 100644
index 00000000..27c12a14
--- /dev/null
+++ b/vendor/pimple/pimple/ext/pimple/tests/018.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Test register()
+--SKIPIF--
+
+--FILE--
+register(new Foo, array(42 => 'bar'));
+
+var_dump($p[42]);
+--EXPECTF--
+object(Pimple\Container)#1 (0) {
+}
+string(3) "bar"
\ No newline at end of file
diff --git a/vendor/pimple/pimple/ext/pimple/tests/019.phpt b/vendor/pimple/pimple/ext/pimple/tests/019.phpt
new file mode 100644
index 00000000..28a9aeca
--- /dev/null
+++ b/vendor/pimple/pimple/ext/pimple/tests/019.phpt
@@ -0,0 +1,18 @@
+--TEST--
+Test register() returns static and is a fluent interface
+--SKIPIF--
+
+--FILE--
+register(new Foo));
+--EXPECTF--
+bool(true)
diff --git a/vendor/pimple/pimple/ext/pimple/tests/bench.phpb b/vendor/pimple/pimple/ext/pimple/tests/bench.phpb
new file mode 100644
index 00000000..8f983e65
--- /dev/null
+++ b/vendor/pimple/pimple/ext/pimple/tests/bench.phpb
@@ -0,0 +1,51 @@
+factory($factory);
+
+$p['factory'] = $factory;
+
+echo $p['factory'];
+echo $p['factory'];
+echo $p['factory'];
+
+}
+
+echo microtime(true) - $time;
diff --git a/vendor/pimple/pimple/ext/pimple/tests/bench_shared.phpb b/vendor/pimple/pimple/ext/pimple/tests/bench_shared.phpb
new file mode 100644
index 00000000..aec541f0
--- /dev/null
+++ b/vendor/pimple/pimple/ext/pimple/tests/bench_shared.phpb
@@ -0,0 +1,25 @@
+
diff --git a/vendor/pimple/pimple/phpunit.xml.dist b/vendor/pimple/pimple/phpunit.xml.dist
new file mode 100644
index 00000000..5c8d487f
--- /dev/null
+++ b/vendor/pimple/pimple/phpunit.xml.dist
@@ -0,0 +1,14 @@
+
+
+
+
+
+ ./src/Pimple/Tests
+
+
+
diff --git a/vendor/pimple/pimple/src/Pimple/Container.php b/vendor/pimple/pimple/src/Pimple/Container.php
new file mode 100644
index 00000000..e761964b
--- /dev/null
+++ b/vendor/pimple/pimple/src/Pimple/Container.php
@@ -0,0 +1,298 @@
+factories = new \SplObjectStorage();
+ $this->protected = new \SplObjectStorage();
+
+ foreach ($values as $key => $value) {
+ $this->offsetSet($key, $value);
+ }
+ }
+
+ /**
+ * Sets a parameter or an object.
+ *
+ * Objects must be defined as Closures.
+ *
+ * Allowing any PHP callable leads to difficult to debug problems
+ * as function names (strings) are callable (creating a function with
+ * the same name as an existing parameter would break your container).
+ *
+ * @param string $id The unique identifier for the parameter or object
+ * @param mixed $value The value of the parameter or a closure to define an object
+ *
+ * @throws FrozenServiceException Prevent override of a frozen service
+ */
+ public function offsetSet($id, $value)
+ {
+ if (isset($this->frozen[$id])) {
+ throw new FrozenServiceException($id);
+ }
+
+ $this->values[$id] = $value;
+ $this->keys[$id] = true;
+ }
+
+ /**
+ * Gets a parameter or an object.
+ *
+ * @param string $id The unique identifier for the parameter or object
+ *
+ * @return mixed The value of the parameter or an object
+ *
+ * @throws UnknownIdentifierException If the identifier is not defined
+ */
+ public function offsetGet($id)
+ {
+ if (!isset($this->keys[$id])) {
+ throw new UnknownIdentifierException($id);
+ }
+
+ if (
+ isset($this->raw[$id])
+ || !is_object($this->values[$id])
+ || isset($this->protected[$this->values[$id]])
+ || !method_exists($this->values[$id], '__invoke')
+ ) {
+ return $this->values[$id];
+ }
+
+ if (isset($this->factories[$this->values[$id]])) {
+ return $this->values[$id]($this);
+ }
+
+ $raw = $this->values[$id];
+ $val = $this->values[$id] = $raw($this);
+ $this->raw[$id] = $raw;
+
+ $this->frozen[$id] = true;
+
+ return $val;
+ }
+
+ /**
+ * Checks if a parameter or an object is set.
+ *
+ * @param string $id The unique identifier for the parameter or object
+ *
+ * @return bool
+ */
+ public function offsetExists($id)
+ {
+ return isset($this->keys[$id]);
+ }
+
+ /**
+ * Unsets a parameter or an object.
+ *
+ * @param string $id The unique identifier for the parameter or object
+ */
+ public function offsetUnset($id)
+ {
+ if (isset($this->keys[$id])) {
+ if (is_object($this->values[$id])) {
+ unset($this->factories[$this->values[$id]], $this->protected[$this->values[$id]]);
+ }
+
+ unset($this->values[$id], $this->frozen[$id], $this->raw[$id], $this->keys[$id]);
+ }
+ }
+
+ /**
+ * Marks a callable as being a factory service.
+ *
+ * @param callable $callable A service definition to be used as a factory
+ *
+ * @return callable The passed callable
+ *
+ * @throws ExpectedInvokableException Service definition has to be a closure or an invokable object
+ */
+ public function factory($callable)
+ {
+ if (!method_exists($callable, '__invoke')) {
+ throw new ExpectedInvokableException('Service definition is not a Closure or invokable object.');
+ }
+
+ $this->factories->attach($callable);
+
+ return $callable;
+ }
+
+ /**
+ * Protects a callable from being interpreted as a service.
+ *
+ * This is useful when you want to store a callable as a parameter.
+ *
+ * @param callable $callable A callable to protect from being evaluated
+ *
+ * @return callable The passed callable
+ *
+ * @throws ExpectedInvokableException Service definition has to be a closure or an invokable object
+ */
+ public function protect($callable)
+ {
+ if (!method_exists($callable, '__invoke')) {
+ throw new ExpectedInvokableException('Callable is not a Closure or invokable object.');
+ }
+
+ $this->protected->attach($callable);
+
+ return $callable;
+ }
+
+ /**
+ * Gets a parameter or the closure defining an object.
+ *
+ * @param string $id The unique identifier for the parameter or object
+ *
+ * @return mixed The value of the parameter or the closure defining an object
+ *
+ * @throws UnknownIdentifierException If the identifier is not defined
+ */
+ public function raw($id)
+ {
+ if (!isset($this->keys[$id])) {
+ throw new UnknownIdentifierException($id);
+ }
+
+ if (isset($this->raw[$id])) {
+ return $this->raw[$id];
+ }
+
+ return $this->values[$id];
+ }
+
+ /**
+ * Extends an object definition.
+ *
+ * Useful when you want to extend an existing object definition,
+ * without necessarily loading that object.
+ *
+ * @param string $id The unique identifier for the object
+ * @param callable $callable A service definition to extend the original
+ *
+ * @return callable The wrapped callable
+ *
+ * @throws UnknownIdentifierException If the identifier is not defined
+ * @throws FrozenServiceException If the service is frozen
+ * @throws InvalidServiceIdentifierException If the identifier belongs to a parameter
+ * @throws ExpectedInvokableException If the extension callable is not a closure or an invokable object
+ */
+ public function extend($id, $callable)
+ {
+ if (!isset($this->keys[$id])) {
+ throw new UnknownIdentifierException($id);
+ }
+
+ if (isset($this->frozen[$id])) {
+ throw new FrozenServiceException($id);
+ }
+
+ if (!is_object($this->values[$id]) || !method_exists($this->values[$id], '__invoke')) {
+ throw new InvalidServiceIdentifierException($id);
+ }
+
+ if (isset($this->protected[$this->values[$id]])) {
+ @trigger_error(sprintf('How Pimple behaves when extending protected closures will be fixed in Pimple 4. Are you sure "%s" should be protected?', $id), E_USER_DEPRECATED);
+ }
+
+ if (!is_object($callable) || !method_exists($callable, '__invoke')) {
+ throw new ExpectedInvokableException('Extension service definition is not a Closure or invokable object.');
+ }
+
+ $factory = $this->values[$id];
+
+ $extended = function ($c) use ($callable, $factory) {
+ return $callable($factory($c), $c);
+ };
+
+ if (isset($this->factories[$factory])) {
+ $this->factories->detach($factory);
+ $this->factories->attach($extended);
+ }
+
+ return $this[$id] = $extended;
+ }
+
+ /**
+ * Returns all defined value names.
+ *
+ * @return array An array of value names
+ */
+ public function keys()
+ {
+ return array_keys($this->values);
+ }
+
+ /**
+ * Registers a service provider.
+ *
+ * @param ServiceProviderInterface $provider A ServiceProviderInterface instance
+ * @param array $values An array of values that customizes the provider
+ *
+ * @return static
+ */
+ public function register(ServiceProviderInterface $provider, array $values = array())
+ {
+ $provider->register($this);
+
+ foreach ($values as $key => $value) {
+ $this[$key] = $value;
+ }
+
+ return $this;
+ }
+}
diff --git a/vendor/pimple/pimple/src/Pimple/Exception/ExpectedInvokableException.php b/vendor/pimple/pimple/src/Pimple/Exception/ExpectedInvokableException.php
new file mode 100644
index 00000000..7228421b
--- /dev/null
+++ b/vendor/pimple/pimple/src/Pimple/Exception/ExpectedInvokableException.php
@@ -0,0 +1,38 @@
+
+ */
+class ExpectedInvokableException extends \InvalidArgumentException implements ContainerExceptionInterface
+{
+}
diff --git a/vendor/pimple/pimple/src/Pimple/Exception/FrozenServiceException.php b/vendor/pimple/pimple/src/Pimple/Exception/FrozenServiceException.php
new file mode 100644
index 00000000..64b02659
--- /dev/null
+++ b/vendor/pimple/pimple/src/Pimple/Exception/FrozenServiceException.php
@@ -0,0 +1,45 @@
+
+ */
+class FrozenServiceException extends \RuntimeException implements ContainerExceptionInterface
+{
+ /**
+ * @param string $id Identifier of the frozen service
+ */
+ public function __construct($id)
+ {
+ parent::__construct(sprintf('Cannot override frozen service "%s".', $id));
+ }
+}
diff --git a/vendor/pimple/pimple/src/Pimple/Exception/InvalidServiceIdentifierException.php b/vendor/pimple/pimple/src/Pimple/Exception/InvalidServiceIdentifierException.php
new file mode 100644
index 00000000..9df9c663
--- /dev/null
+++ b/vendor/pimple/pimple/src/Pimple/Exception/InvalidServiceIdentifierException.php
@@ -0,0 +1,45 @@
+
+ */
+class InvalidServiceIdentifierException extends \InvalidArgumentException implements NotFoundExceptionInterface
+{
+ /**
+ * @param string $id The invalid identifier
+ */
+ public function __construct($id)
+ {
+ parent::__construct(sprintf('Identifier "%s" does not contain an object definition.', $id));
+ }
+}
diff --git a/vendor/pimple/pimple/src/Pimple/Exception/UnknownIdentifierException.php b/vendor/pimple/pimple/src/Pimple/Exception/UnknownIdentifierException.php
new file mode 100644
index 00000000..28413189
--- /dev/null
+++ b/vendor/pimple/pimple/src/Pimple/Exception/UnknownIdentifierException.php
@@ -0,0 +1,45 @@
+
+ */
+class UnknownIdentifierException extends \InvalidArgumentException implements NotFoundExceptionInterface
+{
+ /**
+ * @param string $id The unknown identifier
+ */
+ public function __construct($id)
+ {
+ parent::__construct(sprintf('Identifier "%s" is not defined.', $id));
+ }
+}
diff --git a/vendor/pimple/pimple/src/Pimple/Psr11/Container.php b/vendor/pimple/pimple/src/Pimple/Psr11/Container.php
new file mode 100644
index 00000000..cadbfffa
--- /dev/null
+++ b/vendor/pimple/pimple/src/Pimple/Psr11/Container.php
@@ -0,0 +1,55 @@
+
+ */
+final class Container implements ContainerInterface
+{
+ private $pimple;
+
+ public function __construct(PimpleContainer $pimple)
+ {
+ $this->pimple = $pimple;
+ }
+
+ public function get($id)
+ {
+ return $this->pimple[$id];
+ }
+
+ public function has($id)
+ {
+ return isset($this->pimple[$id]);
+ }
+}
diff --git a/vendor/pimple/pimple/src/Pimple/Psr11/ServiceLocator.php b/vendor/pimple/pimple/src/Pimple/Psr11/ServiceLocator.php
new file mode 100644
index 00000000..61e49848
--- /dev/null
+++ b/vendor/pimple/pimple/src/Pimple/Psr11/ServiceLocator.php
@@ -0,0 +1,75 @@
+
+ */
+class ServiceLocator implements ContainerInterface
+{
+ private $container;
+ private $aliases = array();
+
+ /**
+ * @param PimpleContainer $container The Container instance used to locate services
+ * @param array $ids Array of service ids that can be located. String keys can be used to define aliases
+ */
+ public function __construct(PimpleContainer $container, array $ids)
+ {
+ $this->container = $container;
+
+ foreach ($ids as $key => $id) {
+ $this->aliases[is_int($key) ? $id : $key] = $id;
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get($id)
+ {
+ if (!isset($this->aliases[$id])) {
+ throw new UnknownIdentifierException($id);
+ }
+
+ return $this->container[$this->aliases[$id]];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function has($id)
+ {
+ return isset($this->aliases[$id]) && isset($this->container[$this->aliases[$id]]);
+ }
+}
diff --git a/vendor/pimple/pimple/src/Pimple/ServiceIterator.php b/vendor/pimple/pimple/src/Pimple/ServiceIterator.php
new file mode 100644
index 00000000..744271dd
--- /dev/null
+++ b/vendor/pimple/pimple/src/Pimple/ServiceIterator.php
@@ -0,0 +1,69 @@
+
+ */
+final class ServiceIterator implements \Iterator
+{
+ private $container;
+ private $ids;
+
+ public function __construct(Container $container, array $ids)
+ {
+ $this->container = $container;
+ $this->ids = $ids;
+ }
+
+ public function rewind()
+ {
+ reset($this->ids);
+ }
+
+ public function current()
+ {
+ return $this->container[current($this->ids)];
+ }
+
+ public function key()
+ {
+ return current($this->ids);
+ }
+
+ public function next()
+ {
+ next($this->ids);
+ }
+
+ public function valid()
+ {
+ return null !== key($this->ids);
+ }
+}
diff --git a/vendor/pimple/pimple/src/Pimple/ServiceProviderInterface.php b/vendor/pimple/pimple/src/Pimple/ServiceProviderInterface.php
new file mode 100644
index 00000000..c004594b
--- /dev/null
+++ b/vendor/pimple/pimple/src/Pimple/ServiceProviderInterface.php
@@ -0,0 +1,46 @@
+value = $value;
+
+ return $service;
+ }
+}
diff --git a/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/NonInvokable.php b/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/NonInvokable.php
new file mode 100644
index 00000000..33cd4e54
--- /dev/null
+++ b/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/NonInvokable.php
@@ -0,0 +1,34 @@
+factory(function () {
+ return new Service();
+ });
+ }
+}
diff --git a/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/Service.php b/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/Service.php
new file mode 100644
index 00000000..d71b184d
--- /dev/null
+++ b/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/Service.php
@@ -0,0 +1,35 @@
+
+ */
+class Service
+{
+ public $value;
+}
diff --git a/vendor/pimple/pimple/src/Pimple/Tests/PimpleServiceProviderInterfaceTest.php b/vendor/pimple/pimple/src/Pimple/Tests/PimpleServiceProviderInterfaceTest.php
new file mode 100644
index 00000000..8e5c4c73
--- /dev/null
+++ b/vendor/pimple/pimple/src/Pimple/Tests/PimpleServiceProviderInterfaceTest.php
@@ -0,0 +1,76 @@
+
+ */
+class PimpleServiceProviderInterfaceTest extends \PHPUnit_Framework_TestCase
+{
+ public function testProvider()
+ {
+ $pimple = new Container();
+
+ $pimpleServiceProvider = new Fixtures\PimpleServiceProvider();
+ $pimpleServiceProvider->register($pimple);
+
+ $this->assertEquals('value', $pimple['param']);
+ $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $pimple['service']);
+
+ $serviceOne = $pimple['factory'];
+ $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceOne);
+
+ $serviceTwo = $pimple['factory'];
+ $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceTwo);
+
+ $this->assertNotSame($serviceOne, $serviceTwo);
+ }
+
+ public function testProviderWithRegisterMethod()
+ {
+ $pimple = new Container();
+
+ $pimple->register(new Fixtures\PimpleServiceProvider(), array(
+ 'anotherParameter' => 'anotherValue',
+ ));
+
+ $this->assertEquals('value', $pimple['param']);
+ $this->assertEquals('anotherValue', $pimple['anotherParameter']);
+
+ $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $pimple['service']);
+
+ $serviceOne = $pimple['factory'];
+ $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceOne);
+
+ $serviceTwo = $pimple['factory'];
+ $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceTwo);
+
+ $this->assertNotSame($serviceOne, $serviceTwo);
+ }
+}
diff --git a/vendor/pimple/pimple/src/Pimple/Tests/PimpleTest.php b/vendor/pimple/pimple/src/Pimple/Tests/PimpleTest.php
new file mode 100644
index 00000000..acb66e00
--- /dev/null
+++ b/vendor/pimple/pimple/src/Pimple/Tests/PimpleTest.php
@@ -0,0 +1,589 @@
+
+ */
+class PimpleTest extends \PHPUnit_Framework_TestCase
+{
+ public function testWithString()
+ {
+ $pimple = new Container();
+ $pimple['param'] = 'value';
+
+ $this->assertEquals('value', $pimple['param']);
+ }
+
+ public function testWithClosure()
+ {
+ $pimple = new Container();
+ $pimple['service'] = function () {
+ return new Fixtures\Service();
+ };
+
+ $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $pimple['service']);
+ }
+
+ public function testServicesShouldBeDifferent()
+ {
+ $pimple = new Container();
+ $pimple['service'] = $pimple->factory(function () {
+ return new Fixtures\Service();
+ });
+
+ $serviceOne = $pimple['service'];
+ $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceOne);
+
+ $serviceTwo = $pimple['service'];
+ $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceTwo);
+
+ $this->assertNotSame($serviceOne, $serviceTwo);
+ }
+
+ public function testShouldPassContainerAsParameter()
+ {
+ $pimple = new Container();
+ $pimple['service'] = function () {
+ return new Fixtures\Service();
+ };
+ $pimple['container'] = function ($container) {
+ return $container;
+ };
+
+ $this->assertNotSame($pimple, $pimple['service']);
+ $this->assertSame($pimple, $pimple['container']);
+ }
+
+ public function testIsset()
+ {
+ $pimple = new Container();
+ $pimple['param'] = 'value';
+ $pimple['service'] = function () {
+ return new Fixtures\Service();
+ };
+
+ $pimple['null'] = null;
+
+ $this->assertTrue(isset($pimple['param']));
+ $this->assertTrue(isset($pimple['service']));
+ $this->assertTrue(isset($pimple['null']));
+ $this->assertFalse(isset($pimple['non_existent']));
+ }
+
+ public function testConstructorInjection()
+ {
+ $params = array('param' => 'value');
+ $pimple = new Container($params);
+
+ $this->assertSame($params['param'], $pimple['param']);
+ }
+
+ /**
+ * @expectedException \Pimple\Exception\UnknownIdentifierException
+ * @expectedExceptionMessage Identifier "foo" is not defined.
+ */
+ public function testOffsetGetValidatesKeyIsPresent()
+ {
+ $pimple = new Container();
+ echo $pimple['foo'];
+ }
+
+ /**
+ * @group legacy
+ * @expectedException \InvalidArgumentException
+ * @expectedExceptionMessage Identifier "foo" is not defined.
+ */
+ public function testLegacyOffsetGetValidatesKeyIsPresent()
+ {
+ $pimple = new Container();
+ echo $pimple['foo'];
+ }
+
+ public function testOffsetGetHonorsNullValues()
+ {
+ $pimple = new Container();
+ $pimple['foo'] = null;
+ $this->assertNull($pimple['foo']);
+ }
+
+ public function testUnset()
+ {
+ $pimple = new Container();
+ $pimple['param'] = 'value';
+ $pimple['service'] = function () {
+ return new Fixtures\Service();
+ };
+
+ unset($pimple['param'], $pimple['service']);
+ $this->assertFalse(isset($pimple['param']));
+ $this->assertFalse(isset($pimple['service']));
+ }
+
+ /**
+ * @dataProvider serviceDefinitionProvider
+ */
+ public function testShare($service)
+ {
+ $pimple = new Container();
+ $pimple['shared_service'] = $service;
+
+ $serviceOne = $pimple['shared_service'];
+ $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceOne);
+
+ $serviceTwo = $pimple['shared_service'];
+ $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceTwo);
+
+ $this->assertSame($serviceOne, $serviceTwo);
+ }
+
+ /**
+ * @dataProvider serviceDefinitionProvider
+ */
+ public function testProtect($service)
+ {
+ $pimple = new Container();
+ $pimple['protected'] = $pimple->protect($service);
+
+ $this->assertSame($service, $pimple['protected']);
+ }
+
+ public function testGlobalFunctionNameAsParameterValue()
+ {
+ $pimple = new Container();
+ $pimple['global_function'] = 'strlen';
+ $this->assertSame('strlen', $pimple['global_function']);
+ }
+
+ public function testRaw()
+ {
+ $pimple = new Container();
+ $pimple['service'] = $definition = $pimple->factory(function () { return 'foo'; });
+ $this->assertSame($definition, $pimple->raw('service'));
+ }
+
+ public function testRawHonorsNullValues()
+ {
+ $pimple = new Container();
+ $pimple['foo'] = null;
+ $this->assertNull($pimple->raw('foo'));
+ }
+
+ public function testFluentRegister()
+ {
+ $pimple = new Container();
+ $this->assertSame($pimple, $pimple->register($this->getMockBuilder('Pimple\ServiceProviderInterface')->getMock()));
+ }
+
+ /**
+ * @expectedException \Pimple\Exception\UnknownIdentifierException
+ * @expectedExceptionMessage Identifier "foo" is not defined.
+ */
+ public function testRawValidatesKeyIsPresent()
+ {
+ $pimple = new Container();
+ $pimple->raw('foo');
+ }
+
+ /**
+ * @group legacy
+ * @expectedException \InvalidArgumentException
+ * @expectedExceptionMessage Identifier "foo" is not defined.
+ */
+ public function testLegacyRawValidatesKeyIsPresent()
+ {
+ $pimple = new Container();
+ $pimple->raw('foo');
+ }
+
+ /**
+ * @dataProvider serviceDefinitionProvider
+ */
+ public function testExtend($service)
+ {
+ $pimple = new Container();
+ $pimple['shared_service'] = function () {
+ return new Fixtures\Service();
+ };
+ $pimple['factory_service'] = $pimple->factory(function () {
+ return new Fixtures\Service();
+ });
+
+ $pimple->extend('shared_service', $service);
+ $serviceOne = $pimple['shared_service'];
+ $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceOne);
+ $serviceTwo = $pimple['shared_service'];
+ $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceTwo);
+ $this->assertSame($serviceOne, $serviceTwo);
+ $this->assertSame($serviceOne->value, $serviceTwo->value);
+
+ $pimple->extend('factory_service', $service);
+ $serviceOne = $pimple['factory_service'];
+ $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceOne);
+ $serviceTwo = $pimple['factory_service'];
+ $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceTwo);
+ $this->assertNotSame($serviceOne, $serviceTwo);
+ $this->assertNotSame($serviceOne->value, $serviceTwo->value);
+ }
+
+ public function testExtendDoesNotLeakWithFactories()
+ {
+ if (extension_loaded('pimple')) {
+ $this->markTestSkipped('Pimple extension does not support this test');
+ }
+ $pimple = new Container();
+
+ $pimple['foo'] = $pimple->factory(function () { return; });
+ $pimple['foo'] = $pimple->extend('foo', function ($foo, $pimple) { return; });
+ unset($pimple['foo']);
+
+ $p = new \ReflectionProperty($pimple, 'values');
+ $p->setAccessible(true);
+ $this->assertEmpty($p->getValue($pimple));
+
+ $p = new \ReflectionProperty($pimple, 'factories');
+ $p->setAccessible(true);
+ $this->assertCount(0, $p->getValue($pimple));
+ }
+
+ /**
+ * @expectedException \Pimple\Exception\UnknownIdentifierException
+ * @expectedExceptionMessage Identifier "foo" is not defined.
+ */
+ public function testExtendValidatesKeyIsPresent()
+ {
+ $pimple = new Container();
+ $pimple->extend('foo', function () {});
+ }
+
+ /**
+ * @group legacy
+ * @expectedException \InvalidArgumentException
+ * @expectedExceptionMessage Identifier "foo" is not defined.
+ */
+ public function testLegacyExtendValidatesKeyIsPresent()
+ {
+ $pimple = new Container();
+ $pimple->extend('foo', function () {});
+ }
+
+ public function testKeys()
+ {
+ $pimple = new Container();
+ $pimple['foo'] = 123;
+ $pimple['bar'] = 123;
+
+ $this->assertEquals(array('foo', 'bar'), $pimple->keys());
+ }
+
+ /** @test */
+ public function settingAnInvokableObjectShouldTreatItAsFactory()
+ {
+ $pimple = new Container();
+ $pimple['invokable'] = new Fixtures\Invokable();
+
+ $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $pimple['invokable']);
+ }
+
+ /** @test */
+ public function settingNonInvokableObjectShouldTreatItAsParameter()
+ {
+ $pimple = new Container();
+ $pimple['non_invokable'] = new Fixtures\NonInvokable();
+
+ $this->assertInstanceOf('Pimple\Tests\Fixtures\NonInvokable', $pimple['non_invokable']);
+ }
+
+ /**
+ * @dataProvider badServiceDefinitionProvider
+ * @expectedException \Pimple\Exception\ExpectedInvokableException
+ * @expectedExceptionMessage Service definition is not a Closure or invokable object.
+ */
+ public function testFactoryFailsForInvalidServiceDefinitions($service)
+ {
+ $pimple = new Container();
+ $pimple->factory($service);
+ }
+
+ /**
+ * @group legacy
+ * @dataProvider badServiceDefinitionProvider
+ * @expectedException \InvalidArgumentException
+ * @expectedExceptionMessage Service definition is not a Closure or invokable object.
+ */
+ public function testLegacyFactoryFailsForInvalidServiceDefinitions($service)
+ {
+ $pimple = new Container();
+ $pimple->factory($service);
+ }
+
+ /**
+ * @dataProvider badServiceDefinitionProvider
+ * @expectedException \Pimple\Exception\ExpectedInvokableException
+ * @expectedExceptionMessage Callable is not a Closure or invokable object.
+ */
+ public function testProtectFailsForInvalidServiceDefinitions($service)
+ {
+ $pimple = new Container();
+ $pimple->protect($service);
+ }
+
+ /**
+ * @group legacy
+ * @dataProvider badServiceDefinitionProvider
+ * @expectedException \InvalidArgumentException
+ * @expectedExceptionMessage Callable is not a Closure or invokable object.
+ */
+ public function testLegacyProtectFailsForInvalidServiceDefinitions($service)
+ {
+ $pimple = new Container();
+ $pimple->protect($service);
+ }
+
+ /**
+ * @dataProvider badServiceDefinitionProvider
+ * @expectedException \Pimple\Exception\InvalidServiceIdentifierException
+ * @expectedExceptionMessage Identifier "foo" does not contain an object definition.
+ */
+ public function testExtendFailsForKeysNotContainingServiceDefinitions($service)
+ {
+ $pimple = new Container();
+ $pimple['foo'] = $service;
+ $pimple->extend('foo', function () {});
+ }
+
+ /**
+ * @group legacy
+ * @dataProvider badServiceDefinitionProvider
+ * @expectedException \InvalidArgumentException
+ * @expectedExceptionMessage Identifier "foo" does not contain an object definition.
+ */
+ public function testLegacyExtendFailsForKeysNotContainingServiceDefinitions($service)
+ {
+ $pimple = new Container();
+ $pimple['foo'] = $service;
+ $pimple->extend('foo', function () {});
+ }
+
+ /**
+ * @group legacy
+ * @expectedDeprecation How Pimple behaves when extending protected closures will be fixed in Pimple 4. Are you sure "foo" should be protected?
+ */
+ public function testExtendingProtectedClosureDeprecation()
+ {
+ $pimple = new Container();
+ $pimple['foo'] = $pimple->protect(function () {
+ return 'bar';
+ });
+
+ $pimple->extend('foo', function ($value) {
+ return $value.'-baz';
+ });
+
+ $this->assertSame('bar-baz', $pimple['foo']);
+ }
+
+ /**
+ * @dataProvider badServiceDefinitionProvider
+ * @expectedException \Pimple\Exception\ExpectedInvokableException
+ * @expectedExceptionMessage Extension service definition is not a Closure or invokable object.
+ */
+ public function testExtendFailsForInvalidServiceDefinitions($service)
+ {
+ $pimple = new Container();
+ $pimple['foo'] = function () {};
+ $pimple->extend('foo', $service);
+ }
+
+ /**
+ * @group legacy
+ * @dataProvider badServiceDefinitionProvider
+ * @expectedException \InvalidArgumentException
+ * @expectedExceptionMessage Extension service definition is not a Closure or invokable object.
+ */
+ public function testLegacyExtendFailsForInvalidServiceDefinitions($service)
+ {
+ $pimple = new Container();
+ $pimple['foo'] = function () {};
+ $pimple->extend('foo', $service);
+ }
+
+ /**
+ * @expectedException \Pimple\Exception\FrozenServiceException
+ * @expectedExceptionMessage Cannot override frozen service "foo".
+ */
+ public function testExtendFailsIfFrozenServiceIsNonInvokable()
+ {
+ $pimple = new Container();
+ $pimple['foo'] = function () {
+ return new Fixtures\NonInvokable();
+ };
+ $foo = $pimple['foo'];
+
+ $pimple->extend('foo', function () {});
+ }
+
+ /**
+ * @expectedException \Pimple\Exception\FrozenServiceException
+ * @expectedExceptionMessage Cannot override frozen service "foo".
+ */
+ public function testExtendFailsIfFrozenServiceIsInvokable()
+ {
+ $pimple = new Container();
+ $pimple['foo'] = function () {
+ return new Fixtures\Invokable();
+ };
+ $foo = $pimple['foo'];
+
+ $pimple->extend('foo', function () {});
+ }
+
+ /**
+ * Provider for invalid service definitions.
+ */
+ public function badServiceDefinitionProvider()
+ {
+ return array(
+ array(123),
+ array(new Fixtures\NonInvokable()),
+ );
+ }
+
+ /**
+ * Provider for service definitions.
+ */
+ public function serviceDefinitionProvider()
+ {
+ return array(
+ array(function ($value) {
+ $service = new Fixtures\Service();
+ $service->value = $value;
+
+ return $service;
+ }),
+ array(new Fixtures\Invokable()),
+ );
+ }
+
+ public function testDefiningNewServiceAfterFreeze()
+ {
+ $pimple = new Container();
+ $pimple['foo'] = function () {
+ return 'foo';
+ };
+ $foo = $pimple['foo'];
+
+ $pimple['bar'] = function () {
+ return 'bar';
+ };
+ $this->assertSame('bar', $pimple['bar']);
+ }
+
+ /**
+ * @expectedException \Pimple\Exception\FrozenServiceException
+ * @expectedExceptionMessage Cannot override frozen service "foo".
+ */
+ public function testOverridingServiceAfterFreeze()
+ {
+ $pimple = new Container();
+ $pimple['foo'] = function () {
+ return 'foo';
+ };
+ $foo = $pimple['foo'];
+
+ $pimple['foo'] = function () {
+ return 'bar';
+ };
+ }
+
+ /**
+ * @group legacy
+ * @expectedException \RuntimeException
+ * @expectedExceptionMessage Cannot override frozen service "foo".
+ */
+ public function testLegacyOverridingServiceAfterFreeze()
+ {
+ $pimple = new Container();
+ $pimple['foo'] = function () {
+ return 'foo';
+ };
+ $foo = $pimple['foo'];
+
+ $pimple['foo'] = function () {
+ return 'bar';
+ };
+ }
+
+ public function testRemovingServiceAfterFreeze()
+ {
+ $pimple = new Container();
+ $pimple['foo'] = function () {
+ return 'foo';
+ };
+ $foo = $pimple['foo'];
+
+ unset($pimple['foo']);
+ $pimple['foo'] = function () {
+ return 'bar';
+ };
+ $this->assertSame('bar', $pimple['foo']);
+ }
+
+ public function testExtendingService()
+ {
+ $pimple = new Container();
+ $pimple['foo'] = function () {
+ return 'foo';
+ };
+ $pimple['foo'] = $pimple->extend('foo', function ($foo, $app) {
+ return "$foo.bar";
+ });
+ $pimple['foo'] = $pimple->extend('foo', function ($foo, $app) {
+ return "$foo.baz";
+ });
+ $this->assertSame('foo.bar.baz', $pimple['foo']);
+ }
+
+ public function testExtendingServiceAfterOtherServiceFreeze()
+ {
+ $pimple = new Container();
+ $pimple['foo'] = function () {
+ return 'foo';
+ };
+ $pimple['bar'] = function () {
+ return 'bar';
+ };
+ $foo = $pimple['foo'];
+
+ $pimple['bar'] = $pimple->extend('bar', function ($bar, $app) {
+ return "$bar.baz";
+ });
+ $this->assertSame('bar.baz', $pimple['bar']);
+ }
+}
diff --git a/vendor/pimple/pimple/src/Pimple/Tests/Psr11/ContainerTest.php b/vendor/pimple/pimple/src/Pimple/Tests/Psr11/ContainerTest.php
new file mode 100644
index 00000000..7ca2d7ff
--- /dev/null
+++ b/vendor/pimple/pimple/src/Pimple/Tests/Psr11/ContainerTest.php
@@ -0,0 +1,77 @@
+assertSame($pimple['service'], $psr->get('service'));
+ }
+
+ /**
+ * @expectedException \Psr\Container\NotFoundExceptionInterface
+ * @expectedExceptionMessage Identifier "service" is not defined.
+ */
+ public function testGetThrowsExceptionIfServiceIsNotFound()
+ {
+ $pimple = new Container();
+ $psr = new PsrContainer($pimple);
+
+ $psr->get('service');
+ }
+
+ public function testHasReturnsTrueIfServiceExists()
+ {
+ $pimple = new Container();
+ $pimple['service'] = function () {
+ return new Service();
+ };
+ $psr = new PsrContainer($pimple);
+
+ $this->assertTrue($psr->has('service'));
+ }
+
+ public function testHasReturnsFalseIfServiceDoesNotExist()
+ {
+ $pimple = new Container();
+ $psr = new PsrContainer($pimple);
+
+ $this->assertFalse($psr->has('service'));
+ }
+}
diff --git a/vendor/pimple/pimple/src/Pimple/Tests/Psr11/ServiceLocatorTest.php b/vendor/pimple/pimple/src/Pimple/Tests/Psr11/ServiceLocatorTest.php
new file mode 100644
index 00000000..c9a08125
--- /dev/null
+++ b/vendor/pimple/pimple/src/Pimple/Tests/Psr11/ServiceLocatorTest.php
@@ -0,0 +1,134 @@
+
+ */
+class ServiceLocatorTest extends TestCase
+{
+ public function testCanAccessServices()
+ {
+ $pimple = new Container();
+ $pimple['service'] = function () {
+ return new Fixtures\Service();
+ };
+ $locator = new ServiceLocator($pimple, array('service'));
+
+ $this->assertSame($pimple['service'], $locator->get('service'));
+ }
+
+ public function testCanAccessAliasedServices()
+ {
+ $pimple = new Container();
+ $pimple['service'] = function () {
+ return new Fixtures\Service();
+ };
+ $locator = new ServiceLocator($pimple, array('alias' => 'service'));
+
+ $this->assertSame($pimple['service'], $locator->get('alias'));
+ }
+
+ /**
+ * @expectedException \Pimple\Exception\UnknownIdentifierException
+ * @expectedExceptionMessage Identifier "service" is not defined.
+ */
+ public function testCannotAccessAliasedServiceUsingRealIdentifier()
+ {
+ $pimple = new Container();
+ $pimple['service'] = function () {
+ return new Fixtures\Service();
+ };
+ $locator = new ServiceLocator($pimple, array('alias' => 'service'));
+
+ $service = $locator->get('service');
+ }
+
+ /**
+ * @expectedException \Pimple\Exception\UnknownIdentifierException
+ * @expectedExceptionMessage Identifier "foo" is not defined.
+ */
+ public function testGetValidatesServiceCanBeLocated()
+ {
+ $pimple = new Container();
+ $pimple['service'] = function () {
+ return new Fixtures\Service();
+ };
+ $locator = new ServiceLocator($pimple, array('alias' => 'service'));
+
+ $service = $locator->get('foo');
+ }
+
+ /**
+ * @expectedException \Pimple\Exception\UnknownIdentifierException
+ * @expectedExceptionMessage Identifier "invalid" is not defined.
+ */
+ public function testGetValidatesTargetServiceExists()
+ {
+ $pimple = new Container();
+ $pimple['service'] = function () {
+ return new Fixtures\Service();
+ };
+ $locator = new ServiceLocator($pimple, array('alias' => 'invalid'));
+
+ $service = $locator->get('alias');
+ }
+
+ public function testHasValidatesServiceCanBeLocated()
+ {
+ $pimple = new Container();
+ $pimple['service1'] = function () {
+ return new Fixtures\Service();
+ };
+ $pimple['service2'] = function () {
+ return new Fixtures\Service();
+ };
+ $locator = new ServiceLocator($pimple, array('service1'));
+
+ $this->assertTrue($locator->has('service1'));
+ $this->assertFalse($locator->has('service2'));
+ }
+
+ public function testHasChecksIfTargetServiceExists()
+ {
+ $pimple = new Container();
+ $pimple['service'] = function () {
+ return new Fixtures\Service();
+ };
+ $locator = new ServiceLocator($pimple, array('foo' => 'service', 'bar' => 'invalid'));
+
+ $this->assertTrue($locator->has('foo'));
+ $this->assertFalse($locator->has('bar'));
+ }
+}
diff --git a/vendor/pimple/pimple/src/Pimple/Tests/ServiceIteratorTest.php b/vendor/pimple/pimple/src/Pimple/Tests/ServiceIteratorTest.php
new file mode 100644
index 00000000..5dd52f0d
--- /dev/null
+++ b/vendor/pimple/pimple/src/Pimple/Tests/ServiceIteratorTest.php
@@ -0,0 +1,52 @@
+assertSame(array('service1' => $pimple['service1'], 'service2' => $pimple['service2']), iterator_to_array($iterator));
+ }
+}
diff --git a/vendor/psr/container/.gitignore b/vendor/psr/container/.gitignore
new file mode 100644
index 00000000..b2395aa0
--- /dev/null
+++ b/vendor/psr/container/.gitignore
@@ -0,0 +1,3 @@
+composer.lock
+composer.phar
+/vendor/
diff --git a/vendor/psr/container/LICENSE b/vendor/psr/container/LICENSE
new file mode 100644
index 00000000..2877a489
--- /dev/null
+++ b/vendor/psr/container/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2013-2016 container-interop
+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/vendor/psr/container/README.md b/vendor/psr/container/README.md
new file mode 100644
index 00000000..084f6df5
--- /dev/null
+++ b/vendor/psr/container/README.md
@@ -0,0 +1,5 @@
+# PSR Container
+
+This repository holds all interfaces/classes/traits related to [PSR-11](https://github.com/container-interop/fig-standards/blob/master/proposed/container.md).
+
+Note that this is not a container implementation of its own. See the specification for more details.
diff --git a/vendor/psr/container/composer.json b/vendor/psr/container/composer.json
new file mode 100644
index 00000000..b8ee0126
--- /dev/null
+++ b/vendor/psr/container/composer.json
@@ -0,0 +1,27 @@
+{
+ "name": "psr/container",
+ "type": "library",
+ "description": "Common Container Interface (PHP FIG PSR-11)",
+ "keywords": ["psr", "psr-11", "container", "container-interop", "container-interface"],
+ "homepage": "https://github.com/php-fig/container",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "http://www.php-fig.org/"
+ }
+ ],
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Container\\": "src/"
+ }
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ }
+}
diff --git a/vendor/psr/container/src/ContainerExceptionInterface.php b/vendor/psr/container/src/ContainerExceptionInterface.php
new file mode 100644
index 00000000..d35c6b4d
--- /dev/null
+++ b/vendor/psr/container/src/ContainerExceptionInterface.php
@@ -0,0 +1,13 @@
+log(LogLevel::EMERGENCY, $message, $context);
+ }
+
+ /**
+ * Action must be taken immediately.
+ *
+ * Example: Entire website down, database unavailable, etc. This should
+ * trigger the SMS alerts and wake you up.
+ *
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function alert($message, array $context = array())
+ {
+ $this->log(LogLevel::ALERT, $message, $context);
+ }
+
+ /**
+ * Critical conditions.
+ *
+ * Example: Application component unavailable, unexpected exception.
+ *
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function critical($message, array $context = array())
+ {
+ $this->log(LogLevel::CRITICAL, $message, $context);
+ }
+
+ /**
+ * Runtime errors that do not require immediate action but should typically
+ * be logged and monitored.
+ *
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function error($message, array $context = array())
+ {
+ $this->log(LogLevel::ERROR, $message, $context);
+ }
+
+ /**
+ * Exceptional occurrences that are not errors.
+ *
+ * Example: Use of deprecated APIs, poor use of an API, undesirable things
+ * that are not necessarily wrong.
+ *
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function warning($message, array $context = array())
+ {
+ $this->log(LogLevel::WARNING, $message, $context);
+ }
+
+ /**
+ * Normal but significant events.
+ *
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function notice($message, array $context = array())
+ {
+ $this->log(LogLevel::NOTICE, $message, $context);
+ }
+
+ /**
+ * Interesting events.
+ *
+ * Example: User logs in, SQL logs.
+ *
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function info($message, array $context = array())
+ {
+ $this->log(LogLevel::INFO, $message, $context);
+ }
+
+ /**
+ * Detailed debug information.
+ *
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function debug($message, array $context = array())
+ {
+ $this->log(LogLevel::DEBUG, $message, $context);
+ }
+}
diff --git a/vendor/psr/log/Psr/Log/InvalidArgumentException.php b/vendor/psr/log/Psr/Log/InvalidArgumentException.php
new file mode 100644
index 00000000..67f852d1
--- /dev/null
+++ b/vendor/psr/log/Psr/Log/InvalidArgumentException.php
@@ -0,0 +1,7 @@
+logger = $logger;
+ }
+}
diff --git a/vendor/psr/log/Psr/Log/LoggerInterface.php b/vendor/psr/log/Psr/Log/LoggerInterface.php
new file mode 100644
index 00000000..5ea72438
--- /dev/null
+++ b/vendor/psr/log/Psr/Log/LoggerInterface.php
@@ -0,0 +1,123 @@
+log(LogLevel::EMERGENCY, $message, $context);
+ }
+
+ /**
+ * Action must be taken immediately.
+ *
+ * Example: Entire website down, database unavailable, etc. This should
+ * trigger the SMS alerts and wake you up.
+ *
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function alert($message, array $context = array())
+ {
+ $this->log(LogLevel::ALERT, $message, $context);
+ }
+
+ /**
+ * Critical conditions.
+ *
+ * Example: Application component unavailable, unexpected exception.
+ *
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function critical($message, array $context = array())
+ {
+ $this->log(LogLevel::CRITICAL, $message, $context);
+ }
+
+ /**
+ * Runtime errors that do not require immediate action but should typically
+ * be logged and monitored.
+ *
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function error($message, array $context = array())
+ {
+ $this->log(LogLevel::ERROR, $message, $context);
+ }
+
+ /**
+ * Exceptional occurrences that are not errors.
+ *
+ * Example: Use of deprecated APIs, poor use of an API, undesirable things
+ * that are not necessarily wrong.
+ *
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function warning($message, array $context = array())
+ {
+ $this->log(LogLevel::WARNING, $message, $context);
+ }
+
+ /**
+ * Normal but significant events.
+ *
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function notice($message, array $context = array())
+ {
+ $this->log(LogLevel::NOTICE, $message, $context);
+ }
+
+ /**
+ * Interesting events.
+ *
+ * Example: User logs in, SQL logs.
+ *
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function info($message, array $context = array())
+ {
+ $this->log(LogLevel::INFO, $message, $context);
+ }
+
+ /**
+ * Detailed debug information.
+ *
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function debug($message, array $context = array())
+ {
+ $this->log(LogLevel::DEBUG, $message, $context);
+ }
+
+ /**
+ * Logs with an arbitrary level.
+ *
+ * @param mixed $level
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ abstract public function log($level, $message, array $context = array());
+}
diff --git a/vendor/psr/log/Psr/Log/NullLogger.php b/vendor/psr/log/Psr/Log/NullLogger.php
new file mode 100644
index 00000000..d8cd682c
--- /dev/null
+++ b/vendor/psr/log/Psr/Log/NullLogger.php
@@ -0,0 +1,28 @@
+logger) { }`
+ * blocks.
+ */
+class NullLogger extends AbstractLogger
+{
+ /**
+ * Logs with an arbitrary level.
+ *
+ * @param mixed $level
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function log($level, $message, array $context = array())
+ {
+ // noop
+ }
+}
diff --git a/vendor/psr/log/Psr/Log/Test/LoggerInterfaceTest.php b/vendor/psr/log/Psr/Log/Test/LoggerInterfaceTest.php
new file mode 100644
index 00000000..a0391a52
--- /dev/null
+++ b/vendor/psr/log/Psr/Log/Test/LoggerInterfaceTest.php
@@ -0,0 +1,140 @@
+ ".
+ *
+ * Example ->error('Foo') would yield "error Foo".
+ *
+ * @return string[]
+ */
+ abstract public function getLogs();
+
+ public function testImplements()
+ {
+ $this->assertInstanceOf('Psr\Log\LoggerInterface', $this->getLogger());
+ }
+
+ /**
+ * @dataProvider provideLevelsAndMessages
+ */
+ public function testLogsAtAllLevels($level, $message)
+ {
+ $logger = $this->getLogger();
+ $logger->{$level}($message, array('user' => 'Bob'));
+ $logger->log($level, $message, array('user' => 'Bob'));
+
+ $expected = array(
+ $level.' message of level '.$level.' with context: Bob',
+ $level.' message of level '.$level.' with context: Bob',
+ );
+ $this->assertEquals($expected, $this->getLogs());
+ }
+
+ public function provideLevelsAndMessages()
+ {
+ return array(
+ LogLevel::EMERGENCY => array(LogLevel::EMERGENCY, 'message of level emergency with context: {user}'),
+ LogLevel::ALERT => array(LogLevel::ALERT, 'message of level alert with context: {user}'),
+ LogLevel::CRITICAL => array(LogLevel::CRITICAL, 'message of level critical with context: {user}'),
+ LogLevel::ERROR => array(LogLevel::ERROR, 'message of level error with context: {user}'),
+ LogLevel::WARNING => array(LogLevel::WARNING, 'message of level warning with context: {user}'),
+ LogLevel::NOTICE => array(LogLevel::NOTICE, 'message of level notice with context: {user}'),
+ LogLevel::INFO => array(LogLevel::INFO, 'message of level info with context: {user}'),
+ LogLevel::DEBUG => array(LogLevel::DEBUG, 'message of level debug with context: {user}'),
+ );
+ }
+
+ /**
+ * @expectedException \Psr\Log\InvalidArgumentException
+ */
+ public function testThrowsOnInvalidLevel()
+ {
+ $logger = $this->getLogger();
+ $logger->log('invalid level', 'Foo');
+ }
+
+ public function testContextReplacement()
+ {
+ $logger = $this->getLogger();
+ $logger->info('{Message {nothing} {user} {foo.bar} a}', array('user' => 'Bob', 'foo.bar' => 'Bar'));
+
+ $expected = array('info {Message {nothing} Bob Bar a}');
+ $this->assertEquals($expected, $this->getLogs());
+ }
+
+ public function testObjectCastToString()
+ {
+ if (method_exists($this, 'createPartialMock')) {
+ $dummy = $this->createPartialMock('Psr\Log\Test\DummyTest', array('__toString'));
+ } else {
+ $dummy = $this->getMock('Psr\Log\Test\DummyTest', array('__toString'));
+ }
+ $dummy->expects($this->once())
+ ->method('__toString')
+ ->will($this->returnValue('DUMMY'));
+
+ $this->getLogger()->warning($dummy);
+
+ $expected = array('warning DUMMY');
+ $this->assertEquals($expected, $this->getLogs());
+ }
+
+ public function testContextCanContainAnything()
+ {
+ $context = array(
+ 'bool' => true,
+ 'null' => null,
+ 'string' => 'Foo',
+ 'int' => 0,
+ 'float' => 0.5,
+ 'nested' => array('with object' => new DummyTest),
+ 'object' => new \DateTime,
+ 'resource' => fopen('php://memory', 'r'),
+ );
+
+ $this->getLogger()->warning('Crazy context data', $context);
+
+ $expected = array('warning Crazy context data');
+ $this->assertEquals($expected, $this->getLogs());
+ }
+
+ public function testContextExceptionKeyCanBeExceptionOrOtherValues()
+ {
+ $logger = $this->getLogger();
+ $logger->warning('Random message', array('exception' => 'oops'));
+ $logger->critical('Uncaught Exception!', array('exception' => new \LogicException('Fail')));
+
+ $expected = array(
+ 'warning Random message',
+ 'critical Uncaught Exception!'
+ );
+ $this->assertEquals($expected, $this->getLogs());
+ }
+}
+
+class DummyTest
+{
+ public function __toString()
+ {
+ }
+}
diff --git a/vendor/psr/log/README.md b/vendor/psr/log/README.md
new file mode 100644
index 00000000..574bc1cb
--- /dev/null
+++ b/vendor/psr/log/README.md
@@ -0,0 +1,45 @@
+PSR Log
+=======
+
+This repository holds all interfaces/classes/traits related to
+[PSR-3](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md).
+
+Note that this is not a logger of its own. It is merely an interface that
+describes a logger. See the specification for more details.
+
+Usage
+-----
+
+If you need a logger, you can use the interface like this:
+
+```php
+logger = $logger;
+ }
+
+ public function doSomething()
+ {
+ if ($this->logger) {
+ $this->logger->info('Doing work');
+ }
+
+ // do something useful
+ }
+}
+```
+
+You can then pick one of the implementations of the interface to get a logger.
+
+If you want to implement the interface, you can require this package and
+implement `Psr\Log\LoggerInterface` in your code. Please read the
+[specification text](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md)
+for details.
diff --git a/vendor/psr/log/composer.json b/vendor/psr/log/composer.json
new file mode 100644
index 00000000..87934d70
--- /dev/null
+++ b/vendor/psr/log/composer.json
@@ -0,0 +1,26 @@
+{
+ "name": "psr/log",
+ "description": "Common interface for logging libraries",
+ "keywords": ["psr", "psr-3", "log"],
+ "homepage": "https://github.com/php-fig/log",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "http://www.php-fig.org/"
+ }
+ ],
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Log\\": "Psr/Log/"
+ }
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ }
+}
diff --git a/vendor/silex/silex/.gitignore b/vendor/silex/silex/.gitignore
new file mode 100644
index 00000000..3d4ff050
--- /dev/null
+++ b/vendor/silex/silex/.gitignore
@@ -0,0 +1,5 @@
+/phpunit.xml
+/vendor
+/build
+/composer.lock
+
diff --git a/vendor/silex/silex/.travis.yml b/vendor/silex/silex/.travis.yml
new file mode 100644
index 00000000..a2b7fe8c
--- /dev/null
+++ b/vendor/silex/silex/.travis.yml
@@ -0,0 +1,59 @@
+language: php
+
+sudo: false
+
+env:
+ global:
+ - SYMFONY_DEPRECATIONS_HELPER=weak
+
+cache:
+ directories:
+ - $HOME/.composer/cache/files
+ - .phpunit
+
+before_install:
+ - if [[ $TRAVIS_PHP_VERSION != hhvm ]]; then phpenv config-rm xdebug.ini; fi
+
+before_script:
+ # Twig 1.x
+ - if [[ $TWIG_VERSION != 2.0 ]]; then sed -i 's/~1.8|~2.0/~1.8/g' composer.json; fi
+
+ # Symfony 2.8
+ - if [[ $SYMFONY_DEPS_VERSION = 2.8 ]]; then sed -i 's/~2\.8|^3\.0/2.8.*@dev/g' composer.json; fi
+ # Symfony 3.0
+ - if [[ $SYMFONY_DEPS_VERSION = 3.0 ]]; then sed -i 's/~2\.8|^3\.0/3.0.*@dev/g' composer.json; fi
+ # Symfony 3.1
+ - if [[ $SYMFONY_DEPS_VERSION = 3.1 ]]; then sed -i 's/~2\.8|^3\.0/3.1.*@dev/g' composer.json; fi
+ # Symfony 3.2
+ - if [[ $SYMFONY_DEPS_VERSION = 3.2 ]]; then sed -i 's/~2\.8|^3\.0/3.2.*@dev/g' composer.json; fi
+ # Symfony 3.3
+ - |
+ if [[ $SYMFONY_DEPS_VERSION = 3.3 ]]; then
+ sed -i 's/~2\.8|^3\.0/3.3.*@dev/g' composer.json;
+ composer require --dev --no-update symfony/web-link:3.3.*
+ fi
+
+ - composer update --no-suggest
+
+script: ./vendor/bin/simple-phpunit
+
+matrix:
+ include:
+ - php: 5.5
+ - php: 5.6
+ env: TWIG_VERSION=2.0
+ - php: 5.6
+ env: SYMFONY_DEPS_VERSION=2.8
+ - php: 5.6
+ env: SYMFONY_DEPS_VERSION=3.0
+ - php: 5.6
+ env: SYMFONY_DEPS_VERSION=3.1
+ - php: 5.6
+ env: SYMFONY_DEPS_VERSION=3.2
+ - php: 5.6
+ env: SYMFONY_DEPS_VERSION=3.3
+ - php: 5.6
+ - php: 7.0
+ - php: 7.1
+ - php: hhvm
+ dist: trusty
diff --git a/vendor/silex/silex/LICENSE b/vendor/silex/silex/LICENSE
new file mode 100644
index 00000000..b420d719
--- /dev/null
+++ b/vendor/silex/silex/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2010-2017 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/vendor/silex/silex/README.rst b/vendor/silex/silex/README.rst
new file mode 100644
index 00000000..b79e47b6
--- /dev/null
+++ b/vendor/silex/silex/README.rst
@@ -0,0 +1,64 @@
+Silex, a simple Web Framework
+=============================
+
+Silex is a PHP micro-framework to develop websites based on `Symfony
+components`_:
+
+.. code-block:: php
+
+ get('/hello/{name}', function ($name) use ($app) {
+ return 'Hello '.$app->escape($name);
+ });
+
+ $app->run();
+
+Silex works with PHP 5.5.9 or later.
+
+Installation
+------------
+
+The recommended way to install Silex is through `Composer`_:
+
+.. code-block:: bash
+
+ composer require silex/silex "~2.0"
+
+Alternatively, you can download the `silex.zip`_ file and extract it.
+
+More Information
+----------------
+
+Read the `documentation`_ for more information and `changelog
+`_ for upgrading information.
+
+Tests
+-----
+
+To run the test suite, you need `Composer`_ and `PHPUnit`_:
+
+.. code-block:: bash
+
+ composer install
+ phpunit
+
+Community
+---------
+
+Check out #silex-php on irc.freenode.net.
+
+License
+-------
+
+Silex is licensed under the MIT license.
+
+.. _Symfony components: http://symfony.com
+.. _Composer: http://getcomposer.org
+.. _PHPUnit: https://phpunit.de
+.. _silex.zip: http://silex.sensiolabs.org/download
+.. _documentation: http://silex.sensiolabs.org/documentation
diff --git a/vendor/silex/silex/composer.json b/vendor/silex/silex/composer.json
new file mode 100644
index 00000000..935c5181
--- /dev/null
+++ b/vendor/silex/silex/composer.json
@@ -0,0 +1,72 @@
+{
+ "name": "silex/silex",
+ "description": "The PHP micro-framework based on the Symfony Components",
+ "keywords": ["microframework"],
+ "homepage": "http://silex.sensiolabs.org",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Igor Wiedler",
+ "email": "igor@wiedler.ch"
+ }
+ ],
+ "require": {
+ "php": ">=5.5.9",
+ "pimple/pimple": "~3.0",
+ "symfony/event-dispatcher": "~2.8|^3.0",
+ "symfony/http-foundation": "~2.8|^3.0",
+ "symfony/http-kernel": "~2.8|^3.0",
+ "symfony/routing": "~2.8|^3.0"
+ },
+ "require-dev": {
+ "symfony/asset": "~2.8|^3.0",
+ "symfony/expression-language": "~2.8|^3.0",
+ "symfony/security": "~2.8|^3.0",
+ "symfony/config": "~2.8|^3.0",
+ "symfony/form": "~2.8|^3.0",
+ "symfony/browser-kit": "~2.8|^3.0",
+ "symfony/css-selector": "~2.8|^3.0",
+ "symfony/debug": "~2.8|^3.0",
+ "symfony/dom-crawler": "~2.8|^3.0",
+ "symfony/finder": "~2.8|^3.0",
+ "symfony/intl": "~2.8|^3.0",
+ "symfony/monolog-bridge": "~2.8|^3.0",
+ "symfony/doctrine-bridge": "~2.8|^3.0",
+ "symfony/options-resolver": "~2.8|^3.0",
+ "symfony/phpunit-bridge": "^3.2",
+ "symfony/process": "~2.8|^3.0",
+ "symfony/serializer": "~2.8|^3.0",
+ "symfony/translation": "~2.8|^3.0",
+ "symfony/twig-bridge": "~2.8|^3.0",
+ "symfony/validator": "~2.8|^3.0",
+ "symfony/var-dumper": "~2.8|^3.0",
+ "twig/twig": "~1.28|~2.0",
+ "doctrine/dbal": "~2.2",
+ "swiftmailer/swiftmailer": "~5",
+ "monolog/monolog": "^1.4.1",
+ "symfony/web-link": "^3.3"
+ },
+ "conflict": {
+ "phpunit/phpunit": "<4.8.35 || >= 5.0, <5.4.3"
+ },
+ "replace": {
+ "silex/api": "self.version",
+ "silex/providers": "self.version"
+ },
+ "autoload": {
+ "psr-4": { "Silex\\": "src/Silex" }
+ },
+ "autoload-dev" : {
+ "psr-4": { "Silex\\Tests\\" : "tests/Silex/Tests" }
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.2.x-dev"
+ }
+ },
+ "minimum-stability": "dev"
+}
diff --git a/vendor/silex/silex/doc/changelog.rst b/vendor/silex/silex/doc/changelog.rst
new file mode 100644
index 00000000..a2917561
--- /dev/null
+++ b/vendor/silex/silex/doc/changelog.rst
@@ -0,0 +1,387 @@
+Changelog
+=========
+
+2.2.0 (2017-07-23)
+------------------
+
+* added json manifest version strategy support
+* fixed EsiFragment constructor
+* fixed RedirectableUrlMatcher compatibility with Symfony
+* fixed compatibility with Pimple 3.2
+* fixed WebTestCase compatibility with PHPUnit 6+
+
+2.1.0 (2017-05-03)
+------------------
+
+* added more options to security.firewalls
+* added WebLink component integration
+* added parameters to configure the Twig core extension behavior
+* fixed deprecation notices with symfony/twig-bridge 3.2+ in TwigServiceProvider
+* added FormRegistry as a service to enable the extension point
+* removed the build scripts
+* fixed some deprecation warnings
+* added support for registering Swiftmailer plugins
+
+2.0.4 (2016-11-06)
+------------------
+
+* fixed twig.app_variable definition
+* added support for latest versions of Twig 1.x and 2.0 (Twig runtime loaders)
+* added support for Symfony 2.3
+
+2.0.3 (2016-08-22)
+------------------
+
+* fixed lazy evaluation of 'monolog.use_error_handler'
+* fixed PHP7 type hint on controllers
+
+2.0.2 (2016-06-14)
+------------------
+
+* fixed Symfony 3.1 deprecations
+
+2.0.1 (2016-05-27)
+------------------
+
+* fixed the silex form extension registration to allow overriding default ones
+* removed support for the obsolete Locale Symfony component (uses the Intl one now)
+* added support for Symfony 3.1
+
+2.0.0 (2016-05-18)
+------------------
+
+* decoupled the exception handler from HttpKernelServiceProvider
+* Switched to BCrypt as the default encoder in the security provider
+* added full support for RequestMatcher
+* added support for Symfony Guard
+* added support for callables in CallbackResolver
+* added FormTrait::namedForm()
+* added support for delivery_addresses, delivery_whitelist, and sender_address
+* added support to register form types / form types extensions / form types guessers as services
+* added support for callable in mounts (allow nested route collection to be built easily)
+* added support for conditions on routes
+* added support for the Symfony VarDumper Component
+* added a global Twig variable (an AppVariable instance)
+* [BC BREAK] CSRF has been moved to a standalone provider (``form.secret`` is not available anymore)
+* added support for the Symfony HttpFoundation Twig bridge extension
+* added support for the Symfony Asset Component
+* bumped minimum version of Symfony to 2.8
+* bumped minimum version of PHP to 5.5.0
+* Updated Pimple to 3.0
+* Updated session listeners to extends HttpKernel ones
+* [BC BREAK] Locale management has been moved to LocaleServiceProvider which must be registered
+ if you want Silex to manage your locale (must also be registered for the translation service provider)
+* [BC BREAK] Provider interfaces moved to Silex\Api namespace, published as
+ separate package via subtree split
+* [BC BREAK] ServiceProviderInterface split in to EventListenerProviderInterface
+ and BootableProviderInterface
+* [BC BREAK] Service Provider support files moved under Silex\Provider
+ namespace, allowing publishing as separate package via sub-tree split
+* ``monolog.exception.logger_filter`` option added to Monolog service provider
+* [BC BREAK] ``$app['request']`` service removed, use ``$app['request_stack']`` instead
+
+1.3.6 (2016-XX-XX)
+------------------
+
+* n/a
+
+1.3.5 (2016-01-06)
+------------------
+
+* fixed typo in SecurityServiceProvider
+
+1.3.4 (2015-09-15)
+------------------
+
+* fixed some new deprecations
+* fixed translation registration for the validators
+
+1.3.3 (2015-09-08)
+------------------
+
+* added support for Symfony 3.0 and Twig 2.0
+* fixed some Form deprecations
+* removed deprecated method call in the exception handler
+* fixed Swiftmailer spool flushing when spool is not enabled
+
+1.3.2 (2015-08-24)
+------------------
+
+* no changes
+
+1.3.1 (2015-08-04)
+------------------
+
+* added missing support for the Expression constraint
+* fixed the possibility to override translations for validator error messages
+* fixed sub-mounts with same name clash
+* fixed session logout handler when a firewall is stateless
+
+1.3.0 (2015-06-05)
+------------------
+
+* added a `$app['user']` to get the current user (security provider)
+* added view handlers
+* added support for the OPTIONS HTTP method
+* added caching for the Translator provider
+* deprecated `$app['exception_handler']->disable()` in favor of `unset($app['exception_handler'])`
+* made Silex compatible with Symfony 2.7 an 2.8 (and keep compatibility with Symfony 2.3, 2.5, and 2.6)
+* removed deprecated TwigCoreExtension class (register the new HttpFragmentServiceProvider instead)
+* bumped minimum version of PHP to 5.3.9
+
+1.2.5 (2015-06-04)
+------------------
+
+* no code changes (last version of the 1.2 branch)
+
+1.2.4 (2015-04-11)
+------------------
+
+* fixed the exception message when mounting a collection that doesn't return a ControllerCollection
+* fixed Symfony dependencies (Silex 1.2 is not compatible with Symfony 2.7)
+
+1.2.3 (2015-01-20)
+------------------
+
+* fixed remember me listener
+* fixed translation files loading when they do not exist
+* allowed global after middlewares to return responses like route specific ones
+
+1.2.2 (2014-09-26)
+------------------
+
+* fixed Translator locale management
+* added support for the $app argument in application middlewares (to make it consistent with route middlewares)
+* added form.types to the Form provider
+
+1.2.1 (2014-07-01)
+------------------
+
+* added support permissions in the Monolog provider
+* fixed Switfmailer spool where the event dispatcher is different from the other ones
+* fixed locale when changing it on the translator itself
+
+1.2.0 (2014-03-29)
+------------------
+
+* Allowed disabling the boot logic of MonologServiceProvider
+* Reverted "convert attributes on the request that actually exist"
+* [BC BREAK] Routes are now always added in the order of their registration (even for mounted routes)
+* Added run() on Route to be able to define the controller code
+* Deprecated TwigCoreExtension (register the new HttpFragmentServiceProvider instead)
+* Added HttpFragmentServiceProvider
+* Allowed a callback to be a method call on a service (before, after, finish, error, on Application; convert, before, after on Controller)
+
+1.1.3 (2013-XX-XX)
+------------------
+
+* Fixed translator locale management
+
+1.1.2 (2013-10-30)
+------------------
+
+* Added missing "security.hide_user_not_found" support in SecurityServiceProvider
+* Fixed event listeners that are registered after the boot via the on() method
+
+1.0.2 (2013-10-30)
+------------------
+
+* Fixed SecurityServiceProvider to use null as a fake controller so that routes can be dumped
+
+1.1.1 (2013-10-11)
+------------------
+
+* Removed or replaced deprecated Symfony code
+* Updated code to take advantages of 2.3 new features
+* Only convert attributes on the request that actually exist.
+
+1.1.0 (2013-07-04)
+------------------
+
+* Support for any ``Psr\Log\LoggerInterface`` as opposed to the monolog-bridge
+ one.
+* Made dispatcher proxy methods ``on``, ``before``, ``after`` and ``error``
+ lazy, so that they will not instantiate the dispatcher early.
+* Dropped support for 2.1 and 2.2 versions of Symfony.
+
+1.0.1 (2013-07-04)
+------------------
+
+* Fixed RedirectableUrlMatcher::redirect() when Silex is configured to use a logger
+* Make ``DoctrineServiceProvider`` multi-db support lazy.
+
+1.0.0 (2013-05-03)
+------------------
+
+* **2013-04-12**: Added support for validators as services.
+
+* **2013-04-01**: Added support for host matching with symfony 2.2::
+
+ $app->match('/', function() {
+ // app-specific action
+ })->host('example.com');
+
+ $app->match('/', function ($user) {
+ // user-specific action
+ })->host('{user}.example.com');
+
+* **2013-03-08**: Added support for form type extensions and guessers as
+ services.
+
+* **2013-03-08**: Added support for remember-me via the
+ ``RememberMeServiceProvider``.
+
+* **2013-02-07**: Added ``Application::sendFile()`` to ease sending
+ ``BinaryFileResponse``.
+
+* **2012-11-05**: Filters have been renamed to application middlewares in the
+ documentation.
+
+* **2012-11-05**: The ``before()``, ``after()``, ``error()``, and ``finish()``
+ listener priorities now set the priority of the underlying Symfony event
+ instead of a custom one before.
+
+* **2012-11-05**: Removing the default exception handler should now be done
+ via its ``disable()`` method:
+
+ Before:
+
+ unset($app['exception_handler']);
+
+ After:
+
+ $app['exception_handler']->disable();
+
+* **2012-07-15**: removed the ``monolog.configure`` service. Use the
+ ``extend`` method instead:
+
+ Before::
+
+ $app['monolog.configure'] = $app->protect(function ($monolog) use ($app) {
+ // do something
+ });
+
+ After::
+
+ $app['monolog'] = $app->share($app->extend('monolog', function($monolog, $app) {
+ // do something
+
+ return $monolog;
+ }));
+
+
+* **2012-06-17**: ``ControllerCollection`` now takes a required route instance
+ as a constructor argument.
+
+ Before::
+
+ $controllers = new ControllerCollection();
+
+ After::
+
+ $controllers = new ControllerCollection(new Route());
+
+ // or even better
+ $controllers = $app['controllers_factory'];
+
+* **2012-06-17**: added application traits for PHP 5.4
+
+* **2012-06-16**: renamed ``request.default_locale`` to ``locale``
+
+* **2012-06-16**: Removed the ``translator.loader`` service. See documentation
+ for how to use XLIFF or YAML-based translation files.
+
+* **2012-06-15**: removed the ``twig.configure`` service. Use the ``extend``
+ method instead:
+
+ Before::
+
+ $app['twig.configure'] = $app->protect(function ($twig) use ($app) {
+ // do something
+ });
+
+ After::
+
+ $app['twig'] = $app->share($app->extend('twig', function($twig, $app) {
+ // do something
+
+ return $twig;
+ }));
+
+* **2012-06-13**: Added a route ``before`` middleware
+
+* **2012-06-13**: Renamed the route ``middleware`` to ``before``
+
+* **2012-06-13**: Added an extension for the Symfony Security component
+
+* **2012-05-31**: Made the ``BrowserKit``, ``CssSelector``, ``DomCrawler``,
+ ``Finder`` and ``Process`` components optional dependencies. Projects that
+ depend on them (e.g. through functional tests) should add those dependencies
+ to their ``composer.json``.
+
+* **2012-05-26**: added ``boot()`` to ``ServiceProviderInterface``.
+
+* **2012-05-26**: Removed ``SymfonyBridgesServiceProvider``. It is now implicit
+ by checking the existence of the bridge.
+
+* **2012-05-26**: Removed the ``translator.messages`` parameter (use
+ ``translator.domains`` instead).
+
+* **2012-05-24**: Removed the ``autoloader`` service (use composer instead).
+ The ``*.class_path`` settings on all the built-in providers have also been
+ removed in favor of Composer.
+
+* **2012-05-21**: Changed error() to allow handling specific exceptions.
+
+* **2012-05-20**: Added a way to define settings on a controller collection.
+
+* **2012-05-20**: The Request instance is not available anymore from the
+ Application after it has been handled.
+
+* **2012-04-01**: Added ``finish`` filters.
+
+* **2012-03-20**: Added ``json`` helper::
+
+ $data = array('some' => 'data');
+ $response = $app->json($data);
+
+* **2012-03-11**: Added route middlewares.
+
+* **2012-03-02**: Switched to use Composer for dependency management.
+
+* **2012-02-27**: Updated to Symfony 2.1 session handling.
+
+* **2012-01-02**: Introduced support for streaming responses.
+
+* **2011-09-22**: ``ExtensionInterface`` has been renamed to
+ ``ServiceProviderInterface``. All built-in extensions have been renamed
+ accordingly (for instance, ``Silex\Extension\TwigExtension`` has been
+ renamed to ``Silex\Provider\TwigServiceProvider``).
+
+* **2011-09-22**: The way reusable applications work has changed. The
+ ``mount()`` method now takes an instance of ``ControllerCollection`` instead
+ of an ``Application`` one.
+
+ Before::
+
+ $app = new Application();
+ $app->get('/bar', function() { return 'foo'; });
+
+ return $app;
+
+ After::
+
+ $app = new ControllerCollection();
+ $app->get('/bar', function() { return 'foo'; });
+
+ return $app;
+
+* **2011-08-08**: The controller method configuration is now done on the Controller itself
+
+ Before::
+
+ $app->match('/', function () { echo 'foo'; }, 'GET|POST');
+
+ After::
+
+ $app->match('/', function () { echo 'foo'; })->method('GET|POST');
diff --git a/vendor/silex/silex/doc/conf.py b/vendor/silex/silex/doc/conf.py
new file mode 100644
index 00000000..dfe355c7
--- /dev/null
+++ b/vendor/silex/silex/doc/conf.py
@@ -0,0 +1,17 @@
+import sys, os
+from sphinx.highlighting import lexers
+from pygments.lexers.web import PhpLexer
+
+sys.path.append(os.path.abspath('_exts'))
+
+extensions = []
+master_doc = 'index'
+highlight_language = 'php'
+
+project = u'Silex'
+copyright = u'2010 Fabien Potencier'
+
+version = '0'
+release = '0.0.0'
+
+lexers['php'] = PhpLexer(startinline=True)
diff --git a/vendor/silex/silex/doc/contributing.rst b/vendor/silex/silex/doc/contributing.rst
new file mode 100644
index 00000000..34a339d8
--- /dev/null
+++ b/vendor/silex/silex/doc/contributing.rst
@@ -0,0 +1,34 @@
+Contributing
+============
+
+We are open to contributions to the Silex code. If you find a bug or want to
+contribute a provider, just follow these steps:
+
+* Fork `the Silex repository `_;
+
+* Make your feature addition or bug fix;
+
+* Add tests for it;
+
+* Optionally, add some documentation;
+
+* `Send a pull request
+ `_, to the correct
+ target branch (1.3 for bug fixes, master for new features).
+
+.. note::
+
+ Any code you contribute must be licensed under the MIT
+ License.
+
+Writing Documentation
+=====================
+
+The documentation is written in `reStructuredText
+`_ and can be generated using `sphinx
+`_.
+
+.. code-block:: bash
+
+ $ cd doc
+ $ sphinx-build -b html . build
diff --git a/vendor/silex/silex/doc/cookbook/error_handler.rst b/vendor/silex/silex/doc/cookbook/error_handler.rst
new file mode 100644
index 00000000..235c263a
--- /dev/null
+++ b/vendor/silex/silex/doc/cookbook/error_handler.rst
@@ -0,0 +1,38 @@
+Converting Errors to Exceptions
+===============================
+
+Silex catches exceptions that are thrown from within a request/response cycle.
+However, it does *not* catch PHP errors and notices. This recipe tells you how
+to catch them by converting them to exceptions.
+
+Registering the ErrorHandler
+----------------------------
+
+The ``Symfony/Debug`` package has an ``ErrorHandler`` class that solves this
+problem. It converts all errors to exceptions, and exceptions are then caught
+by Silex.
+
+Register it by calling the static ``register`` method::
+
+ use Symfony\Component\Debug\ErrorHandler;
+
+ ErrorHandler::register();
+
+It is recommended that you do this as early as possible.
+
+Handling fatal errors
+---------------------
+
+To handle fatal errors, you can additionally register a global
+``ExceptionHandler``::
+
+ use Symfony\Component\Debug\ExceptionHandler;
+
+ ExceptionHandler::register();
+
+In production you may want to disable the debug output by passing ``false`` as
+the ``$debug`` argument::
+
+ use Symfony\Component\Debug\ExceptionHandler;
+
+ ExceptionHandler::register(false);
diff --git a/vendor/silex/silex/doc/cookbook/form_no_csrf.rst b/vendor/silex/silex/doc/cookbook/form_no_csrf.rst
new file mode 100644
index 00000000..e9bf595e
--- /dev/null
+++ b/vendor/silex/silex/doc/cookbook/form_no_csrf.rst
@@ -0,0 +1,36 @@
+Disabling CSRF Protection on a Form using the FormExtension
+===========================================================
+
+The *FormExtension* provides a service for building form in your application
+with the Symfony Form component. When the :doc:`CSRF Service Provider
+` is registered, the *FormExtension* uses the CSRF Protection
+avoiding Cross-site request forgery, a method by which a malicious user
+attempts to make your legitimate users unknowingly submit data that they don't
+intend to submit.
+
+You can find more details about CSRF Protection and CSRF token in the
+`Symfony Book
+`_.
+
+In some cases (for example, when embedding a form in an html email) you might
+want not to use this protection. The easiest way to avoid this is to
+understand that it is possible to give specific options to your form builder
+through the ``createBuilder()`` function.
+
+Example
+-------
+
+.. code-block:: php
+
+ $form = $app['form.factory']->createBuilder('form', null, array('csrf_protection' => false));
+
+That's it, your form could be submitted from everywhere without CSRF Protection.
+
+Going further
+-------------
+
+This specific example showed how to change the ``csrf_protection`` in the
+``$options`` parameter of the ``createBuilder()`` function. More of them could
+be passed through this parameter, it is as simple as using the Symfony
+``getDefaultOptions()`` method in your form classes. `See more here
+`_.
diff --git a/vendor/silex/silex/doc/cookbook/guard_authentication.rst b/vendor/silex/silex/doc/cookbook/guard_authentication.rst
new file mode 100644
index 00000000..8774f686
--- /dev/null
+++ b/vendor/silex/silex/doc/cookbook/guard_authentication.rst
@@ -0,0 +1,183 @@
+How to Create a Custom Authentication System with Guard
+=======================================================
+
+Whether you need to build a traditional login form, an API token
+authentication system or you need to integrate with some proprietary
+single-sign-on system, the Guard component can make it easy... and fun!
+
+In this example, you'll build an API token authentication system and
+learn how to work with Guard.
+
+Step 1) Create the Authenticator Class
+--------------------------------------
+
+Suppose you have an API where your clients will send an X-AUTH-TOKEN
+header on each request. This token is composed of the username followed
+by a password, separated by a colon (e.g. ``X-AUTH-TOKEN: coolguy:awesomepassword``).
+Your job is to read this, find the associated user (if any) and check
+the password.
+
+To create a custom authentication system, just create a class and make
+it implement GuardAuthenticatorInterface. Or, extend the simpler
+AbstractGuardAuthenticator. This requires you to implement six methods:
+
+.. code-block:: php
+
+ encoderFactory = $encoderFactory;
+ }
+
+ public function getCredentials(Request $request)
+ {
+ // Checks if the credential header is provided
+ if (!$token = $request->headers->get('X-AUTH-TOKEN')) {
+ return;
+ }
+
+ // Parse the header or ignore it if the format is incorrect.
+ if (false === strpos($token, ':')) {
+ return;
+ }
+ list($username, $secret) = explode(':', $token, 2);
+
+ return array(
+ 'username' => $username,
+ 'secret' => $secret,
+ );
+ }
+
+ public function getUser($credentials, UserProviderInterface $userProvider)
+ {
+ return $userProvider->loadUserByUsername($credentials['username']);
+ }
+
+ public function checkCredentials($credentials, UserInterface $user)
+ {
+ // check credentials - e.g. make sure the password is valid
+ // return true to cause authentication success
+
+ $encoder = $this->encoderFactory->getEncoder($user);
+
+ return $encoder->isPasswordValid(
+ $user->getPassword(),
+ $credentials['secret'],
+ $user->getSalt()
+ );
+ }
+
+ public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
+ {
+ // on success, let the request continue
+ return;
+ }
+
+ public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
+ {
+ $data = array(
+ 'message' => strtr($exception->getMessageKey(), $exception->getMessageData()),
+
+ // or to translate this message
+ // $this->translator->trans($exception->getMessageKey(), $exception->getMessageData())
+ );
+
+ return new JsonResponse($data, 403);
+ }
+
+ /**
+ * Called when authentication is needed, but it's not sent
+ */
+ public function start(Request $request, AuthenticationException $authException = null)
+ {
+ $data = array(
+ // you might translate this message
+ 'message' => 'Authentication Required',
+ );
+
+ return new JsonResponse($data, 401);
+ }
+
+ public function supportsRememberMe()
+ {
+ return false;
+ }
+ }
+
+
+Step 2) Configure the Authenticator
+-----------------------------------
+
+To finish this, register the class as a service:
+
+.. code-block:: php
+
+ $app['app.token_authenticator'] = function ($app) {
+ return new App\Security\TokenAuthenticator($app['security.encoder_factory']);
+ };
+
+
+Finally, configure your `security.firewalls` key to use this authenticator:
+
+.. code-block:: php
+
+ $app['security.firewalls'] = array(
+ 'main' => array(
+ 'guard' => array(
+ 'authenticators' => array(
+ 'app.token_authenticator'
+ ),
+
+ // Using more than 1 authenticator, you must specify
+ // which one is used as entry point.
+ // 'entry_point' => 'app.token_authenticator',
+ ),
+ // configure where your users come from. Hardcode them, or load them from somewhere
+ // http://silex.sensiolabs.org/doc/providers/security.html#defining-a-custom-user-provider
+ 'users' => array(
+ //raw password = foo
+ 'victoria' => array('ROLE_USER', '$2y$10$3i9/lVd8UOFIJ6PAMFt8gu3/r5g0qeCJvoSlLCsvMTythye19F77a'),
+ ),
+ // 'anonymous' => true
+ ),
+ );
+
+.. note::
+ You can use many authenticators, they are executed by the order
+ they are configured.
+
+You did it! You now have a fully-working API token authentication
+system. If your homepage required ROLE_USER, then you could test it
+under different conditions:
+
+.. code-block:: bash
+
+ # test with no token
+ curl http://localhost:8000/
+ # {"message":"Authentication Required"}
+
+ # test with a bad token
+ curl -H "X-AUTH-TOKEN: alan" http://localhost:8000/
+ # {"message":"Username could not be found."}
+
+ # test with a working token
+ curl -H "X-AUTH-TOKEN: victoria:foo" http://localhost:8000/
+ # the homepage controller is executed: the page loads normally
+
+For more details read the Symfony cookbook entry on
+`How to Create a Custom Authentication System with Guard `_.
diff --git a/vendor/silex/silex/doc/cookbook/index.rst b/vendor/silex/silex/doc/cookbook/index.rst
new file mode 100644
index 00000000..53b10fe2
--- /dev/null
+++ b/vendor/silex/silex/doc/cookbook/index.rst
@@ -0,0 +1,40 @@
+Cookbook
+========
+
+The cookbook section contains recipes for solving specific problems.
+
+.. toctree::
+ :maxdepth: 1
+ :hidden:
+
+ json_request_body
+ session_storage
+ form_no_csrf
+ validator_yaml
+ sub_requests
+ error_handler
+ multiple_loggers
+ guard_authentication
+
+Recipes
+-------
+
+* :doc:`Accepting a JSON Request Body ` A common need when
+ building a restful API is the ability to accept a JSON encoded entity from
+ the request body.
+
+* :doc:`Using PdoSessionStorage to store Sessions in the Database
+ `.
+
+* :doc:`Disabling the CSRF Protection on a Form using the FormExtension
+ `.
+
+* :doc:`Using YAML to configure Validation `.
+
+* :doc:`Making sub-Requests `.
+
+* :doc:`Converting Errors to Exceptions `.
+
+* :doc:`Using multiple Monolog Loggers `.
+
+* :doc:`How to Create a Custom Authentication System with Guard `.
diff --git a/vendor/silex/silex/doc/cookbook/json_request_body.rst b/vendor/silex/silex/doc/cookbook/json_request_body.rst
new file mode 100644
index 00000000..47159008
--- /dev/null
+++ b/vendor/silex/silex/doc/cookbook/json_request_body.rst
@@ -0,0 +1,95 @@
+Accepting a JSON Request Body
+=============================
+
+A common need when building a restful API is the ability to accept a JSON
+encoded entity from the request body.
+
+An example for such an API could be a blog post creation.
+
+Example API
+-----------
+
+In this example we will create an API for creating a blog post. The following
+is a spec of how we want it to work.
+
+Request
+~~~~~~~
+
+In the request we send the data for the blog post as a JSON object. We also
+indicate that using the ``Content-Type`` header:
+
+.. code-block:: text
+
+ POST /blog/posts
+ Accept: application/json
+ Content-Type: application/json
+ Content-Length: 57
+
+ {"title":"Hello World!","body":"This is my first post!"}
+
+Response
+~~~~~~~~
+
+The server responds with a 201 status code, telling us that the post was
+created. It tells us the ``Content-Type`` of the response, which is also
+JSON:
+
+.. code-block:: text
+
+ HTTP/1.1 201 Created
+ Content-Type: application/json
+ Content-Length: 65
+ Connection: close
+
+ {"id":"1","title":"Hello World!","body":"This is my first post!"}
+
+Parsing the request body
+------------------------
+
+The request body should only be parsed as JSON if the ``Content-Type`` header
+begins with ``application/json``. Since we want to do this for every request,
+the easiest solution is to use an application before middleware.
+
+We simply use ``json_decode`` to parse the content of the request and then
+replace the request data on the ``$request`` object::
+
+ use Symfony\Component\HttpFoundation\Request;
+ use Symfony\Component\HttpFoundation\ParameterBag;
+
+ $app->before(function (Request $request) {
+ if (0 === strpos($request->headers->get('Content-Type'), 'application/json')) {
+ $data = json_decode($request->getContent(), true);
+ $request->request->replace(is_array($data) ? $data : array());
+ }
+ });
+
+Controller implementation
+-------------------------
+
+Our controller will create a new blog post from the data provided and will
+return the post object, including its ``id``, as JSON::
+
+ use Symfony\Component\HttpFoundation\Request;
+ use Symfony\Component\HttpFoundation\Response;
+
+ $app->post('/blog/posts', function (Request $request) use ($app) {
+ $post = array(
+ 'title' => $request->request->get('title'),
+ 'body' => $request->request->get('body'),
+ );
+
+ $post['id'] = createPost($post);
+
+ return $app->json($post, 201);
+ });
+
+Manual testing
+--------------
+
+In order to manually test our API, we can use the ``curl`` command line
+utility, which allows sending HTTP requests:
+
+.. code-block:: bash
+
+ $ curl http://blog.lo/blog/posts -d '{"title":"Hello World!","body":"This is my first post!"}' -H 'Content-Type: application/json'
+ {"id":"1","title":"Hello World!","body":"This is my first post!"}
diff --git a/vendor/silex/silex/doc/cookbook/multiple_loggers.rst b/vendor/silex/silex/doc/cookbook/multiple_loggers.rst
new file mode 100644
index 00000000..cb103953
--- /dev/null
+++ b/vendor/silex/silex/doc/cookbook/multiple_loggers.rst
@@ -0,0 +1,69 @@
+Using multiple Monolog Loggers
+==============================
+
+Having separate instances of Monolog for different parts of your system is
+often desirable and allows you to configure them independently, allowing for fine
+grained control of where your logging goes and in what detail.
+
+This simple example allows you to quickly configure several monolog instances,
+using the bundled handler, but each with a different channel.
+
+.. code-block:: php
+
+ $app['monolog.factory'] = $app->protect(function ($name) use ($app) {
+ $log = new $app['monolog.logger.class']($name);
+ $log->pushHandler($app['monolog.handler']);
+
+ return $log;
+ });
+
+ foreach (array('auth', 'payments', 'stats') as $channel) {
+ $app['monolog.'.$channel] = function ($app) use ($channel) {
+ return $app['monolog.factory']($channel);
+ };
+ }
+
+As your application grows, or your logging needs for certain areas of the
+system become apparent, it should be straightforward to then configure that
+particular service separately, including your customizations.
+
+.. code-block:: php
+
+ use Monolog\Handler\StreamHandler;
+
+ $app['monolog.payments'] = function ($app) {
+ $log = new $app['monolog.logger.class']('payments');
+ $handler = new StreamHandler($app['monolog.payments.logfile'], $app['monolog.payment.level']);
+ $log->pushHandler($handler);
+
+ return $log;
+ };
+
+Alternatively, you could attempt to make the factory more complicated, and rely
+on some conventions, such as checking for an array of handlers registered with
+the container with the channel name, defaulting to the bundled handler.
+
+.. code-block:: php
+
+ use Monolog\Handler\StreamHandler;
+ use Monolog\Logger;
+
+ $app['monolog.factory'] = $app->protect(function ($name) use ($app) {
+ $log = new $app['monolog.logger.class']($name);
+
+ $handlers = isset($app['monolog.'.$name.'.handlers'])
+ ? $app['monolog.'.$name.'.handlers']
+ : array($app['monolog.handler']);
+
+ foreach ($handlers as $handler) {
+ $log->pushHandler($handler);
+ }
+
+ return $log;
+ });
+
+ $app['monolog.payments.handlers'] = function ($app) {
+ return array(
+ new StreamHandler(__DIR__.'/../payments.log', Logger::DEBUG),
+ );
+ };
diff --git a/vendor/silex/silex/doc/cookbook/session_storage.rst b/vendor/silex/silex/doc/cookbook/session_storage.rst
new file mode 100644
index 00000000..29328b49
--- /dev/null
+++ b/vendor/silex/silex/doc/cookbook/session_storage.rst
@@ -0,0 +1,89 @@
+Using PdoSessionStorage to store Sessions in the Database
+=========================================================
+
+By default, the :doc:`SessionServiceProvider ` writes
+session information in files using Symfony NativeFileSessionStorage. Most
+medium to large websites use a database to store sessions instead of files,
+because databases are easier to use and scale in a multi-webserver environment.
+
+Symfony's `NativeSessionStorage
+`_
+has multiple storage handlers and one of them uses PDO to store sessions,
+`PdoSessionHandler
+`_.
+To use it, replace the ``session.storage.handler`` service in your application
+like explained below.
+
+With a dedicated PDO service
+----------------------------
+
+.. code-block:: php
+
+ use Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler;
+
+ $app->register(new Silex\Provider\SessionServiceProvider());
+
+ $app['pdo.dsn'] = 'mysql:dbname=mydatabase';
+ $app['pdo.user'] = 'myuser';
+ $app['pdo.password'] = 'mypassword';
+
+ $app['session.db_options'] = array(
+ 'db_table' => 'session',
+ 'db_id_col' => 'session_id',
+ 'db_data_col' => 'session_value',
+ 'db_time_col' => 'session_time',
+ );
+
+ $app['pdo'] = function () use ($app) {
+ return new PDO(
+ $app['pdo.dsn'],
+ $app['pdo.user'],
+ $app['pdo.password']
+ );
+ };
+
+ $app['session.storage.handler'] = function () use ($app) {
+ return new PdoSessionHandler(
+ $app['pdo'],
+ $app['session.db_options']
+ );
+ };
+
+Using the DoctrineServiceProvider
+---------------------------------
+
+When using the :doc:`DoctrineServiceProvider ` You don't
+have to make another database connection, simply pass the getWrappedConnection method.
+
+.. code-block:: php
+
+ use Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler;
+
+ $app->register(new Silex\Provider\SessionServiceProvider());
+
+ $app['session.storage.handler'] = function () use ($app) {
+ return new PdoSessionHandler(
+ $app['db']->getWrappedConnection(),
+ array(
+ 'db_table' => 'session',
+ 'db_id_col' => 'session_id',
+ 'db_data_col' => 'session_value',
+ 'db_lifetime_col' => 'session_lifetime',
+ 'db_time_col' => 'session_time',
+ )
+ );
+ };
+
+Database structure
+------------------
+
+PdoSessionStorage needs a database table with 3 columns:
+
+* ``session_id``: ID column (VARCHAR(255) or larger)
+* ``session_value``: Value column (TEXT or CLOB)
+* ``session_lifetime``: Lifetime column (INTEGER)
+* ``session_time``: Time column (INTEGER)
+
+You can find examples of SQL statements to create the session table in the
+`Symfony cookbook
+`_
diff --git a/vendor/silex/silex/doc/cookbook/sub_requests.rst b/vendor/silex/silex/doc/cookbook/sub_requests.rst
new file mode 100644
index 00000000..95d39136
--- /dev/null
+++ b/vendor/silex/silex/doc/cookbook/sub_requests.rst
@@ -0,0 +1,137 @@
+Making sub-Requests
+===================
+
+Since Silex is based on the ``HttpKernelInterface``, it allows you to simulate
+requests against your application. This means that you can embed a page within
+another, it also allows you to forward a request which is essentially an
+internal redirect that does not change the URL.
+
+Basics
+------
+
+You can make a sub-request by calling the ``handle`` method on the
+``Application``. This method takes three arguments:
+
+* ``$request``: An instance of the ``Request`` class which represents the
+ HTTP request.
+
+* ``$type``: Must be either ``HttpKernelInterface::MASTER_REQUEST`` or
+ ``HttpKernelInterface::SUB_REQUEST``. Certain listeners are only executed for
+ the master request, so it's important that this is set to ``SUB_REQUEST``.
+
+* ``$catch``: Catches exceptions and turns them into a response with status code
+ ``500``. This argument defaults to ``true``. For sub-requests you will most
+ likely want to set it to ``false``.
+
+By calling ``handle``, you can make a sub-request manually. Here's an example::
+
+ use Symfony\Component\HttpFoundation\Request;
+ use Symfony\Component\HttpKernel\HttpKernelInterface;
+
+ $subRequest = Request::create('/');
+ $response = $app->handle($subRequest, HttpKernelInterface::SUB_REQUEST, false);
+
+There's some more things that you need to keep in mind though. In most cases
+you will want to forward some parts of the current master request to the
+sub-request like cookies, server information, or the session.
+
+Here is a more advanced example that forwards said information (``$request``
+holds the master request)::
+
+ use Symfony\Component\HttpFoundation\Request;
+ use Symfony\Component\HttpKernel\HttpKernelInterface;
+
+ $subRequest = Request::create('/', 'GET', array(), $request->cookies->all(), array(), $request->server->all());
+ if ($request->getSession()) {
+ $subRequest->setSession($request->getSession());
+ }
+
+ $response = $app->handle($subRequest, HttpKernelInterface::SUB_REQUEST, false);
+
+To forward this response to the client, you can simply return it from a
+controller::
+
+ use Silex\Application;
+ use Symfony\Component\HttpFoundation\Request;
+ use Symfony\Component\HttpKernel\HttpKernelInterface;
+
+ $app->get('/foo', function (Application $app, Request $request) {
+ $subRequest = Request::create('/', ...);
+ $response = $app->handle($subRequest, HttpKernelInterface::SUB_REQUEST, false);
+
+ return $response;
+ });
+
+If you want to embed the response as part of a larger page you can call
+``Response::getContent``::
+
+ $header = ...;
+ $footer = ...;
+ $body = $response->getContent();
+
+ return $header.$body.$footer;
+
+Rendering pages in Twig templates
+---------------------------------
+
+The :doc:`TwigServiceProvider ` provides a ``render``
+function that you can use in Twig templates. It gives you a convenient way to
+embed pages.
+
+.. code-block:: jinja
+
+ {{ render('/sidebar') }}
+
+For details, refer to the :doc:`TwigServiceProvider ` docs.
+
+Edge Side Includes
+------------------
+
+You can use ESI either through the :doc:`HttpCacheServiceProvider
+` or a reverse proxy cache such as Varnish. This also
+allows you to embed pages, however it also gives you the benefit of caching
+parts of the page.
+
+Here is an example of how you would embed a page via ESI:
+
+.. code-block:: jinja
+
+
+
+For details, refer to the :doc:`HttpCacheServiceProvider
+` docs.
+
+Dealing with the request base URL
+---------------------------------
+
+One thing to watch out for is the base URL. If your application is not
+hosted at the webroot of your web server, then you may have an URL like
+``http://example.org/foo/index.php/articles/42``.
+
+In this case, ``/foo/index.php`` is your request base path. Silex accounts for
+this path prefix in the routing process, it reads it from
+``$request->server``. In the context of sub-requests this can lead to issues,
+because if you do not prepend the base path the request could mistake a part
+of the path you want to match as the base path and cut it off.
+
+You can prevent that from happening by always prepending the base path when
+constructing a request::
+
+ $url = $request->getUriForPath('/');
+ $subRequest = Request::create($url, 'GET', array(), $request->cookies->all(), array(), $request->server->all());
+
+This is something to be aware of when making sub-requests by hand.
+
+Services depending on the Request
+---------------------------------
+
+The container is a concept that is global to a Silex application, since the
+application object **is** the container. Any request that is run against an
+application will re-use the same set of services. Since these services are
+mutable, code in a master request can affect the sub-requests and vice versa.
+Any services depending on the ``request`` service will store the first request
+that they get (could be master or sub-request), and keep using it, even if
+that request is already over.
+
+Instead of injecting the ``request`` service, you should always inject the
+``request_stack`` one instead.
diff --git a/vendor/silex/silex/doc/cookbook/validator_yaml.rst b/vendor/silex/silex/doc/cookbook/validator_yaml.rst
new file mode 100644
index 00000000..10a41fcf
--- /dev/null
+++ b/vendor/silex/silex/doc/cookbook/validator_yaml.rst
@@ -0,0 +1,35 @@
+Using YAML to configure Validation
+==================================
+
+Simplicity is at the heart of Silex so there is no out of the box solution to
+use YAML files for validation. But this doesn't mean that this is not
+possible. Let's see how to do it.
+
+First, you need to install the YAML Component:
+
+.. code-block:: bash
+
+ composer require symfony/yaml
+
+Next, you need to tell the Validation Service that you are not using
+``StaticMethodLoader`` to load your class metadata but a YAML file::
+
+ $app->register(new ValidatorServiceProvider());
+
+ $app['validator.mapping.class_metadata_factory'] = new Symfony\Component\Validator\Mapping\Factory\LazyLoadingMetadataFactory(
+ new Symfony\Component\Validator\Mapping\Loader\YamlFileLoader(__DIR__.'/validation.yml')
+ );
+
+Now, we can replace the usage of the static method and move all the validation
+rules to ``validation.yml``:
+
+.. code-block:: yaml
+
+ # validation.yml
+ Post:
+ properties:
+ title:
+ - NotNull: ~
+ - NotBlank: ~
+ body:
+ - Min: 100
diff --git a/vendor/silex/silex/doc/index.rst b/vendor/silex/silex/doc/index.rst
new file mode 100644
index 00000000..d1a851d0
--- /dev/null
+++ b/vendor/silex/silex/doc/index.rst
@@ -0,0 +1,19 @@
+The Book
+========
+
+.. toctree::
+ :maxdepth: 1
+
+ intro
+ usage
+ middlewares
+ organizing_controllers
+ services
+ providers
+ testing
+ cookbook/index
+ internals
+ contributing
+ providers/index
+ web_servers
+ changelog
diff --git a/vendor/silex/silex/doc/internals.rst b/vendor/silex/silex/doc/internals.rst
new file mode 100644
index 00000000..c7ffac8c
--- /dev/null
+++ b/vendor/silex/silex/doc/internals.rst
@@ -0,0 +1,84 @@
+Internals
+=========
+
+This chapter will tell you how Silex works internally.
+
+Silex
+-----
+
+Application
+~~~~~~~~~~~
+
+The application is the main interface to Silex. It implements Symfony's
+`HttpKernelInterface
+`_,
+so you can pass a `Request
+`_
+to the ``handle`` method and it will return a `Response
+`_.
+
+It extends the ``Pimple`` service container, allowing for flexibility on the
+outside as well as the inside. You could replace any service, and you are also
+able to read them.
+
+The application makes strong use of the `EventDispatcher
+`_ to hook into the Symfony `HttpKernel
+`_
+events. This allows fetching the ``Request``, converting string responses into
+``Response`` objects and handling Exceptions. We also use it to dispatch some
+custom events like before/after middlewares and errors.
+
+Controller
+~~~~~~~~~~
+
+The Symfony `Route
+`_ is
+actually quite powerful. Routes can be named, which allows for URL generation.
+They can also have requirements for the variable parts. In order to allow
+setting these through a nice interface, the ``match`` method (which is used by
+``get``, ``post``, etc.) returns an instance of the ``Controller``, which
+wraps a route.
+
+ControllerCollection
+~~~~~~~~~~~~~~~~~~~~
+
+One of the goals of exposing the `RouteCollection
+`_
+was to make it mutable, so providers could add stuff to it. The challenge here
+is the fact that routes know nothing about their name. The name only has
+meaning in context of the ``RouteCollection`` and cannot be changed.
+
+To solve this challenge we came up with a staging area for routes. The
+``ControllerCollection`` holds the controllers until ``flush`` is called, at
+which point the routes are added to the ``RouteCollection``. Also, the
+controllers are then frozen. This means that they can no longer be modified
+and will throw an Exception if you try to do so.
+
+Unfortunately no good way for flushing implicitly could be found, which is why
+flushing is now always explicit. The Application will flush, but if you want
+to read the ``ControllerCollection`` before the request takes place, you will
+have to call flush yourself.
+
+The ``Application`` provides a shortcut ``flush`` method for flushing the
+``ControllerCollection``.
+
+.. tip::
+
+ Instead of creating an instance of ``RouteCollection`` yourself, use the
+ ``$app['controllers_factory']`` factory instead.
+
+Symfony
+-------
+
+Following Symfony components are used by Silex:
+
+* **HttpFoundation**: For ``Request`` and ``Response``.
+
+* **HttpKernel**: Because we need a heart.
+
+* **Routing**: For matching defined routes.
+
+* **EventDispatcher**: For hooking into the HttpKernel.
+
+For more information, `check out the Symfony website `_.
diff --git a/vendor/silex/silex/doc/intro.rst b/vendor/silex/silex/doc/intro.rst
new file mode 100644
index 00000000..2ab2bc30
--- /dev/null
+++ b/vendor/silex/silex/doc/intro.rst
@@ -0,0 +1,50 @@
+Introduction
+============
+
+Silex is a PHP microframework. It is built on the shoulders of `Symfony`_ and
+`Pimple`_ and also inspired by `Sinatra`_.
+
+Silex aims to be:
+
+* *Concise*: Silex exposes an intuitive and concise API.
+
+* *Extensible*: Silex has an extension system based around the Pimple
+ service-container that makes it easy to tie in third party libraries.
+
+* *Testable*: Silex uses Symfony's HttpKernel which abstracts request and
+ response. This makes it very easy to test apps and the framework itself. It
+ also respects the HTTP specification and encourages its proper use.
+
+In a nutshell, you define controllers and map them to routes, all in one step.
+
+Usage
+-----
+
+.. code-block:: php
+
+ get('/hello/{name}', function ($name) use ($app) {
+ return 'Hello '.$app->escape($name);
+ });
+
+ $app->run();
+
+All that is needed to get access to the Framework is to include the
+autoloader.
+
+Next, a route for ``/hello/{name}`` that matches for ``GET`` requests is
+defined. When the route matches, the function is executed and the return value
+is sent back to the client.
+
+Finally, the app is run. Visit ``/hello/world`` to see the result. It's really
+that easy!
+
+.. _Symfony: http://symfony.com/
+.. _Pimple: http://pimple.sensiolabs.org/
+.. _Sinatra: http://www.sinatrarb.com/
diff --git a/vendor/silex/silex/doc/middlewares.rst b/vendor/silex/silex/doc/middlewares.rst
new file mode 100644
index 00000000..c5c17cf0
--- /dev/null
+++ b/vendor/silex/silex/doc/middlewares.rst
@@ -0,0 +1,162 @@
+Middleware
+==========
+
+Silex allows you to run code, that changes the default Silex behavior, at
+different stages during the handling of a request through *middleware*:
+
+* *Application middleware* is triggered independently of the current handled
+ request;
+
+* *Route middleware* is triggered when its associated route is matched.
+
+Application Middleware
+----------------------
+
+Application middleware is only run for the "master" Request.
+
+Before Middleware
+~~~~~~~~~~~~~~~~~
+
+A *before* application middleware allows you to tweak the Request before the
+controller is executed::
+
+ $app->before(function (Request $request, Application $app) {
+ // ...
+ });
+
+By default, the middleware is run after the routing and the security.
+
+If you want your middleware to be run even if an exception is thrown early on
+(on a 404 or 403 error for instance), then, you need to register it as an
+early event::
+
+ $app->before(function (Request $request, Application $app) {
+ // ...
+ }, Application::EARLY_EVENT);
+
+In this case, the routing and the security won't have been executed, and so you
+won't have access to the locale, the current route, or the security user.
+
+.. note::
+
+ The before middleware is an event registered on the Symfony *request*
+ event.
+
+After Middleware
+~~~~~~~~~~~~~~~~
+
+An *after* application middleware allows you to tweak the Response before it
+is sent to the client::
+
+ $app->after(function (Request $request, Response $response) {
+ // ...
+ });
+
+.. note::
+
+ The after middleware is an event registered on the Symfony *response*
+ event.
+
+Finish Middleware
+~~~~~~~~~~~~~~~~~
+
+A *finish* application middleware allows you to execute tasks after the
+Response has been sent to the client (like sending emails or logging)::
+
+ $app->finish(function (Request $request, Response $response) {
+ // ...
+ // Warning: modifications to the Request or Response will be ignored
+ });
+
+.. note::
+
+ The finish middleware is an event registered on the Symfony *terminate*
+ event.
+
+Route Middleware
+----------------
+
+Route middleware is added to routes or route collections and it is only
+triggered when the corresponding route is matched. You can also stack them::
+
+ $app->get('/somewhere', function () {
+ // ...
+ })
+ ->before($before1)
+ ->before($before2)
+ ->after($after1)
+ ->after($after2)
+ ;
+
+Before Middleware
+~~~~~~~~~~~~~~~~~
+
+A *before* route middleware is fired just before the route callback, but after
+the *before* application middleware::
+
+ $before = function (Request $request, Application $app) {
+ // ...
+ };
+
+ $app->get('/somewhere', function () {
+ // ...
+ })
+ ->before($before);
+
+After Middleware
+~~~~~~~~~~~~~~~~
+
+An *after* route middleware is fired just after the route callback, but before
+the application *after* application middleware::
+
+ $after = function (Request $request, Response $response, Application $app) {
+ // ...
+ };
+
+ $app->get('/somewhere', function () {
+ // ...
+ })
+ ->after($after);
+
+Middleware Priority
+-------------------
+
+You can add as much middleware as you want, in which case they are triggered
+in the same order as you added them.
+
+You can explicitly control the priority of your middleware by passing an
+additional argument to the registration methods::
+
+ $app->before(function (Request $request) {
+ // ...
+ }, 32);
+
+As a convenience, two constants allow you to register an event as early as
+possible or as late as possible::
+
+ $app->before(function (Request $request) {
+ // ...
+ }, Application::EARLY_EVENT);
+
+ $app->before(function (Request $request) {
+ // ...
+ }, Application::LATE_EVENT);
+
+Short-circuiting the Controller
+-------------------------------
+
+If a *before* middleware returns a ``Response`` object, the request handling is
+short-circuited (the next middleware won't be run, nor the route
+callback), and the Response is passed to the *after* middleware right away::
+
+ $app->before(function (Request $request) {
+ // redirect the user to the login screen if access to the Resource is protected
+ if (...) {
+ return new RedirectResponse('/login');
+ }
+ });
+
+.. note::
+
+ A ``RuntimeException`` is thrown if a before middleware does not return a
+ Response or ``null``.
diff --git a/vendor/silex/silex/doc/organizing_controllers.rst b/vendor/silex/silex/doc/organizing_controllers.rst
new file mode 100644
index 00000000..50558cbb
--- /dev/null
+++ b/vendor/silex/silex/doc/organizing_controllers.rst
@@ -0,0 +1,84 @@
+Organizing Controllers
+======================
+
+When your application starts to define too many controllers, you might want to
+group them logically::
+
+ // define controllers for a blog
+ $blog = $app['controllers_factory'];
+ $blog->get('/', function () {
+ return 'Blog home page';
+ });
+ // ...
+
+ // define controllers for a forum
+ $forum = $app['controllers_factory'];
+ $forum->get('/', function () {
+ return 'Forum home page';
+ });
+
+ // define "global" controllers
+ $app->get('/', function () {
+ return 'Main home page';
+ });
+
+ $app->mount('/blog', $blog);
+ $app->mount('/forum', $forum);
+
+ // define controllers for a admin
+ $app->mount('/admin', function ($admin) {
+ // recursively mount
+ $admin->mount('/blog', function ($user) {
+ $user->get('/', function () {
+ return 'Admin Blog home page';
+ });
+ });
+ });
+
+.. note::
+
+ ``$app['controllers_factory']`` is a factory that returns a new instance
+ of ``ControllerCollection`` when used.
+
+``mount()`` prefixes all routes with the given prefix and merges them into the
+main Application. So, ``/`` will map to the main home page, ``/blog/`` to the
+blog home page, ``/forum/`` to the forum home page, and ``/admin/blog/`` to the
+admin blog home page.
+
+.. caution::
+
+ When mounting a route collection under ``/blog``, it is not possible to
+ define a route for the ``/blog`` URL. The shortest possible URL is
+ ``/blog/``.
+
+.. note::
+
+ When calling ``get()``, ``match()``, or any other HTTP methods on the
+ Application, you are in fact calling them on a default instance of
+ ``ControllerCollection`` (stored in ``$app['controllers']``).
+
+Another benefit is the ability to apply settings on a set of controllers very
+easily. Building on the example from the middleware section, here is how you
+would secure all controllers for the backend collection::
+
+ $backend = $app['controllers_factory'];
+
+ // ensure that all controllers require logged-in users
+ $backend->before($mustBeLogged);
+
+.. tip::
+
+ For a better readability, you can split each controller collection into a
+ separate file::
+
+ // blog.php
+ $blog = $app['controllers_factory'];
+ $blog->get('/', function () { return 'Blog home page'; });
+
+ return $blog;
+
+ // app.php
+ $app->mount('/blog', include 'blog.php');
+
+ Instead of requiring a file, you can also create a :ref:`Controller
+ provider `.
diff --git a/vendor/silex/silex/doc/providers.rst b/vendor/silex/silex/doc/providers.rst
new file mode 100644
index 00000000..c3d049db
--- /dev/null
+++ b/vendor/silex/silex/doc/providers.rst
@@ -0,0 +1,262 @@
+Providers
+=========
+
+Providers allow the developer to reuse parts of an application into another
+one. Silex provides two types of providers defined by two interfaces:
+``ServiceProviderInterface`` for services and ``ControllerProviderInterface``
+for controllers.
+
+Service Providers
+-----------------
+
+Loading providers
+~~~~~~~~~~~~~~~~~
+
+In order to load and use a service provider, you must register it on the
+application::
+
+ $app = new Silex\Application();
+
+ $app->register(new Acme\DatabaseServiceProvider());
+
+You can also provide some parameters as a second argument. These will be set
+**after** the provider is registered, but **before** it is booted::
+
+ $app->register(new Acme\DatabaseServiceProvider(), array(
+ 'database.dsn' => 'mysql:host=localhost;dbname=myapp',
+ 'database.user' => 'root',
+ 'database.password' => 'secret_root_password',
+ ));
+
+Conventions
+~~~~~~~~~~~
+
+You need to watch out in what order you do certain things when interacting
+with providers. Just keep these rules in mind:
+
+* Overriding existing services must occur **after** the provider is
+ registered.
+
+ *Reason: If the service already exists, the provider will overwrite it.*
+
+* You can set parameters any time **after** the provider is registered, but
+ **before** the service is accessed.
+
+ *Reason: Providers can set default values for parameters. Just like with
+ services, the provider will overwrite existing values.*
+
+Included providers
+~~~~~~~~~~~~~~~~~~
+
+There are a few providers that you get out of the box. All of these are within
+the ``Silex\Provider`` namespace:
+
+* :doc:`AssetServiceProvider `
+* :doc:`CsrfServiceProvider `
+* :doc:`DoctrineServiceProvider `
+* :doc:`FormServiceProvider `
+* :doc:`HttpCacheServiceProvider `
+* :doc:`HttpFragmentServiceProvider `
+* :doc:`LocaleServiceProvider `
+* :doc:`MonologServiceProvider `
+* :doc:`RememberMeServiceProvider `
+* :doc:`SecurityServiceProvider `
+* :doc:`SerializerServiceProvider `
+* :doc:`ServiceControllerServiceProvider `
+* :doc:`SessionServiceProvider `
+* :doc:`SwiftmailerServiceProvider `
+* :doc:`TranslationServiceProvider `
+* :doc:`TwigServiceProvider `
+* :doc:`ValidatorServiceProvider `
+* :doc:`VarDumperServiceProvider `
+
+.. note::
+
+ The Silex core team maintains a `WebProfiler
+ `_ provider that helps debug
+ code in the development environment thanks to the Symfony web debug toolbar
+ and the Symfony profiler.
+
+Third party providers
+~~~~~~~~~~~~~~~~~~~~~
+
+Some service providers are developed by the community. Those third-party
+providers are listed on `Silex' repository wiki
+`_.
+
+You are encouraged to share yours.
+
+Creating a provider
+~~~~~~~~~~~~~~~~~~~
+
+Providers must implement the ``Pimple\ServiceProviderInterface``::
+
+ interface ServiceProviderInterface
+ {
+ public function register(Container $container);
+ }
+
+This is very straight forward, just create a new class that implements the
+register method. In the ``register()`` method, you can define services on the
+application which then may make use of other services and parameters.
+
+.. tip::
+
+ The ``Pimple\ServiceProviderInterface`` belongs to the Pimple package, so
+ take care to only use the API of ``Pimple\Container`` within your
+ ``register`` method. Not only is this a good practice due to the way Pimple
+ and Silex work, but may allow your provider to be used outside of Silex.
+
+Optionally, your service provider can implement the
+``Silex\Api\BootableProviderInterface``. A bootable provider must
+implement the ``boot()`` method, with which you can configure the application, just
+before it handles a request::
+
+ interface BootableProviderInterface
+ {
+ function boot(Application $app);
+ }
+
+Another optional interface, is the ``Silex\Api\EventListenerProviderInterface``.
+This interface contains the ``subscribe()`` method, which allows your provider to
+subscribe event listener with Silex's EventDispatcher, just before it handles a
+request::
+
+ interface EventListenerProviderInterface
+ {
+ function subscribe(Container $app, EventDispatcherInterface $dispatcher);
+ }
+
+Here is an example of such a provider::
+
+ namespace Acme;
+
+ use Pimple\Container;
+ use Pimple\ServiceProviderInterface;
+ use Silex\Application;
+ use Silex\Api\BootableProviderInterface;
+ use Silex\Api\EventListenerProviderInterface;
+ use Symfony\Component\EventDispatcher\EventDispatcherInterface;
+ use Symfony\Component\HttpKernel\KernelEvents;
+ use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
+
+ class HelloServiceProvider implements ServiceProviderInterface, BootableProviderInterface, EventListenerProviderInterface
+ {
+ public function register(Container $app)
+ {
+ $app['hello'] = $app->protect(function ($name) use ($app) {
+ $default = $app['hello.default_name'] ? $app['hello.default_name'] : '';
+ $name = $name ?: $default;
+
+ return 'Hello '.$app->escape($name);
+ });
+ }
+
+ public function boot(Application $app)
+ {
+ // do something
+ }
+
+ public function subscribe(Container $app, EventDispatcherInterface $dispatcher)
+ {
+ $dispatcher->addListener(KernelEvents::REQUEST, function(FilterResponseEvent $event) use ($app) {
+ // do something
+ });
+ }
+ }
+
+This class provides a ``hello`` service which is a protected closure. It takes
+a ``name`` argument and will return ``hello.default_name`` if no name is
+given. If the default is also missing, it will use an empty string.
+
+You can now use this provider as follows::
+
+ use Symfony\Component\HttpFoundation\Request;
+
+ $app = new Silex\Application();
+
+ $app->register(new Acme\HelloServiceProvider(), array(
+ 'hello.default_name' => 'Igor',
+ ));
+
+ $app->get('/hello', function (Request $request) use ($app) {
+ $name = $request->get('name');
+
+ return $app['hello']($name);
+ });
+
+In this example we are getting the ``name`` parameter from the query string,
+so the request path would have to be ``/hello?name=Fabien``.
+
+.. _controller-providers:
+
+Controller Providers
+--------------------
+
+Loading providers
+~~~~~~~~~~~~~~~~~
+
+In order to load and use a controller provider, you must "mount" its
+controllers under a path::
+
+ $app = new Silex\Application();
+
+ $app->mount('/blog', new Acme\BlogControllerProvider());
+
+All controllers defined by the provider will now be available under the
+``/blog`` path.
+
+Creating a provider
+~~~~~~~~~~~~~~~~~~~
+
+Providers must implement the ``Silex\Api\ControllerProviderInterface``::
+
+ interface ControllerProviderInterface
+ {
+ public function connect(Application $app);
+ }
+
+Here is an example of such a provider::
+
+ namespace Acme;
+
+ use Silex\Application;
+ use Silex\Api\ControllerProviderInterface;
+
+ class HelloControllerProvider implements ControllerProviderInterface
+ {
+ public function connect(Application $app)
+ {
+ // creates a new controller based on the default route
+ $controllers = $app['controllers_factory'];
+
+ $controllers->get('/', function (Application $app) {
+ return $app->redirect('/hello');
+ });
+
+ return $controllers;
+ }
+ }
+
+The ``connect`` method must return an instance of ``ControllerCollection``.
+``ControllerCollection`` is the class where all controller related methods are
+defined (like ``get``, ``post``, ``match``, ...).
+
+.. tip::
+
+ The ``Application`` class acts in fact as a proxy for these methods.
+
+You can use this provider as follows::
+
+ $app = new Silex\Application();
+
+ $app->mount('/blog', new Acme\HelloControllerProvider());
+
+In this example, the ``/blog/`` path now references the controller defined in
+the provider.
+
+.. tip::
+
+ You can also define a provider that implements both the service and the
+ controller provider interface and package in the same class the services
+ needed to make your controllers work.
diff --git a/vendor/silex/silex/doc/providers/asset.rst b/vendor/silex/silex/doc/providers/asset.rst
new file mode 100644
index 00000000..72c3d703
--- /dev/null
+++ b/vendor/silex/silex/doc/providers/asset.rst
@@ -0,0 +1,67 @@
+Asset
+=====
+
+The *AssetServiceProvider* provides a way to manage URL generation and
+versioning of web assets such as CSS stylesheets, JavaScript files and image
+files.
+
+Parameters
+----------
+
+* **assets.version**: Default version for assets.
+
+* **assets.format_version** (optional): Default format for assets.
+
+* **assets.named_packages** (optional): Named packages. Keys are the package
+ names and values the configuration (supported keys are ``version``,
+ ``version_format``, ``base_urls``, and ``base_path``).
+
+Services
+--------
+
+* **assets.packages**: The asset service.
+
+Registering
+-----------
+
+.. code-block:: php
+
+ $app->register(new Silex\Provider\AssetServiceProvider(), array(
+ 'assets.version' => 'v1',
+ 'assets.version_format' => '%s?version=%s',
+ 'assets.named_packages' => array(
+ 'css' => array('version' => 'css2', 'base_path' => '/whatever-makes-sense'),
+ 'images' => array('base_urls' => array('https://img.example.com')),
+ ),
+ ));
+
+.. note::
+
+ Add the Symfony Asset Component as a dependency:
+
+ .. code-block:: bash
+
+ composer require symfony/asset
+
+ If you want to use assets in your Twig templates, you must also install the
+ Symfony Twig Bridge:
+
+ .. code-block:: bash
+
+ composer require symfony/twig-bridge
+
+Usage
+-----
+
+The AssetServiceProvider is mostly useful with the Twig provider:
+
+.. code-block:: jinja
+
+ {{ asset('/css/foo.png') }}
+ {{ asset('/css/foo.css', 'css') }}
+ {{ asset('/img/foo.png', 'images') }}
+
+ {{ asset_version('/css/foo.png') }}
+
+For more information, check out the `Asset Component documentation
+`_.
diff --git a/vendor/silex/silex/doc/providers/csrf.rst b/vendor/silex/silex/doc/providers/csrf.rst
new file mode 100644
index 00000000..a055c112
--- /dev/null
+++ b/vendor/silex/silex/doc/providers/csrf.rst
@@ -0,0 +1,53 @@
+CSRF
+====
+
+The *CsrfServiceProvider* provides a service for building forms in your
+application with the Symfony Form component.
+
+Parameters
+----------
+
+* none
+
+Services
+--------
+
+* **csrf.token_manager**: An instance of an implementation of the
+ `CsrfTokenManagerInterface
+ `_,
+
+Registering
+-----------
+
+.. code-block:: php
+
+ use Silex\Provider\CsrfServiceProvider;
+
+ $app->register(new CsrfServiceProvider());
+
+.. note::
+
+ Add the Symfony's `Security CSRF Component
+ `_ as a
+ dependency:
+
+ .. code-block:: bash
+
+ composer require symfony/security-csrf
+
+Usage
+-----
+
+When the CSRF Service Provider is registered, all forms created via the Form
+Service Provider are protected against CSRF by default.
+
+You can also use the CSRF protection without using the Symfony Form component.
+If, for example, you're doing a DELETE action, create a CSRF token to use in
+your code::
+
+ use Symfony\Component\Security\Csrf\CsrfToken;
+ $csrfToken = $app['csrf.token_manager']->getToken('token_id'); //'TOKEN'
+
+Then check it::
+
+ $app['csrf.token_manager']->isTokenValid(new CsrfToken('token_id', 'TOKEN'));
diff --git a/vendor/silex/silex/doc/providers/doctrine.rst b/vendor/silex/silex/doc/providers/doctrine.rst
new file mode 100644
index 00000000..0ef167b7
--- /dev/null
+++ b/vendor/silex/silex/doc/providers/doctrine.rst
@@ -0,0 +1,137 @@
+Doctrine
+========
+
+The *DoctrineServiceProvider* provides integration with the `Doctrine DBAL
+`_ for easy database access
+(Doctrine ORM integration is **not** supplied).
+
+Parameters
+----------
+
+* **db.options**: Array of Doctrine DBAL options.
+
+ These options are available:
+
+ * **driver**: The database driver to use, defaults to ``pdo_mysql``.
+ Can be any of: ``pdo_mysql``, ``pdo_sqlite``, ``pdo_pgsql``,
+ ``pdo_oci``, ``oci8``, ``ibm_db2``, ``pdo_ibm``, ``pdo_sqlsrv``.
+
+ * **dbname**: The name of the database to connect to.
+
+ * **host**: The host of the database to connect to. Defaults to
+ localhost.
+
+ * **user**: The user of the database to connect to. Defaults to
+ root.
+
+ * **password**: The password of the database to connect to.
+
+ * **charset**: Only relevant for ``pdo_mysql``, and ``pdo_oci/oci8``,
+ specifies the charset used when connecting to the database.
+
+ * **path**: Only relevant for ``pdo_sqlite``, specifies the path to
+ the SQLite database.
+
+ * **port**: Only relevant for ``pdo_mysql``, ``pdo_pgsql``, and ``pdo_oci/oci8``,
+ specifies the port of the database to connect to.
+
+ These and additional options are described in detail in the `Doctrine DBAL
+ configuration documentation `_.
+
+Services
+--------
+
+* **db**: The database connection, instance of
+ ``Doctrine\DBAL\Connection``.
+
+* **db.config**: Configuration object for Doctrine. Defaults to
+ an empty ``Doctrine\DBAL\Configuration``.
+
+* **db.event_manager**: Event Manager for Doctrine.
+
+Registering
+-----------
+
+.. code-block:: php
+
+ $app->register(new Silex\Provider\DoctrineServiceProvider(), array(
+ 'db.options' => array(
+ 'driver' => 'pdo_sqlite',
+ 'path' => __DIR__.'/app.db',
+ ),
+ ));
+
+.. note::
+
+ Add the Doctrine DBAL as a dependency:
+
+ .. code-block:: bash
+
+ composer require "doctrine/dbal:~2.2"
+
+Usage
+-----
+
+The Doctrine provider provides a ``db`` service. Here is a usage
+example::
+
+ $app->get('/blog/{id}', function ($id) use ($app) {
+ $sql = "SELECT * FROM posts WHERE id = ?";
+ $post = $app['db']->fetchAssoc($sql, array((int) $id));
+
+ return "{$post['title']}
".
+ "{$post['body']}
";
+ });
+
+Using multiple databases
+------------------------
+
+The Doctrine provider can allow access to multiple databases. In order to
+configure the data sources, replace the **db.options** with **dbs.options**.
+**dbs.options** is an array of configurations where keys are connection names
+and values are options::
+
+ $app->register(new Silex\Provider\DoctrineServiceProvider(), array(
+ 'dbs.options' => array (
+ 'mysql_read' => array(
+ 'driver' => 'pdo_mysql',
+ 'host' => 'mysql_read.someplace.tld',
+ 'dbname' => 'my_database',
+ 'user' => 'my_username',
+ 'password' => 'my_password',
+ 'charset' => 'utf8mb4',
+ ),
+ 'mysql_write' => array(
+ 'driver' => 'pdo_mysql',
+ 'host' => 'mysql_write.someplace.tld',
+ 'dbname' => 'my_database',
+ 'user' => 'my_username',
+ 'password' => 'my_password',
+ 'charset' => 'utf8mb4',
+ ),
+ ),
+ ));
+
+The first registered connection is the default and can simply be accessed as
+you would if there was only one connection. Given the above configuration,
+these two lines are equivalent::
+
+ $app['db']->fetchAll('SELECT * FROM table');
+
+ $app['dbs']['mysql_read']->fetchAll('SELECT * FROM table');
+
+Using multiple connections::
+
+ $app->get('/blog/{id}', function ($id) use ($app) {
+ $sql = "SELECT * FROM posts WHERE id = ?";
+ $post = $app['dbs']['mysql_read']->fetchAssoc($sql, array((int) $id));
+
+ $sql = "UPDATE posts SET value = ? WHERE id = ?";
+ $app['dbs']['mysql_write']->executeUpdate($sql, array('newValue', (int) $id));
+
+ return "{$post['title']}
".
+ "{$post['body']}
";
+ });
+
+For more information, consult the `Doctrine DBAL documentation
+`_.
diff --git a/vendor/silex/silex/doc/providers/form.rst b/vendor/silex/silex/doc/providers/form.rst
new file mode 100644
index 00000000..6818b858
--- /dev/null
+++ b/vendor/silex/silex/doc/providers/form.rst
@@ -0,0 +1,216 @@
+Form
+====
+
+The *FormServiceProvider* provides a service for building forms in
+your application with the Symfony Form component.
+
+Parameters
+----------
+
+* none
+
+Services
+--------
+
+* **form.factory**: An instance of `FormFactory
+ `_,
+ that is used to build a form.
+
+Registering
+-----------
+
+.. code-block:: php
+
+ use Silex\Provider\FormServiceProvider;
+
+ $app->register(new FormServiceProvider());
+
+.. note::
+
+ If you don't want to create your own form layout, it's fine: a default one
+ will be used. But you will have to register the :doc:`translation provider
+ ` as the default form layout requires it::
+
+ $app->register(new Silex\Provider\TranslationServiceProvider(), array(
+ 'translator.domains' => array(),
+ ));
+
+ If you want to use validation with forms, do not forget to register the
+ :doc:`Validator provider `.
+
+.. note::
+
+ Add the Symfony Form Component as a dependency:
+
+ .. code-block:: bash
+
+ composer require symfony/form
+
+ If you are going to use the validation extension with forms, you must also
+ add a dependency to the ``symfony/validator`` and ``symfony/config``
+ components:
+
+ .. code-block:: bash
+
+ composer require symfony/validator symfony/config
+
+ If you want to use forms in your Twig templates, you can also install the
+ Symfony Twig Bridge. Make sure to install, if you didn't do that already,
+ the Translation component in order for the bridge to work:
+
+ .. code-block:: bash
+
+ composer require symfony/twig-bridge
+
+Usage
+-----
+
+The FormServiceProvider provides a ``form.factory`` service. Here is a usage
+example::
+
+ use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
+ use Symfony\Component\Form\Extension\Core\Type\FormType;
+ use Symfony\Component\Form\Extension\Core\Type\SubmitType;
+
+ $app->match('/form', function (Request $request) use ($app) {
+ // some default data for when the form is displayed the first time
+ $data = array(
+ 'name' => 'Your name',
+ 'email' => 'Your email',
+ );
+
+ $form = $app['form.factory']->createBuilder(FormType::class, $data)
+ ->add('name')
+ ->add('email')
+ ->add('billing_plan', ChoiceType::class, array(
+ 'choices' => array('free' => 1, 'small business' => 2, 'corporate' => 3),
+ 'expanded' => true,
+ ))
+ ->add('submit', SubmitType::class, [
+ 'label' => 'Save',
+ ])
+ ->getForm();
+
+ $form->handleRequest($request);
+
+ if ($form->isValid()) {
+ $data = $form->getData();
+
+ // do something with the data
+
+ // redirect somewhere
+ return $app->redirect('...');
+ }
+
+ // display the form
+ return $app['twig']->render('index.twig', array('form' => $form->createView()));
+ });
+
+And here is the ``index.twig`` form template (requires ``symfony/twig-bridge``):
+
+.. code-block:: jinja
+
+
+
+If you are using the validator provider, you can also add validation to your
+form by adding constraints on the fields::
+
+ use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
+ use Symfony\Component\Form\Extension\Core\Type\FormType;
+ use Symfony\Component\Form\Extension\Core\Type\SubmitType;
+ use Symfony\Component\Form\Extension\Core\Type\TextType;
+ use Symfony\Component\Validator\Constraints as Assert;
+
+ $app->register(new Silex\Provider\ValidatorServiceProvider());
+ $app->register(new Silex\Provider\TranslationServiceProvider(), array(
+ 'translator.domains' => array(),
+ ));
+
+ $form = $app['form.factory']->createBuilder(FormType::class)
+ ->add('name', TextType::class, array(
+ 'constraints' => array(new Assert\NotBlank(), new Assert\Length(array('min' => 5)))
+ ))
+ ->add('email', TextType::class, array(
+ 'constraints' => new Assert\Email()
+ ))
+ ->add('billing_plan', ChoiceType::class, array(
+ 'choices' => array('free' => 1, 'small business' => 2, 'corporate' => 3),
+ 'expanded' => true,
+ 'constraints' => new Assert\Choice(array(1, 2, 3)),
+ ))
+ ->add('submit', SubmitType::class, [
+ 'label' => 'Save',
+ ])
+ ->getForm();
+
+You can register form types by extending ``form.types``::
+
+ $app['your.type.service'] = function ($app) {
+ return new YourServiceFormType();
+ };
+ $app->extend('form.types', function ($types) use ($app) {
+ $types[] = new YourFormType();
+ $types[] = 'your.type.service';
+
+ return $types;
+ }));
+
+You can register form extensions by extending ``form.extensions``::
+
+ $app->extend('form.extensions', function ($extensions) use ($app) {
+ $extensions[] = new YourTopFormExtension();
+
+ return $extensions;
+ });
+
+
+You can register form type extensions by extending ``form.type.extensions``::
+
+ $app['your.type.extension.service'] = function ($app) {
+ return new YourServiceFormTypeExtension();
+ };
+ $app->extend('form.type.extensions', function ($extensions) use ($app) {
+ $extensions[] = new YourFormTypeExtension();
+ $extensions[] = 'your.type.extension.service';
+
+ return $extensions;
+ });
+
+You can register form type guessers by extending ``form.type.guessers``::
+
+ $app['your.type.guesser.service'] = function ($app) {
+ return new YourServiceFormTypeGuesser();
+ };
+ $app->extend('form.type.guessers', function ($guessers) use ($app) {
+ $guessers[] = new YourFormTypeGuesser();
+ $guessers[] = 'your.type.guesser.service';
+
+ return $guessers;
+ });
+
+.. warning::
+
+ CSRF protection is only available and automatically enabled when the
+ :doc:`CSRF Service Provider ` is registered.
+
+Traits
+------
+
+``Silex\Application\FormTrait`` adds the following shortcuts:
+
+* **form**: Creates a FormBuilderInterface instance.
+
+* **namedForm**: Creates a FormBuilderInterface instance (named).
+
+.. code-block:: php
+
+ $app->form($data);
+
+ $app->namedForm($name, $data, $options, $type);
+
+For more information, consult the `Symfony Forms documentation
+`_.
diff --git a/vendor/silex/silex/doc/providers/http_cache.rst b/vendor/silex/silex/doc/providers/http_cache.rst
new file mode 100644
index 00000000..8bc98f67
--- /dev/null
+++ b/vendor/silex/silex/doc/providers/http_cache.rst
@@ -0,0 +1,128 @@
+HTTP Cache
+==========
+
+The *HttpCacheServiceProvider* provides support for the Symfony Reverse
+Proxy.
+
+Parameters
+----------
+
+* **http_cache.cache_dir**: The cache directory to store the HTTP cache data.
+
+* **http_cache.options** (optional): An array of options for the `HttpCache
+ `_
+ constructor.
+
+Services
+--------
+
+* **http_cache**: An instance of `HttpCache
+ `_.
+
+* **http_cache.esi**: An instance of `Esi
+ `_,
+ that implements the ESI capabilities to Request and Response instances.
+
+* **http_cache.store**: An instance of `Store
+ `_,
+ that implements all the logic for storing cache metadata (Request and Response
+ headers).
+
+Registering
+-----------
+
+.. code-block:: php
+
+ $app->register(new Silex\Provider\HttpCacheServiceProvider(), array(
+ 'http_cache.cache_dir' => __DIR__.'/cache/',
+ ));
+
+Usage
+-----
+
+Silex already supports any reverse proxy like Varnish out of the box by
+setting Response HTTP cache headers::
+
+ use Symfony\Component\HttpFoundation\Response;
+
+ $app->get('/', function() {
+ return new Response('Foo', 200, array(
+ 'Cache-Control' => 's-maxage=5',
+ ));
+ });
+
+.. tip::
+
+ If you want Silex to trust the ``X-Forwarded-For*`` headers from your
+ reverse proxy at address $ip, you will need to whitelist it as documented
+ in `Trusting Proxies
+ `_.
+
+ If you would be running Varnish in front of your application on the same machine::
+
+ use Symfony\Component\HttpFoundation\Request;
+
+ Request::setTrustedProxies(array('127.0.0.1', '::1'));
+ $app->run();
+
+This provider allows you to use the Symfony reverse proxy natively with
+Silex applications by using the ``http_cache`` service. The Symfony reverse proxy
+acts much like any other proxy would, so you will want to whitelist it::
+
+ use Symfony\Component\HttpFoundation\Request;
+
+ Request::setTrustedProxies(array('127.0.0.1'));
+ $app['http_cache']->run();
+
+The provider also provides ESI support::
+
+ $app->get('/', function() {
+ $response = new Response(<<
+
+ Hello
+
+
+