Merge branch '3.4'

* 3.4:
  [Bridge\Doctrine][FrameworkBundle] Deprecate some remaining uses of ContainerAwareTrait
  [FrameworkBundle] Fix bad interface hint in AbstractController
  [VarDumper] deprecate MongoCaster
  [HttpFoundation] deprecate using  with the legacy mongo extension; use it with the mongodb/mongodb package and ext-mongodb instead
  Fix BC layer
  Reset profiler.
  [DI] Improve some deprecation messages
  [DI] remove inheritdoc from dumped container
  [Config] Fix dumped files invalidation by OPCache
  [Security] Add Guard authenticator <supports> method
  [Cache] Fix race condition in TagAwareAdapter
  [DI] Allow setting any public non-initialized services
  [Yaml] parse references on merge keys
  treat trailing backslashes in multi-line strings
  [FrameworkBundle] Expose dotenv in bin/console about
  fix refreshing line numbers for the inline parser
  fix version in changelog
  [FrameworkBundle] Make Controller helpers final
  [DoctrineBridge] Deprecate DbalSessionHandler
This commit is contained in:
Nicolas Grekas 2017-10-05 17:11:25 +02:00
commit 522d079110
104 changed files with 1272 additions and 544 deletions

View File

@ -63,6 +63,12 @@ Debug
* Support for stacked errors in the `ErrorHandler` is deprecated and will be removed in Symfony 4.0.
EventDispatcher
---------------
* Implementing `TraceableEventDispatcherInterface` without the `reset()` method
is deprecated and will be unsupported in 4.0.
Filesystem
----------
@ -234,6 +240,9 @@ HttpFoundation
* `NativeSessionStorage::setSaveHandler()` now takes an instance of `\SessionHandlerInterface` as argument.
Not passing it is deprecated and will throw a `TypeError` in 4.0.
* Using `Symfony\Component\HttpFoundation\Session\Storage\Handler\MongoDbSessionHandler` with the legacy mongo extension
has been deprecated and will be removed in 4.0. Use it with the mongodb/mongodb package and ext-mongodb instead.
HttpKernel
----------
@ -270,6 +279,10 @@ HttpKernel
* The `Symfony\Component\HttpKernel\Config\EnvParametersResource` class has been deprecated and will be removed in 4.0.
* Implementing `DataCollectorInterface` without a `reset()` method has been deprecated and will be unsupported in 4.0.
* Implementing `DebugLoggerInterface` without a `clear()` method has been deprecated and will be unsupported in 4.0.
* The `ChainCacheClearer::add()` method has been deprecated and will be removed in 4.0,
inject the list of clearers as a constructor argument instead.
@ -295,6 +308,9 @@ Security
* Deprecated the HTTP digest authentication: `NonceExpiredException`,
`DigestAuthenticationListener` and `DigestAuthenticationEntryPoint` will be
removed in 4.0. Use another authentication system like `http_basic` instead.
* The `GuardAuthenticatorInterface` has been deprecated and will be removed in 4.0.
Use `AuthenticatorInterface` instead.
SecurityBundle
--------------
@ -320,11 +336,11 @@ SecurityBundle
* Deprecated the HTTP digest authentication: `HttpDigestFactory` will be removed in 4.0.
Use another authentication system like `http_basic` instead.
* Deprecated setting the `switch_user.stateless` option to false when the firewall is `stateless`.
Setting it to false will have no effect in 4.0.
* Not configuring explicitly the provider on a firewall is ambiguous when there is more than one registered provider.
* Not configuring explicitly the provider on a firewall is ambiguous when there is more than one registered provider.
Using the first configured provider is deprecated since 3.4 and will throw an exception on 4.0.
Explicitly configure the provider to use on your firewalls.

View File

@ -192,6 +192,8 @@ EventDispatcher
* The `ContainerAwareEventDispatcher` class has been removed.
Use `EventDispatcher` with closure factories instead.
* The `reset()` method has been added to `TraceableEventDispatcherInterface`.
ExpressionLanguage
------------------
@ -540,6 +542,9 @@ HttpFoundation
* `NativeSessionStorage::setSaveHandler()` now requires an instance of `\SessionHandlerInterface` as argument.
* The `Symfony\Component\HttpFoundation\Session\Storage\Handler\MongoDbSessionHandler` does not work with the legacy
mongo extension anymore. It requires mongodb/mongodb package and ext-mongodb.
HttpKernel
----------
@ -611,6 +616,10 @@ HttpKernel
* The `Symfony\Component\HttpKernel\Config\EnvParametersResource` class has been removed.
* The `reset()` method has been added to `Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface`.
* The `clear()` method has been added to `Symfony\Component\HttpKernel\Log\DebugLoggerInterface`.
* The `ChainCacheClearer::add()` method has been removed,
inject the list of clearers as a constructor argument instead.
@ -673,6 +682,9 @@ Security
`DigestAuthenticationListener` and `DigestAuthenticationEntryPoint` classes
have been removed. Use another authentication system like `http_basic` instead.
* The `GuardAuthenticatorInterface` interface has been removed.
Use `AuthenticatorInterface` instead.
SecurityBundle
--------------
@ -693,10 +705,10 @@ SecurityBundle
* Removed the HTTP digest authentication system. The `HttpDigestFactory` class
has been removed. Use another authentication system like `http_basic` instead.
* The `switch_user.stateless` option is now always true if the firewall is stateless.
* Not configuring explicitly the provider on a firewall is ambiguous when there is more than one registered provider.
* Not configuring explicitly the provider on a firewall is ambiguous when there is more than one registered provider.
The first configured provider is not used anymore and an exception is thrown instead.
Explicitly configure the provider to use on your firewalls.

View File

@ -20,7 +20,7 @@
"ext-xml": "*",
"doctrine/common": "~2.4",
"fig/link-util": "^1.0",
"twig/twig": "~1.34|~2.4",
"twig/twig": "^1.35|^2.4.4",
"psr/cache": "~1.0",
"psr/container": "^1.0",
"psr/link": "^1.0",

View File

@ -28,6 +28,10 @@ class DoctrineDataCollector extends DataCollector
private $registry;
private $connections;
private $managers;
/**
* @var DebugStack[]
*/
private $loggers = array();
public function __construct(ManagerRegistry $registry)
@ -65,6 +69,16 @@ class DoctrineDataCollector extends DataCollector
);
}
public function reset()
{
$this->data = array();
foreach ($this->loggers as $logger) {
$logger->queries = array();
$logger->currentQuery = 0;
}
}
public function getManagers()
{
return $this->data['managers'];

View File

@ -11,6 +11,8 @@
namespace Symfony\Bridge\Doctrine\HttpFoundation;
@trigger_error(sprintf('The class %s is deprecated since version 3.4 and will be removed in 4.0. Use Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler instead.', DbalSessionHandler::class), E_USER_DEPRECATED);
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Driver\DriverException;
use Doctrine\DBAL\Driver\ServerInfoAwareConnection;
@ -25,6 +27,8 @@ use Doctrine\DBAL\Platforms\SQLServer2008Platform;
* @author Fabien Potencier <fabien@symfony.com>
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
* @author Tobias Schultze <http://tobion.de>
*
* @deprecated since version 3.4, to be removed in 4.0. Use Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler instead.
*/
class DbalSessionHandler implements \SessionHandlerInterface
{

View File

@ -11,12 +11,16 @@
namespace Symfony\Bridge\Doctrine\HttpFoundation;
@trigger_error(sprintf('The class %s is deprecated since version 3.4 and will be removed in 4.0. Use Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler::createTable instead.', DbalSessionHandlerSchema::class), E_USER_DEPRECATED);
use Doctrine\DBAL\Schema\Schema;
/**
* DBAL Session Storage Schema.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*
* @deprecated since version 3.4, to be removed in 4.0. Use Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler::createTable instead.
*/
final class DbalSessionHandlerSchema extends Schema
{

View File

@ -12,9 +12,10 @@
namespace Symfony\Bridge\Doctrine;
use ProxyManager\Proxy\LazyLoadingInterface;
use Psr\Container\ContainerInterface;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerAwareTrait;
use Symfony\Component\DependencyInjection\ContainerInterface as SymfonyContainerInterface;
use Doctrine\Common\Persistence\AbstractManagerRegistry;
/**
@ -24,7 +25,21 @@ use Doctrine\Common\Persistence\AbstractManagerRegistry;
*/
abstract class ManagerRegistry extends AbstractManagerRegistry implements ContainerAwareInterface
{
use ContainerAwareTrait;
/**
* @var ContainerInterface
*/
protected $container;
/**
* @deprecated since version 3.4, to be removed in 4.0 alongside with the ContainerAwareInterface type.
* @final since version 3.4
*/
public function setContainer(SymfonyContainerInterface $container = null)
{
@trigger_error(sprintf('The "%s()" method is deprecated since version 3.4 and will be removed in 4.0. Inject a PSR-11 container using the constructor instead.', __METHOD__), E_USER_DEPRECATED);
$this->container = $container;
}
/**
* {@inheritdoc}

View File

@ -101,6 +101,20 @@ class DoctrineDataCollectorTest extends TestCase
$this->assertTrue($collectedQueries['default'][1]['explainable']);
}
public function testReset()
{
$queries = array(
array('sql' => 'SELECT * FROM table1', 'params' => array(), 'types' => array(), 'executionMS' => 1),
);
$c = $this->createCollector($queries);
$c->collect(new Request(), new Response());
$c->reset();
$c->collect(new Request(), new Response());
$this->assertEquals(array('default' => array()), $c->getQueries());
}
/**
* @dataProvider paramProvider
*/

View File

@ -18,6 +18,8 @@ use Symfony\Bridge\Doctrine\HttpFoundation\DbalSessionHandler;
* Test class for DbalSessionHandler.
*
* @author Drak <drak@zikula.org>
*
* @group legacy
*/
class DbalSessionHandlerTest extends TestCase
{

View File

@ -31,7 +31,7 @@ class ManagerRegistryTest extends TestCase
$container = new \LazyServiceProjectServiceContainer();
$registry = new TestManagerRegistry('name', array(), array('defaultManager' => 'foo'), 'defaultConnection', 'defaultManager', 'proxyInterfaceName');
$registry->setContainer($container);
$registry->setTestContainer($container);
$foo = $container->get('foo');
$foo->bar = 123;
@ -46,6 +46,11 @@ class ManagerRegistryTest extends TestCase
class TestManagerRegistry extends ManagerRegistry
{
public function setTestContainer($container)
{
$this->container = $container;
}
public function getAliasNamespace($alias)
{
return 'Foo';

View File

@ -45,6 +45,16 @@ class Logger extends BaseLogger implements DebugLoggerInterface
return 0;
}
/**
* {@inheritdoc}
*/
public function clear()
{
if (($logger = $this->getDebugLogger()) && method_exists($logger, 'clear')) {
$logger->clear();
}
}
/**
* Returns a DebugLoggerInterface instance if one is registered with this logger.
*

View File

@ -55,4 +55,13 @@ class DebugProcessor implements DebugLoggerInterface
{
return $this->errorCount;
}
/**
* {@inheritdoc}
*/
public function clear()
{
$this->records = array();
$this->errorCount = 0;
}
}

View File

@ -78,4 +78,17 @@ class LoggerTest extends TestCase
$this->assertEquals('test', $record['message']);
$this->assertEquals(Logger::INFO, $record['priority']);
}
public function testClear()
{
$handler = new TestHandler();
$logger = new Logger('test', array($handler));
$logger->pushProcessor(new DebugProcessor());
$logger->addInfo('test');
$logger->clear();
$this->assertEmpty($logger->getLogs());
$this->assertSame(0, $logger->countErrors());
}
}

View File

@ -44,6 +44,16 @@ class TwigDataCollector extends DataCollector implements LateDataCollectorInterf
{
}
/**
* {@inheritdoc}
*/
public function reset()
{
$this->profile->reset();
$this->computed = null;
$this->data = array();
}
/**
* {@inheritdoc}
*/

View File

@ -17,7 +17,7 @@
],
"require": {
"php": "^7.1.3",
"twig/twig": "~1.34|~2.4"
"twig/twig": "^1.35|^2.4.4"
},
"require-dev": {
"fig/link-util": "^1.0",

View File

@ -81,6 +81,7 @@ CHANGELOG
and `YamlLintCommand` classes have been marked as final
* Added `asset.request_context.base_path` and `asset.request_context.secure` parameters
to provide a default request context in case the stack is empty (similar to `router.request_context.*` parameters)
* Display environment variables managed by `Dotenv` in `AboutCommand`
3.3.0
-----

View File

@ -36,7 +36,19 @@ class AboutCommand extends Command
*/
protected function configure()
{
$this->setDescription('Displays information about the current project');
$this
->setDescription('Displays information about the current project')
->setHelp(<<<'EOT'
The <info>%command.name%</info> command displays information about the current Symfony project.
The <info>PHP</info> section displays important configuration that could affect your application. The values might
be different between web and CLI.
The <info>Environment</info> section displays the current environment variables managed by Symfony Dotenv. It will not
be shown if no variables were found. The values might be different between web and CLI.
EOT
)
;
}
/**
@ -49,7 +61,7 @@ class AboutCommand extends Command
/** @var $kernel KernelInterface */
$kernel = $this->getApplication()->getKernel();
$io->table(array(), array(
$rows = array(
array('<info>Symfony</>'),
new TableSeparator(),
array('Version', Kernel::VERSION),
@ -76,7 +88,19 @@ class AboutCommand extends Command
array('OPcache', extension_loaded('Zend OPcache') && ini_get('opcache.enable') ? 'true' : 'false'),
array('APCu', extension_loaded('apcu') && ini_get('apc.enabled') ? 'true' : 'false'),
array('Xdebug', extension_loaded('xdebug') ? 'true' : 'false'),
));
);
if ($dotenv = self::getDotEnvVars()) {
$rows = array_merge($rows, array(
new TableSeparator(),
array('<info>Environment (.env)</>'),
new TableSeparator(),
), array_map(function ($value, $name) {
return array($name, $value);
}, $dotenv, array_keys($dotenv)));
}
$io->table(array(), $rows);
}
private static function formatPath($path, $baseDir = null)
@ -104,4 +128,16 @@ class AboutCommand extends Command
return false !== $date && new \DateTime() > $date->modify('last day of this month 23:59:59');
}
private static function getDotEnvVars()
{
$vars = array();
foreach (explode(',', getenv('SYMFONY_DOTENV_VARS')) as $name) {
if ('' !== $name && false !== $value = getenv($name)) {
$vars[$name] = $value;
}
}
return $vars;
}
}

View File

@ -26,30 +26,6 @@ abstract class Controller implements ContainerAwareInterface
use ContainerAwareTrait;
use ControllerTrait;
/**
* Returns true if the service id is defined.
*
* @param string $id The service id
*
* @return bool true if the service id is defined, false otherwise
*/
protected function has($id)
{
return $this->container->has($id);
}
/**
* Gets a container service by its id.
*
* @param string $id The service id
*
* @return object The service
*/
protected function get($id)
{
return $this->container->get($id);
}
/**
* Gets a container configuration parameter by its name.
*

View File

@ -48,13 +48,7 @@ class ControllerResolver extends ContainerControllerResolver
$resolvedController = parent::createController($controller);
if (1 === substr_count($controller, ':') && is_array($resolvedController)) {
if ($resolvedController[0] instanceof ContainerAwareInterface) {
$resolvedController[0]->setContainer($this->container);
}
if ($resolvedController[0] instanceof AbstractController && null !== $previousContainer = $resolvedController[0]->setContainer($this->container)) {
$resolvedController[0]->setContainer($previousContainer);
}
$resolvedController[0] = $this->configureController($resolvedController[0]);
}
return $resolvedController;
@ -65,9 +59,19 @@ class ControllerResolver extends ContainerControllerResolver
*/
protected function instantiateController($class)
{
$controller = parent::instantiateController($class);
return $this->configureController(parent::instantiateController($class));
}
private function configureController($controller)
{
if ($controller instanceof ContainerAwareInterface) {
// @deprecated switch, to be removed in 4.0 where these classes
// won't implement ContainerAwareInterface anymore
switch (\get_class($controller)) {
case RedirectController::class:
case TemplateController::class:
return $controller;
}
$controller->setContainer($this->container);
}
if ($controller instanceof AbstractController && null !== $previousContainer = $controller->setContainer($this->container)) {

View File

@ -39,6 +39,34 @@ use Doctrine\Bundle\DoctrineBundle\Registry;
*/
trait ControllerTrait
{
/**
* Returns true if the service id is defined.
*
* @param string $id The service id
*
* @return bool true if the service id is defined, false otherwise
*
* @final since version 3.4
*/
protected function has($id)
{
return $this->container->has($id);
}
/**
* Gets a container service by its id.
*
* @param string $id The service id
*
* @return object The service
*
* @final since version 3.4
*/
protected function get($id)
{
return $this->container->get($id);
}
/**
* Generates a URL from the given parameters.
*
@ -49,6 +77,8 @@ trait ControllerTrait
* @return string The generated URL
*
* @see UrlGeneratorInterface
*
* @final since version 3.4
*/
protected function generateUrl($route, $parameters = array(), $referenceType = UrlGeneratorInterface::ABSOLUTE_PATH)
{
@ -63,6 +93,8 @@ trait ControllerTrait
* @param array $query An array of query parameters
*
* @return Response A Response instance
*
* @final since version 3.4
*/
protected function forward($controller, array $path = array(), array $query = array())
{
@ -81,6 +113,8 @@ trait ControllerTrait
* @param int $status The status code to use for the Response
*
* @return RedirectResponse
*
* @final since version 3.4
*/
protected function redirect($url, $status = 302)
{
@ -95,6 +129,8 @@ trait ControllerTrait
* @param int $status The status code to use for the Response
*
* @return RedirectResponse
*
* @final since version 3.4
*/
protected function redirectToRoute($route, array $parameters = array(), $status = 302)
{
@ -110,6 +146,8 @@ trait ControllerTrait
* @param array $context Context to pass to serializer when using serializer component
*
* @return JsonResponse
*
* @final since version 3.4
*/
protected function json($data, $status = 200, $headers = array(), $context = array())
{
@ -132,6 +170,8 @@ trait ControllerTrait
* @param string $disposition Disposition of response ("attachment" is default, other type is "inline")
*
* @return BinaryFileResponse
*
* @final since version 3.4
*/
protected function file($file, $fileName = null, $disposition = ResponseHeaderBag::DISPOSITION_ATTACHMENT)
{
@ -148,6 +188,8 @@ trait ControllerTrait
* @param string $message The message
*
* @throws \LogicException
*
* @final since version 3.4
*/
protected function addFlash($type, $message)
{
@ -167,6 +209,8 @@ trait ControllerTrait
* @return bool
*
* @throws \LogicException
*
* @final since version 3.4
*/
protected function isGranted($attributes, $subject = null)
{
@ -186,6 +230,8 @@ trait ControllerTrait
* @param string $message The message passed to the exception
*
* @throws AccessDeniedException
*
* @final since version 3.4
*/
protected function denyAccessUnlessGranted($attributes, $subject = null, $message = 'Access Denied.')
{
@ -205,6 +251,8 @@ trait ControllerTrait
* @param array $parameters An array of parameters to pass to the view
*
* @return string The rendered view
*
* @final since version 3.4
*/
protected function renderView($view, array $parameters = array())
{
@ -227,14 +275,16 @@ trait ControllerTrait
* @param Response $response A response instance
*
* @return Response A Response instance
*
* @final since version 3.4
*/
protected function render($view, array $parameters = array(), Response $response = null)
{
if ($this->container->has('templating')) {
return $this->container->get('templating')->renderResponse($view, $parameters, $response);
}
if (!$this->container->has('twig')) {
$content = $this->container->get('templating')->render($view, $parameters);
} elseif ($this->container->has('twig')) {
$content = $this->container->get('twig')->render($view, $parameters);
} else {
throw new \LogicException('You can not use the "render" method if the Templating Component or the Twig Bundle are not available.');
}
@ -242,7 +292,7 @@ trait ControllerTrait
$response = new Response();
}
$response->setContent($this->container->get('twig')->render($view, $parameters));
$response->setContent($content);
return $response;
}
@ -255,6 +305,8 @@ trait ControllerTrait
* @param StreamedResponse $response A response instance
*
* @return StreamedResponse A StreamedResponse instance
*
* @final since version 3.4
*/
protected function stream($view, array $parameters = array(), StreamedResponse $response = null)
{
@ -294,6 +346,8 @@ trait ControllerTrait
* @param \Exception|null $previous The previous exception
*
* @return NotFoundHttpException
*
* @final since version 3.4
*/
protected function createNotFoundException($message = 'Not Found', \Exception $previous = null)
{
@ -311,6 +365,8 @@ trait ControllerTrait
* @param \Exception|null $previous The previous exception
*
* @return AccessDeniedException
*
* @final since version 3.4
*/
protected function createAccessDeniedException($message = 'Access Denied.', \Exception $previous = null)
{
@ -325,6 +381,8 @@ trait ControllerTrait
* @param array $options Options for the form
*
* @return Form
*
* @final since version 3.4
*/
protected function createForm($type, $data = null, array $options = array())
{
@ -338,6 +396,8 @@ trait ControllerTrait
* @param array $options Options for the form
*
* @return FormBuilder
*
* @final since version 3.4
*/
protected function createFormBuilder($data = null, array $options = array())
{
@ -350,6 +410,8 @@ trait ControllerTrait
* @return Registry
*
* @throws \LogicException If DoctrineBundle is not available
*
* @final since version 3.4
*/
protected function getDoctrine()
{
@ -368,6 +430,8 @@ trait ControllerTrait
* @throws \LogicException If SecurityBundle is not available
*
* @see TokenInterface::getUser()
*
* @final since version 3.4
*/
protected function getUser()
{
@ -394,6 +458,8 @@ trait ControllerTrait
* @param string $token The actual token sent with the request that should be validated
*
* @return bool
*
* @final since version 3.4
*/
protected function isCsrfTokenValid($id, $token)
{

View File

@ -12,7 +12,7 @@
namespace Symfony\Bundle\FrameworkBundle\Controller;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerAwareTrait;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
@ -23,10 +23,37 @@ use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
* Redirects a request to another URL.
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @final since version 3.4
*/
class RedirectController implements ContainerAwareInterface
{
use ContainerAwareTrait;
/**
* @deprecated since version 3.4, to be removed in 4.0
*/
protected $container;
private $router;
private $httpPort;
private $httpsPort;
public function __construct(UrlGeneratorInterface $router = null, $httpPort = null, $httpsPort = null)
{
$this->router = $router;
$this->httpPort = $httpPort;
$this->httpsPort = $httpsPort;
}
/**
* @deprecated since version 3.4, to be removed in 4.0 alongside with the ContainerAwareInterface type.
*/
public function setContainer(ContainerInterface $container = null)
{
@trigger_error(sprintf('The "%s()" method is deprecated since version 3.4 and will be removed in 4.0. Inject an UrlGeneratorInterface using the constructor instead.', __METHOD__), E_USER_DEPRECATED);
$this->container = $container;
$this->router = $container->get('router');
}
/**
* Redirects to another route with the given name.
@ -61,7 +88,7 @@ class RedirectController implements ContainerAwareInterface
}
}
return new RedirectResponse($this->container->get('router')->generate($route, $attributes, UrlGeneratorInterface::ABSOLUTE_URL), $permanent ? 301 : 302);
return new RedirectResponse($this->router->generate($route, $attributes, UrlGeneratorInterface::ABSOLUTE_URL), $permanent ? 301 : 302);
}
/**
@ -115,8 +142,11 @@ class RedirectController implements ContainerAwareInterface
if (null === $httpPort) {
if ('http' === $request->getScheme()) {
$httpPort = $request->getPort();
} elseif ($this->container->hasParameter('request_listener.http_port')) {
} elseif ($this->container && $this->container->hasParameter('request_listener.http_port')) {
@trigger_error(sprintf('Passing the http port as a container parameter is deprecated since Symfony 3.4 and won\'t be possible in 4.0. Pass it to the constructor of the "%s" class instead.', __CLASS__), E_USER_DEPRECATED);
$httpPort = $this->container->getParameter('request_listener.http_port');
} else {
$httpPort = $this->httpPort;
}
}
@ -127,8 +157,11 @@ class RedirectController implements ContainerAwareInterface
if (null === $httpsPort) {
if ('https' === $request->getScheme()) {
$httpsPort = $request->getPort();
} elseif ($this->container->hasParameter('request_listener.https_port')) {
} elseif ($this->container && $this->container->hasParameter('request_listener.https_port')) {
@trigger_error(sprintf('Passing the https port as a container parameter is deprecated since Symfony 3.4 and won\'t be possible in 4.0. Pass it to the constructor of the "%s" class instead.', __CLASS__), E_USER_DEPRECATED);
$httpsPort = $this->container->getParameter('request_listener.https_port');
} else {
$httpsPort = $this->httpsPort;
}
}

View File

@ -12,17 +12,48 @@
namespace Symfony\Bundle\FrameworkBundle\Controller;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerAwareTrait;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Templating\EngineInterface;
use Twig\Environment;
/**
* TemplateController.
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @final since version 3.4
*/
class TemplateController implements ContainerAwareInterface
{
use ContainerAwareTrait;
/**
* @deprecated since version 3.4, to be removed in 4.0
*/
protected $container;
private $twig;
private $templating;
public function __construct(Environment $twig = null, EngineInterface $templating = null)
{
$this->twig = $twig;
$this->templating = $templating;
}
/**
* @deprecated since version 3.4, to be removed in 4.0 alongside with the ContainerAwareInterface type.
*/
public function setContainer(ContainerInterface $container = null)
{
@trigger_error(sprintf('The "%s()" method is deprecated since version 3.4 and will be removed in 4.0. Inject a Twig Environment or an EngineInterface using the constructor instead.', __METHOD__), E_USER_DEPRECATED);
if ($container->has('templating')) {
$this->templating = $container->get('templating');
} elseif ($container->has('twig')) {
$this->twig = $container->get('twig');
}
$this->container = $container;
}
/**
* Renders a template.
@ -36,10 +67,10 @@ class TemplateController implements ContainerAwareInterface
*/
public function templateAction($template, $maxAge = null, $sharedAge = null, $private = null)
{
if ($this->container->has('templating')) {
$response = $this->container->get('templating')->renderResponse($template);
} elseif ($this->container->has('twig')) {
$response = new Response($this->container->get('twig')->render($template));
if ($this->templating) {
$response = new Response($this->templating->render($template));
} elseif ($this->twig) {
$response = new Response($this->twig->render($template));
} else {
throw new \LogicException('You can not use the TemplateController if the Templating Component or the Twig Bundle are not available.');
}

View File

@ -466,9 +466,9 @@ class FrameworkExtension extends Extension
$container->setParameter('profiler.storage.dsn', $config['dsn']);
if (!$config['collect']) {
$container->getDefinition('profiler')->addMethodCall('disable', array());
}
$container->getDefinition('profiler')
->addArgument($config['collect'])
->addTag('kernel.reset', array('method' => 'reset'));
}
/**

View File

@ -104,5 +104,16 @@
<argument>%kernel.project_dir%</argument>
<argument>%kernel.debug%</argument>
</service>
<service id="Symfony\Bundle\FrameworkBundle\Controller\RedirectController" public="true">
<argument type="service" id="router" />
<argument>%request_listener.http_port%</argument>
<argument>%request_listener.https_port%</argument>
</service>
<service id="Symfony\Bundle\FrameworkBundle\Controller\TemplateController" public="true">
<argument type="service" id="twig" on-invalid="ignore" />
<argument type="service" id="templating" on-invalid="ignore" />
</service>
</services>
</container>

View File

@ -451,7 +451,7 @@ abstract class ControllerTraitTest extends TestCase
public function testRenderTemplating()
{
$templating = $this->getMockBuilder('Symfony\Bundle\FrameworkBundle\Templating\EngineInterface')->getMock();
$templating->expects($this->once())->method('renderResponse')->willReturn(new Response('bar'));
$templating->expects($this->once())->method('render')->willReturn('bar');
$container = new Container();
$container->set('templating', $templating);

View File

@ -15,6 +15,7 @@ use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\ParameterBag;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Bundle\FrameworkBundle\Controller\RedirectController;
use Symfony\Bundle\FrameworkBundle\Tests\TestCase;
@ -66,23 +67,14 @@ class RedirectControllerTest extends TestCase
$request->attributes = new ParameterBag($attributes);
$router = $this->getMockBuilder('Symfony\Component\Routing\RouterInterface')->getMock();
$router = $this->getMockBuilder(UrlGeneratorInterface::class)->getMock();
$router
->expects($this->once())
->method('generate')
->with($this->equalTo($route), $this->equalTo($expectedAttributes))
->will($this->returnValue($url));
$container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock();
$container
->expects($this->once())
->method('get')
->with($this->equalTo('router'))
->will($this->returnValue($router));
$controller = new RedirectController();
$controller->setContainer($container);
$controller = new RedirectController($router);
$returnResponse = $controller->redirectAction($request, $route, $permanent, $ignoreAttributes);
@ -130,7 +122,7 @@ class RedirectControllerTest extends TestCase
$this->assertEquals(302, $returnResponse->getStatusCode());
}
public function testUrlRedirectDefaultPortParameters()
public function testUrlRedirectDefaultPorts()
{
$host = 'www.example.com';
$baseUrl = '/base';
@ -151,6 +143,30 @@ class RedirectControllerTest extends TestCase
$this->assertRedirectUrl($returnValue, $expectedUrl);
}
/**
* @group legacy
*/
public function testUrlRedirectDefaultPortParameters()
{
$host = 'www.example.com';
$baseUrl = '/base';
$path = '/redirect-path';
$httpPort = 1080;
$httpsPort = 1443;
$expectedUrl = "https://$host:$httpsPort$baseUrl$path";
$request = $this->createRequestObject('http', $host, $httpPort, $baseUrl);
$controller = $this->createLegacyRedirectController(null, $httpsPort);
$returnValue = $controller->urlRedirectAction($request, $path, false, 'https');
$this->assertRedirectUrl($returnValue, $expectedUrl);
$expectedUrl = "http://$host:$httpPort$baseUrl$path";
$request = $this->createRequestObject('https', $host, $httpPort, $baseUrl);
$controller = $this->createLegacyRedirectController($httpPort);
$returnValue = $controller->urlRedirectAction($request, $path, false, 'http');
$this->assertRedirectUrl($returnValue, $expectedUrl);
}
public function urlRedirectProvider()
{
return array(
@ -256,6 +272,14 @@ class RedirectControllerTest extends TestCase
}
private function createRedirectController($httpPort = null, $httpsPort = null)
{
return new RedirectController(null, $httpPort, $httpsPort);
}
/**
* @deprecated
*/
private function createLegacyRedirectController($httpPort = null, $httpsPort = null)
{
$container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock();

View File

@ -12,8 +12,8 @@
namespace Symfony\Bundle\FrameworkBundle\Tests\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\TemplateController;
use Symfony\Bundle\FrameworkBundle\Templating\EngineInterface;
use Symfony\Bundle\FrameworkBundle\Tests\TestCase;
use Symfony\Component\HttpFoundation\Response;
/**
* @author Kévin Dunglas <dunglas@gmail.com>
@ -25,6 +25,29 @@ class TemplateControllerTest extends TestCase
$twig = $this->getMockBuilder('Twig\Environment')->disableOriginalConstructor()->getMock();
$twig->expects($this->once())->method('render')->willReturn('bar');
$controller = new TemplateController($twig);
$this->assertEquals('bar', $controller->templateAction('mytemplate')->getContent());
}
public function testTemplating()
{
$templating = $this->getMockBuilder(EngineInterface::class)->getMock();
$templating->expects($this->once())->method('render')->willReturn('bar');
$controller = new TemplateController(null, $templating);
$this->assertEquals('bar', $controller->templateAction('mytemplate')->getContent());
}
/**
* @group legacy
*/
public function testLegacyTwig()
{
$twig = $this->getMockBuilder('Twig\Environment')->disableOriginalConstructor()->getMock();
$twig->expects($this->once())->method('render')->willReturn('bar');
$container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock();
$container->expects($this->at(0))->method('has')->will($this->returnValue(false));
$container->expects($this->at(1))->method('has')->will($this->returnValue(true));
@ -36,10 +59,13 @@ class TemplateControllerTest extends TestCase
$this->assertEquals('bar', $controller->templateAction('mytemplate')->getContent());
}
public function testTemplating()
/**
* @group legacy
*/
public function testLegacyTemplating()
{
$templating = $this->getMockBuilder('Symfony\Bundle\FrameworkBundle\Templating\EngineInterface')->getMock();
$templating->expects($this->once())->method('renderResponse')->willReturn(new Response('bar'));
$templating->expects($this->once())->method('render')->willReturn('bar');
$container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock();
$container->expects($this->at(0))->method('has')->willReturn(true);
@ -57,12 +83,7 @@ class TemplateControllerTest extends TestCase
*/
public function testNoTwigNorTemplating()
{
$container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock();
$container->expects($this->at(0))->method('has')->willReturn(false);
$container->expects($this->at(1))->method('has')->willReturn(false);
$controller = new TemplateController();
$controller->setContainer($container);
$controller->templateAction('mytemplate')->getContent();
}

View File

@ -194,6 +194,14 @@ class SecurityDataCollector extends DataCollector implements LateDataCollectorIn
}
}
/**
* {@inheritdoc}
*/
public function reset()
{
$this->data = array();
}
public function lateCollect()
{
$this->data = $this->cloneVar($this->data);

View File

@ -254,19 +254,12 @@ class TagAwareAdapter implements TagAwareAdapterInterface, PruneableInterface, R
$f = $this->getTagsByKey;
$tagsByKey = $f($items);
$deletedTags = $this->deferred = array();
$this->deferred = array();
$tagVersions = $this->getTagVersions($tagsByKey);
$f = $this->createCacheItem;
foreach ($tagsByKey as $key => $tags) {
if ($tags) {
$this->pool->saveDeferred($f(static::TAGS_PREFIX.$key, array_intersect_key($tagVersions, $tags), $items[$key]));
} else {
$deletedTags[] = static::TAGS_PREFIX.$key;
}
}
if ($deletedTags) {
$this->pool->deleteItems($deletedTags);
$this->pool->saveDeferred($f(static::TAGS_PREFIX.$key, array_intersect_key($tagVersions, $tags), $items[$key]));
}
}

View File

@ -53,6 +53,15 @@ class CacheDataCollector extends DataCollector implements LateDataCollectorInter
$this->data['total']['statistics'] = $this->calculateTotalStatistics();
}
public function reset()
{
$this->data = array();
foreach ($this->instances as $instance) {
// Calling getCalls() will clear the calls.
$instance->getCalls();
}
}
public function lateCollect()
{
$this->data = $this->cloneVar($this->data);

View File

@ -132,6 +132,10 @@ class ResourceCheckerConfigCache implements ConfigCacheInterface
// discard chmod failure (some filesystem may not support it)
}
}
if (\function_exists('opcache_invalidate') && ini_get('opcache.enable')) {
@opcache_invalidate($this->file, true);
}
}
/**

View File

@ -152,8 +152,8 @@ class Container implements ResettableContainerInterface
throw new InvalidArgumentException('You cannot set service "service_container".');
}
if (isset($this->fileMap[$id]) || isset($this->methodMap[$id])) {
throw new InvalidArgumentException(sprintf('You cannot set the pre-defined service "%s".', $id));
if (isset($this->services[$id]) && (isset($this->fileMap[$id]) || isset($this->methodMap[$id]))) {
throw new InvalidArgumentException(sprintf('The "%s" service is already initialized, you cannot replace it.', $id));
}
if (isset($this->aliases[$id])) {

View File

@ -889,26 +889,17 @@ EOF;
$code .= <<<EOF
}
/*{$this->docStar}
* {@inheritdoc}
*/
public function reset()
{
\$this->privates = array();
parent::reset();
}
/*{$this->docStar}
* {@inheritdoc}
*/
public function compile()
{
throw new LogicException('You cannot compile a dumped container that was already compiled.');
}
/*{$this->docStar}
* {@inheritdoc}
*/
public function isCompiled()
{
return true;
@ -919,9 +910,6 @@ EOF;
if ($this->asFiles) {
$code .= <<<EOF
/*{$this->docStar}
* {@inheritdoc}
*/
protected function load(\$file, \$lazyLoad = true)
{
return require \$file;
@ -1052,9 +1040,6 @@ EOF;
$code = <<<'EOF'
/**
* {@inheritdoc}
*/
public function getParameter($name)
{
$name = (string) $name;
@ -1069,9 +1054,6 @@ EOF;
return $this->parameters[$name];
}
/**
* {@inheritdoc}
*/
public function hasParameter($name)
{
$name = (string) $name;
@ -1079,17 +1061,11 @@ EOF;
return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters);
}
/**
* {@inheritdoc}
*/
public function setParameter($name, $value)
{
throw new LogicException('Impossible to call set() on a frozen ParameterBag.');
}
/**
* {@inheritdoc}
*/
public function getParameterBag()
{
if (null === $this->parameterBag) {
@ -1104,9 +1080,6 @@ EOF;
}
EOF;
if ('' === $this->docStar) {
$code = str_replace('/**', '/*', $code);
}
if ($dynamicPhp) {
$loadedDynamicParameters = $this->exportParameters(array_combine(array_keys($dynamicPhp), array_fill(0, count($dynamicPhp), false)), '', 8);

View File

@ -165,6 +165,36 @@ class ContainerTest extends TestCase
$this->assertSame($foo, $c->get('alias'), '->set() replaces an existing alias');
}
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
* @expectedExceptionMessage The "bar" service is already initialized, you cannot replace it.
*/
public function testSetWithNullOnInitializedPredefinedService()
{
$sc = new Container();
$sc->set('foo', new \stdClass());
$sc->set('foo', null);
$this->assertFalse($sc->has('foo'), '->set() with null service resets the service');
$sc = new ProjectServiceContainer();
$sc->get('bar');
$sc->set('bar', null);
$this->assertTrue($sc->has('bar'), '->set() with null service resets the pre-defined service');
}
public function testSetWithNullOnUninitializedPredefinedService()
{
$sc = new Container();
$sc->set('foo', new \stdClass());
$sc->get('foo', null);
$sc->set('foo', null);
$this->assertFalse($sc->has('foo'), '->set() with null service resets the service');
$sc = new ProjectServiceContainer();
$sc->set('bar', null);
$this->assertTrue($sc->has('bar'), '->set() with null service resets the pre-defined service');
}
public function testGet()
{
$sc = new ProjectServiceContainer();
@ -362,16 +392,6 @@ class ContainerTest extends TestCase
$c->get('internal_dependency');
$c->get('internal');
}
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
* @expectedExceptionMessage You cannot set the pre-defined service "bar".
*/
public function testReplacingAPreDefinedService()
{
$c = new ProjectServiceContainer();
$c->set('bar', new \stdClass());
}
}
class ProjectServiceContainer extends Container

View File

@ -286,7 +286,7 @@ class PhpDumperTest extends TestCase
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
* @expectedExceptionMessage You cannot set the pre-defined service "bar".
* @expectedExceptionMessage The "bar2" service is already initialized, you cannot replace it.
*/
public function testOverrideServiceWhenUsingADumpedContainer()
{
@ -294,7 +294,8 @@ class PhpDumperTest extends TestCase
require_once self::$fixturesPath.'/includes/foo.php';
$container = new \ProjectServiceContainer();
$container->set('bar', $bar = new \stdClass());
$container->get('bar2');
$container->set('bar2', new \stdClass());
}
/**

View File

@ -29,26 +29,17 @@ class Container extends AbstractContainer
$this->aliases = array();
}
/**
* {@inheritdoc}
*/
public function reset()
{
$this->privates = array();
parent::reset();
}
/**
* {@inheritdoc}
*/
public function compile()
{
throw new LogicException('You cannot compile a dumped container that was already compiled.');
}
/**
* {@inheritdoc}
*/
public function isCompiled()
{
return true;

View File

@ -27,26 +27,17 @@ class ProjectServiceContainer extends Container
$this->aliases = array();
}
/**
* {@inheritdoc}
*/
public function reset()
{
$this->privates = array();
parent::reset();
}
/**
* {@inheritdoc}
*/
public function compile()
{
throw new LogicException('You cannot compile a dumped container that was already compiled.');
}
/**
* {@inheritdoc}
*/
public function isCompiled()
{
return true;

View File

@ -32,26 +32,17 @@ class ProjectServiceContainer extends Container
$this->aliases = array();
}
/**
* {@inheritdoc}
*/
public function reset()
{
$this->privates = array();
parent::reset();
}
/**
* {@inheritdoc}
*/
public function compile()
{
throw new LogicException('You cannot compile a dumped container that was already compiled.');
}
/**
* {@inheritdoc}
*/
public function isCompiled()
{
return true;
@ -67,9 +58,6 @@ class ProjectServiceContainer extends Container
return $this->services['test'] = new \stdClass(array('only dot' => '.', 'concatenation as value' => '.\'\'.', 'concatenation from the start value' => '\'\'.', '.' => 'dot as a key', '.\'\'.' => 'concatenation as a key', '\'\'.' => 'concatenation from the start key', 'optimize concatenation' => 'string1-string2', 'optimize concatenation with empty string' => 'string1string2', 'optimize concatenation from the start' => 'start', 'optimize concatenation at the end' => 'end'));
}
/**
* {@inheritdoc}
*/
public function getParameter($name)
{
$name = (string) $name;
@ -84,9 +72,6 @@ class ProjectServiceContainer extends Container
return $this->parameters[$name];
}
/**
* {@inheritdoc}
*/
public function hasParameter($name)
{
$name = (string) $name;
@ -94,17 +79,11 @@ class ProjectServiceContainer extends Container
return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters);
}
/**
* {@inheritdoc}
*/
public function setParameter($name, $value)
{
throw new LogicException('Impossible to call set() on a frozen ParameterBag.');
}
/**
* {@inheritdoc}
*/
public function getParameterBag()
{
if (null === $this->parameterBag) {

View File

@ -36,26 +36,17 @@ class ProjectServiceContainer extends Container
$this->aliases = array();
}
/**
* {@inheritdoc}
*/
public function reset()
{
$this->privates = array();
parent::reset();
}
/**
* {@inheritdoc}
*/
public function compile()
{
throw new LogicException('You cannot compile a dumped container that was already compiled.');
}
/**
* {@inheritdoc}
*/
public function isCompiled()
{
return true;
@ -71,9 +62,6 @@ class ProjectServiceContainer extends Container
return $this->services['test'] = new \stdClass(('wiz'.$this->targetDirs[1]), array(('wiz'.$this->targetDirs[1]) => ($this->targetDirs[2].'/')));
}
/**
* {@inheritdoc}
*/
public function getParameter($name)
{
$name = (string) $name;
@ -88,9 +76,6 @@ class ProjectServiceContainer extends Container
return $this->parameters[$name];
}
/**
* {@inheritdoc}
*/
public function hasParameter($name)
{
$name = (string) $name;
@ -98,17 +83,11 @@ class ProjectServiceContainer extends Container
return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters);
}
/**
* {@inheritdoc}
*/
public function setParameter($name, $value)
{
throw new LogicException('Impossible to call set() on a frozen ParameterBag.');
}
/**
* {@inheritdoc}
*/
public function getParameterBag()
{
if (null === $this->parameterBag) {

View File

@ -30,26 +30,17 @@ class ProjectServiceContainer extends Container
$this->aliases = array();
}
/**
* {@inheritdoc}
*/
public function reset()
{
$this->privates = array();
parent::reset();
}
/**
* {@inheritdoc}
*/
public function compile()
{
throw new LogicException('You cannot compile a dumped container that was already compiled.');
}
/**
* {@inheritdoc}
*/
public function isCompiled()
{
return true;

View File

@ -31,26 +31,17 @@ class ProjectServiceContainer extends Container
$this->aliases = array();
}
/**
* {@inheritdoc}
*/
public function reset()
{
$this->privates = array();
parent::reset();
}
/**
* {@inheritdoc}
*/
public function compile()
{
throw new LogicException('You cannot compile a dumped container that was already compiled.');
}
/**
* {@inheritdoc}
*/
public function isCompiled()
{
return true;

View File

@ -30,26 +30,17 @@ class ProjectServiceContainer extends Container
$this->aliases = array();
}
/**
* {@inheritdoc}
*/
public function reset()
{
$this->privates = array();
parent::reset();
}
/**
* {@inheritdoc}
*/
public function compile()
{
throw new LogicException('You cannot compile a dumped container that was already compiled.');
}
/**
* {@inheritdoc}
*/
public function isCompiled()
{
return true;

View File

@ -36,26 +36,17 @@ class Symfony_DI_PhpDumper_Test_EnvParameters extends Container
$this->aliases = array();
}
/**
* {@inheritdoc}
*/
public function reset()
{
$this->privates = array();
parent::reset();
}
/**
* {@inheritdoc}
*/
public function compile()
{
throw new LogicException('You cannot compile a dumped container that was already compiled.');
}
/**
* {@inheritdoc}
*/
public function isCompiled()
{
return true;
@ -73,9 +64,6 @@ class Symfony_DI_PhpDumper_Test_EnvParameters extends Container
return $this->services['test'] = new $class($this->getEnv('Bar'), 'foo'.$this->getEnv('string:FOO').'baz', $this->getEnv('int:Baz'));
}
/**
* {@inheritdoc}
*/
public function getParameter($name)
{
$name = (string) $name;
@ -90,9 +78,6 @@ class Symfony_DI_PhpDumper_Test_EnvParameters extends Container
return $this->parameters[$name];
}
/**
* {@inheritdoc}
*/
public function hasParameter($name)
{
$name = (string) $name;
@ -100,17 +85,11 @@ class Symfony_DI_PhpDumper_Test_EnvParameters extends Container
return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters);
}
/**
* {@inheritdoc}
*/
public function setParameter($name, $value)
{
throw new LogicException('Impossible to call set() on a frozen ParameterBag.');
}
/**
* {@inheritdoc}
*/
public function getParameterBag()
{
if (null === $this->parameterBag) {

View File

@ -30,22 +30,26 @@ class ProjectServiceContainer extends Container
$this->aliases = array();
}
/**
* {@inheritdoc}
*/
public function compile()
{
throw new LogicException('You cannot compile a dumped container that was already compiled.');
}
/**
* {@inheritdoc}
*/
public function isCompiled()
{
return true;
}
<<<<<<< HEAD
=======
public function isFrozen()
{
@trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED);
return true;
}
>>>>>>> 3.4
/**
* Gets the 'foo' service.
*

View File

@ -31,26 +31,17 @@ class ProjectServiceContainer extends Container
$this->aliases = array();
}
/**
* {@inheritdoc}
*/
public function reset()
{
$this->privates = array();
parent::reset();
}
/**
* {@inheritdoc}
*/
public function compile()
{
throw new LogicException('You cannot compile a dumped container that was already compiled.');
}
/**
* {@inheritdoc}
*/
public function isCompiled()
{
return true;

View File

@ -29,34 +29,22 @@ class ProjectServiceContainer extends Container
$this->aliases = array();
}
/**
* {@inheritdoc}
*/
public function reset()
{
$this->privates = array();
parent::reset();
}
/**
* {@inheritdoc}
*/
public function compile()
{
throw new LogicException('You cannot compile a dumped container that was already compiled.');
}
/**
* {@inheritdoc}
*/
public function isCompiled()
{
return true;
}
/**
* {@inheritdoc}
*/
public function getParameter($name)
{
$name = (string) $name;
@ -71,9 +59,6 @@ class ProjectServiceContainer extends Container
return $this->parameters[$name];
}
/**
* {@inheritdoc}
*/
public function hasParameter($name)
{
$name = (string) $name;
@ -81,17 +66,11 @@ class ProjectServiceContainer extends Container
return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters);
}
/**
* {@inheritdoc}
*/
public function setParameter($name, $value)
{
throw new LogicException('Impossible to call set() on a frozen ParameterBag.');
}
/**
* {@inheritdoc}
*/
public function getParameterBag()
{
if (null === $this->parameterBag) {

View File

@ -351,34 +351,22 @@ class Container%s extends Container
);
}
/**
* {@inheritdoc}
*/
public function reset()
{
$this->privates = array();
parent::reset();
}
/**
* {@inheritdoc}
*/
public function compile()
{
throw new LogicException('You cannot compile a dumped container that was already compiled.');
}
/**
* {@inheritdoc}
*/
public function isCompiled()
{
return true;
}
/**
* {@inheritdoc}
*/
protected function load($file, $lazyLoad = true)
{
return require $file;
@ -394,9 +382,6 @@ class Container%s extends Container
return new \Bar\FooClass(($this->services['deprecated_service'] ?? $this->load(__DIR__.'/getDeprecatedServiceService.php')));
}
/**
* {@inheritdoc}
*/
public function getParameter($name)
{
$name = (string) $name;
@ -411,9 +396,6 @@ class Container%s extends Container
return $this->parameters[$name];
}
/**
* {@inheritdoc}
*/
public function hasParameter($name)
{
$name = (string) $name;
@ -421,17 +403,11 @@ class Container%s extends Container
return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters);
}
/**
* {@inheritdoc}
*/
public function setParameter($name, $value)
{
throw new LogicException('Impossible to call set() on a frozen ParameterBag.');
}
/**
* {@inheritdoc}
*/
public function getParameterBag()
{
if (null === $this->parameterBag) {

View File

@ -56,26 +56,17 @@ class ProjectServiceContainer extends Container
);
}
/**
* {@inheritdoc}
*/
public function reset()
{
$this->privates = array();
parent::reset();
}
/**
* {@inheritdoc}
*/
public function compile()
{
throw new LogicException('You cannot compile a dumped container that was already compiled.');
}
/**
* {@inheritdoc}
*/
public function isCompiled()
{
return true;
@ -395,9 +386,6 @@ class ProjectServiceContainer extends Container
return $this->privates['factory_simple'] = new \SimpleFactoryClass('foo');
}
/**
* {@inheritdoc}
*/
public function getParameter($name)
{
$name = (string) $name;
@ -412,9 +400,6 @@ class ProjectServiceContainer extends Container
return $this->parameters[$name];
}
/**
* {@inheritdoc}
*/
public function hasParameter($name)
{
$name = (string) $name;
@ -422,17 +407,11 @@ class ProjectServiceContainer extends Container
return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters);
}
/**
* {@inheritdoc}
*/
public function setParameter($name, $value)
{
throw new LogicException('Impossible to call set() on a frozen ParameterBag.');
}
/**
* {@inheritdoc}
*/
public function getParameterBag()
{
if (null === $this->parameterBag) {

View File

@ -36,26 +36,17 @@ class ProjectServiceContainer extends Container
$this->aliases = array();
}
/**
* {@inheritdoc}
*/
public function reset()
{
$this->privates = array();
parent::reset();
}
/**
* {@inheritdoc}
*/
public function compile()
{
throw new LogicException('You cannot compile a dumped container that was already compiled.');
}
/**
* {@inheritdoc}
*/
public function isCompiled()
{
return true;
@ -75,9 +66,6 @@ class ProjectServiceContainer extends Container
return $instance;
}
/**
* {@inheritdoc}
*/
public function getParameter($name)
{
$name = (string) $name;
@ -92,9 +80,6 @@ class ProjectServiceContainer extends Container
return $this->parameters[$name];
}
/**
* {@inheritdoc}
*/
public function hasParameter($name)
{
$name = (string) $name;
@ -102,17 +87,11 @@ class ProjectServiceContainer extends Container
return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters);
}
/**
* {@inheritdoc}
*/
public function setParameter($name, $value)
{
throw new LogicException('Impossible to call set() on a frozen ParameterBag.');
}
/**
* {@inheritdoc}
*/
public function getParameterBag()
{
if (null === $this->parameterBag) {

View File

@ -29,34 +29,22 @@ class Symfony_DI_PhpDumper_Test_Base64Parameters extends Container
$this->aliases = array();
}
/**
* {@inheritdoc}
*/
public function reset()
{
$this->privates = array();
parent::reset();
}
/**
* {@inheritdoc}
*/
public function compile()
{
throw new LogicException('You cannot compile a dumped container that was already compiled.');
}
/**
* {@inheritdoc}
*/
public function isCompiled()
{
return true;
}
/**
* {@inheritdoc}
*/
public function getParameter($name)
{
$name = (string) $name;
@ -71,9 +59,6 @@ class Symfony_DI_PhpDumper_Test_Base64Parameters extends Container
return $this->parameters[$name];
}
/**
* {@inheritdoc}
*/
public function hasParameter($name)
{
$name = (string) $name;
@ -81,17 +66,11 @@ class Symfony_DI_PhpDumper_Test_Base64Parameters extends Container
return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters);
}
/**
* {@inheritdoc}
*/
public function setParameter($name, $value)
{
throw new LogicException('Impossible to call set() on a frozen ParameterBag.');
}
/**
* {@inheritdoc}
*/
public function getParameterBag()
{
if (null === $this->parameterBag) {

View File

@ -37,26 +37,17 @@ class ProjectServiceContainer extends Container
$this->aliases = array();
}
/**
* {@inheritdoc}
*/
public function reset()
{
$this->privates = array();
parent::reset();
}
/**
* {@inheritdoc}
*/
public function compile()
{
throw new LogicException('You cannot compile a dumped container that was already compiled.');
}
/**
* {@inheritdoc}
*/
public function isCompiled()
{
return true;

View File

@ -31,26 +31,17 @@ class ProjectServiceContainer extends Container
$this->aliases = array();
}
/**
* {@inheritdoc}
*/
public function reset()
{
$this->privates = array();
parent::reset();
}
/**
* {@inheritdoc}
*/
public function compile()
{
throw new LogicException('You cannot compile a dumped container that was already compiled.');
}
/**
* {@inheritdoc}
*/
public function isCompiled()
{
return true;

View File

@ -30,26 +30,17 @@ class ProjectServiceContainer extends Container
$this->aliases = array();
}
/**
* {@inheritdoc}
*/
public function reset()
{
$this->privates = array();
parent::reset();
}
/**
* {@inheritdoc}
*/
public function compile()
{
throw new LogicException('You cannot compile a dumped container that was already compiled.');
}
/**
* {@inheritdoc}
*/
public function isCompiled()
{
return true;

View File

@ -33,26 +33,17 @@ class Symfony_DI_PhpDumper_Test_Rot13Parameters extends Container
$this->aliases = array();
}
/**
* {@inheritdoc}
*/
public function reset()
{
$this->privates = array();
parent::reset();
}
/**
* {@inheritdoc}
*/
public function compile()
{
throw new LogicException('You cannot compile a dumped container that was already compiled.');
}
/**
* {@inheritdoc}
*/
public function isCompiled()
{
return true;
@ -80,9 +71,6 @@ class Symfony_DI_PhpDumper_Test_Rot13Parameters extends Container
}));
}
/**
* {@inheritdoc}
*/
public function getParameter($name)
{
$name = (string) $name;
@ -97,9 +85,6 @@ class Symfony_DI_PhpDumper_Test_Rot13Parameters extends Container
return $this->parameters[$name];
}
/**
* {@inheritdoc}
*/
public function hasParameter($name)
{
$name = (string) $name;
@ -107,17 +92,11 @@ class Symfony_DI_PhpDumper_Test_Rot13Parameters extends Container
return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters);
}
/**
* {@inheritdoc}
*/
public function setParameter($name, $value)
{
throw new LogicException('Impossible to call set() on a frozen ParameterBag.');
}
/**
* {@inheritdoc}
*/
public function getParameterBag()
{
if (null === $this->parameterBag) {

View File

@ -31,26 +31,17 @@ class ProjectServiceContainer extends Container
$this->aliases = array();
}
/**
* {@inheritdoc}
*/
public function reset()
{
$this->privates = array();
parent::reset();
}
/**
* {@inheritdoc}
*/
public function compile()
{
throw new LogicException('You cannot compile a dumped container that was already compiled.');
}
/**
* {@inheritdoc}
*/
public function isCompiled()
{
return true;

View File

@ -32,26 +32,17 @@ class Symfony_DI_PhpDumper_Test_Uninitialized_Reference extends Container
$this->aliases = array();
}
/**
* {@inheritdoc}
*/
public function reset()
{
$this->privates = array();
parent::reset();
}
/**
* {@inheritdoc}
*/
public function compile()
{
throw new LogicException('You cannot compile a dumped container that was already compiled.');
}
/**
* {@inheritdoc}
*/
public function isCompiled()
{
return true;

View File

@ -6,6 +6,11 @@ CHANGELOG
* removed the `ContainerAwareEventDispatcher` class
3.4.0
-----
* Implementing `TraceableEventDispatcherInterface` without the `reset()` method has been deprecated.
3.3.0
-----

View File

@ -212,6 +212,11 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface
return $notCalled;
}
public function reset()
{
$this->called = array();
}
/**
* Proxies all method calls to the original event dispatcher.
*

View File

@ -15,6 +15,8 @@ use Symfony\Component\EventDispatcher\EventDispatcherInterface;
/**
* @author Fabien Potencier <fabien@symfony.com>
*
* @method reset() Resets the trace.
*/
interface TraceableEventDispatcherInterface extends EventDispatcherInterface
{

View File

@ -124,6 +124,21 @@ class TraceableEventDispatcherTest extends TestCase
$this->assertEquals(array(), $tdispatcher->getNotCalledListeners());
}
public function testClearCalledListeners()
{
$tdispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch());
$tdispatcher->addListener('foo', function () {}, 5);
$tdispatcher->dispatch('foo');
$tdispatcher->reset();
$listeners = $tdispatcher->getNotCalledListeners();
$this->assertArrayHasKey('stub', $listeners['foo.closure']);
unset($listeners['foo.closure']['stub']);
$this->assertEquals(array(), $tdispatcher->getCalledListeners());
$this->assertEquals(array('foo.closure' => array('event' => 'foo', 'pretty' => 'closure', 'priority' => 5)), $listeners);
}
public function testGetCalledListenersNested()
{
$tdispatcher = null;

View File

@ -6,11 +6,15 @@ CHANGELOG
* removed `LockHandler`
3.4.0
-----
* support for passing relative paths to `Filesystem::makePathRelative()` is deprecated and will be removed in 4.0
3.3.0
-----
* added `appendToFile()` to append contents to existing files
* support for passing relative paths to `Filesystem::makePathRelative()` is deprecated and will be removed in 4.0
3.2.0
-----

View File

@ -74,11 +74,8 @@ class FormDataCollector extends DataCollector implements FormDataCollectorInterf
}
$this->dataExtractor = $dataExtractor;
$this->data = array(
'forms' => array(),
'forms_by_hash' => array(),
'nb_errors' => 0,
);
$this->reset();
}
/**
@ -88,6 +85,15 @@ class FormDataCollector extends DataCollector implements FormDataCollectorInterf
{
}
public function reset()
{
$this->data = array(
'forms' => array(),
'forms_by_hash' => array(),
'nb_errors' => 0,
);
}
/**
* {@inheritdoc}
*/

View File

@ -695,6 +695,36 @@ class FormDataCollectorTest extends TestCase
$this->assertFalse(isset($child21Data['has_children_error']), 'The leaf data does not contains "has_children_error" property.');
}
public function testReset()
{
$form = $this->createForm('my_form');
$this->dataExtractor->expects($this->any())
->method('extractConfiguration')
->will($this->returnValue(array()));
$this->dataExtractor->expects($this->any())
->method('extractDefaultData')
->will($this->returnValue(array()));
$this->dataExtractor->expects($this->any())
->method('extractSubmittedData')
->with($form)
->will($this->returnValue(array('errors' => array('baz'))));
$this->dataCollector->buildPreliminaryFormTree($form);
$this->dataCollector->collectSubmittedData($form);
$this->dataCollector->reset();
$this->assertSame(
array(
'forms' => array(),
'forms_by_hash' => array(),
'nb_errors' => 0,
),
$this->dataCollector->getData()
);
}
private function createForm($name)
{
$builder = new FormBuilder($name, null, $this->dispatcher, $this->factory);

View File

@ -29,6 +29,7 @@ CHANGELOG
* deprecated the `NativeSessionHandler` class,
* deprecated the `AbstractProxy`, `NativeProxy` and `SessionHandlerProxy` classes,
* deprecated setting session save handlers that do not implement `\SessionHandlerInterface` in `NativeSessionStorage::setSaveHandler()`
* deprecated using `MongoDbSessionHandler` with the legacy mongo extension; use it with the mongodb/mongodb package and ext-mongodb instead
3.3.0
-----

View File

@ -12,7 +12,12 @@
namespace Symfony\Component\HttpFoundation\Session\Storage\Handler;
/**
* Session handler using the mongodb/mongodb package and MongoDB driver extension.
*
* @author Markus Bachmann <markus.bachmann@bachi.biz>
*
* @see https://packagist.org/packages/mongodb/mongodb
* @see http://php.net/manual/en/set.mongodb.php
*/
class MongoDbSessionHandler implements \SessionHandlerInterface
{
@ -57,14 +62,18 @@ class MongoDbSessionHandler implements \SessionHandlerInterface
* If you use such an index, you can drop `gc_probability` to 0 since
* no garbage-collection is required.
*
* @param \Mongo|\MongoClient|\MongoDB\Client $mongo A MongoDB\Client, MongoClient or Mongo instance
* @param array $options An associative array of field options
* @param \MongoDB\Client $mongo A MongoDB\Client instance
* @param array $options An associative array of field options
*
* @throws \InvalidArgumentException When MongoClient or Mongo instance not provided
* @throws \InvalidArgumentException When "database" or "collection" not provided
*/
public function __construct($mongo, array $options)
{
if ($mongo instanceof \MongoClient || $mongo instanceof \Mongo) {
@trigger_error(sprintf('Using %s with the legacy mongo extension is deprecated as of 3.4 and will be removed in 4.0. Use it with the mongodb/mongodb package and ext-mongodb instead.', __CLASS__), E_USER_DEPRECATED);
}
if (!($mongo instanceof \MongoDB\Client || $mongo instanceof \MongoClient || $mongo instanceof \Mongo)) {
throw new \InvalidArgumentException('MongoClient or Mongo instance required');
}

View File

@ -17,6 +17,7 @@ use Symfony\Component\HttpFoundation\Session\Storage\Handler\MongoDbSessionHandl
/**
* @author Markus Bachmann <markus.bachmann@bachi.biz>
* @group time-sensitive
* @requires extension mongodb
*/
class MongoDbSessionHandlerTest extends TestCase
{
@ -31,21 +32,11 @@ class MongoDbSessionHandlerTest extends TestCase
{
parent::setUp();
if (extension_loaded('mongodb')) {
if (!class_exists('MongoDB\Client')) {
$this->markTestSkipped('The mongodb/mongodb package is required.');
}
} elseif (!extension_loaded('mongo')) {
$this->markTestSkipped('The Mongo or MongoDB extension is required.');
if (!class_exists('MongoDB\Client')) {
$this->markTestSkipped('The mongodb/mongodb package is required.');
}
if (phpversion('mongodb')) {
$mongoClass = 'MongoDB\Client';
} else {
$mongoClass = version_compare(phpversion('mongo'), '1.3.0', '<') ? 'Mongo' : 'MongoClient';
}
$this->mongo = $this->getMockBuilder($mongoClass)
$this->mongo = $this->getMockBuilder('MongoDB\Client')
->disableOriginalConstructor()
->getMock();
@ -307,23 +298,12 @@ class MongoDbSessionHandlerTest extends TestCase
$method = new \ReflectionMethod($this->storage, 'getMongo');
$method->setAccessible(true);
if (phpversion('mongodb')) {
$mongoClass = 'MongoDB\Client';
} else {
$mongoClass = version_compare(phpversion('mongo'), '1.3.0', '<') ? 'Mongo' : 'MongoClient';
}
$this->assertInstanceOf($mongoClass, $method->invoke($this->storage));
$this->assertInstanceOf('MongoDB\Client', $method->invoke($this->storage));
}
private function createMongoCollectionMock()
{
$collectionClass = 'MongoCollection';
if (phpversion('mongodb')) {
$collectionClass = 'MongoDB\Collection';
}
$collection = $this->getMockBuilder($collectionClass)
$collection = $this->getMockBuilder('MongoDB\Collection')
->disableOriginalConstructor()
->getMock();

View File

@ -38,7 +38,9 @@ CHANGELOG
* deprecated the `ChainCacheClearer::add()` method
* deprecated the `CacheaWarmerAggregate::add()` and `setWarmers()` methods
* made `CacheWarmerAggregate` and `ChainCacheClearer` classes final
* added the possibility to reset the profiler to its initial state
* deprecated data collectors without a `reset()` method
* deprecated implementing `DebugLoggerInterface` without a `clear()` method
3.3.0
-----

View File

@ -26,6 +26,11 @@ class AjaxDataCollector extends DataCollector
// all collecting is done client side
}
public function reset()
{
// all collecting is done client side
}
public function getName()
{
return 'ajax';

View File

@ -95,6 +95,14 @@ class ConfigDataCollector extends DataCollector implements LateDataCollectorInte
}
}
/**
* {@inheritdoc}
*/
public function reset()
{
$this->data = array();
}
public function lateCollect()
{
$this->data = $this->cloneVar($this->data);

View File

@ -18,6 +18,8 @@ use Symfony\Component\HttpFoundation\Response;
* DataCollectorInterface.
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @method reset() Resets this data collector to its initial state.
*/
interface DataCollectorInterface
{

View File

@ -27,6 +27,9 @@ class EventDataCollector extends DataCollector implements LateDataCollectorInter
public function __construct(EventDispatcherInterface $dispatcher = null)
{
if ($dispatcher instanceof TraceableEventDispatcherInterface && !method_exists($dispatcher, 'reset')) {
@trigger_error(sprintf('Implementing "%s" without the "reset()" method is deprecated since version 3.4 and will be unsupported in 4.0 for class "%s".', TraceableEventDispatcherInterface::class, \get_class($dispatcher)), E_USER_DEPRECATED);
}
$this->dispatcher = $dispatcher;
}
@ -41,6 +44,19 @@ class EventDataCollector extends DataCollector implements LateDataCollectorInter
);
}
public function reset()
{
$this->data = array();
if ($this->dispatcher instanceof TraceableEventDispatcherInterface) {
if (!method_exists($this->dispatcher, 'reset')) {
return; // @deprecated
}
$this->dispatcher->reset();
}
}
public function lateCollect()
{
if ($this->dispatcher instanceof TraceableEventDispatcherInterface) {

View File

@ -34,6 +34,14 @@ class ExceptionDataCollector extends DataCollector
}
}
/**
* {@inheritdoc}
*/
public function reset()
{
$this->data = array();
}
/**
* Checks if the exception is not null.
*

View File

@ -29,6 +29,10 @@ class LoggerDataCollector extends DataCollector implements LateDataCollectorInte
public function __construct($logger = null, $containerPathPrefix = null)
{
if (null !== $logger && $logger instanceof DebugLoggerInterface) {
if (!method_exists($logger, 'clear')) {
@trigger_error(sprintf('Implementing "%s" without the "clear()" method is deprecated since version 3.4 and will be unsupported in 4.0 for class "%s".', DebugLoggerInterface::class, \get_class($logger)), E_USER_DEPRECATED);
}
$this->logger = $logger;
}
@ -43,6 +47,17 @@ class LoggerDataCollector extends DataCollector implements LateDataCollectorInte
// everything is done as late as possible
}
/**
* {@inheritdoc}
*/
public function reset()
{
if ($this->logger && method_exists($this->logger, 'clear')) {
$this->logger->clear();
}
$this->data = array();
}
/**
* {@inheritdoc}
*/

View File

@ -23,10 +23,7 @@ class MemoryDataCollector extends DataCollector implements LateDataCollectorInte
{
public function __construct()
{
$this->data = array(
'memory' => 0,
'memory_limit' => $this->convertToBytes(ini_get('memory_limit')),
);
$this->reset();
}
/**
@ -37,6 +34,17 @@ class MemoryDataCollector extends DataCollector implements LateDataCollectorInte
$this->updateMemoryUsage();
}
/**
* {@inheritdoc}
*/
public function reset()
{
$this->data = array(
'memory' => 0,
'memory_limit' => $this->convertToBytes(ini_get('memory_limit')),
);
}
/**
* {@inheritdoc}
*/

View File

@ -156,6 +156,12 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter
$this->data = $this->cloneVar($this->data);
}
public function reset()
{
$this->data = array();
$this->controllers = new \SplObjectStorage();
}
public function getMethod()
{
return $this->data['method'];

View File

@ -23,17 +23,14 @@ use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
*/
class RouterDataCollector extends DataCollector
{
/**
* @var \SplObjectStorage
*/
protected $controllers;
public function __construct()
{
$this->controllers = new \SplObjectStorage();
$this->data = array(
'redirect' => false,
'url' => null,
'route' => null,
);
$this->reset();
}
/**
@ -53,6 +50,17 @@ class RouterDataCollector extends DataCollector
unset($this->controllers[$request]);
}
public function reset()
{
$this->controllers = new \SplObjectStorage();
$this->data = array(
'redirect' => false,
'url' => null,
'route' => null,
);
}
protected function guessRoute(Request $request, $controller)
{
return 'n/a';

View File

@ -49,6 +49,14 @@ class TimeDataCollector extends DataCollector implements LateDataCollectorInterf
);
}
/**
* {@inheritdoc}
*/
public function reset()
{
$this->data = array();
}
/**
* {@inheritdoc}
*/

View File

@ -15,6 +15,8 @@ namespace Symfony\Component\HttpKernel\Log;
* DebugLoggerInterface.
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @method clear() Removes all log records.
*/
interface DebugLoggerInterface
{

View File

@ -40,6 +40,11 @@ class Profiler
*/
private $logger;
/**
* @var bool
*/
private $initiallyEnabled = true;
/**
* @var bool
*/
@ -48,11 +53,13 @@ class Profiler
/**
* @param ProfilerStorageInterface $storage A ProfilerStorageInterface instance
* @param LoggerInterface $logger A LoggerInterface instance
* @param bool $enable The initial enabled state
*/
public function __construct(ProfilerStorageInterface $storage, LoggerInterface $logger = null)
public function __construct(ProfilerStorageInterface $storage, LoggerInterface $logger = null, $enable = true)
{
$this->storage = $storage;
$this->logger = $logger;
$this->initiallyEnabled = $this->enabled = (bool) $enable;
}
/**
@ -188,6 +195,18 @@ class Profiler
return $profile;
}
public function reset()
{
foreach ($this->collectors as $collector) {
if (!method_exists($collector, 'reset')) {
continue;
}
$collector->reset();
}
$this->enabled = $this->initiallyEnabled;
}
/**
* Gets the Collectors associated with this profiler.
*
@ -218,6 +237,10 @@ class Profiler
*/
public function add(DataCollectorInterface $collector)
{
if (!method_exists($collector, 'reset')) {
@trigger_error(sprintf('Implementing "%s" without the "reset()" method is deprecated since version 3.4 and will be unsupported in 4.0 for class "%s".', DataCollectorInterface::class, \get_class($collector)), E_USER_DEPRECATED);
}
$this->collectors[$collector->getName()] = $collector;
}

View File

@ -37,4 +37,23 @@ class ExceptionDataCollectorTest extends TestCase
$this->assertSame('exception', $c->getName());
$this->assertSame($trace, $c->getTrace());
}
public function testCollectWithoutException()
{
$c = new ExceptionDataCollector();
$c->collect(new Request(), new Response());
$this->assertFalse($c->hasException());
}
public function testReset()
{
$c = new ExceptionDataCollector();
$c->collect(new Request(), new Response(), new \Exception());
$c->reset();
$c->collect(new Request(), new Response());
$this->assertFalse($c->hasException());
}
}

View File

@ -19,7 +19,10 @@ class LoggerDataCollectorTest extends TestCase
{
public function testCollectWithUnexpectedFormat()
{
$logger = $this->getMockBuilder('Symfony\Component\HttpKernel\Log\DebugLoggerInterface')->getMock();
$logger = $this
->getMockBuilder('Symfony\Component\HttpKernel\Log\DebugLoggerInterface')
->setMethods(array('countErrors', 'getLogs', 'clear'))
->getMock();
$logger->expects($this->once())->method('countErrors')->will($this->returnValue('foo'));
$logger->expects($this->exactly(2))->method('getLogs')->will($this->returnValue(array()));
@ -43,7 +46,10 @@ class LoggerDataCollectorTest extends TestCase
*/
public function testCollect($nb, $logs, $expectedLogs, $expectedDeprecationCount, $expectedScreamCount, $expectedPriorities = null)
{
$logger = $this->getMockBuilder('Symfony\Component\HttpKernel\Log\DebugLoggerInterface')->getMock();
$logger = $this
->getMockBuilder('Symfony\Component\HttpKernel\Log\DebugLoggerInterface')
->setMethods(array('countErrors', 'getLogs', 'clear'))
->getMock();
$logger->expects($this->once())->method('countErrors')->will($this->returnValue($nb));
$logger->expects($this->exactly(2))->method('getLogs')->will($this->returnValue($logs));
@ -70,6 +76,18 @@ class LoggerDataCollectorTest extends TestCase
}
}
public function testReset()
{
$logger = $this
->getMockBuilder('Symfony\Component\HttpKernel\Log\DebugLoggerInterface')
->setMethods(array('countErrors', 'getLogs', 'clear'))
->getMock();
$logger->expects($this->once())->method('clear');
$c = new LoggerDataCollector($logger);
$c->reset();
}
public function getCollectTestData()
{
yield 'simple log' => array(

View File

@ -29,6 +29,11 @@ class CloneVarDataCollector extends DataCollector
$this->data = $this->cloneVar($this->varToClone);
}
public function reset()
{
$this->data = array();
}
public function getData()
{
return $this->data;

View File

@ -25,4 +25,8 @@ class TestEventDispatcher extends EventDispatcher implements TraceableEventDispa
{
return array('bar');
}
public function reset()
{
}
}

View File

@ -12,6 +12,7 @@
namespace Symfony\Component\HttpKernel\Tests\Profiler;
use PHPUnit\Framework\TestCase;
use Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface;
use Symfony\Component\HttpKernel\DataCollector\RequestDataCollector;
use Symfony\Component\HttpKernel\Profiler\FileProfilerStorage;
use Symfony\Component\HttpKernel\Profiler\Profiler;
@ -40,6 +41,19 @@ class ProfilerTest extends TestCase
$this->assertSame('bar', $profile->getCollector('request')->getRequestQuery()->all()['foo']->getValue());
}
public function testReset()
{
$collector = $this->getMockBuilder(DataCollectorInterface::class)
->setMethods(['collect', 'getName', 'reset'])
->getMock();
$collector->expects($this->any())->method('getName')->willReturn('mock');
$collector->expects($this->once())->method('reset');
$profiler = new Profiler($this->storage);
$profiler->add($collector);
$profiler->reset();
}
public function testFindWorksWithDates()
{
$profiler = new Profiler($this->storage);

View File

@ -26,6 +26,7 @@ CHANGELOG
requests.
* deprecated HTTP digest authentication
* Added a new password encoder for the Argon2i hashing algorithm
* deprecated `GuardAuthenticatorInterface` in favor of `AuthenticatorInterface`
3.3.0
-----

View File

@ -11,6 +11,7 @@
namespace Symfony\Component\Security\Guard;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Guard\Token\PostAuthenticationGuardToken;
@ -19,8 +20,20 @@ use Symfony\Component\Security\Guard\Token\PostAuthenticationGuardToken;
*
* @author Ryan Weaver <ryan@knpuniversity.com>
*/
abstract class AbstractGuardAuthenticator implements GuardAuthenticatorInterface
abstract class AbstractGuardAuthenticator implements AuthenticatorInterface
{
/**
* {@inheritdoc}
*
* @deprecated since version 3.4, to be removed in 4.0
*/
public function supports(Request $request)
{
@trigger_error(sprintf('The "%s()" method is deprecated since version 3.4 and will be removed in 4.0. Implement the "%s::supports()" method in class "%s" instead.', __METHOD__, AuthenticatorInterface::class, get_class($this)), E_USER_DEPRECATED);
return true;
}
/**
* Shortcut to create a PostAuthenticationGuardToken for you, if you don't really
* care about which authenticated token you're using.

View File

@ -0,0 +1,63 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Guard;
use Symfony\Component\HttpFoundation\Request;
/**
* The interface for all "guard" authenticators.
*
* The methods on this interface are called throughout the guard authentication
* process to give you the power to control most parts of the process from
* one location.
*
* @author Ryan Weaver <ryan@knpuniversity.com>
* @author Amaury Leroux de Lens <amaury@lerouxdelens.com>
*/
interface AuthenticatorInterface extends GuardAuthenticatorInterface
{
/**
* Does the authenticator support the given Request?
*
* If this returns false, the authenticator will be skipped.
*
* @param Request $request
*
* @return bool
*/
public function supports(Request $request);
/**
* Get the authentication credentials from the request and return them
* as any type (e.g. an associate array).
*
* Whatever value you return here will be passed to getUser() and checkCredentials()
*
* For example, for a form login, you might:
*
* return array(
* 'username' => $request->request->get('_username'),
* 'password' => $request->request->get('_password'),
* );
*
* Or for an API token that's on a header, you might use:
*
* return array('api_key' => $request->headers->get('X-API-TOKEN'));
*
* @param Request $request
*
* @return mixed Any non-null value
*
* @throws \UnexpectedValueException If null is returned
*/
public function getCredentials(Request $request);
}

View File

@ -15,9 +15,10 @@ use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\Security\Guard\GuardAuthenticatorHandler;
use Symfony\Component\Security\Guard\GuardAuthenticatorInterface;
use Symfony\Component\Security\Guard\Token\PreAuthenticationGuardToken;
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
use Symfony\Component\Security\Guard\GuardAuthenticatorInterface;
use Symfony\Component\Security\Guard\AuthenticatorInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
@ -28,6 +29,7 @@ use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface;
* Authentication listener for the "guard" system.
*
* @author Ryan Weaver <ryan@knpuniversity.com>
* @author Amaury Leroux de Lens <amaury@lerouxdelens.com>
*/
class GuardAuthenticationListener implements ListenerInterface
{
@ -39,11 +41,11 @@ class GuardAuthenticationListener implements ListenerInterface
private $rememberMeServices;
/**
* @param GuardAuthenticatorHandler $guardHandler The Guard handler
* @param AuthenticationManagerInterface $authenticationManager An AuthenticationManagerInterface instance
* @param string $providerKey The provider (i.e. firewall) key
* @param iterable|GuardAuthenticatorInterface[] $guardAuthenticators The authenticators, with keys that match what's passed to GuardAuthenticationProvider
* @param LoggerInterface $logger A LoggerInterface instance
* @param GuardAuthenticatorHandler $guardHandler The Guard handler
* @param AuthenticationManagerInterface $authenticationManager An AuthenticationManagerInterface instance
* @param string $providerKey The provider (i.e. firewall) key
* @param iterable|AuthenticatorInterface[] $guardAuthenticators The authenticators, with keys that match what's passed to GuardAuthenticationProvider
* @param LoggerInterface $logger A LoggerInterface instance
*/
public function __construct(GuardAuthenticatorHandler $guardHandler, AuthenticationManagerInterface $authenticationManager, $providerKey, $guardAuthenticators, LoggerInterface $logger = null)
{
@ -100,12 +102,29 @@ class GuardAuthenticationListener implements ListenerInterface
$this->logger->debug('Calling getCredentials() on guard configurator.', array('firewall_key' => $this->providerKey, 'authenticator' => get_class($guardAuthenticator)));
}
// abort the execution of the authenticator if it doesn't support the request
if ($guardAuthenticator instanceof AuthenticatorInterface) {
if (!$guardAuthenticator->supports($request)) {
return;
}
// as there was a support for given request,
// authenticator is expected to give not-null credentials.
$credentialsCanBeNull = false;
} else {
// deprecated since version 3.4, to be removed in 4.0
$credentialsCanBeNull = true;
}
// allow the authenticator to fetch authentication info from the request
$credentials = $guardAuthenticator->getCredentials($request);
// allow null to be returned to skip authentication
if (null === $credentials) {
return;
// deprecated since version 3.4, to be removed in 4.0
if ($credentialsCanBeNull) {
return;
}
throw new \UnexpectedValueException(sprintf('The return value of "%s::getCredentials()" must not be null. Return false from "%s::supports()" instead.', get_class($guardAuthenticator), get_class($guardAuthenticator)));
}
// create a token with the unique key, so that the provider knows which authenticator to use
@ -172,10 +191,10 @@ class GuardAuthenticationListener implements ListenerInterface
* Checks to see if remember me is supported in the authenticator and
* on the firewall. If it is, the RememberMeServicesInterface is notified.
*
* @param GuardAuthenticatorInterface $guardAuthenticator
* @param Request $request
* @param TokenInterface $token
* @param Response $response
* @param AuthenticatorInterface $guardAuthenticator
* @param Request $request
* @param TokenInterface $token
* @param Response $response
*/
private function triggerRememberMe(GuardAuthenticatorInterface $guardAuthenticator, Request $request, TokenInterface $token, Response $response = null)
{

View File

@ -29,6 +29,8 @@ use Symfony\Component\Security\Http\SecurityEvents;
* can be called directly (e.g. for manual authentication) or overridden.
*
* @author Ryan Weaver <ryan@knpuniversity.com>
*
* @final since version 3.4
*/
class GuardAuthenticatorHandler
{
@ -61,10 +63,10 @@ class GuardAuthenticatorHandler
/**
* Returns the "on success" response for the given GuardAuthenticator.
*
* @param TokenInterface $token
* @param Request $request
* @param GuardAuthenticatorInterface $guardAuthenticator
* @param string $providerKey The provider (i.e. firewall) key
* @param TokenInterface $token
* @param Request $request
* @param AuthenticatorInterface $guardAuthenticator
* @param string $providerKey The provider (i.e. firewall) key
*
* @return null|Response
*/
@ -88,10 +90,10 @@ class GuardAuthenticatorHandler
* Convenience method for authenticating the user and returning the
* Response *if any* for success.
*
* @param UserInterface $user
* @param Request $request
* @param GuardAuthenticatorInterface $authenticator
* @param string $providerKey The provider (i.e. firewall) key
* @param UserInterface $user
* @param Request $request
* @param AuthenticatorInterface $authenticator
* @param string $providerKey The provider (i.e. firewall) key
*
* @return Response|null
*/
@ -110,10 +112,10 @@ class GuardAuthenticatorHandler
* Handles an authentication failure and returns the Response for the
* GuardAuthenticator.
*
* @param AuthenticationException $authenticationException
* @param Request $request
* @param GuardAuthenticatorInterface $guardAuthenticator
* @param string $providerKey The key of the firewall
* @param AuthenticationException $authenticationException
* @param Request $request
* @param AuthenticatorInterface $guardAuthenticator
* @param string $providerKey The key of the firewall
*
* @return null|Response
*/

View File

@ -28,6 +28,8 @@ use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface
* one location.
*
* @author Ryan Weaver <ryan@knpuniversity.com>
*
* @deprecated since version 3.4, to be removed in 4.0. Use AuthenticatorInterface instead
*/
interface GuardAuthenticatorInterface extends AuthenticationEntryPointInterface
{

View File

@ -14,7 +14,7 @@ namespace Symfony\Component\Security\Guard\Provider;
use Symfony\Component\Security\Core\Authentication\Provider\AuthenticationProviderInterface;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Guard\GuardAuthenticatorInterface;
use Symfony\Component\Security\Guard\AuthenticatorInterface;
use Symfony\Component\Security\Guard\Token\GuardTokenInterface;
use Symfony\Component\Security\Guard\Token\PreAuthenticationGuardToken;
use Symfony\Component\Security\Core\User\UserCheckerInterface;
@ -32,7 +32,7 @@ use Symfony\Component\Security\Core\Exception\AuthenticationExpiredException;
class GuardAuthenticationProvider implements AuthenticationProviderInterface
{
/**
* @var GuardAuthenticatorInterface[]
* @var AuthenticatorInterface[]
*/
private $guardAuthenticators;
private $userProvider;
@ -40,10 +40,10 @@ class GuardAuthenticationProvider implements AuthenticationProviderInterface
private $userChecker;
/**
* @param iterable|GuardAuthenticatorInterface[] $guardAuthenticators The authenticators, with keys that match what's passed to GuardAuthenticationListener
* @param UserProviderInterface $userProvider The user provider
* @param string $providerKey The provider (i.e. firewall) key
* @param UserCheckerInterface $userChecker
* @param iterable|AuthenticatorInterface[] $guardAuthenticators The authenticators, with keys that match what's passed to GuardAuthenticationListener
* @param UserProviderInterface $userProvider The user provider
* @param string $providerKey The provider (i.e. firewall) key
* @param UserCheckerInterface $userChecker
*/
public function __construct($guardAuthenticators, UserProviderInterface $userProvider, $providerKey, UserCheckerInterface $userChecker)
{
@ -101,7 +101,7 @@ class GuardAuthenticationProvider implements AuthenticationProviderInterface
// instances that will be checked if you have multiple firewalls.
}
private function authenticateViaGuard(GuardAuthenticatorInterface $guardAuthenticator, PreAuthenticationGuardToken $token)
private function authenticateViaGuard($guardAuthenticator, PreAuthenticationGuardToken $token)
{
// get the user from the GuardAuthenticator
$user = $guardAuthenticator->getUser($token->getCredentials(), $this->userProvider);

View File

@ -14,12 +14,16 @@ namespace Symfony\Component\Security\Guard\Tests\Firewall;
use PHPUnit\Framework\TestCase;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Guard\AuthenticatorInterface;
use Symfony\Component\Security\Guard\Firewall\GuardAuthenticationListener;
use Symfony\Component\Security\Guard\GuardAuthenticatorInterface;
use Symfony\Component\Security\Guard\Token\PreAuthenticationGuardToken;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
/**
* @author Ryan Weaver <weaverryan@gmail.com>
* @author Amaury Leroux de Lens <amaury@lerouxdelens.com>
*/
class GuardAuthenticationListenerTest extends TestCase
{
@ -32,11 +36,16 @@ class GuardAuthenticationListenerTest extends TestCase
public function testHandleSuccess()
{
$authenticator = $this->getMockBuilder('Symfony\Component\Security\Guard\GuardAuthenticatorInterface')->getMock();
$authenticateToken = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock();
$authenticator = $this->getMockBuilder(AuthenticatorInterface::class)->getMock();
$authenticateToken = $this->getMockBuilder(TokenInterface::class)->getMock();
$providerKey = 'my_firewall';
$credentials = array('username' => 'weaverryan', 'password' => 'all_your_base');
$authenticator
->expects($this->once())
->method('supports')
->willReturn(true);
$authenticator
->expects($this->once())
->method('getCredentials')
@ -82,10 +91,14 @@ class GuardAuthenticationListenerTest extends TestCase
public function testHandleSuccessStopsAfterResponseIsSet()
{
$authenticator1 = $this->getMockBuilder('Symfony\Component\Security\Guard\GuardAuthenticatorInterface')->getMock();
$authenticator2 = $this->getMockBuilder('Symfony\Component\Security\Guard\GuardAuthenticatorInterface')->getMock();
$authenticator1 = $this->getMockBuilder(AuthenticatorInterface::class)->getMock();
$authenticator2 = $this->getMockBuilder(AuthenticatorInterface::class)->getMock();
// mock the first authenticator to fail, and set a Response
$authenticator1
->expects($this->once())
->method('supports')
->willReturn(true);
$authenticator1
->expects($this->once())
->method('getCredentials')
@ -112,10 +125,15 @@ class GuardAuthenticationListenerTest extends TestCase
public function testHandleSuccessWithRememberMe()
{
$authenticator = $this->getMockBuilder('Symfony\Component\Security\Guard\GuardAuthenticatorInterface')->getMock();
$authenticateToken = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock();
$authenticator = $this->getMockBuilder(AuthenticatorInterface::class)->getMock();
$authenticateToken = $this->getMockBuilder(TokenInterface::class)->getMock();
$providerKey = 'my_firewall_with_rememberme';
$authenticator
->expects($this->once())
->method('supports')
->with($this->equalTo($this->request))
->willReturn(true);
$authenticator
->expects($this->once())
->method('getCredentials')
@ -155,10 +173,14 @@ class GuardAuthenticationListenerTest extends TestCase
public function testHandleCatchesAuthenticationException()
{
$authenticator = $this->getMockBuilder('Symfony\Component\Security\Guard\GuardAuthenticatorInterface')->getMock();
$authenticator = $this->getMockBuilder(AuthenticatorInterface::class)->getMock();
$providerKey = 'my_firewall2';
$authException = new AuthenticationException('Get outta here crazy user with a bad password!');
$authenticator
->expects($this->once())
->method('supports')
->willReturn(true);
$authenticator
->expects($this->once())
->method('getCredentials')
@ -185,6 +207,96 @@ class GuardAuthenticationListenerTest extends TestCase
$listener->handle($this->event);
}
/**
* @group legacy
*/
public function testLegacyInterfaceNullCredentials()
{
$authenticatorA = $this->getMockBuilder(GuardAuthenticatorInterface::class)->getMock();
$providerKey = 'my_firewall3';
$authenticatorA
->expects($this->once())
->method('getCredentials')
->will($this->returnValue(null));
// this is not called
$this->authenticationManager
->expects($this->never())
->method('authenticate');
$this->guardAuthenticatorHandler
->expects($this->never())
->method('handleAuthenticationSuccess');
$listener = new GuardAuthenticationListener(
$this->guardAuthenticatorHandler,
$this->authenticationManager,
$providerKey,
array($authenticatorA),
$this->logger
);
$listener->handle($this->event);
}
/**
* @group legacy
*/
public function testLegacyInterfaceKeepsWorking()
{
$authenticator = $this->getMockBuilder(GuardAuthenticatorInterface::class)->getMock();
$authenticateToken = $this->getMockBuilder(TokenInterface::class)->getMock();
$providerKey = 'my_firewall';
$credentials = array('username' => 'weaverryan', 'password' => 'all_your_base');
$authenticator
->expects($this->once())
->method('getCredentials')
->with($this->equalTo($this->request))
->will($this->returnValue($credentials));
// a clone of the token that should be created internally
$uniqueGuardKey = 'my_firewall_0';
$nonAuthedToken = new PreAuthenticationGuardToken($credentials, $uniqueGuardKey);
$this->authenticationManager
->expects($this->once())
->method('authenticate')
->with($this->equalTo($nonAuthedToken))
->will($this->returnValue($authenticateToken));
$this->guardAuthenticatorHandler
->expects($this->once())
->method('authenticateWithToken')
->with($authenticateToken, $this->request);
$this->guardAuthenticatorHandler
->expects($this->once())
->method('handleAuthenticationSuccess')
->with($authenticateToken, $this->request, $authenticator, $providerKey);
$listener = new GuardAuthenticationListener(
$this->guardAuthenticatorHandler,
$this->authenticationManager,
$providerKey,
array($authenticator),
$this->logger
);
$listener->setRememberMeServices($this->rememberMeServices);
// should never be called - our handleAuthenticationSuccess() does not return a Response
$this->rememberMeServices
->expects($this->never())
->method('loginSuccess');
$listener->handle($this->event);
}
/**
* @group legacy
*/
public function testReturnNullToSkipAuth()
{
$authenticatorA = $this->getMockBuilder('Symfony\Component\Security\Guard\GuardAuthenticatorInterface')->getMock();
@ -220,6 +332,62 @@ class GuardAuthenticationListenerTest extends TestCase
$listener->handle($this->event);
}
public function testSupportsReturnFalseSkipAuth()
{
$authenticator = $this->getMockBuilder(AuthenticatorInterface::class)->getMock();
$providerKey = 'my_firewall4';
$authenticator
->expects($this->once())
->method('supports')
->will($this->returnValue(false));
// this is not called
$authenticator
->expects($this->never())
->method('getCredentials');
$listener = new GuardAuthenticationListener(
$this->guardAuthenticatorHandler,
$this->authenticationManager,
$providerKey,
array($authenticator),
$this->logger
);
$listener->handle($this->event);
}
/**
* @expectedException \UnexpectedValueException
*/
public function testReturnNullFromGetCredentials()
{
$authenticator = $this->getMockBuilder(AuthenticatorInterface::class)->getMock();
$providerKey = 'my_firewall4';
$authenticator
->expects($this->once())
->method('supports')
->will($this->returnValue(true));
// this will raise exception
$authenticator
->expects($this->once())
->method('getCredentials')
->will($this->returnValue(null));
$listener = new GuardAuthenticationListener(
$this->guardAuthenticatorHandler,
$this->authenticationManager,
$providerKey,
array($authenticator),
$this->logger
);
$listener->handle($this->event);
}
protected function setUp()
{
$this->authenticationManager = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\AuthenticationProviderManager')

View File

@ -14,6 +14,7 @@ namespace Symfony\Component\Security\Guard\Tests;
use PHPUnit\Framework\TestCase;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Guard\AuthenticatorInterface;
use Symfony\Component\Security\Guard\GuardAuthenticatorHandler;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
@ -128,7 +129,7 @@ class GuardAuthenticatorHandlerTest extends TestCase
$this->dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')->getMock();
$this->token = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock();
$this->request = new Request(array(), array(), array(), array(), array(), array());
$this->guardAuthenticator = $this->getMockBuilder('Symfony\Component\Security\Guard\GuardAuthenticatorInterface')->getMock();
$this->guardAuthenticator = $this->getMockBuilder(AuthenticatorInterface::class)->getMock();
}
protected function tearDown()

View File

@ -12,6 +12,9 @@
namespace Symfony\Component\Security\Guard\Tests\Provider;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Guard\AuthenticatorInterface;
use Symfony\Component\Security\Guard\Provider\GuardAuthenticationProvider;
use Symfony\Component\Security\Guard\Token\PostAuthenticationGuardToken;
@ -28,6 +31,68 @@ class GuardAuthenticationProviderTest extends TestCase
{
$providerKey = 'my_cool_firewall';
$authenticatorA = $this->getMockBuilder(AuthenticatorInterface::class)->getMock();
$authenticatorB = $this->getMockBuilder(AuthenticatorInterface::class)->getMock();
$authenticatorC = $this->getMockBuilder(AuthenticatorInterface::class)->getMock();
$authenticators = array($authenticatorA, $authenticatorB, $authenticatorC);
// called 2 times - for authenticator A and B (stops on B because of match)
$this->preAuthenticationToken->expects($this->exactly(2))
->method('getGuardProviderKey')
// it will return the "1" index, which will match authenticatorB
->will($this->returnValue('my_cool_firewall_1'));
$enteredCredentials = array(
'username' => '_weaverryan_test_user',
'password' => 'guard_auth_ftw',
);
$this->preAuthenticationToken->expects($this->atLeastOnce())
->method('getCredentials')
->will($this->returnValue($enteredCredentials));
// authenticators A and C are never called
$authenticatorA->expects($this->never())
->method('getUser');
$authenticatorC->expects($this->never())
->method('getUser');
$mockedUser = $this->getMockBuilder(UserInterface::class)->getMock();
$authenticatorB->expects($this->once())
->method('getUser')
->with($enteredCredentials, $this->userProvider)
->will($this->returnValue($mockedUser));
// checkCredentials is called
$authenticatorB->expects($this->once())
->method('checkCredentials')
->with($enteredCredentials, $mockedUser)
// authentication works!
->will($this->returnValue(true));
$authedToken = $this->getMockBuilder(TokenInterface::class)->getMock();
$authenticatorB->expects($this->once())
->method('createAuthenticatedToken')
->with($mockedUser, $providerKey)
->will($this->returnValue($authedToken));
// user checker should be called
$this->userChecker->expects($this->once())
->method('checkPreAuth')
->with($mockedUser);
$this->userChecker->expects($this->once())
->method('checkPostAuth')
->with($mockedUser);
$provider = new GuardAuthenticationProvider($authenticators, $this->userProvider, $providerKey, $this->userChecker);
$actualAuthedToken = $provider->authenticate($this->preAuthenticationToken);
$this->assertSame($authedToken, $actualAuthedToken);
}
/**
* @group legacy
*/
public function testLegacyAuthenticate()
{
$providerKey = 'my_cool_firewall';
$authenticatorA = $this->getMockBuilder('Symfony\Component\Security\Guard\GuardAuthenticatorInterface')->getMock();
$authenticatorB = $this->getMockBuilder('Symfony\Component\Security\Guard\GuardAuthenticatorInterface')->getMock();
$authenticatorC = $this->getMockBuilder('Symfony\Component\Security\Guard\GuardAuthenticatorInterface')->getMock();

View File

@ -29,7 +29,7 @@ class PreAuthenticationGuardToken extends AbstractToken implements GuardTokenInt
/**
* @param mixed $credentials
* @param string $guardProviderKey Unique key that bind this token to a specific GuardAuthenticatorInterface
* @param string $guardProviderKey Unique key that bind this token to a specific AuthenticatorInterface
*/
public function __construct($credentials, $guardProviderKey)
{

View File

@ -58,6 +58,14 @@ class TranslationDataCollector extends DataCollector implements LateDataCollecto
{
}
/**
* {@inheritdoc}
*/
public function reset()
{
$this->data = array();
}
/**
* @return array
*/

View File

@ -19,6 +19,7 @@ use Symfony\Component\HttpKernel\DataCollector\LateDataCollectorInterface;
use Symfony\Component\Validator\Validator\TraceableValidator;
use Symfony\Component\VarDumper\Caster\Caster;
use Symfony\Component\VarDumper\Caster\ClassStub;
use Symfony\Component\VarDumper\Cloner\Data;
use Symfony\Component\VarDumper\Cloner\Stub;
/**
@ -31,10 +32,7 @@ class ValidatorDataCollector extends DataCollector implements LateDataCollectorI
public function __construct(TraceableValidator $validator)
{
$this->validator = $validator;
$this->data = array(
'calls' => array(),
'violations_count' => 0,
);
$this->reset();
}
/**
@ -45,6 +43,15 @@ class ValidatorDataCollector extends DataCollector implements LateDataCollectorI
// Everything is collected once, on kernel terminate.
}
public function reset()
{
$this->validator->reset();
$this->data = array(
'calls' => $this->cloneVar(array()),
'violations_count' => 0,
);
}
/**
* {@inheritdoc}
*/
@ -52,16 +59,22 @@ class ValidatorDataCollector extends DataCollector implements LateDataCollectorI
{
$collected = $this->validator->getCollectedData();
$this->data['calls'] = $this->cloneVar($collected);
$this->data['violations_count'] += array_reduce($collected, function ($previous, $item) {
return $previous += count($item['violations']);
$this->data['violations_count'] = array_reduce($collected, function ($previous, $item) {
return $previous + count($item['violations']);
}, 0);
}
/**
* @return Data
*/
public function getCalls()
{
return $this->data['calls'];
}
/**
* @return int
*/
public function getViolationsCount()
{
return $this->data['violations_count'];

View File

@ -50,6 +50,33 @@ class ValidatorDataCollectorTest extends TestCase
$this->assertCount(2, $call['violations']);
}
public function testReset()
{
$originalValidator = $this->createMock(ValidatorInterface::class);
$validator = new TraceableValidator($originalValidator);
$collector = new ValidatorDataCollector($validator);
$violations = new ConstraintViolationList(array(
$this->createMock(ConstraintViolation::class),
$this->createMock(ConstraintViolation::class),
));
$originalValidator->method('validate')->willReturn($violations);
$validator->validate(new \stdClass());
$collector->lateCollect();
$collector->reset();
$this->assertCount(0, $collector->getCalls());
$this->assertSame(0, $collector->getViolationsCount());
$collector->lateCollect();
$this->assertCount(0, $collector->getCalls());
$this->assertSame(0, $collector->getViolationsCount());
}
protected function createMock($classname)
{
return $this->getMockBuilder($classname)->disableOriginalConstructor()->getMock();

View File

@ -11,7 +11,6 @@
namespace Symfony\Component\Validator\Validator;
use Symfony\Component\Validator\ConstraintViolationList;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
/**
@ -30,13 +29,18 @@ class TraceableValidator implements ValidatorInterface
}
/**
* @return ConstraintViolationList[]
* @return array
*/
public function getCollectedData()
{
return $this->collectedData;
}
public function reset()
{
$this->collectedData = array();
}
/**
* {@inheritdoc}
*/

View File

@ -16,6 +16,7 @@ CHANGELOG
-----
* added `AbstractCloner::setMinDepth()` function to ensure minimum tree depth
* deprecated `MongoCaster`
2.7.0
-----

Some files were not shown because too many files have changed in this diff Show More