Commit eaa5429e authored by Fabien Potencier's avatar Fabien Potencier

Merge branch '1.3'

* 1.3: (44 commits)
  Add a isGranted() function to Silex\Application\SecurityTrait + unit tests
  Type hint against EventDispatcherInterface
  Update usage.rst
  Use PSR-4 for autoloading, works same as the PSR-0 configuration. Use autoload-dev for autoloading tests
  updated CHANGELOG
  Patch debug and caching translator (Symfony 2.6+ with caching enabled).
  Updated year in License
  Update testing.rst
  Add docblock for the $app field
  fixed CS
  Update intro.rst
  Correct exception message when mounting
  fixed compatibility with 2.7
  updated .travis.yml with only maintained Symfony versions
  Link to Monolog provider chapter
  Fix README doc about running unit tests
  add values to parameters copied from symfony docs
  Use the constant to refer to session auth strategy
  Revert "Merge branch '1.2' into 1.3"
  updated deps as Silex 1.2 is not compatible with Symfony 2.7
  ...

Conflicts:
	.travis.yml
	README.rst
	composer.json
	doc/changelog.rst
	doc/providers/security.rst
	doc/usage.rst
	src/Silex/Api/BootableProviderInterface.php
	src/Silex/Application.php
	src/Silex/Provider/FormServiceProvider.php
	src/Silex/Provider/HttpCacheServiceProvider.php
	src/Silex/Provider/SecurityServiceProvider.php
	src/Silex/Provider/Translation/Translator.php
	src/Silex/Provider/TranslationServiceProvider.php
	src/Silex/Provider/ValidatorServiceProvider.php
	tests/Silex/Tests/Provider/MonologServiceProviderTest.php
	tests/Silex/Tests/Provider/TwigServiceProviderTest.php
parents 0aa47527 1c954619
...@@ -2,6 +2,7 @@ language: php ...@@ -2,6 +2,7 @@ language: php
before_script: before_script:
# symfony/* # symfony/*
- sh -c "if [ '$SYMFONY_DEPS_VERSION' = '2.8' ]; then sed -i 's/~2.4/2.8.*@dev/g' composer.json; composer update --dev --prefer-source; fi"
- sh -c "if [ '$SYMFONY_DEPS_VERSION' = '2.7' ]; then sed -i 's/~2.4/2.7.*@dev/g' composer.json; composer update --dev --prefer-source; fi" - sh -c "if [ '$SYMFONY_DEPS_VERSION' = '2.7' ]; then sed -i 's/~2.4/2.7.*@dev/g' composer.json; composer update --dev --prefer-source; fi"
- sh -c "if [ '$SYMFONY_DEPS_VERSION' = '' ]; then sed -i 's/~2.4/2.6.*@dev/g' composer.json; composer update --dev --prefer-source; fi" - sh -c "if [ '$SYMFONY_DEPS_VERSION' = '' ]; then sed -i 's/~2.4/2.6.*@dev/g' composer.json; composer update --dev --prefer-source; fi"
- sh -c "if [ '$SYMFONY_DEPS_VERSION' = '2.5' ]; then sed -i 's/~2.4/2.5.*@dev/g' composer.json; composer update --dev --prefer-source; fi" - sh -c "if [ '$SYMFONY_DEPS_VERSION' = '2.5' ]; then sed -i 's/~2.4/2.5.*@dev/g' composer.json; composer update --dev --prefer-source; fi"
...@@ -27,3 +28,5 @@ matrix: ...@@ -27,3 +28,5 @@ matrix:
env: SYMFONY_DEPS_VERSION=2.5 env: SYMFONY_DEPS_VERSION=2.5
- php: 5.6 - php: 5.6
env: SYMFONY_DEPS_VERSION=2.7 env: SYMFONY_DEPS_VERSION=2.7
- php: 5.6
env: SYMFONY_DEPS_VERSION=2.8
Copyright (c) 2010-2014 Fabien Potencier Copyright (c) 2010-2015 Fabien Potencier
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
......
...@@ -27,7 +27,7 @@ The recommended way to install Silex is through `Composer`_: ...@@ -27,7 +27,7 @@ The recommended way to install Silex is through `Composer`_:
.. code-block:: bash .. code-block:: bash
php composer.phar require silex/silex "~2.0@dev" composer require silex/silex "~2.0@dev"
Alternatively, you can download the `silex.zip`_ file and extract it. Alternatively, you can download the `silex.zip`_ file and extract it.
...@@ -39,12 +39,12 @@ Read the `documentation`_ for more information. ...@@ -39,12 +39,12 @@ Read the `documentation`_ for more information.
Tests Tests
----- -----
To run the test suite, you need `Composer`_: To run the test suite, you need `Composer`_ and `PHPUnit`_:
.. code-block:: bash .. code-block:: bash
$ php composer.phar install --dev $ composer install
$ vendor/bin/phpunit $ phpunit
Community Community
--------- ---------
...@@ -58,5 +58,6 @@ Silex is licensed under the MIT license. ...@@ -58,5 +58,6 @@ Silex is licensed under the MIT license.
.. _Symfony2 components: http://symfony.com .. _Symfony2 components: http://symfony.com
.. _Composer: http://getcomposer.org .. _Composer: http://getcomposer.org
.. _PHPUnit: https://phpunit.de
.. _silex.zip: http://silex.sensiolabs.org/download .. _silex.zip: http://silex.sensiolabs.org/download
.. _documentation: http://silex.sensiolabs.org/documentation .. _documentation: http://silex.sensiolabs.org/documentation
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
} }
], ],
"require": { "require": {
"php": ">=5.3.3", "php": ">=5.3.9",
"pimple/pimple": "~3.0", "pimple/pimple": "~3.0",
"symfony/event-dispatcher": "~2.4", "symfony/event-dispatcher": "~2.4",
"symfony/http-foundation": "~2.4", "symfony/http-foundation": "~2.4",
...@@ -57,7 +57,10 @@ ...@@ -57,7 +57,10 @@
"silex/providers": "self.version" "silex/providers": "self.version"
}, },
"autoload": { "autoload": {
"psr-0": { "Silex": "src/" } "psr-4": { "Silex\\": "src/Silex" }
},
"autoload-dev" : {
"psr-4": { "Silex\\Tests\\" : "tests/Silex/Tests" }
}, },
"extra": { "extra": {
"branch-alias": { "branch-alias": {
......
...@@ -17,6 +17,22 @@ Changelog ...@@ -17,6 +17,22 @@ Changelog
* ``monolog.exception.logger_filter`` option added to Monolog service provider * ``monolog.exception.logger_filter`` option added to Monolog service provider
* [BC BREAK] ``$app['request']`` service removed, use ``$app['request_stack']`` instead * [BC BREAK] ``$app['request']`` service removed, use ``$app['request_stack']`` instead
1.3.0 (2015-XX-XX)
------------------
* 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 (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.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) 1.2.2 (2014-09-26)
------------------ ------------------
......
...@@ -23,6 +23,8 @@ Usage ...@@ -23,6 +23,8 @@ Usage
.. code-block:: php .. code-block:: php
<?php
// web/index.php // web/index.php
require_once __DIR__.'/../vendor/autoload.php'; require_once __DIR__.'/../vendor/autoload.php';
......
...@@ -19,11 +19,10 @@ Services ...@@ -19,11 +19,10 @@ Services
<http://api.symfony.com/master/Symfony/Component/Form/FormFactory.html>`_, <http://api.symfony.com/master/Symfony/Component/Form/FormFactory.html>`_,
that is used for build a form. that is used for build a form.
* **form.csrf_provider**: An instance of an implementation of the * **form.csrf_provider**: An instance of an implementation of
`CsrfProviderInterface `CsrfProviderInterface
<http://api.symfony.com/master/Symfony/Component/Form/Extension/Csrf/CsrfProvider/CsrfProviderInterface.html>`_, <http://api.symfony.com/2.3/Symfony/Component/Form/Extension/Csrf/CsrfProvider/CsrfProviderInterface.html>`_ for Symfony 2.3 or
defaults to a `DefaultCsrfProvider `CsrfTokenManagerInterface <http://api.symfony.com/2.7/Symfony/Component/Security/Csrf/CsrfTokenManagerInterface.html>`_ for Symfony 2.4+.
<http://api.symfony.com/master/Symfony/Component/Form/Extension/Csrf/CsrfProvider/DefaultCsrfProvider.html>`_.
Registering Registering
----------- -----------
...@@ -67,7 +66,8 @@ Registering ...@@ -67,7 +66,8 @@ Registering
composer require symfony/validator symfony/config symfony/translation composer require symfony/validator symfony/config symfony/translation
The Symfony Security CSRF component is used to protect forms against CSRF attacks: The Symfony Security CSRF component is used to protect forms against CSRF
attacks (as of Symfony 2.4+):
.. code-block:: bash .. code-block:: bash
......
...@@ -14,7 +14,12 @@ Services ...@@ -14,7 +14,12 @@ Services
-------- --------
* **security**: The main entry point for the security provider. Use it to get * **security**: The main entry point for the security provider. Use it to get
the current user token. the current user token (only for Symfony up to 2.5).
* **security.token_storage**: Gives access to the user token (Symfony 2.6+).
* **security.authorization_checker**: Allows to check authorizations for the
users (Symfony 2.6+).
* **security.authentication_manager**: An instance of * **security.authentication_manager**: An instance of
`AuthenticationProviderManager `AuthenticationProviderManager
...@@ -95,6 +100,10 @@ Accessing the current User ...@@ -95,6 +100,10 @@ Accessing the current User
The current user information is stored in a token that is accessible via the The current user information is stored in a token that is accessible via the
``security`` service:: ``security`` service::
// Symfony 2.6+
$token = $app['security.token_storage']->getToken();
// Symfony 2.3/2.5
$token = $app['security']->getToken(); $token = $app['security']->getToken();
If there is no information about the user, the token is ``null``. If the user If there is no information about the user, the token is ``null``. If the user
...@@ -327,6 +336,12 @@ Checking User Roles ...@@ -327,6 +336,12 @@ Checking User Roles
To check if a user is granted some role, use the ``isGranted()`` method on the To check if a user is granted some role, use the ``isGranted()`` method on the
security context:: security context::
// Symfony 2.6+
if ($app['security.authorization_checker']->isGranted('ROLE_ADMIN')) {
// ...
}
// Symfony 2.3/2.5
if ($app['security']->isGranted('ROLE_ADMIN')) { if ($app['security']->isGranted('ROLE_ADMIN')) {
// ... // ...
} }
...@@ -566,7 +581,8 @@ use in your configuration:: ...@@ -566,7 +581,8 @@ use in your configuration::
// define the authentication listener object // define the authentication listener object
$app['security.authentication_listener.'.$name.'.wsse'] = function () use ($app) { $app['security.authentication_listener.'.$name.'.wsse'] = function () use ($app) {
return new WsseListener($app['security'], $app['security.authentication_manager']); // use 'security' instead of 'security.token_storage' on Symfony <2.6
return new WsseListener($app['security.token_storage'], $app['security.authentication_manager']);
}; };
return array( return array(
......
...@@ -21,8 +21,8 @@ Parameters ...@@ -21,8 +21,8 @@ Parameters
* **port**: SMTP port, defaults to 25. * **port**: SMTP port, defaults to 25.
* **username**: SMTP username, defaults to an empty string. * **username**: SMTP username, defaults to an empty string.
* **password**: SMTP password, defaults to an empty string. * **password**: SMTP password, defaults to an empty string.
* **encryption**: SMTP encryption, defaults to null. * **encryption**: SMTP encryption, defaults to null. Valid values are 'tls', 'ssl', or null (indicating no encryption).
* **auth_mode**: SMTP authentication mode, defaults to null. * **auth_mode**: SMTP authentication mode, defaults to null. Valid values are 'plain', 'login', 'cram-md5', or null.
Example usage:: Example usage::
......
...@@ -14,7 +14,7 @@ Services ...@@ -14,7 +14,7 @@ Services
-------- --------
* **validator**: An instance of `Validator * **validator**: An instance of `Validator
<http://api.symfony.com/master/Symfony/Component/Validator/Validator.html>`_. <http://api.symfony.com/master/Symfony/Component/Validator/ValidatorInterface.html>`_.
* **validator.mapping.class_metadata_factory**: Factory for metadata loaders, * **validator.mapping.class_metadata_factory**: Factory for metadata loaders,
which can read validation constraint information from classes. Defaults to which can read validation constraint information from classes. Defaults to
......
...@@ -204,9 +204,9 @@ don't want to mess with most of them. ...@@ -204,9 +204,9 @@ don't want to mess with most of them.
the request that is used by the Router and the UrlGenerator. the request that is used by the Router and the UrlGenerator.
* **exception_handler**: The Exception handler is the default handler that is * **exception_handler**: The Exception handler is the default handler that is
used when you don't register one via the ``error()`` method or if your handler used when you don't register one via the ``error()`` method or if your
does not return a Response. Disable it with handler does not return a Response. Disable it with
``$app['exception_handler']->disable()``. ``unset($app['exception_handler'])``.
* **logger**: A ``Psr\Log\LoggerInterface`` instance. By default, logging is * **logger**: A ``Psr\Log\LoggerInterface`` instance. By default, logging is
disabled as the value is set to ``null``. To enable logging you can either use disabled as the value is set to ``null``. To enable logging you can either use
......
...@@ -71,11 +71,6 @@ use it by making your test extend it:: ...@@ -71,11 +71,6 @@ use it by making your test extend it::
... ...
} }
.. note::
To make your application testable, you need to make sure you follow "Reusing
applications" instructions from :doc:`usage`.
.. note:: .. note::
If you want to use the Symfony2 ``WebTestCase`` class you will need to If you want to use the Symfony2 ``WebTestCase`` class you will need to
...@@ -108,7 +103,7 @@ executed before every test. ...@@ -108,7 +103,7 @@ executed before every test.
{ {
$app = require __DIR__.'/path/to/app.php'; $app = require __DIR__.'/path/to/app.php';
$app['debug'] = true; $app['debug'] = true;
$app['exception_handler']->disable(); unset($app['exception_handler']);
return $app; return $app;
} }
......
...@@ -262,7 +262,7 @@ closure arguments match the names of the variable parts:: ...@@ -262,7 +262,7 @@ closure arguments match the names of the variable parts::
// ... // ...
}); });
While it's not recommend, you could also do this (note the switched While it's not recommended, you could also do this (note the switched
arguments):: arguments)::
$app->get('/blog/{postId}/{commentId}', function ($commentId, $postId) { $app->get('/blog/{postId}/{commentId}', function ($commentId, $postId) {
...@@ -284,8 +284,8 @@ You can also ask for the current Request and Application objects:: ...@@ -284,8 +284,8 @@ You can also ask for the current Request and Application objects::
// ... // ...
}); });
Route Variables Converters Route Variable Converters
~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~
Before injecting the route variables into the controller, you can apply some Before injecting the route variables into the controller, you can apply some
converters:: converters::
...@@ -322,7 +322,7 @@ The converter callback also receives the ``Request`` as its second argument:: ...@@ -322,7 +322,7 @@ The converter callback also receives the ``Request`` as its second argument::
A converter can also be defined as a service. For example, here is a user A converter can also be defined as a service. For example, here is a user
converter based on Doctrine ObjectManager:: converter based on Doctrine ObjectManager::
use Doctrine\Common\Persistence\ObjectManager use Doctrine\Common\Persistence\ObjectManager;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class UserConverter class UserConverter
...@@ -539,7 +539,7 @@ once a response is returned, the following handlers are ignored. ...@@ -539,7 +539,7 @@ once a response is returned, the following handlers are ignored.
.. note:: .. note::
Silex ships with a provider for Monolog_ which handles logging of errors. Silex ships with a provider for Monolog_ which handles logging of errors.
Check out the *Providers* chapter for details. Check out the *Providers* :doc:`chapter <providers/monolog>` for details.
.. tip:: .. tip::
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
processIsolation="false" processIsolation="false"
stopOnFailure="false" stopOnFailure="false"
syntaxCheck="false" syntaxCheck="false"
bootstrap="tests/bootstrap.php" bootstrap="vendor/autoload.php"
> >
<testsuites> <testsuites>
<testsuite name="Silex Test Suite"> <testsuite name="Silex Test Suite">
......
...@@ -13,6 +13,7 @@ namespace Silex; ...@@ -13,6 +13,7 @@ namespace Silex;
use Pimple\Container; use Pimple\Container;
use Pimple\ServiceProviderInterface; use Pimple\ServiceProviderInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\BinaryFileResponse; use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpKernel\HttpKernel; use Symfony\Component\HttpKernel\HttpKernel;
use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\HttpKernelInterface;
...@@ -84,7 +85,6 @@ class Application extends Container implements HttpKernelInterface, TerminableIn ...@@ -84,7 +85,6 @@ class Application extends Container implements HttpKernelInterface, TerminableIn
return new ExceptionHandler($app['debug']); return new ExceptionHandler($app['debug']);
}; };
$this['callback_resolver'] = function () use ($app) { $this['callback_resolver'] = function () use ($app) {
return new CallbackResolver($app); return new CallbackResolver($app);
}; };
...@@ -253,7 +253,7 @@ class Application extends Container implements HttpKernelInterface, TerminableIn ...@@ -253,7 +253,7 @@ class Application extends Container implements HttpKernelInterface, TerminableIn
return; return;
} }
$this->extend('dispatcher', function ($dispatcher, $app) use ($callback, $priority, $eventName) { $this->extend('dispatcher', function (EventDispatcherInterface $dispatcher, $app) use ($callback, $priority, $eventName) {
$dispatcher->addListener($eventName, $app['callback_resolver']->resolveCallback($callback), $priority); $dispatcher->addListener($eventName, $app['callback_resolver']->resolveCallback($callback), $priority);
return $dispatcher; return $dispatcher;
...@@ -304,7 +304,12 @@ class Application extends Container implements HttpKernelInterface, TerminableIn ...@@ -304,7 +304,12 @@ class Application extends Container implements HttpKernelInterface, TerminableIn
return; return;
} }
call_user_func($app['callback_resolver']->resolveCallback($callback), $event->getRequest(), $event->getResponse(), $app); $response = call_user_func($app['callback_resolver']->resolveCallback($callback), $event->getRequest(), $event->getResponse(), $app);
if ($response instanceof Response) {
$event->setResponse($response);
} elseif (null !== $response) {
throw new \RuntimeException('An after middleware returned an invalid response value. Must return null or an instance of Response.');
}
}, $priority); }, $priority);
} }
...@@ -454,15 +459,15 @@ class Application extends Container implements HttpKernelInterface, TerminableIn ...@@ -454,15 +459,15 @@ class Application extends Container implements HttpKernelInterface, TerminableIn
public function mount($prefix, $controllers) public function mount($prefix, $controllers)
{ {
if ($controllers instanceof ControllerProviderInterface) { if ($controllers instanceof ControllerProviderInterface) {
$controllers = $controllers->connect($this); $connectedControllers = $controllers->connect($this);
if (!$controllers instanceof ControllerCollection) { if (!$connectedControllers instanceof ControllerCollection) {
throw new \LogicException('The "connect" method of the ControllerProviderInterface must return a ControllerCollection.'); throw new \LogicException(sprintf('The method "%s::connect" must return a "ControllerCollection" instance. Got: "%s"', get_class($controllers), is_object($connectedControllers) ? get_class($connectedControllers) : gettype($connectedControllers)));
}
} }
if (!$controllers instanceof ControllerCollection) { $controllers = $connectedControllers;
throw new \LogicException('The "mount" method takes either a ControllerCollection or a ControllerProviderInterface instance.'); } elseif (!$controllers instanceof ControllerCollection) {
throw new \LogicException('The "mount" method takes either a "ControllerCollection" or a "ControllerProviderInterface" instance.');
} }
$this['controllers']->mount($prefix, $controllers); $this['controllers']->mount($prefix, $controllers);
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
namespace Silex\Application; namespace Silex\Application;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException;
use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\User\UserInterface;
/** /**
...@@ -30,7 +31,7 @@ trait SecurityTrait ...@@ -30,7 +31,7 @@ trait SecurityTrait
*/ */
public function user() public function user()
{ {
if (null === $token = $this['security']->getToken()) { if (null === $token = $this['security.token_storage']->getToken()) {
return; return;
} }
...@@ -55,4 +56,19 @@ trait SecurityTrait ...@@ -55,4 +56,19 @@ trait SecurityTrait
{ {
return $this['security.encoder_factory']->getEncoder($user)->encodePassword($password, $user->getSalt()); return $this['security.encoder_factory']->getEncoder($user)->encodePassword($password, $user->getSalt());
} }
/**
* Checks if the attributes are granted against the current authentication token and optionally supplied object.
*
* @param mixed $attributes
* @param mixed $object
*
* @return bool
*
* @throws AuthenticationCredentialsNotFoundException when the token storage has no authentication token.
*/
public function isGranted($attributes, $object = null)
{
return $this['security.authorization_checker']->isGranted($attributes, $object);
}
} }
...@@ -19,14 +19,14 @@ use Silex\Exception\ControllerFrozenException; ...@@ -19,14 +19,14 @@ use Silex\Exception\ControllerFrozenException;
* __call() forwards method-calls to Route, but returns instance of Controller * __call() forwards method-calls to Route, but returns instance of Controller
* listing Route's methods below, so that IDEs know they are valid * listing Route's methods below, so that IDEs know they are valid
* *
* @method \Silex\Controller assert(string $variable, string $regexp) * @method Controller assert(string $variable, string $regexp)
* @method \Silex\Controller value(string $variable, mixed $default) * @method Controller value(string $variable, mixed $default)
* @method \Silex\Controller convert(string $variable, mixed $callback) * @method Controller convert(string $variable, mixed $callback)
* @method \Silex\Controller method(string $method) * @method Controller method(string $method)
* @method \Silex\Controller requireHttp() * @method Controller requireHttp()
* @method \Silex\Controller requireHttps() * @method Controller requireHttps()
* @method \Silex\Controller before(mixed $callback) * @method Controller before(mixed $callback)
* @method \Silex\Controller after(mixed $callback) * @method Controller after(mixed $callback)
* @author Igor Wiedler <igor@wiedler.ch> * @author Igor Wiedler <igor@wiedler.ch>
*/ */
class Controller class Controller
...@@ -106,10 +106,9 @@ class Controller ...@@ -106,10 +106,9 @@ class Controller
public function generateRouteName($prefix) public function generateRouteName($prefix)
{ {
$requirements = $this->route->getRequirements(); $methods = implode('_', $this->route->getMethods());
$method = isset($requirements['_method']) ? $requirements['_method'] : '';
$routeName = $prefix.$method.$this->route->getPath(); $routeName = $prefix.$methods.$this->route->getPath();
$routeName = str_replace(array('/', ':', '|', '-'), '_', $routeName); $routeName = str_replace(array('/', ':', '|', '-'), '_', $routeName);
$routeName = preg_replace('/[^a-z0-9A-Z_.]+/', '', $routeName); $routeName = preg_replace('/[^a-z0-9A-Z_.]+/', '', $routeName);
......
...@@ -24,14 +24,14 @@ use Symfony\Component\HttpFoundation\Request; ...@@ -24,14 +24,14 @@ use Symfony\Component\HttpFoundation\Request;
* __call() forwards method-calls to Route, but returns instance of ControllerCollection * __call() forwards method-calls to Route, but returns instance of ControllerCollection
* listing Route's methods below, so that IDEs know they are valid * listing Route's methods below, so that IDEs know they are valid
* *
* @method \Silex\ControllerCollection assert(string $variable, string $regexp) * @method ControllerCollection assert(string $variable, string $regexp)
* @method \Silex\ControllerCollection value(string $variable, mixed $default) * @method ControllerCollection value(string $variable, mixed $default)
* @method \Silex\ControllerCollection convert(string $variable, mixed $callback) * @method ControllerCollection convert(string $variable, mixed $callback)
* @method \Silex\ControllerCollection method(string $method) * @method ControllerCollection method(string $method)
* @method \Silex\ControllerCollection requireHttp() * @method ControllerCollection requireHttp()
* @method \Silex\ControllerCollection requireHttps() * @method ControllerCollection requireHttps()
* @method \Silex\ControllerCollection before(mixed $callback) * @method ControllerCollection before(mixed $callback)
* @method \Silex\ControllerCollection after(mixed $callback) * @method ControllerCollection after(mixed $callback)
* *
* @author Igor Wiedler <igor@wiedler.ch> * @author Igor Wiedler <igor@wiedler.ch>
* @author Fabien Potencier <fabien@symfony.com> * @author Fabien Potencier <fabien@symfony.com>
......
...@@ -32,6 +32,9 @@ class ExceptionHandler implements EventSubscriberInterface ...@@ -32,6 +32,9 @@ class ExceptionHandler implements EventSubscriberInterface
$this->enabled = true; $this->enabled = true;
} }
/**
* @deprecated since 1.3, to be removed in 2.0
*/
public function disable() public function disable()
{ {
$this->enabled = false; $this->enabled = false;
......
...@@ -33,7 +33,6 @@ class DoctrineServiceProvider implements ServiceProviderInterface ...@@ -33,7 +33,6 @@ class DoctrineServiceProvider implements ServiceProviderInterface
'host' => 'localhost', 'host' => 'localhost',
'user' => 'root', 'user' => 'root',
'password' => null, 'password' => null,
'port' => 3306,
); );
$app['dbs.options.initializer'] = $app->protect(function () use ($app) { $app['dbs.options.initializer'] = $app->protect(function () use ($app) {
......
...@@ -20,6 +20,9 @@ use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationExtension; ...@@ -20,6 +20,9 @@ use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationExtension;
use Symfony\Component\Form\Extension\Validator\ValidatorExtension as FormValidatorExtension; use Symfony\Component\Form\Extension\Validator\ValidatorExtension as FormValidatorExtension;
use Symfony\Component\Form\Forms; use Symfony\Component\Form\Forms;
use Symfony\Component\Form\ResolvedFormTypeFactory; use Symfony\Component\Form\ResolvedFormTypeFactory;
use Symfony\Component\Security\Csrf\CsrfTokenManager;
use Symfony\Component\Security\Csrf\TokenStorage\NativeSessionTokenStorage;
use Symfony\Component\Security\Csrf\TokenStorage\SessionTokenStorage;
/** /**
* Symfony Form component Provider. * Symfony Form component Provider.
...@@ -78,7 +81,10 @@ class FormServiceProvider implements ServiceProviderInterface ...@@ -78,7 +81,10 @@ class FormServiceProvider implements ServiceProviderInterface
if (isset($app['translator']) && method_exists($app['translator'], 'addResource')) { if (isset($app['translator']) && method_exists($app['translator'], 'addResource')) {
$r = new \ReflectionClass('Symfony\Component\Form\Form'); $r = new \ReflectionClass('Symfony\Component\Form\Form');
$app['translator']->addResource('xliff', dirname($r->getFilename()).'/Resources/translations/validators.'.$app['locale'].'.xlf', $app['locale'], 'validators'); $file = dirname($r->getFilename()).'/Resources/translations/validators.'.$app['locale'].'.xlf';
if (file_exists($file)) {
$app['translator']->addResource('xliff', $file, $app['locale'], 'validators');
}
} }
} }
...@@ -101,11 +107,19 @@ class FormServiceProvider implements ServiceProviderInterface ...@@ -101,11 +107,19 @@ class FormServiceProvider implements ServiceProviderInterface
}; };
$app['form.csrf_provider'] = function ($app) { $app['form.csrf_provider'] = function ($app) {
if (!class_exists('Symfony\Component\Form\Extension\DataCollector\DataCollectorExtension')) {
// Symfony 2.3
if (isset($app['session'])) { if (isset($app['session'])) {
return new SessionCsrfProvider($app['session'], $app['form.secret']); return new SessionCsrfProvider($app['session'], $app['form.secret']);
} }
return new DefaultCsrfProvider($app['form.secret']); return new DefaultCsrfProvider($app['form.secret']);
} else {
// Symfony 2.4+
$storage = isset($app['session']) ? new SessionTokenStorage($app['session']) : new NativeSessionTokenStorage();
return new CsrfTokenManager(null, $storage);
}
}; };
} }
} }
...@@ -19,6 +19,7 @@ use Symfony\Component\EventDispatcher\EventDispatcherInterface; ...@@ -19,6 +19,7 @@ use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpKernel\HttpCache\Esi; use Symfony\Component\HttpKernel\HttpCache\Esi;
use Symfony\Component\HttpKernel\HttpCache\Store; use Symfony\Component\HttpKernel\HttpCache\Store;
use Symfony\Component\HttpKernel\EventListener\EsiListener; use Symfony\Component\HttpKernel\EventListener\EsiListener;
use Symfony\Component\HttpKernel\EventListener\SurrogateListener;
/** /**
* Symfony HttpKernel component Provider for HTTP cache. * Symfony HttpKernel component Provider for HTTP cache.
...@@ -48,6 +49,10 @@ class HttpCacheServiceProvider implements ServiceProviderInterface, EventListene ...@@ -48,6 +49,10 @@ class HttpCacheServiceProvider implements ServiceProviderInterface, EventListene
}; };
$app['http_cache.esi_listener'] = function ($app) { $app['http_cache.esi_listener'] = function ($app) {
if (class_exists('Symfony\Component\HttpKernel\EventListener\SurrogateListener')) {
return new SurrogateListener($app['http_cache.esi']);
}
return new EsiListener($app['http_cache.esi']); return new EsiListener($app['http_cache.esi']);
}; };
......
...@@ -82,7 +82,7 @@ class RememberMeServiceProvider implements ServiceProviderInterface, EventListen ...@@ -82,7 +82,7 @@ class RememberMeServiceProvider implements ServiceProviderInterface, EventListen
$app['security.authentication_listener.remember_me._proto'] = $app->protect(function ($providerKey) use ($app) { $app['security.authentication_listener.remember_me._proto'] = $app->protect(function ($providerKey) use ($app) {
return function () use ($app, $providerKey) { return function () use ($app, $providerKey) {
$listener = new RememberMeListener( $listener = new RememberMeListener(
$app['security'], $app['security.token_storage'],
$app['security.remember_me.service.'.$providerKey], $app['security.remember_me.service.'.$providerKey],
$app['security.authentication_manager'], $app['security.authentication_manager'],
$app['logger'], $app['logger'],
......
...@@ -20,6 +20,7 @@ use Silex\Api\EventListenerProviderInterface; ...@@ -20,6 +20,7 @@ use Silex\Api\EventListenerProviderInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\RequestMatcher; use Symfony\Component\HttpFoundation\RequestMatcher;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Core\SecurityContext; use Symfony\Component\Security\Core\SecurityContext;
use Symfony\Component\Security\Core\SecurityContextInterface; use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\Security\Core\User\UserChecker; use Symfony\Component\Security\Core\User\UserChecker;
...@@ -32,6 +33,8 @@ use Symfony\Component\Security\Core\Authentication\AuthenticationProviderManager ...@@ -32,6 +33,8 @@ use Symfony\Component\Security\Core\Authentication\AuthenticationProviderManager
use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolver; use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolver;
use Symfony\Component\Security\Http\Authentication\DefaultAuthenticationSuccessHandler; use Symfony\Component\Security\Http\Authentication\DefaultAuthenticationSuccessHandler;
use Symfony\Component\Security\Http\Authentication\DefaultAuthenticationFailureHandler; use Symfony\Component\Security\Http\Authentication\DefaultAuthenticationFailureHandler;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
use Symfony\Component\Security\Core\Authorization\AuthorizationChecker;
use Symfony\Component\Security\Core\Authorization\Voter\RoleHierarchyVoter; use Symfony\Component\Security\Core\Authorization\Voter\RoleHierarchyVoter;
use Symfony\Component\Security\Core\Authorization\Voter\AuthenticatedVoter; use Symfony\Component\Security\Core\Authorization\Voter\AuthenticatedVoter;
use Symfony\Component\Security\Core\Authorization\AccessDecisionManager; use Symfony\Component\Security\Core\Authorization\AccessDecisionManager;
...@@ -77,9 +80,31 @@ class SecurityServiceProvider implements ServiceProviderInterface, EventListener ...@@ -77,9 +80,31 @@ class SecurityServiceProvider implements ServiceProviderInterface, EventListener
$app['security.access_rules'] = array(); $app['security.access_rules'] = array();
$app['security.hide_user_not_found'] = true; $app['security.hide_user_not_found'] = true;
$r = new \ReflectionMethod('Symfony\Component\Security\Http\Firewall\ContextListener', '__construct');
$params = $r->getParameters();
if ('Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface' === $params[0]->getClass()->getName()) {
$app['security.authorization_checker'] = function ($app) {
return new AuthorizationChecker($app['security.token_storage'], $app['security.authentication_manager'], $app['security.access_manager']);
};
$app['security.token_storage'] = function ($app) {
return new TokenStorage();
};
$app['security'] = function ($app) {
// Deprecated, to be removed in 2.0
return new SecurityContext($app['security.token_storage'], $app['security.authorization_checker']);
};
} else {
$app['security.token_storage'] = $app['security.authorization_checker'] = function ($app) {
return $app['security'];
};
$app['security'] = function ($app) { $app['security'] = function ($app) {
// Deprecated, to be removed in 2.0
return new SecurityContext($app['security.authentication_manager'], $app['security.access_manager']); return new SecurityContext($app['security.authentication_manager'], $app['security.access_manager']);
}; };
}
$app['security.authentication_manager'] = function ($app) { $app['security.authentication_manager'] = function ($app) {
$manager = new AuthenticationProviderManager($app['security.authentication_providers']); $manager = new AuthenticationProviderManager($app['security.authentication_providers']);
...@@ -284,7 +309,7 @@ class SecurityServiceProvider implements ServiceProviderInterface, EventListener ...@@ -284,7 +309,7 @@ class SecurityServiceProvider implements ServiceProviderInterface, EventListener
$app['security.access_listener'] = function ($app) { $app['security.access_listener'] = function ($app) {
return new AccessListener( return new AccessListener(
$app['security'], $app['security.token_storage'],
$app['security.access_manager'], $app['security.access_manager'],
$app['security.access_map'], $app['security.access_map'],
$app['security.authentication_manager'], $app['security.authentication_manager'],
...@@ -311,7 +336,7 @@ class SecurityServiceProvider implements ServiceProviderInterface, EventListener ...@@ -311,7 +336,7 @@ class SecurityServiceProvider implements ServiceProviderInterface, EventListener
}; };
$app['security.session_strategy'] = function ($app) { $app['security.session_strategy'] = function ($app) {
return new SessionAuthenticationStrategy('migrate'); return new SessionAuthenticationStrategy(SessionAuthenticationStrategy::MIGRATE);
}; };
$app['security.http_utils'] = function ($app) { $app['security.http_utils'] = function ($app) {
...@@ -319,14 +344,19 @@ class SecurityServiceProvider implements ServiceProviderInterface, EventListener ...@@ -319,14 +344,19 @@ class SecurityServiceProvider implements ServiceProviderInterface, EventListener
}; };
$app['security.last_error'] = $app->protect(function (Request $request) { $app['security.last_error'] = $app->protect(function (Request $request) {
if ($request->attributes->has(SecurityContextInterface::AUTHENTICATION_ERROR)) { if (class_exists('Symfony\Component\Security\Core\Security')) {
return $request->attributes->get(SecurityContextInterface::AUTHENTICATION_ERROR)->getMessage(); $error = Security::AUTHENTICATION_ERROR;
} else {
$error = SecurityContextInterface::AUTHENTICATION_ERROR;
}
if ($request->attributes->has($error)) {
return $request->attributes->get($error)->getMessage();
} }
$session = $request->getSession(); $session = $request->getSession();
if ($session && $session->has(SecurityContextInterface::AUTHENTICATION_ERROR)) { if ($session && $session->has($error)) {
$error = $session->get(SecurityContextInterface::AUTHENTICATION_ERROR)->getMessage(); $error = $session->get($error)->getMessage();
$session->remove(SecurityContextInterface::AUTHENTICATION_ERROR); $session->remove($error);
return $error; return $error;
} }
...@@ -337,7 +367,7 @@ class SecurityServiceProvider implements ServiceProviderInterface, EventListener ...@@ -337,7 +367,7 @@ class SecurityServiceProvider implements ServiceProviderInterface, EventListener
$app['security.context_listener._proto'] = $app->protect(function ($providerKey, $userProviders) use ($app) { $app['security.context_listener._proto'] = $app->protect(function ($providerKey, $userProviders) use ($app) {
return function () use ($app, $userProviders, $providerKey) { return function () use ($app, $userProviders, $providerKey) {
return new ContextListener( return new ContextListener(
$app['security'], $app['security.token_storage'],
$userProviders, $userProviders,
$providerKey, $providerKey,
$app['logger'], $app['logger'],
...@@ -360,7 +390,7 @@ class SecurityServiceProvider implements ServiceProviderInterface, EventListener ...@@ -360,7 +390,7 @@ class SecurityServiceProvider implements ServiceProviderInterface, EventListener
$app['security.exception_listener._proto'] = $app->protect(function ($entryPoint, $name, $accessDeniedHandler = null) use ($app) { $app['security.exception_listener._proto'] = $app->protect(function ($entryPoint, $name, $accessDeniedHandler = null) use ($app) {
return function () use ($app, $entryPoint, $name, $accessDeniedHandler) { return function () use ($app, $entryPoint, $name, $accessDeniedHandler) {
return new ExceptionListener( return new ExceptionListener(
$app['security'], $app['security.token_storage'],
$app['security.trust_resolver'], $app['security.trust_resolver'],
$app['security.http_utils'], $app['security.http_utils'],
$name, $name,
...@@ -414,7 +444,7 @@ class SecurityServiceProvider implements ServiceProviderInterface, EventListener ...@@ -414,7 +444,7 @@ class SecurityServiceProvider implements ServiceProviderInterface, EventListener
} }
return new $class( return new $class(
$app['security'], $app['security.token_storage'],
$app['security.authentication_manager'], $app['security.authentication_manager'],
isset($app['security.session_strategy.'.$name]) ? $app['security.session_strategy.'.$name] : $app['security.session_strategy'], isset($app['security.session_strategy.'.$name]) ? $app['security.session_strategy.'.$name] : $app['security.session_strategy'],
$app['security.http_utils'], $app['security.http_utils'],
...@@ -432,7 +462,7 @@ class SecurityServiceProvider implements ServiceProviderInterface, EventListener ...@@ -432,7 +462,7 @@ class SecurityServiceProvider implements ServiceProviderInterface, EventListener
$app['security.authentication_listener.http._proto'] = $app->protect(function ($providerKey, $options) use ($app) { $app['security.authentication_listener.http._proto'] = $app->protect(function ($providerKey, $options) use ($app) {
return function () use ($app, $providerKey, $options) { return function () use ($app, $providerKey, $options) {
return new BasicAuthenticationListener( return new BasicAuthenticationListener(
$app['security'], $app['security.token_storage'],
$app['security.authentication_manager'], $app['security.authentication_manager'],
$providerKey, $providerKey,
$app['security.entry_point.'.$providerKey.'.http'], $app['security.entry_point.'.$providerKey.'.http'],
...@@ -444,7 +474,7 @@ class SecurityServiceProvider implements ServiceProviderInterface, EventListener ...@@ -444,7 +474,7 @@ class SecurityServiceProvider implements ServiceProviderInterface, EventListener
$app['security.authentication_listener.anonymous._proto'] = $app->protect(function ($providerKey, $options) use ($app) { $app['security.authentication_listener.anonymous._proto'] = $app->protect(function ($providerKey, $options) use ($app) {
return function () use ($app, $providerKey, $options) { return function () use ($app, $providerKey, $options) {
return new AnonymousAuthenticationListener( return new AnonymousAuthenticationListener(
$app['security'], $app['security.token_storage'],
$providerKey, $providerKey,
$app['logger'] $app['logger']
); );
...@@ -473,7 +503,7 @@ class SecurityServiceProvider implements ServiceProviderInterface, EventListener ...@@ -473,7 +503,7 @@ class SecurityServiceProvider implements ServiceProviderInterface, EventListener
} }
$listener = new LogoutListener( $listener = new LogoutListener(
$app['security'], $app['security.token_storage'],
$app['security.http_utils'], $app['security.http_utils'],
$app['security.authentication.logout_handler.'.$name], $app['security.authentication.logout_handler.'.$name],
$options, $options,
...@@ -489,7 +519,7 @@ class SecurityServiceProvider implements ServiceProviderInterface, EventListener ...@@ -489,7 +519,7 @@ class SecurityServiceProvider implements ServiceProviderInterface, EventListener
$app['security.authentication_listener.switch_user._proto'] = $app->protect(function ($name, $options) use ($app, $that) { $app['security.authentication_listener.switch_user._proto'] = $app->protect(function ($name, $options) use ($app, $that) {
return function () use ($app, $name, $options, $that) { return function () use ($app, $name, $options, $that) {
return new SwitchUserListener( return new SwitchUserListener(
$app['security'], $app['security.token_storage'],
$app['security.user_provider.'.$name], $app['security.user_provider.'.$name],
$app['security.user_checker'], $app['security.user_checker'],
$name, $name,
...@@ -537,7 +567,7 @@ class SecurityServiceProvider implements ServiceProviderInterface, EventListener ...@@ -537,7 +567,7 @@ class SecurityServiceProvider implements ServiceProviderInterface, EventListener
if (isset($app['validator'])) { if (isset($app['validator'])) {
$app['security.validator.user_password_validator'] = function ($app) { $app['security.validator.user_password_validator'] = function ($app) {
return new UserPasswordValidator($app['security'], $app['security.encoder_factory']); return new UserPasswordValidator($app['security.token_storage'], $app['security.encoder_factory']);
}; };
if (!isset($app['validator.validator_service_ids'])) { if (!isset($app['validator.validator_service_ids'])) {
......
...@@ -24,11 +24,11 @@ class Translator extends BaseTranslator ...@@ -24,11 +24,11 @@ class Translator extends BaseTranslator
{ {
protected $app; protected $app;
public function __construct(Container $app, MessageSelector $selector) public function __construct(Container $app, MessageSelector $selector, $cacheDir = null, $debug = false)
{ {
$this->app = $app; $this->app = $app;
parent::__construct(null, $selector); parent::__construct(null, $selector, $cacheDir, $debug);
} }
public function getLocale() public function getLocale()
......
...@@ -32,6 +32,13 @@ class TranslationServiceProvider implements ServiceProviderInterface ...@@ -32,6 +32,13 @@ class TranslationServiceProvider implements ServiceProviderInterface
throw new \LogicException('You must register the LocaleServiceProvider to use the TranslationServiceProvider'); throw new \LogicException('You must register the LocaleServiceProvider to use the TranslationServiceProvider');
} }
$translator = new Translator($app, $app['translator.message_selector'], $app['translator.cache_dir'], $app['debug']);
// Handle deprecated 'locale_fallback'
if (isset($app['locale_fallback'])) {
$app['locale_fallbacks'] = (array) $app['locale_fallback'];
}
$translator = new Translator($app, $app['translator.message_selector']); $translator = new Translator($app, $app['translator.message_selector']);
$translator->setFallbackLocales($app['locale_fallbacks']); $translator->setFallbackLocales($app['locale_fallbacks']);
$translator->addLoader('array', new ArrayLoader()); $translator->addLoader('array', new ArrayLoader());
...@@ -52,5 +59,6 @@ class TranslationServiceProvider implements ServiceProviderInterface ...@@ -52,5 +59,6 @@ class TranslationServiceProvider implements ServiceProviderInterface
$app['translator.domains'] = array(); $app['translator.domains'] = array();
$app['locale_fallbacks'] = array('en'); $app['locale_fallbacks'] = array('en');
$app['translator.cache_dir'] = null;
} }
} }
...@@ -60,8 +60,8 @@ class TwigServiceProvider implements ServiceProviderInterface ...@@ -60,8 +60,8 @@ class TwigServiceProvider implements ServiceProviderInterface
$twig->addExtension(new TranslationExtension($app['translator'])); $twig->addExtension(new TranslationExtension($app['translator']));
} }
if (isset($app['security'])) { if (isset($app['security.authorization_checker'])) {
$twig->addExtension(new SecurityExtension($app['security'])); $twig->addExtension(new SecurityExtension($app['security.authorization_checker']));
} }
if (isset($app['fragment.handler'])) { if (isset($app['fragment.handler'])) {
......
...@@ -14,10 +14,13 @@ namespace Silex\Provider; ...@@ -14,10 +14,13 @@ namespace Silex\Provider;
use Pimple\Container; use Pimple\Container;
use Pimple\ServiceProviderInterface; use Pimple\ServiceProviderInterface;
use Silex\Provider\Validator\ConstraintValidatorFactory; use Silex\Provider\Validator\ConstraintValidatorFactory;
use Silex\Application;
use Symfony\Component\Validator\Validator; use Symfony\Component\Validator\Validator;
use Symfony\Component\Validator\DefaultTranslator; use Symfony\Component\Validator\DefaultTranslator;
use Symfony\Component\Validator\Mapping\ClassMetadataFactory; use Symfony\Component\Validator\Mapping\ClassMetadataFactory;
use Symfony\Component\Validator\Mapping\Factory\LazyLoadingMetadataFactory;
use Symfony\Component\Validator\Mapping\Loader\StaticMethodLoader; use Symfony\Component\Validator\Mapping\Loader\StaticMethodLoader;
use Symfony\Component\Validator\Validation;
/** /**
* Symfony Validator component Provider. * Symfony Validator component Provider.
...@@ -29,22 +32,35 @@ class ValidatorServiceProvider implements ServiceProviderInterface ...@@ -29,22 +32,35 @@ class ValidatorServiceProvider implements ServiceProviderInterface
public function register(Container $app) public function register(Container $app)
{ {
$app['validator'] = function ($app) { $app['validator'] = function ($app) {
if (isset($app['translator']) && method_exists($app['translator'], 'addResource')) { if (isset($app['translator'])) {
$r = new \ReflectionClass('Symfony\Component\Validator\Validator'); $r = new \ReflectionClass('Symfony\Component\Validator\Validation');
$file = dirname($r->getFilename()).'/Resources/translations/validators.'.$app['locale'].'.xlf';
if (file_exists($file)) {
$app['translator']->addResource('xliff', $file, $app['locale'], 'validators');
}
}
return $app['validator.builder']->getValidator();
};
$app['translator']->addResource('xliff', dirname($r->getFilename()).'/Resources/translations/validators.'.$app['locale'].'.xlf', $app['locale'], 'validators'); $app['validator.builder'] = function ($app) {
$builder = Validation::createValidatorBuilder();
$builder->setConstraintValidatorFactory($app['validator.validator_factory']);
$builder->setTranslationDomain('validators');
$builder->addObjectInitializers($app['validator.object_initializers']);
$builder->setMetadataFactory($app['validator.mapping.class_metadata_factory']);
if (isset($app['translator'])) {
$builder->setTranslator($app['translator']);
} }
return new Validator( return $builder;
$app['validator.mapping.class_metadata_factory'],
$app['validator.validator_factory'],
isset($app['translator']) ? $app['translator'] : new DefaultTranslator(),
'validators',
$app['validator.object_initializers']
);
}; };
$app['validator.mapping.class_metadata_factory'] = function ($app) { $app['validator.mapping.class_metadata_factory'] = function ($app) {
if (class_exists('Symfony\Component\Validator\Mapping\Factory\LazyLoadingMetadataFactory')) {
return new LazyLoadingMetadataFactory(new StaticMethodLoader());
}
return new ClassMetadataFactory(new StaticMethodLoader()); return new ClassMetadataFactory(new StaticMethodLoader());
}; };
......
...@@ -23,7 +23,7 @@ trait SecurityTrait ...@@ -23,7 +23,7 @@ trait SecurityTrait
public function secure($roles) public function secure($roles)
{ {
$this->before(function ($request, $app) use ($roles) { $this->before(function ($request, $app) use ($roles) {
if (!$app['security']->isGranted($roles)) { if (!$app['security.authorization_checker']->isGranted($roles)) {
throw new AccessDeniedException(); throw new AccessDeniedException();
} }
}); });
......
...@@ -21,6 +21,11 @@ use Symfony\Component\HttpKernel\HttpKernel; ...@@ -21,6 +21,11 @@ use Symfony\Component\HttpKernel\HttpKernel;
*/ */
abstract class WebTestCase extends \PHPUnit_Framework_TestCase abstract class WebTestCase extends \PHPUnit_Framework_TestCase
{ {
/**
* Application instance.
*
* @var Application
*/
protected $app; protected $app;
/** /**
......
...@@ -13,6 +13,7 @@ namespace Silex\Tests\Application; ...@@ -13,6 +13,7 @@ namespace Silex\Tests\Application;
use Silex\Provider\SecurityServiceProvider; use Silex\Provider\SecurityServiceProvider;
use Symfony\Component\Security\Core\User\User; use Symfony\Component\Security\Core\User\User;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
/** /**
...@@ -28,7 +29,9 @@ class SecurityTraitTest extends \PHPUnit_Framework_TestCase ...@@ -28,7 +29,9 @@ class SecurityTraitTest extends \PHPUnit_Framework_TestCase
{ {
$request = Request::create('/'); $request = Request::create('/');
$app = $this->createApplication(); $app = $this->createApplication(array(
'fabien' => array('ROLE_ADMIN', '5FZ2Z8QIkA7UTZ4BYkoC+GsReLf569mSKDsfods6LYQ8t+a8EW9oaircfMpmaLbPBh4FOBiiFyLfuZmTSUwzZg=='),
));
$app->get('/', function () { return 'foo'; }); $app->get('/', function () { return 'foo'; });
$app->handle($request); $app->handle($request);
$this->assertNull($app->user()); $this->assertNull($app->user());
...@@ -40,24 +43,83 @@ class SecurityTraitTest extends \PHPUnit_Framework_TestCase ...@@ -40,24 +43,83 @@ class SecurityTraitTest extends \PHPUnit_Framework_TestCase
$this->assertEquals('fabien', $app->user()->getUsername()); $this->assertEquals('fabien', $app->user()->getUsername());
} }
public function testEncodePassword() public function testUserWithNoToken()
{
$request = Request::create('/');
$app = $this->createApplication();
$app->get('/', function () { return 'foo'; });
$app->handle($request);
$this->assertNull($app->user());
}
public function testUserWithInvalidUser()
{ {
$request = Request::create('/');
$app = $this->createApplication(); $app = $this->createApplication();
$app->boot();
$app['security.token_storage']->setToken(new UsernamePasswordToken('foo', 'foo', 'foo'));
$app->get('/', function () { return 'foo'; });
$app->handle($request);
$this->assertNull($app->user());
}
public function testEncodePassword()
{
$app = $this->createApplication(array(
'fabien' => array('ROLE_ADMIN', '5FZ2Z8QIkA7UTZ4BYkoC+GsReLf569mSKDsfods6LYQ8t+a8EW9oaircfMpmaLbPBh4FOBiiFyLfuZmTSUwzZg=='),
));
$user = new User('foo', 'bar'); $user = new User('foo', 'bar');
$this->assertEquals('5FZ2Z8QIkA7UTZ4BYkoC+GsReLf569mSKDsfods6LYQ8t+a8EW9oaircfMpmaLbPBh4FOBiiFyLfuZmTSUwzZg==', $app->encodePassword($user, 'foo')); $this->assertEquals('5FZ2Z8QIkA7UTZ4BYkoC+GsReLf569mSKDsfods6LYQ8t+a8EW9oaircfMpmaLbPBh4FOBiiFyLfuZmTSUwzZg==', $app->encodePassword($user, 'foo'));
} }
public function createApplication() /**
* @expectedException \Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException
*/
public function testIsGrantedWithoutTokenThrowsException()
{
$app = $this->createApplication();
$app->get('/', function () { return 'foo'; });
$app->handle(Request::create('/'));
$app->isGranted('ROLE_ADMIN');
}
public function testIsGranted()
{
$request = Request::create('/');
$app = $this->createApplication(array(
'fabien' => array('ROLE_ADMIN', '5FZ2Z8QIkA7UTZ4BYkoC+GsReLf569mSKDsfods6LYQ8t+a8EW9oaircfMpmaLbPBh4FOBiiFyLfuZmTSUwzZg=='),
'monique' => array('ROLE_USER', '5FZ2Z8QIkA7UTZ4BYkoC+GsReLf569mSKDsfods6LYQ8t+a8EW9oaircfMpmaLbPBh4FOBiiFyLfuZmTSUwzZg=='),
));
$app->get('/', function () { return 'foo'; });
// User is Monique (ROLE_USER)
$request->headers->set('PHP_AUTH_USER', 'monique');
$request->headers->set('PHP_AUTH_PW', 'foo');
$app->handle($request);
$this->assertTrue($app->isGranted('ROLE_USER'));
$this->assertFalse($app->isGranted('ROLE_ADMIN'));
// User is Fabien (ROLE_ADMIN)
$request->headers->set('PHP_AUTH_USER', 'fabien');
$request->headers->set('PHP_AUTH_PW', 'foo');
$app->handle($request);
$this->assertFalse($app->isGranted('ROLE_USER'));
$this->assertTrue($app->isGranted('ROLE_ADMIN'));
}
public function createApplication($users = array())
{ {
$app = new SecurityApplication(); $app = new SecurityApplication();
$app->register(new SecurityServiceProvider(), array( $app->register(new SecurityServiceProvider(), array(
'security.firewalls' => array( 'security.firewalls' => array(
'default' => array( 'default' => array(
'http' => true, 'http' => true,
'users' => array( 'users' => $users,
'fabien' => array('ROLE_ADMIN', '5FZ2Z8QIkA7UTZ4BYkoC+GsReLf569mSKDsfods6LYQ8t+a8EW9oaircfMpmaLbPBh4FOBiiFyLfuZmTSUwzZg=='),
),
), ),
), ),
)); ));
......
...@@ -13,6 +13,7 @@ namespace Silex\Tests; ...@@ -13,6 +13,7 @@ namespace Silex\Tests;
use Silex\Application; use Silex\Application;
use Silex\ControllerCollection; use Silex\ControllerCollection;
use Silex\Api\ControllerProviderInterface;
use Silex\Route; use Silex\Route;
use Silex\Provider\MonologServiceProvider; use Silex\Provider\MonologServiceProvider;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
...@@ -460,6 +461,26 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase ...@@ -460,6 +461,26 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase
$this->assertEquals(array('first', 'second', 'third'), array_keys(iterator_to_array($app['routes']))); $this->assertEquals(array('first', 'second', 'third'), array_keys(iterator_to_array($app['routes'])));
} }
/**
* @expectedException \LogicException
* @expectedExceptionMessage The "mount" method takes either a "ControllerCollection" or a "ControllerProviderInterface" instance.
*/
public function testMountNullException()
{
$app = new Application();
$app->mount('/exception', null);
}
/**
* @expectedException \LogicException
* @expectedExceptionMessage The method "Silex\Tests\IncorrectControllerCollection::connect" must return a "ControllerCollection" instance. Got: "NULL"
*/
public function testMountWrongConnectReturnValueException()
{
$app = new Application();
$app->mount('/exception', new IncorrectControllerCollection());
}
public function testSendFile() public function testSendFile()
{ {
$app = new Application(); $app = new Application();
...@@ -480,7 +501,7 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase ...@@ -480,7 +501,7 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase
public function testGetRouteCollectionWithRouteWithoutController() public function testGetRouteCollectionWithRouteWithoutController()
{ {
$app = new Application(); $app = new Application();
$app['exception_handler']->disable(); unset($app['exception_handler']);
$app->match('/')->bind('homepage'); $app->match('/')->bind('homepage');
$app->handle(Request::create('/')); $app->handle(Request::create('/'));
} }
...@@ -518,3 +539,11 @@ class FooController ...@@ -518,3 +539,11 @@ class FooController
return 'Hello '.$app->escape($name); return 'Hello '.$app->escape($name);
} }
} }
class IncorrectControllerCollection implements ControllerProviderInterface
{
public function connect(Application $app)
{
return;
}
}
...@@ -13,7 +13,6 @@ namespace Silex\Tests; ...@@ -13,7 +13,6 @@ namespace Silex\Tests;
use Silex\Application; use Silex\Application;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Silex\Provider\ServiceControllerServiceProvider; use Silex\Provider\ServiceControllerServiceProvider;
/** /**
......
...@@ -129,11 +129,11 @@ class ControllerCollectionTest extends \PHPUnit_Framework_TestCase ...@@ -129,11 +129,11 @@ class ControllerCollectionTest extends \PHPUnit_Framework_TestCase
$controllers->requireHttp(); $controllers->requireHttp();
$controller = $controllers->match('/{id}/{name}/{extra}', function () {})->requireHttps(); $controller = $controllers->match('/{id}/{name}/{extra}', function () {})->requireHttps();
$this->assertEquals('https', $controller->getRoute()->getRequirement('_scheme')); $this->assertEquals(array('https'), $controller->getRoute()->getSchemes());
$controllers->requireHttp(); $controllers->requireHttp();
$this->assertEquals('http', $controller->getRoute()->getRequirement('_scheme')); $this->assertEquals(array('http'), $controller->getRoute()->getSchemes());
} }
public function testBefore() public function testBefore()
......
...@@ -91,8 +91,8 @@ class ControllerTest extends \PHPUnit_Framework_TestCase ...@@ -91,8 +91,8 @@ class ControllerTest extends \PHPUnit_Framework_TestCase
public function provideRouteAndExpectedRouteName() public function provideRouteAndExpectedRouteName()
{ {
return array( return array(
array(new Route('/Invalid%Symbols#Stripped', array(), array('_method' => 'POST')), 'POST_InvalidSymbolsStripped'), array(new Route('/Invalid%Symbols#Stripped', array(), array(), array(), '', array(), array('POST')), 'POST_InvalidSymbolsStripped'),
array(new Route('/post/{id}', array(), array('_method' => 'GET')), 'GET_post_id'), array(new Route('/post/{id}', array(), array(), array(), '', array(), array('GET')), 'GET_post_id'),
array(new Route('/colon:pipe|dashes-escaped'), '_colon_pipe_dashes_escaped'), array(new Route('/colon:pipe|dashes-escaped'), '_colon_pipe_dashes_escaped'),
array(new Route('/underscores_and.periods'), '_underscores_and.periods'), array(new Route('/underscores_and.periods'), '_underscores_and.periods'),
); );
......
...@@ -107,7 +107,7 @@ class ExceptionHandlerTest extends \PHPUnit_Framework_TestCase ...@@ -107,7 +107,7 @@ class ExceptionHandlerTest extends \PHPUnit_Framework_TestCase
public function testNoExceptionHandler() public function testNoExceptionHandler()
{ {
$app = new Application(); $app = new Application();
$app['exception_handler']->disable(); unset($app['exception_handler']);
$app->match('/foo', function () { $app->match('/foo', function () {
throw new \RuntimeException('foo exception'); throw new \RuntimeException('foo exception');
...@@ -207,6 +207,8 @@ class ExceptionHandlerTest extends \PHPUnit_Framework_TestCase ...@@ -207,6 +207,8 @@ class ExceptionHandlerTest extends \PHPUnit_Framework_TestCase
$this->fail('->handle() should not catch exceptions where an empty error handler was supplied'); $this->fail('->handle() should not catch exceptions where an empty error handler was supplied');
} catch (\RuntimeException $e) { } catch (\RuntimeException $e) {
$this->assertEquals('foo exception', $e->getMessage()); $this->assertEquals('foo exception', $e->getMessage());
} catch (\LogicException $e) {
$this->assertEquals('foo exception', $e->getPrevious()->getMessage());
} }
$this->assertEquals(1, $errors, 'should execute the error handler'); $this->assertEquals(1, $errors, 'should execute the error handler');
...@@ -261,7 +263,7 @@ class ExceptionHandlerTest extends \PHPUnit_Framework_TestCase ...@@ -261,7 +263,7 @@ class ExceptionHandlerTest extends \PHPUnit_Framework_TestCase
// just making sure the dispatcher gets created // just making sure the dispatcher gets created
}); });
$app['exception_handler']->disable(); unset($app['exception_handler']);
try { try {
$request = Request::create('/foo'); $request = Request::create('/foo');
......
...@@ -234,6 +234,20 @@ class MiddlewareTest extends \PHPUnit_Framework_TestCase ...@@ -234,6 +234,20 @@ class MiddlewareTest extends \PHPUnit_Framework_TestCase
$this->assertEquals('foo---', $app->handle($request)->getContent()); $this->assertEquals('foo---', $app->handle($request)->getContent());
} }
public function testAfterFilterCanReturnResponse()
{
$app = new Application();
$app->after(function (Request $request, Response $response) {
return new Response('bar');
});
$app->match('/', function () { return new Response('foo'); });
$request = Request::create('/');
$this->assertEquals('bar', $app->handle($request)->getContent());
}
public function testRouteAndApplicationMiddlewareParameterInjection() public function testRouteAndApplicationMiddlewareParameterInjection()
{ {
$app = new Application(); $app = new Application();
......
...@@ -14,12 +14,17 @@ namespace Silex\Tests\Provider; ...@@ -14,12 +14,17 @@ namespace Silex\Tests\Provider;
use Silex\Application; use Silex\Application;
use Silex\Provider\FormServiceProvider; use Silex\Provider\FormServiceProvider;
use Silex\Provider\TranslationServiceProvider; use Silex\Provider\TranslationServiceProvider;
use Silex\Provider\ValidatorServiceProvider;
use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\AbstractTypeExtension; use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface;
use Symfony\Component\Form\FormTypeGuesserChain; use Symfony\Component\Form\FormTypeGuesserChain;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\OptionsResolver\OptionsResolverInterface; use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\Translation\Exception\NotFoundResourceException;
use Symfony\Component\Security\Csrf\CsrfToken;
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
class FormServiceProviderTest extends \PHPUnit_Framework_TestCase class FormServiceProviderTest extends \PHPUnit_Framework_TestCase
{ {
...@@ -110,7 +115,35 @@ class FormServiceProviderTest extends \PHPUnit_Framework_TestCase ...@@ -110,7 +115,35 @@ class FormServiceProviderTest extends \PHPUnit_Framework_TestCase
)))); ))));
$this->assertFalse($form->isValid()); $this->assertFalse($form->isValid());
$r = new \ReflectionMethod($form, 'getErrors');
if (!$r->getNumberOfParameters()) {
$this->assertContains('ERROR: German translation', $form->getErrorsAsString()); $this->assertContains('ERROR: German translation', $form->getErrorsAsString());
} else {
// as of 2.5
$this->assertContains('ERROR: German translation', (string) $form->getErrors(true, false));
}
}
public function testFormServiceProviderWillNotAddNonexistentTranslationFiles()
{
$app = new Application(array(
'locale' => 'nonexistent',
));
$app->register(new FormServiceProvider());
$app->register(new ValidatorServiceProvider());
$app->register(new TranslationServiceProvider(), array(
'locale_fallbacks' => array(),
));
$app['form.factory'];
$translator = $app['translator'];
try {
$translator->trans('test');
} catch (NotFoundResourceException $e) {
$this->fail('Form factory should not add a translation resource that does not exist');
}
} }
} }
...@@ -125,8 +158,22 @@ class DummyFormType extends AbstractType ...@@ -125,8 +158,22 @@ class DummyFormType extends AbstractType
} }
} }
class DummyFormTypeExtension extends AbstractTypeExtension if (method_exists('Symfony\Component\Form\AbstractType', 'configureOptions')) {
{ class DummyFormTypeExtension extends AbstractTypeExtension
{
public function getExtendedType()
{
return 'file';
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefined(array('image_path'));
}
}
} else {
class DummyFormTypeExtension extends AbstractTypeExtension
{
public function getExtendedType() public function getExtendedType()
{ {
return 'file'; return 'file';
...@@ -134,12 +181,19 @@ class DummyFormTypeExtension extends AbstractTypeExtension ...@@ -134,12 +181,19 @@ class DummyFormTypeExtension extends AbstractTypeExtension
public function setDefaultOptions(OptionsResolverInterface $resolver) public function setDefaultOptions(OptionsResolverInterface $resolver)
{ {
if (!method_exists($resolver, 'setDefined')) {
$resolver->setOptional(array('image_path')); $resolver->setOptional(array('image_path'));
} else {
$resolver->setDefined(array('image_path'));
}
}
} }
} }
class FakeCsrfProvider implements CsrfProviderInterface if (!class_exists('Symfony\Component\Form\Extension\DataCollector\DataCollectorExtension')) {
{ // Symfony 2.3 only
class FakeCsrfProvider implements CsrfProviderInterface
{
public function generateCsrfToken($intention) public function generateCsrfToken($intention)
{ {
return $intention.'123'; return $intention.'123';
...@@ -149,4 +203,27 @@ class FakeCsrfProvider implements CsrfProviderInterface ...@@ -149,4 +203,27 @@ class FakeCsrfProvider implements CsrfProviderInterface
{ {
return $token === $this->generateCsrfToken($intention); return $token === $this->generateCsrfToken($intention);
} }
}
} else {
class FakeCsrfProvider implements CsrfTokenManagerInterface
{
public function getToken($tokenId)
{
return new CsrfToken($tokenId, '123');
}
public function refreshToken($tokenId)
{
return new CsrfToken($tokenId, '123');
}
public function removeToken($tokenId)
{
}
public function isTokenValid(CsrfToken $token)
{
return '123' === $token->getValue();
}
}
} }
...@@ -41,7 +41,9 @@ class MonologServiceProviderTest extends \PHPUnit_Framework_TestCase ...@@ -41,7 +41,9 @@ class MonologServiceProviderTest extends \PHPUnit_Framework_TestCase
$this->assertTrue($app['monolog.handler']->hasDebug('> GET /foo')); $this->assertTrue($app['monolog.handler']->hasDebug('> GET /foo'));
$this->assertTrue($app['monolog.handler']->hasDebug('< 200')); $this->assertTrue($app['monolog.handler']->hasDebug('< 200'));
$this->assertTrue($app['monolog.handler']->hasInfo('Matched route "GET_foo" (parameters: "_controller": "{}", "_route": "GET_foo")'));
$records = $app['monolog.handler']->getRecords();
$this->assertContains('Matched route "GET_foo"', $records[0]['message']);
} }
public function testManualLogging() public function testManualLogging()
......
...@@ -63,7 +63,7 @@ class RememberMeServiceProviderTest extends WebTestCase ...@@ -63,7 +63,7 @@ class RememberMeServiceProviderTest extends WebTestCase
$app = new Application(); $app = new Application();
$app['debug'] = true; $app['debug'] = true;
$app['exception_handler']->disable(); unset($app['exception_handler']);
$app->register(new SessionServiceProvider(), array( $app->register(new SessionServiceProvider(), array(
'session.test' => true, 'session.test' => true,
...@@ -84,9 +84,9 @@ class RememberMeServiceProviderTest extends WebTestCase ...@@ -84,9 +84,9 @@ class RememberMeServiceProviderTest extends WebTestCase
); );
$app->get('/', function () use ($app) { $app->get('/', function () use ($app) {
if ($app['security']->isGranted('IS_AUTHENTICATED_FULLY')) { if ($app['security.authorization_checker']->isGranted('IS_AUTHENTICATED_FULLY')) {
return 'AUTHENTICATED_FULLY'; return 'AUTHENTICATED_FULLY';
} elseif ($app['security']->isGranted('IS_AUTHENTICATED_REMEMBERED')) { } elseif ($app['security.authorization_checker']->isGranted('IS_AUTHENTICATED_REMEMBERED')) {
return 'AUTHENTICATED_REMEMBERED'; return 'AUTHENTICATED_REMEMBERED';
} else { } else {
return 'AUTHENTICATED_ANONYMOUSLY'; return 'AUTHENTICATED_ANONYMOUSLY';
......
...@@ -226,15 +226,15 @@ class SecurityServiceProviderTest extends WebTestCase ...@@ -226,15 +226,15 @@ class SecurityServiceProviderTest extends WebTestCase
}); });
$app->get('/', function () use ($app) { $app->get('/', function () use ($app) {
$user = $app['security']->getToken()->getUser(); $user = $app['security.token_storage']->getToken()->getUser();
$content = is_object($user) ? $user->getUsername() : 'ANONYMOUS'; $content = is_object($user) ? $user->getUsername() : 'ANONYMOUS';
if ($app['security']->isGranted('IS_AUTHENTICATED_FULLY')) { if ($app['security.authorization_checker']->isGranted('IS_AUTHENTICATED_FULLY')) {
$content .= 'AUTHENTICATED'; $content .= 'AUTHENTICATED';
} }
if ($app['security']->isGranted('ROLE_ADMIN')) { if ($app['security.authorization_checker']->isGranted('ROLE_ADMIN')) {
$content .= 'ADMIN'; $content .= 'ADMIN';
} }
...@@ -271,15 +271,14 @@ class SecurityServiceProviderTest extends WebTestCase ...@@ -271,15 +271,14 @@ class SecurityServiceProviderTest extends WebTestCase
)); ));
$app->get('/', function () use ($app) { $app->get('/', function () use ($app) {
$user = $app['security']->getToken()->getUser(); $user = $app['security.token_storage']->getToken()->getUser();
$content = is_object($user) ? $user->getUsername() : 'ANONYMOUS'; $content = is_object($user) ? $user->getUsername() : 'ANONYMOUS';
if ($app['security']->isGranted('IS_AUTHENTICATED_FULLY')) { if ($app['security.authorization_checker']->isGranted('IS_AUTHENTICATED_FULLY')) {
$content .= 'AUTHENTICATED'; $content .= 'AUTHENTICATED';
} }
if ($app['security']->isGranted('ROLE_ADMIN')) { if ($app['security.authorization_checker']->isGranted('ROLE_ADMIN')) {
$content .= 'ADMIN'; $content .= 'ADMIN';
} }
......
...@@ -94,7 +94,7 @@ class SessionServiceProviderTest extends WebTestCase ...@@ -94,7 +94,7 @@ class SessionServiceProviderTest extends WebTestCase
}); });
$app['debug'] = true; $app['debug'] = true;
$app['exception_handler']->disable(); unset($app['exception_handler']);
$client = new Client($app); $client = new Client($app);
......
...@@ -13,6 +13,7 @@ namespace Silex\Tests\Provider; ...@@ -13,6 +13,7 @@ namespace Silex\Tests\Provider;
use Silex\Application; use Silex\Application;
use Silex\Provider\TwigServiceProvider; use Silex\Provider\TwigServiceProvider;
use Silex\Provider\HttpFragmentServiceProvider;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
/** /**
......
...@@ -12,8 +12,10 @@ ...@@ -12,8 +12,10 @@
namespace Silex\Tests\Provider; namespace Silex\Tests\Provider;
use Silex\Application; use Silex\Application;
use Silex\Provider\TranslationServiceProvider;
use Silex\Provider\ValidatorServiceProvider; use Silex\Provider\ValidatorServiceProvider;
use Silex\Provider\FormServiceProvider; use Silex\Provider\FormServiceProvider;
use Symfony\Component\Translation\Exception\NotFoundResourceException;
use Symfony\Component\Validator\Constraints as Assert; use Symfony\Component\Validator\Constraints as Assert;
use Silex\Tests\Provider\ValidatorServiceProviderTest\Constraint\Custom; use Silex\Tests\Provider\ValidatorServiceProviderTest\Constraint\Custom;
use Silex\Tests\Provider\ValidatorServiceProviderTest\Constraint\CustomValidator; use Silex\Tests\Provider\ValidatorServiceProviderTest\Constraint\CustomValidator;
...@@ -67,7 +69,7 @@ class ValidatorServiceProviderTest extends \PHPUnit_Framework_TestCase ...@@ -67,7 +69,7 @@ class ValidatorServiceProviderTest extends \PHPUnit_Framework_TestCase
*/ */
public function testValidatorServiceIsAValidator($app) public function testValidatorServiceIsAValidator($app)
{ {
$this->assertInstanceOf('Symfony\Component\Validator\Validator', $app['validator']); $this->assertInstanceOf('Symfony\Component\Validator\ValidatorInterface', $app['validator']);
} }
/** /**
...@@ -93,13 +95,34 @@ class ValidatorServiceProviderTest extends \PHPUnit_Framework_TestCase ...@@ -93,13 +95,34 @@ class ValidatorServiceProviderTest extends \PHPUnit_Framework_TestCase
->getForm() ->getForm()
; ;
$form->bind(array('email' => $email)); $form->submit(array('email' => $email));
$this->assertEquals($isValid, $form->isValid()); $this->assertEquals($isValid, $form->isValid());
$this->assertEquals($nbGlobalError, count($form->getErrors())); $this->assertEquals($nbGlobalError, count($form->getErrors()));
$this->assertEquals($nbEmailError, count($form->offsetGet('email')->getErrors())); $this->assertEquals($nbEmailError, count($form->offsetGet('email')->getErrors()));
} }
public function testValidatorWillNotAddNonexistentTranslationFiles()
{
$app = new Application(array(
'locale' => 'nonexistent',
));
$app->register(new ValidatorServiceProvider());
$app->register(new TranslationServiceProvider(), array(
'locale_fallbacks' => array(),
));
$app['validator'];
$translator = $app['translator'];
try {
$translator->trans('test');
} catch (NotFoundResourceException $e) {
$this->fail('Validator should not add a translation resource that does not exist');
}
}
public function testValidatorConstraintProvider() public function testValidatorConstraintProvider()
{ {
// Email, form is valid , nb global error, nb email error // Email, form is valid , nb global error, nb email error
......
...@@ -100,7 +100,7 @@ class RouterTest extends \PHPUnit_Framework_TestCase ...@@ -100,7 +100,7 @@ class RouterTest extends \PHPUnit_Framework_TestCase
public function testMissingRoute() public function testMissingRoute()
{ {
$app = new Application(); $app = new Application();
$app['exception_handler']->disable(); unset($app['exception_handler']);
$request = Request::create('/baz'); $request = Request::create('/baz');
$app->handle($request); $app->handle($request);
......
<?php
$loader = require __DIR__.'/../vendor/autoload.php';
$loader->add('Silex\Tests', __DIR__);
if (!class_exists('Symfony\Component\Form\Form')) {
echo "You must install the dev dependencies using:\n";
echo " composer install --dev\n";
exit(1);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment