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
before_script:
# 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' = '' ]; 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"
......@@ -27,3 +28,5 @@ matrix:
env: SYMFONY_DEPS_VERSION=2.5
- php: 5.6
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
of this software and associated documentation files (the "Software"), to deal
......
......@@ -27,7 +27,7 @@ The recommended way to install Silex is through `Composer`_:
.. 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.
......@@ -39,12 +39,12 @@ Read the `documentation`_ for more information.
Tests
-----
To run the test suite, you need `Composer`_:
To run the test suite, you need `Composer`_ and `PHPUnit`_:
.. code-block:: bash
$ php composer.phar install --dev
$ vendor/bin/phpunit
$ composer install
$ phpunit
Community
---------
......@@ -58,5 +58,6 @@ Silex is licensed under the MIT license.
.. _Symfony2 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
......@@ -16,7 +16,7 @@
}
],
"require": {
"php": ">=5.3.3",
"php": ">=5.3.9",
"pimple/pimple": "~3.0",
"symfony/event-dispatcher": "~2.4",
"symfony/http-foundation": "~2.4",
......@@ -57,7 +57,10 @@
"silex/providers": "self.version"
},
"autoload": {
"psr-0": { "Silex": "src/" }
"psr-4": { "Silex\\": "src/Silex" }
},
"autoload-dev" : {
"psr-4": { "Silex\\Tests\\" : "tests/Silex/Tests" }
},
"extra": {
"branch-alias": {
......
......@@ -17,6 +17,22 @@ Changelog
* ``monolog.exception.logger_filter`` option added to Monolog service provider
* [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)
------------------
......
......@@ -23,6 +23,8 @@ Usage
.. code-block:: php
<?php
// web/index.php
require_once __DIR__.'/../vendor/autoload.php';
......
......@@ -19,11 +19,10 @@ Services
<http://api.symfony.com/master/Symfony/Component/Form/FormFactory.html>`_,
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
<http://api.symfony.com/master/Symfony/Component/Form/Extension/Csrf/CsrfProvider/CsrfProviderInterface.html>`_,
defaults to a `DefaultCsrfProvider
<http://api.symfony.com/master/Symfony/Component/Form/Extension/Csrf/CsrfProvider/DefaultCsrfProvider.html>`_.
<http://api.symfony.com/2.3/Symfony/Component/Form/Extension/Csrf/CsrfProvider/CsrfProviderInterface.html>`_ for Symfony 2.3 or
`CsrfTokenManagerInterface <http://api.symfony.com/2.7/Symfony/Component/Security/Csrf/CsrfTokenManagerInterface.html>`_ for Symfony 2.4+.
Registering
-----------
......@@ -67,7 +66,8 @@ Registering
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
......
......@@ -14,7 +14,12 @@ Services
--------
* **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
`AuthenticationProviderManager
......@@ -95,6 +100,10 @@ Accessing the current User
The current user information is stored in a token that is accessible via the
``security`` service::
// Symfony 2.6+
$token = $app['security.token_storage']->getToken();
// Symfony 2.3/2.5
$token = $app['security']->getToken();
If there is no information about the user, the token is ``null``. If the user
......@@ -327,6 +336,12 @@ Checking User Roles
To check if a user is granted some role, use the ``isGranted()`` method on the
security context::
// Symfony 2.6+
if ($app['security.authorization_checker']->isGranted('ROLE_ADMIN')) {
// ...
}
// Symfony 2.3/2.5
if ($app['security']->isGranted('ROLE_ADMIN')) {
// ...
}
......@@ -566,7 +581,8 @@ use in your configuration::
// define the authentication listener object
$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(
......
......@@ -21,8 +21,8 @@ Parameters
* **port**: SMTP port, defaults to 25.
* **username**: SMTP username, defaults to an empty string.
* **password**: SMTP password, defaults to an empty string.
* **encryption**: SMTP encryption, defaults to null.
* **auth_mode**: SMTP authentication mode, 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. Valid values are 'plain', 'login', 'cram-md5', or null.
Example usage::
......
......@@ -14,7 +14,7 @@ Services
--------
* **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,
which can read validation constraint information from classes. Defaults to
......
......@@ -204,9 +204,9 @@ don't want to mess with most of them.
the request that is used by the Router and the UrlGenerator.
* **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
does not return a Response. Disable it with
``$app['exception_handler']->disable()``.
used when you don't register one via the ``error()`` method or if your
handler does not return a Response. Disable it with
``unset($app['exception_handler'])``.
* **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
......
......@@ -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::
If you want to use the Symfony2 ``WebTestCase`` class you will need to
......@@ -108,7 +103,7 @@ executed before every test.
{
$app = require __DIR__.'/path/to/app.php';
$app['debug'] = true;
$app['exception_handler']->disable();
unset($app['exception_handler']);
return $app;
}
......
......@@ -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)::
$app->get('/blog/{postId}/{commentId}', function ($commentId, $postId) {
......@@ -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
converters::
......@@ -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
converter based on Doctrine ObjectManager::
use Doctrine\Common\Persistence\ObjectManager
use Doctrine\Common\Persistence\ObjectManager;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class UserConverter
......@@ -539,7 +539,7 @@ once a response is returned, the following handlers are ignored.
.. note::
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::
......
......@@ -9,7 +9,7 @@
processIsolation="false"
stopOnFailure="false"
syntaxCheck="false"
bootstrap="tests/bootstrap.php"
bootstrap="vendor/autoload.php"
>
<testsuites>
<testsuite name="Silex Test Suite">
......
......@@ -13,6 +13,7 @@ namespace Silex;
use Pimple\Container;
use Pimple\ServiceProviderInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpKernel\HttpKernel;
use Symfony\Component\HttpKernel\HttpKernelInterface;
......@@ -84,7 +85,6 @@ class Application extends Container implements HttpKernelInterface, TerminableIn
return new ExceptionHandler($app['debug']);
};
$this['callback_resolver'] = function () use ($app) {
return new CallbackResolver($app);
};
......@@ -253,7 +253,7 @@ class Application extends Container implements HttpKernelInterface, TerminableIn
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);
return $dispatcher;
......@@ -304,7 +304,12 @@ class Application extends Container implements HttpKernelInterface, TerminableIn
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);
}
......@@ -454,15 +459,15 @@ class Application extends Container implements HttpKernelInterface, TerminableIn
public function mount($prefix, $controllers)
{
if ($controllers instanceof ControllerProviderInterface) {
$controllers = $controllers->connect($this);
$connectedControllers = $controllers->connect($this);
if (!$controllers instanceof ControllerCollection) {
throw new \LogicException('The "connect" method of the ControllerProviderInterface must return a ControllerCollection.');
}
if (!$connectedControllers instanceof 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) {
throw new \LogicException('The "mount" method takes either a ControllerCollection or a ControllerProviderInterface instance.');
$controllers = $connectedControllers;
} elseif (!$controllers instanceof ControllerCollection) {
throw new \LogicException('The "mount" method takes either a "ControllerCollection" or a "ControllerProviderInterface" instance.');
}
$this['controllers']->mount($prefix, $controllers);
......
......@@ -12,6 +12,7 @@
namespace Silex\Application;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException;
use Symfony\Component\Security\Core\User\UserInterface;
/**
......@@ -30,7 +31,7 @@ trait SecurityTrait
*/
public function user()
{
if (null === $token = $this['security']->getToken()) {
if (null === $token = $this['security.token_storage']->getToken()) {
return;
}
......@@ -55,4 +56,19 @@ trait SecurityTrait
{
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;
* __call() forwards method-calls to Route, but returns instance of Controller
* listing Route's methods below, so that IDEs know they are valid
*
* @method \Silex\Controller assert(string $variable, string $regexp)
* @method \Silex\Controller value(string $variable, mixed $default)
* @method \Silex\Controller convert(string $variable, mixed $callback)
* @method \Silex\Controller method(string $method)
* @method \Silex\Controller requireHttp()
* @method \Silex\Controller requireHttps()
* @method \Silex\Controller before(mixed $callback)
* @method \Silex\Controller after(mixed $callback)
* @method Controller assert(string $variable, string $regexp)
* @method Controller value(string $variable, mixed $default)
* @method Controller convert(string $variable, mixed $callback)
* @method Controller method(string $method)
* @method Controller requireHttp()
* @method Controller requireHttps()
* @method Controller before(mixed $callback)
* @method Controller after(mixed $callback)
* @author Igor Wiedler <igor@wiedler.ch>
*/
class Controller
......@@ -106,10 +106,9 @@ class Controller
public function generateRouteName($prefix)
{
$requirements = $this->route->getRequirements();
$method = isset($requirements['_method']) ? $requirements['_method'] : '';
$methods = implode('_', $this->route->getMethods());
$routeName = $prefix.$method.$this->route->getPath();
$routeName = $prefix.$methods.$this->route->getPath();
$routeName = str_replace(array('/', ':', '|', '-'), '_', $routeName);
$routeName = preg_replace('/[^a-z0-9A-Z_.]+/', '', $routeName);
......
......@@ -24,14 +24,14 @@ use Symfony\Component\HttpFoundation\Request;
* __call() forwards method-calls to Route, but returns instance of ControllerCollection
* listing Route's methods below, so that IDEs know they are valid
*
* @method \Silex\ControllerCollection assert(string $variable, string $regexp)
* @method \Silex\ControllerCollection value(string $variable, mixed $default)
* @method \Silex\ControllerCollection convert(string $variable, mixed $callback)
* @method \Silex\ControllerCollection method(string $method)
* @method \Silex\ControllerCollection requireHttp()
* @method \Silex\ControllerCollection requireHttps()
* @method \Silex\ControllerCollection before(mixed $callback)
* @method \Silex\ControllerCollection after(mixed $callback)
* @method ControllerCollection assert(string $variable, string $regexp)
* @method ControllerCollection value(string $variable, mixed $default)
* @method ControllerCollection convert(string $variable, mixed $callback)
* @method ControllerCollection method(string $method)
* @method ControllerCollection requireHttp()
* @method ControllerCollection requireHttps()
* @method ControllerCollection before(mixed $callback)
* @method ControllerCollection after(mixed $callback)
*
* @author Igor Wiedler <igor@wiedler.ch>
* @author Fabien Potencier <fabien@symfony.com>
......
......@@ -32,6 +32,9 @@ class ExceptionHandler implements EventSubscriberInterface
$this->enabled = true;
}
/**
* @deprecated since 1.3, to be removed in 2.0
*/
public function disable()
{
$this->enabled = false;
......
......@@ -33,7 +33,6 @@ class DoctrineServiceProvider implements ServiceProviderInterface
'host' => 'localhost',
'user' => 'root',
'password' => null,
'port' => 3306,
);
$app['dbs.options.initializer'] = $app->protect(function () use ($app) {
......
......@@ -20,6 +20,9 @@ use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationExtension;
use Symfony\Component\Form\Extension\Validator\ValidatorExtension as FormValidatorExtension;
use Symfony\Component\Form\Forms;
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.
......@@ -78,7 +81,10 @@ class FormServiceProvider implements ServiceProviderInterface
if (isset($app['translator']) && method_exists($app['translator'], 'addResource')) {
$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
};
$app['form.csrf_provider'] = function ($app) {
if (!class_exists('Symfony\Component\Form\Extension\DataCollector\DataCollectorExtension')) {
// Symfony 2.3
if (isset($app['session'])) {
return new SessionCsrfProvider($app['session'], $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;
use Symfony\Component\HttpKernel\HttpCache\Esi;
use Symfony\Component\HttpKernel\HttpCache\Store;
use Symfony\Component\HttpKernel\EventListener\EsiListener;
use Symfony\Component\HttpKernel\EventListener\SurrogateListener;
/**
* Symfony HttpKernel component Provider for HTTP cache.
......@@ -48,6 +49,10 @@ class HttpCacheServiceProvider implements ServiceProviderInterface, EventListene
};
$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']);
};
......
......@@ -82,7 +82,7 @@ class RememberMeServiceProvider implements ServiceProviderInterface, EventListen
$app['security.authentication_listener.remember_me._proto'] = $app->protect(function ($providerKey) use ($app) {
return function () use ($app, $providerKey) {
$listener = new RememberMeListener(
$app['security'],
$app['security.token_storage'],
$app['security.remember_me.service.'.$providerKey],
$app['security.authentication_manager'],
$app['logger'],
......
......@@ -20,6 +20,7 @@ use Silex\Api\EventListenerProviderInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\RequestMatcher;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Core\SecurityContext;
use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\Security\Core\User\UserChecker;
......@@ -32,6 +33,8 @@ use Symfony\Component\Security\Core\Authentication\AuthenticationProviderManager
use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolver;
use Symfony\Component\Security\Http\Authentication\DefaultAuthenticationSuccessHandler;
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\AuthenticatedVoter;
use Symfony\Component\Security\Core\Authorization\AccessDecisionManager;
......@@ -77,9 +80,31 @@ class SecurityServiceProvider implements ServiceProviderInterface, EventListener
$app['security.access_rules'] = array();
$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) {
// Deprecated, to be removed in 2.0
return new SecurityContext($app['security.authentication_manager'], $app['security.access_manager']);
};
}
$app['security.authentication_manager'] = function ($app) {
$manager = new AuthenticationProviderManager($app['security.authentication_providers']);
......@@ -284,7 +309,7 @@ class SecurityServiceProvider implements ServiceProviderInterface, EventListener
$app['security.access_listener'] = function ($app) {
return new AccessListener(
$app['security'],
$app['security.token_storage'],
$app['security.access_manager'],
$app['security.access_map'],
$app['security.authentication_manager'],
......@@ -311,7 +336,7 @@ class SecurityServiceProvider implements ServiceProviderInterface, EventListener
};
$app['security.session_strategy'] = function ($app) {
return new SessionAuthenticationStrategy('migrate');
return new SessionAuthenticationStrategy(SessionAuthenticationStrategy::MIGRATE);
};
$app['security.http_utils'] = function ($app) {
......@@ -319,14 +344,19 @@ class SecurityServiceProvider implements ServiceProviderInterface, EventListener
};
$app['security.last_error'] = $app->protect(function (Request $request) {
if ($request->attributes->has(SecurityContextInterface::AUTHENTICATION_ERROR)) {
return $request->attributes->get(SecurityContextInterface::AUTHENTICATION_ERROR)->getMessage();
if (class_exists('Symfony\Component\Security\Core\Security')) {
$error = Security::AUTHENTICATION_ERROR;
} else {
$error = SecurityContextInterface::AUTHENTICATION_ERROR;
}
if ($request->attributes->has($error)) {
return $request->attributes->get($error)->getMessage();
}
$session = $request->getSession();
if ($session && $session->has(SecurityContextInterface::AUTHENTICATION_ERROR)) {
$error = $session->get(SecurityContextInterface::AUTHENTICATION_ERROR)->getMessage();
$session->remove(SecurityContextInterface::AUTHENTICATION_ERROR);
if ($session && $session->has($error)) {
$error = $session->get($error)->getMessage();
$session->remove($error);
return $error;
}
......@@ -337,7 +367,7 @@ class SecurityServiceProvider implements ServiceProviderInterface, EventListener
$app['security.context_listener._proto'] = $app->protect(function ($providerKey, $userProviders) use ($app) {
return function () use ($app, $userProviders, $providerKey) {
return new ContextListener(
$app['security'],
$app['security.token_storage'],
$userProviders,
$providerKey,
$app['logger'],
......@@ -360,7 +390,7 @@ class SecurityServiceProvider implements ServiceProviderInterface, EventListener
$app['security.exception_listener._proto'] = $app->protect(function ($entryPoint, $name, $accessDeniedHandler = null) use ($app) {
return function () use ($app, $entryPoint, $name, $accessDeniedHandler) {
return new ExceptionListener(
$app['security'],
$app['security.token_storage'],
$app['security.trust_resolver'],
$app['security.http_utils'],
$name,
......@@ -414,7 +444,7 @@ class SecurityServiceProvider implements ServiceProviderInterface, EventListener
}
return new $class(
$app['security'],
$app['security.token_storage'],
$app['security.authentication_manager'],
isset($app['security.session_strategy.'.$name]) ? $app['security.session_strategy.'.$name] : $app['security.session_strategy'],
$app['security.http_utils'],
......@@ -432,7 +462,7 @@ class SecurityServiceProvider implements ServiceProviderInterface, EventListener
$app['security.authentication_listener.http._proto'] = $app->protect(function ($providerKey, $options) use ($app) {
return function () use ($app, $providerKey, $options) {
return new BasicAuthenticationListener(
$app['security'],
$app['security.token_storage'],
$app['security.authentication_manager'],
$providerKey,
$app['security.entry_point.'.$providerKey.'.http'],
......@@ -444,7 +474,7 @@ class SecurityServiceProvider implements ServiceProviderInterface, EventListener
$app['security.authentication_listener.anonymous._proto'] = $app->protect(function ($providerKey, $options) use ($app) {
return function () use ($app, $providerKey, $options) {
return new AnonymousAuthenticationListener(
$app['security'],
$app['security.token_storage'],
$providerKey,
$app['logger']
);
......@@ -473,7 +503,7 @@ class SecurityServiceProvider implements ServiceProviderInterface, EventListener
}
$listener = new LogoutListener(
$app['security'],
$app['security.token_storage'],
$app['security.http_utils'],
$app['security.authentication.logout_handler.'.$name],
$options,
......@@ -489,7 +519,7 @@ class SecurityServiceProvider implements ServiceProviderInterface, EventListener
$app['security.authentication_listener.switch_user._proto'] = $app->protect(function ($name, $options) use ($app, $that) {
return function () use ($app, $name, $options, $that) {
return new SwitchUserListener(
$app['security'],
$app['security.token_storage'],
$app['security.user_provider.'.$name],
$app['security.user_checker'],
$name,
......@@ -537,7 +567,7 @@ class SecurityServiceProvider implements ServiceProviderInterface, EventListener
if (isset($app['validator'])) {
$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'])) {
......
......@@ -24,11 +24,11 @@ class Translator extends BaseTranslator
{
protected $app;
public function __construct(Container $app, MessageSelector $selector)
public function __construct(Container $app, MessageSelector $selector, $cacheDir = null, $debug = false)
{
$this->app = $app;
parent::__construct(null, $selector);
parent::__construct(null, $selector, $cacheDir, $debug);
}
public function getLocale()
......
......@@ -32,6 +32,13 @@ class TranslationServiceProvider implements ServiceProviderInterface
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->setFallbackLocales($app['locale_fallbacks']);
$translator->addLoader('array', new ArrayLoader());
......@@ -52,5 +59,6 @@ class TranslationServiceProvider implements ServiceProviderInterface
$app['translator.domains'] = array();
$app['locale_fallbacks'] = array('en');
$app['translator.cache_dir'] = null;
}
}
......@@ -60,8 +60,8 @@ class TwigServiceProvider implements ServiceProviderInterface
$twig->addExtension(new TranslationExtension($app['translator']));
}
if (isset($app['security'])) {
$twig->addExtension(new SecurityExtension($app['security']));
if (isset($app['security.authorization_checker'])) {
$twig->addExtension(new SecurityExtension($app['security.authorization_checker']));
}
if (isset($app['fragment.handler'])) {
......
......@@ -14,10 +14,13 @@ namespace Silex\Provider;
use Pimple\Container;
use Pimple\ServiceProviderInterface;
use Silex\Provider\Validator\ConstraintValidatorFactory;
use Silex\Application;
use Symfony\Component\Validator\Validator;
use Symfony\Component\Validator\DefaultTranslator;
use Symfony\Component\Validator\Mapping\ClassMetadataFactory;
use Symfony\Component\Validator\Mapping\Factory\LazyLoadingMetadataFactory;
use Symfony\Component\Validator\Mapping\Loader\StaticMethodLoader;
use Symfony\Component\Validator\Validation;
/**
* Symfony Validator component Provider.
......@@ -29,22 +32,35 @@ class ValidatorServiceProvider implements ServiceProviderInterface
public function register(Container $app)
{
$app['validator'] = function ($app) {
if (isset($app['translator']) && method_exists($app['translator'], 'addResource')) {
$r = new \ReflectionClass('Symfony\Component\Validator\Validator');
if (isset($app['translator'])) {
$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(
$app['validator.mapping.class_metadata_factory'],
$app['validator.validator_factory'],
isset($app['translator']) ? $app['translator'] : new DefaultTranslator(),
'validators',
$app['validator.object_initializers']
);
return $builder;
};
$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());
};
......
......@@ -23,7 +23,7 @@ trait SecurityTrait
public function secure($roles)
{
$this->before(function ($request, $app) use ($roles) {
if (!$app['security']->isGranted($roles)) {
if (!$app['security.authorization_checker']->isGranted($roles)) {
throw new AccessDeniedException();
}
});
......
......@@ -21,6 +21,11 @@ use Symfony\Component\HttpKernel\HttpKernel;
*/
abstract class WebTestCase extends \PHPUnit_Framework_TestCase
{
/**
* Application instance.
*
* @var Application
*/
protected $app;
/**
......
......@@ -13,6 +13,7 @@ namespace Silex\Tests\Application;
use Silex\Provider\SecurityServiceProvider;
use Symfony\Component\Security\Core\User\User;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\HttpFoundation\Request;
/**
......@@ -28,7 +29,9 @@ class SecurityTraitTest extends \PHPUnit_Framework_TestCase
{
$request = Request::create('/');
$app = $this->createApplication();
$app = $this->createApplication(array(
'fabien' => array('ROLE_ADMIN', '5FZ2Z8QIkA7UTZ4BYkoC+GsReLf569mSKDsfods6LYQ8t+a8EW9oaircfMpmaLbPBh4FOBiiFyLfuZmTSUwzZg=='),
));
$app->get('/', function () { return 'foo'; });
$app->handle($request);
$this->assertNull($app->user());
......@@ -40,24 +43,83 @@ class SecurityTraitTest extends \PHPUnit_Framework_TestCase
$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->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');
$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->register(new SecurityServiceProvider(), array(
'security.firewalls' => array(
'default' => array(
'http' => true,
'users' => array(
'fabien' => array('ROLE_ADMIN', '5FZ2Z8QIkA7UTZ4BYkoC+GsReLf569mSKDsfods6LYQ8t+a8EW9oaircfMpmaLbPBh4FOBiiFyLfuZmTSUwzZg=='),
),
'users' => $users,
),
),
));
......
......@@ -13,6 +13,7 @@ namespace Silex\Tests;
use Silex\Application;
use Silex\ControllerCollection;
use Silex\Api\ControllerProviderInterface;
use Silex\Route;
use Silex\Provider\MonologServiceProvider;
use Symfony\Component\HttpFoundation\Request;
......@@ -460,6 +461,26 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase
$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()
{
$app = new Application();
......@@ -480,7 +501,7 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase
public function testGetRouteCollectionWithRouteWithoutController()
{
$app = new Application();
$app['exception_handler']->disable();
unset($app['exception_handler']);
$app->match('/')->bind('homepage');
$app->handle(Request::create('/'));
}
......@@ -518,3 +539,11 @@ class FooController
return 'Hello '.$app->escape($name);
}
}
class IncorrectControllerCollection implements ControllerProviderInterface
{
public function connect(Application $app)
{
return;
}
}
......@@ -13,7 +13,6 @@ namespace Silex\Tests;
use Silex\Application;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Silex\Provider\ServiceControllerServiceProvider;
/**
......
......@@ -129,11 +129,11 @@ class ControllerCollectionTest extends \PHPUnit_Framework_TestCase
$controllers->requireHttp();
$controller = $controllers->match('/{id}/{name}/{extra}', function () {})->requireHttps();
$this->assertEquals('https', $controller->getRoute()->getRequirement('_scheme'));
$this->assertEquals(array('https'), $controller->getRoute()->getSchemes());
$controllers->requireHttp();
$this->assertEquals('http', $controller->getRoute()->getRequirement('_scheme'));
$this->assertEquals(array('http'), $controller->getRoute()->getSchemes());
}
public function testBefore()
......
......@@ -91,8 +91,8 @@ class ControllerTest extends \PHPUnit_Framework_TestCase
public function provideRouteAndExpectedRouteName()
{
return array(
array(new Route('/Invalid%Symbols#Stripped', array(), array('_method' => 'POST')), 'POST_InvalidSymbolsStripped'),
array(new Route('/post/{id}', array(), array('_method' => 'GET')), 'GET_post_id'),
array(new Route('/Invalid%Symbols#Stripped', array(), array(), array(), '', array(), array('POST')), 'POST_InvalidSymbolsStripped'),
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('/underscores_and.periods'), '_underscores_and.periods'),
);
......
......@@ -107,7 +107,7 @@ class ExceptionHandlerTest extends \PHPUnit_Framework_TestCase
public function testNoExceptionHandler()
{
$app = new Application();
$app['exception_handler']->disable();
unset($app['exception_handler']);
$app->match('/foo', function () {
throw new \RuntimeException('foo exception');
......@@ -207,6 +207,8 @@ class ExceptionHandlerTest extends \PHPUnit_Framework_TestCase
$this->fail('->handle() should not catch exceptions where an empty error handler was supplied');
} catch (\RuntimeException $e) {
$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');
......@@ -261,7 +263,7 @@ class ExceptionHandlerTest extends \PHPUnit_Framework_TestCase
// just making sure the dispatcher gets created
});
$app['exception_handler']->disable();
unset($app['exception_handler']);
try {
$request = Request::create('/foo');
......
......@@ -234,6 +234,20 @@ class MiddlewareTest extends \PHPUnit_Framework_TestCase
$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()
{
$app = new Application();
......
......@@ -14,12 +14,17 @@ namespace Silex\Tests\Provider;
use Silex\Application;
use Silex\Provider\FormServiceProvider;
use Silex\Provider\TranslationServiceProvider;
use Silex\Provider\ValidatorServiceProvider;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface;
use Symfony\Component\Form\FormTypeGuesserChain;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\OptionsResolver\OptionsResolver;
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
{
......@@ -110,7 +115,35 @@ class FormServiceProviderTest extends \PHPUnit_Framework_TestCase
))));
$this->assertFalse($form->isValid());
$r = new \ReflectionMethod($form, 'getErrors');
if (!$r->getNumberOfParameters()) {
$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
}
}
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()
{
return 'file';
......@@ -134,12 +181,19 @@ class DummyFormTypeExtension extends AbstractTypeExtension
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
if (!method_exists($resolver, 'setDefined')) {
$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)
{
return $intention.'123';
......@@ -149,4 +203,27 @@ class FakeCsrfProvider implements CsrfProviderInterface
{
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
$this->assertTrue($app['monolog.handler']->hasDebug('> GET /foo'));
$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()
......
......@@ -63,7 +63,7 @@ class RememberMeServiceProviderTest extends WebTestCase
$app = new Application();
$app['debug'] = true;
$app['exception_handler']->disable();
unset($app['exception_handler']);
$app->register(new SessionServiceProvider(), array(
'session.test' => true,
......@@ -84,9 +84,9 @@ class RememberMeServiceProviderTest extends WebTestCase
);
$app->get('/', function () use ($app) {
if ($app['security']->isGranted('IS_AUTHENTICATED_FULLY')) {
if ($app['security.authorization_checker']->isGranted('IS_AUTHENTICATED_FULLY')) {
return 'AUTHENTICATED_FULLY';
} elseif ($app['security']->isGranted('IS_AUTHENTICATED_REMEMBERED')) {
} elseif ($app['security.authorization_checker']->isGranted('IS_AUTHENTICATED_REMEMBERED')) {
return 'AUTHENTICATED_REMEMBERED';
} else {
return 'AUTHENTICATED_ANONYMOUSLY';
......
......@@ -226,15 +226,15 @@ class SecurityServiceProviderTest extends WebTestCase
});
$app->get('/', function () use ($app) {
$user = $app['security']->getToken()->getUser();
$user = $app['security.token_storage']->getToken()->getUser();
$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';
}
if ($app['security']->isGranted('ROLE_ADMIN')) {
if ($app['security.authorization_checker']->isGranted('ROLE_ADMIN')) {
$content .= 'ADMIN';
}
......@@ -271,15 +271,14 @@ class SecurityServiceProviderTest extends WebTestCase
));
$app->get('/', function () use ($app) {
$user = $app['security']->getToken()->getUser();
$user = $app['security.token_storage']->getToken()->getUser();
$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';
}
if ($app['security']->isGranted('ROLE_ADMIN')) {
if ($app['security.authorization_checker']->isGranted('ROLE_ADMIN')) {
$content .= 'ADMIN';
}
......
......@@ -94,7 +94,7 @@ class SessionServiceProviderTest extends WebTestCase
});
$app['debug'] = true;
$app['exception_handler']->disable();
unset($app['exception_handler']);
$client = new Client($app);
......
......@@ -13,6 +13,7 @@ namespace Silex\Tests\Provider;
use Silex\Application;
use Silex\Provider\TwigServiceProvider;
use Silex\Provider\HttpFragmentServiceProvider;
use Symfony\Component\HttpFoundation\Request;
/**
......
......@@ -12,8 +12,10 @@
namespace Silex\Tests\Provider;
use Silex\Application;
use Silex\Provider\TranslationServiceProvider;
use Silex\Provider\ValidatorServiceProvider;
use Silex\Provider\FormServiceProvider;
use Symfony\Component\Translation\Exception\NotFoundResourceException;
use Symfony\Component\Validator\Constraints as Assert;
use Silex\Tests\Provider\ValidatorServiceProviderTest\Constraint\Custom;
use Silex\Tests\Provider\ValidatorServiceProviderTest\Constraint\CustomValidator;
......@@ -67,7 +69,7 @@ class ValidatorServiceProviderTest extends \PHPUnit_Framework_TestCase
*/
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
->getForm()
;
$form->bind(array('email' => $email));
$form->submit(array('email' => $email));
$this->assertEquals($isValid, $form->isValid());
$this->assertEquals($nbGlobalError, count($form->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()
{
// Email, form is valid , nb global error, nb email error
......
......@@ -100,7 +100,7 @@ class RouterTest extends \PHPUnit_Framework_TestCase
public function testMissingRoute()
{
$app = new Application();
$app['exception_handler']->disable();
unset($app['exception_handler']);
$request = Request::create('/baz');
$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