Merge branch '2.7'

* 2.7: (32 commits)
  [Config] adds missing « use » statement for InvalidTypeException type hint in documentation.
  [Config] fixes broken unit test on ArrayNode class.
  fixed CS
  [Security] Delete old session on auth strategy migrate
  skip if param "translator.logging" doesn't exist.
  [SecurityBundle] fixes SecurityDataCollector::getInheritedRoles() documentation.
  update required minimum TwigBridge version
  Very minor grammar fix in error message
  Added the function providers as container resources
  [Tests] Silenced all deprecations in tests for 2.3
  BinaryFileResponse - add missing newline
  fixed CS
  add a limit and a test to FlattenExceptionTest.
  [DebugBundle] enable the DumpDataCollectorPass
  [FrameworkBundle] Use debug namespace.
  [FrameworkBundle] update debug commands references
  skip compiler pass if interface doesn't exist
  Unify the way to provide expression functions for the DI container
  CS: There should be no empty lines following phpdocs
  [Security] Added the triggering of the security.interactive_login event after set of token
  ...

Conflicts:
	src/Symfony/Component/HttpKernel/Kernel.php
This commit is contained in:
Fabien Potencier 2014-12-20 17:07:50 +01:00
commit fb34a6f938
46 changed files with 463 additions and 217 deletions

View File

@ -15,7 +15,7 @@ use Symfony\Bridge\Propel1\Tests\Fixtures\Item;
use Symfony\Bridge\Propel1\Form\PropelExtension;
use Symfony\Bridge\Propel1\Tests\Fixtures\TranslatableItemI18n;
use Symfony\Bridge\Propel1\Tests\Fixtures\TranslatableItem;
use Symfony\Component\Form\Tests\Extension\Core\Type\TypeTestCase;
use Symfony\Component\Form\Test\TypeTestCase;
class TranslationCollectionTypeTest extends TypeTestCase
{

View File

@ -11,6 +11,8 @@
namespace Symfony\Bundle\DebugBundle;
use Symfony\Bundle\DebugBundle\DependencyInjection\Compiler\DumpDataCollectorPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Bundle\Bundle;
use Symfony\Component\VarDumper\Dumper\CliDumper;
use Symfony\Component\VarDumper\VarDumper;
@ -39,4 +41,14 @@ class DebugBundle extends Bundle
});
}
}
/**
* {@inheritdoc}
*/
public function build(ContainerBuilder $container)
{
parent::build($container);
$container->addCompilerPass(new DumpDataCollectorPass());
}
}

View File

@ -0,0 +1,39 @@
<?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\Bundle\DebugBundle\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
/**
* Registers the file link format for the {@link DumpDataCollector}.
*
* @author Christian Flothmann <christian.flothmann@xabbuh.de>
*/
class DumpDataCollectorPass implements CompilerPassInterface
{
/**
* {@inheritdoc}
*/
public function process(ContainerBuilder $container)
{
if (!$container->hasDefinition('data_collector.dump')) {
return;
}
$definition = $container->getDefinition('data_collector.dump');
if ($container->hasParameter('templating.helper.code.file_link_format')) {
$definition->replaceArgument(1, $container->getParameter('templating.helper.code.file_link_format'));
}
}
}

View File

@ -13,7 +13,7 @@
<service id="data_collector.dump" class="Symfony\Component\HttpKernel\DataCollector\DumpDataCollector">
<tag name="data_collector" id="dump" template="@Debug/Profiler/dump.html.twig" />
<argument type="service" id="debug.stopwatch" on-invalid="ignore" />
<argument>%templating.helper.code.file_link_format%</argument>
<argument>null</argument><!-- %templating.helper.code.file_link_format% -->
</service>
<service id="debug.dump_listener" class="Symfony\Component\HttpKernel\EventListener\DumpListener">

View File

@ -0,0 +1,46 @@
<?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\Bundle\DebugBundle\Tests\DependencyInjection\Compiler;
use Symfony\Bundle\DebugBundle\DependencyInjection\Compiler\DumpDataCollectorPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
class DumpDataCollectorPassTest extends \PHPUnit_Framework_TestCase
{
public function testProcessWithFileLinkFormatParameter()
{
$container = new ContainerBuilder();
$container->addCompilerPass(new DumpDataCollectorPass());
$container->setParameter('templating.helper.code.file_link_format', 'file-link-format');
$definition = new Definition('Symfony\Component\HttpKernel\DataCollector\DumpDataCollector', array(null, null));
$container->setDefinition('data_collector.dump', $definition);
$container->compile();
$this->assertSame('file-link-format', $definition->getArgument(1));
}
public function testProcessWithoutFileLinkFormatParameter()
{
$container = new ContainerBuilder();
$container->addCompilerPass(new DumpDataCollectorPass());
$definition = new Definition('Symfony\Component\HttpKernel\DataCollector\DumpDataCollector', array(null, null));
$container->setDefinition('data_collector.dump', $definition);
$container->compile();
$this->assertNull($definition->getArgument(1));
}
}

View File

@ -75,6 +75,7 @@ EOF
} else {
// the warmup cache dir name must have the same length than the real one
// to avoid the many problems in serialized resources files
$realCacheDir = realpath($realCacheDir);
$warmupDir = substr($realCacheDir, 0, -1).'_';
if ($filesystem->exists($warmupDir)) {
@ -180,12 +181,14 @@ EOF
*/
protected function getTempKernel(KernelInterface $parent, $namespace, $parentClass, $warmupDir)
{
$rootDir = $parent->getRootDir();
$cacheDir = var_export($warmupDir, true);
$rootDir = var_export(realpath($parent->getRootDir()), true);
$logDir = var_export(realpath($parent->getLogDir()), true);
// the temp kernel class name must have the same length than the real one
// to avoid the many problems in serialized resources files
$class = substr($parentClass, 0, -1).'_';
// the temp kernel name must be changed too
$name = substr($parent->getName(), 0, -1).'_';
$name = var_export(substr($parent->getName(), 0, -1).'_', true);
$code = <<<EOF
<?php
@ -195,17 +198,22 @@ namespace $namespace
{
public function getCacheDir()
{
return '$warmupDir';
return $cacheDir;
}
public function getName()
{
return '$name';
return $name;
}
public function getRootDir()
{
return '$rootDir';
return $rootDir;
}
public function getLogDir()
{
return $logDir;
}
protected function buildContainer()

View File

@ -123,7 +123,7 @@ EOF
$helper->describe($output, $object, $options);
if (!$input->getArgument('name') && $input->isInteractive()) {
$output->writeln('To search for a service, re-run this command with a search term. <comment>container:debug log</comment>');
$output->writeln('To search for a service, re-run this command with a search term. <comment>debug:container log</comment>');
}
}

View File

@ -19,7 +19,7 @@ use Symfony\Component\Filesystem\Filesystem;
/**
* Dumps the ContainerBuilder to a cache file so that it can be used by
* debugging tools such as the container:debug console command.
* debugging tools such as the debug:container console command.
*
* @author Ryan Weaver <ryan@thatsquality.com>
* @author Fabien Potencier <fabien@symfony.com>

View File

@ -25,7 +25,12 @@ class LoggingTranslatorPass implements CompilerPassInterface
return;
}
if ($container->getParameter('translator.logging')) {
// skip if the symfony/translation version is lower than 2.6
if (!interface_exists('Symfony\Component\Translation\TranslatorBagInterface')) {
return;
}
if ($container->hasParameter('translator.logging') && $container->getParameter('translator.logging')) {
$translatorAlias = $container->getAlias('translator');
$definition = $container->getDefinition((string) $translatorAlias);
$class = $container->getParameterBag()->resolveValue($definition->getClass());

View File

@ -51,7 +51,7 @@
"symfony/finder": "For using the translation loader and cache warmer",
"symfony/form": "For using forms",
"symfony/validator": "For using validation",
"symfony/yaml": "For using the config:debug and yaml:lint commands",
"symfony/yaml": "For using the debug:config and yaml:lint commands",
"doctrine/cache": "For using alternative cache drivers"
},
"autoload": {

View File

@ -114,7 +114,7 @@ class SecurityDataCollector extends DataCollector
/**
* Gets the inherited roles of the user.
*
* @return string The inherited roles
* @return array The inherited roles
*/
public function getInheritedRoles()
{

View File

@ -165,7 +165,6 @@ class SecurityExtension extends Extension
* @param array $config An array of configuration settings
* @param ContainerBuilder $container A ContainerBuilder instance
*/
private function createRoleHierarchy($config, ContainerBuilder $container)
{
if (!isset($config['role_hierarchy'])) {

View File

@ -172,6 +172,7 @@
<argument /> <!-- Provider-shared Key -->
<argument /> <!-- Authenticator -->
<argument type="service" id="logger" on-invalid="null" />
<argument type="service" id="event_dispatcher" on-invalid="null"/>
</service>
<service id="security.authentication.listener.x509" class="%security.authentication.listener.x509.class%" public="false" abstract="true">

View File

@ -305,7 +305,7 @@ class ArrayNode extends BaseNode implements PrototypeNodeInterface
// if extra fields are present, throw exception
if (count($value) && !$this->ignoreExtraKeys) {
$msg = sprintf('Unrecognized options "%s" under "%s"', implode(', ', array_keys($value)), $this->getPath());
$msg = sprintf('Unrecognized option%s "%s" under "%s"', 1 === count($value) ? '' : 's', implode(', ', array_keys($value)), $this->getPath());
$ex = new InvalidConfigurationException($msg);
$ex->setPath($this->getPath());

View File

@ -14,6 +14,7 @@ namespace Symfony\Component\Config\Definition;
use Symfony\Component\Config\Definition\Exception\Exception;
use Symfony\Component\Config\Definition\Exception\ForbiddenOverwriteException;
use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
use Symfony\Component\Config\Definition\Exception\InvalidTypeException;
/**
* The base node class

View File

@ -27,7 +27,7 @@ class ArrayNodeTest extends \PHPUnit_Framework_TestCase
/**
* @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
* @expectedExceptionMessage Unrecognized options "foo" under "root"
* @expectedExceptionMessage Unrecognized option "foo" under "root"
*/
public function testExceptionThrownOnUnrecognizedChild()
{

View File

@ -210,17 +210,20 @@ class FlattenException
}
}
private function flattenArgs($args, $level = 0)
private function flattenArgs($args, $level = 0, &$count = 0)
{
$result = array();
foreach ($args as $key => $value) {
if (++$count > 1e4) {
return array('array', '*SKIPPED over 10000 entries*');
}
if (is_object($value)) {
$result[$key] = array('object', get_class($value));
} elseif (is_array($value)) {
if ($level > 10) {
$result[$key] = array('array', '*DEEP NESTED ARRAY*');
} else {
$result[$key] = array('array', $this->flattenArgs($value, $level + 1));
$result[$key] = array('array', $this->flattenArgs($value, $level + 1, $count));
}
} elseif (null === $value) {
$result[$key] = array('null', null);

View File

@ -186,6 +186,28 @@ class FlattenExceptionTest extends \PHPUnit_Framework_TestCase
$this->assertContains('*DEEP NESTED ARRAY*', serialize($trace));
}
public function testTooBigArray()
{
$a = array();
for ($i = 0; $i < 20; $i++) {
for ($j = 0; $j < 50; $j++) {
for ($k = 0; $k < 10; $k++) {
$a[$i][$j][$k] = 'value';
}
}
}
$a[20] = 'value';
$a[21] = 'value1';
$exception = $this->createException($a);
$flattened = FlattenException::create($exception);
$trace = $flattened->getTrace();
$serializeTrace = serialize($trace);
$this->assertContains('*SKIPPED over 10000 entries*', $serializeTrace);
$this->assertNotContains('*value1*', $serializeTrace);
}
private function createException($foo)
{
return new \Exception();

View File

@ -1075,6 +1075,14 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
$this->expressionLanguageProviders[] = $provider;
}
/**
* @return ExpressionFunctionProviderInterface[]
*/
public function getExpressionLanguageProviders()
{
return $this->expressionLanguageProviders;
}
/**
* Returns the Service Conditionals.
*

View File

@ -1399,6 +1399,11 @@ EOF;
return sprintf("\$this->getParameter('%s')", strtolower($name));
}
/**
* @deprecated Deprecated since 2.6.2, to be removed in 3.0. Use Symfony\Component\DependencyInjection\ContainerBuilder::addExpressionLanguageProvider instead.
*
* @param ExpressionFunctionProviderInterface $provider
*/
public function addExpressionLanguageProvider(ExpressionFunctionProviderInterface $provider)
{
$this->expressionLanguageProviders[] = $provider;
@ -1493,7 +1498,14 @@ EOF;
if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) {
throw new RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.');
}
$this->expressionLanguage = new ExpressionLanguage(null, $this->expressionLanguageProviders);
$providers = array_merge($this->container->getExpressionLanguageProviders(), $this->expressionLanguageProviders);
$this->expressionLanguage = new ExpressionLanguage(null, $providers);
if ($this->container->isTrackingResources()) {
foreach ($providers as $provider) {
$this->container->addObjectResource($provider);
}
}
}
return $this->expressionLanguage;

View File

@ -0,0 +1,28 @@
<?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\Form\Deprecated;
trigger_error('Constants PRE_BIND, BIND and POST_BIND on class Symfony\Component\Form\FormEvents were deprecated in Symfony 2.3 and will be removed in 3.0. Use PRE_SUBMIT, SUBMIT and POST_SUBMIT instead.', E_USER_DEPRECATED);
/**
* @deprecated since 2.7, to be removed in 3.0.
* @internal
*/
final class FormEvents
{
const PRE_BIND = 'form.pre_bind';
const BIND = 'form.bind';
const POST_BIND = 'form.post_bind';
private function __construct()
{
}
}

View File

@ -0,0 +1,29 @@
<?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\Form\Deprecated;
trigger_error('Constants ROUND_HALFEVEN, ROUND_HALFUP and ROUND_HALFDOWN on class NumberToLocalizedStringTransformer were deprecated in Symfony 2.4 and will be removed in 3.0. Use ROUND_HALF_EVEN, ROUND_HALF_UP and ROUND_HALF_DOWN instead.', E_USER_DEPRECATED);
/**
* @deprecated since 2.7, to be removed in 3.0.
* @internal
*/
final class NumberToLocalizedStringTransformer
{
const ROUND_HALFEVEN = \NumberFormatter::ROUND_HALFEVEN;
const ROUND_HALFUP = \NumberFormatter::ROUND_HALFUP;
const ROUND_HALFDOWN = \NumberFormatter::ROUND_HALFDOWN;
private function __construct()
{
}
}

View File

@ -13,6 +13,7 @@ namespace Symfony\Component\Form\Extension\Core\DataTransformer;
use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\TransformationFailedException;
use Symfony\Component\Form\Deprecated\NumberToLocalizedStringTransformer as Deprecated;
/**
* Transforms between a number type and a localized number with grouping
@ -77,21 +78,21 @@ class NumberToLocalizedStringTransformer implements DataTransformerInterface
*
* @deprecated Deprecated as of Symfony 2.4, to be removed in Symfony 3.0.
*/
const ROUND_HALFEVEN = self::ROUND_HALF_EVEN;
const ROUND_HALFEVEN = Deprecated::ROUND_HALFEVEN;
/**
* Alias for {@link self::ROUND_HALF_UP}.
*
* @deprecated Deprecated as of Symfony 2.4, to be removed in Symfony 3.0.
*/
const ROUND_HALFUP = self::ROUND_HALF_UP;
const ROUND_HALFUP = Deprecated::ROUND_HALFUP;
/**
* Alias for {@link self::ROUND_HALF_DOWN}.
*
* @deprecated Deprecated as of Symfony 2.4, to be removed in Symfony 3.0.
*/
const ROUND_HALFDOWN = self::ROUND_HALF_DOWN;
const ROUND_HALFDOWN = Deprecated::ROUND_HALFDOWN;
protected $precision;

View File

@ -11,6 +11,8 @@
namespace Symfony\Component\Form\Extension\Csrf\CsrfProvider;
trigger_error('Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderAdapter was deprecated in version 2.4 and will be removed in version 3.0. Please use Symfony\Component\Security\Csrf\CsrfTokenManager instead.', E_USER_DEPRECATED);
use Symfony\Component\Form\Exception\BadMethodCallException;
use Symfony\Component\Security\Csrf\CsrfToken;
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;

View File

@ -11,6 +11,8 @@
namespace Symfony\Component\Form\Extension\Csrf\CsrfProvider;
trigger_error('Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface was deprecated in version 2.4 and will be removed in version 3.0. Please use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface instead.', E_USER_DEPRECATED);
/**
* Marks classes able to provide CSRF protection
*

View File

@ -11,6 +11,8 @@
namespace Symfony\Component\Form\Extension\Csrf\CsrfProvider;
trigger_error('Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfTokenManagerAdapter was deprecated in version 2.4 and will be removed in version 3.0. Please use Symfony\Component\Security\Csrf\CsrfTokenManager instead.', E_USER_DEPRECATED);
use Symfony\Component\Security\Csrf\CsrfToken;
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;

View File

@ -11,6 +11,8 @@
namespace Symfony\Component\Form\Extension\Csrf\CsrfProvider;
trigger_error('Symfony\Component\Security\Csrf\CsrfTokenManager was deprecated in version 2.4 and will be removed in version 3.0. Please use \Symfony\Component\Security\Csrf\TokenStorage\NativeSessionTokenStorage instead.', E_USER_DEPRECATED);
/**
* Default implementation of CsrfProviderInterface.
*

View File

@ -11,6 +11,8 @@
namespace Symfony\Component\Form\Extension\Csrf\CsrfProvider;
trigger_error('Symfony\Component\Security\Csrf\CsrfTokenManager was deprecated in version 2.4 and will be removed in version 3.0. Please use Symfony\Component\Security\Csrf\TokenStorage\SessionTokenStorage instead.', E_USER_DEPRECATED);
use Symfony\Component\HttpFoundation\Session\Session;
/**

View File

@ -10,6 +10,8 @@
namespace Symfony\Component\Form;
use Symfony\Component\Form\Deprecated\FormEvents as Deprecated;
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*/
@ -77,7 +79,7 @@ final class FormEvents
*
* @Event
*/
const PRE_BIND = 'form.pre_bind';
const PRE_BIND = Deprecated::PRE_BIND;
/**
* @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
@ -85,7 +87,7 @@ final class FormEvents
*
* @Event
*/
const BIND = 'form.bind';
const BIND = Deprecated::BIND;
/**
* @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
@ -93,7 +95,7 @@ final class FormEvents
*
* @Event
*/
const POST_BIND = 'form.post_bind';
const POST_BIND = Deprecated::POST_BIND;
private function __construct()
{

View File

@ -18,4 +18,9 @@ use Symfony\Component\Form\Test\TypeTestCase as BaseTypeTestCase;
*/
abstract class TypeTestCase extends BaseTypeTestCase
{
protected function setUp()
{
trigger_error('Abstract class "Symfony\Component\Form\Tests\Extension\Core\Type\TypeTestCase" is deprecated since version 2.3 and will be removed in 3.0. Use "Symfony\Component\Form\Test\TypeTestCase" instead.', E_USER_DEPRECATED);
parent::setUp();
}
}

View File

@ -11,6 +11,8 @@
namespace Symfony\Component\Form\Util;
trigger_error('Symfony\Component\Form\Util\VirtualFormAwareIterator is deprecated since Symfony 2.3 and will be removed in 3.0. Use Symfony\Component\Form\Util\InheritDataAwareIterator instead.', E_USER_DEPRECATED);
/**
* Iterator that traverses an array of forms.
*

View File

@ -1,6 +1,6 @@
<?php
/**
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
@ -63,7 +63,7 @@ class BinaryFileResponse extends Response
* @param bool $autoEtag Whether the ETag header should be automatically set
* @param bool $autoLastModified Whether the Last-Modified header should be automatically set
*
* @return BinaryResponse The created response
* @return BinaryFileResponse The created response
*/
public static function create($file = null, $status = 200, $headers = array(), $public = true, $contentDisposition = null, $autoEtag = false, $autoLastModified = true)
{

View File

@ -16,7 +16,6 @@ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler;
*
* @see http://php.net/sessionhandler
*/
if (PHP_VERSION_ID >= 50400) {
class NativeSessionHandler extends \SessionHandler
{

View File

@ -559,12 +559,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface
return array_merge(
array(
'kernel.root_dir' => $this->rootDir,
'kernel.root_dir' => realpath($this->rootDir) ?: $this->rootDir,
'kernel.environment' => $this->environment,
'kernel.debug' => $this->debug,
'kernel.name' => $this->name,
'kernel.cache_dir' => $this->getCacheDir(),
'kernel.logs_dir' => $this->getLogDir(),
'kernel.cache_dir' => realpath($this->getCacheDir()) ?: $this->getCacheDir(),
'kernel.logs_dir' => realpath($this->getLogDir()) ?: $this->getLogDir(),
'kernel.bundles' => $bundles,
'kernel.charset' => $this->getCharset(),
'kernel.container_class' => $this->getContainerClass(),

View File

@ -7,7 +7,6 @@
*
* @example `php NonStopableProcess.php 42` will run the script for 42 seconds
*/
function handleSignal($signal)
{
switch ($signal) {

View File

@ -0,0 +1,31 @@
<?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\PropertyAccess\Tests\Fixtures;
class Ticket5775Object
{
private $property;
public function getProperty()
{
return $this->property;
}
private function setProperty()
{
}
public function __set($property, $value)
{
$this->$property = $value;
}
}

View File

@ -15,6 +15,7 @@ use Symfony\Component\PropertyAccess\PropertyAccessor;
use Symfony\Component\PropertyAccess\Tests\Fixtures\TestClass;
use Symfony\Component\PropertyAccess\Tests\Fixtures\TestClassMagicCall;
use Symfony\Component\PropertyAccess\Tests\Fixtures\TestClassMagicGet;
use Symfony\Component\PropertyAccess\Tests\Fixtures\Ticket5775Object;
class PropertyAccessorTest extends \PHPUnit_Framework_TestCase
{
@ -448,4 +449,13 @@ class PropertyAccessorTest extends \PHPUnit_Framework_TestCase
array((object) array('property' => (object) array('%!@$§' => 'Bernhard')), 'property.%!@$§', 'Bernhard'),
);
}
public function testTicket5755()
{
$object = new Ticket5775Object();
$this->propertyAccessor->setValue($object, 'property', 'foobar');
$this->assertEquals('foobar', $object->getProperty());
}
}

View File

@ -1,6 +1,11 @@
CHANGELOG
=========
2.7.0
-----
* Added the triggering of the `Symfony\Component\Security\Http\SecurityEvents::INTERACTIVE_LOGIN` in `Symfony\Component\Security\Http\Firewall\SimplePreAuthenticationListener`
2.6.0
-----

View File

@ -1,175 +0,0 @@
<?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\Core\Tests\Validator\Constraints;
use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface;
use Symfony\Component\Security\Core\Encoder\PasswordEncoderInterface;
use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\Security\Core\Validator\Constraints\UserPassword;
use Symfony\Component\Security\Core\Validator\Constraints\UserPasswordValidator;
use Symfony\Component\Validator\Tests\Constraints\AbstractConstraintValidatorTest;
use Symfony\Component\Validator\Validation;
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class UserPasswordValidatorTest extends AbstractConstraintValidatorTest
{
const PASSWORD = 's3Cr3t';
const SALT = '^S4lt$';
/**
* @var SecurityContextInterface
*/
protected $securityContext;
/**
* @var PasswordEncoderInterface
*/
protected $encoder;
/**
* @var EncoderFactoryInterface
*/
protected $encoderFactory;
protected function getApiVersion()
{
return Validation::API_VERSION_2_5;
}
protected function createValidator()
{
return new UserPasswordValidator($this->securityContext, $this->encoderFactory);
}
protected function setUp()
{
$user = $this->createUser();
$this->securityContext = $this->createSecurityContext($user);
$this->encoder = $this->createPasswordEncoder();
$this->encoderFactory = $this->createEncoderFactory($this->encoder);
parent::setUp();
}
public function testPasswordIsValid()
{
$constraint = new UserPassword(array(
'message' => 'myMessage',
));
$this->encoder->expects($this->once())
->method('isPasswordValid')
->with(static::PASSWORD, 'secret', static::SALT)
->will($this->returnValue(true));
$this->validator->validate('secret', $constraint);
$this->assertNoViolation();
}
public function testPasswordIsNotValid()
{
$constraint = new UserPassword(array(
'message' => 'myMessage',
));
$this->encoder->expects($this->once())
->method('isPasswordValid')
->with(static::PASSWORD, 'secret', static::SALT)
->will($this->returnValue(false));
$this->validator->validate('secret', $constraint);
$this->buildViolation('myMessage')
->assertRaised();
}
/**
* @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
*/
public function testUserIsNotValid()
{
$user = $this->getMock('Foo\Bar\User');
$this->securityContext = $this->createSecurityContext($user);
$this->validator = $this->createValidator();
$this->validator->initialize($this->context);
$this->validator->validate('secret', new UserPassword());
}
protected function createUser()
{
$mock = $this->getMock('Symfony\Component\Security\Core\User\UserInterface');
$mock
->expects($this->any())
->method('getPassword')
->will($this->returnValue(static::PASSWORD))
;
$mock
->expects($this->any())
->method('getSalt')
->will($this->returnValue(static::SALT))
;
return $mock;
}
protected function createPasswordEncoder($isPasswordValid = true)
{
return $this->getMock('Symfony\Component\Security\Core\Encoder\PasswordEncoderInterface');
}
protected function createEncoderFactory($encoder = null)
{
$mock = $this->getMock('Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface');
$mock
->expects($this->any())
->method('getEncoder')
->will($this->returnValue($encoder))
;
return $mock;
}
protected function createSecurityContext($user = null)
{
$token = $this->createAuthenticationToken($user);
$mock = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface');
$mock
->expects($this->any())
->method('getToken')
->will($this->returnValue($token))
;
return $mock;
}
protected function createAuthenticationToken($user = null)
{
$mock = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
$mock
->expects($this->any())
->method('getUser')
->will($this->returnValue($user))
;
return $mock;
}
}

View File

@ -21,6 +21,9 @@ use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface;
use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Symfony\Component\Security\Http\SecurityEvents;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
/**
* SimplePreAuthenticationListener implements simple proxying to an authenticator.
@ -34,17 +37,19 @@ class SimplePreAuthenticationListener implements ListenerInterface
private $providerKey;
private $simpleAuthenticator;
private $logger;
private $dispatcher;
/**
* Constructor.
*
* @param SecurityContextInterface $securityContext A SecurityContext instance
* @param AuthenticationManagerInterface $authenticationManager An AuthenticationManagerInterface instance
* @param string $providerKey
* @param SimplePreAuthenticatorInterface $simpleAuthenticator A SimplePreAuthenticatorInterface instance
* @param LoggerInterface $logger A LoggerInterface instance
* @param SecurityContextInterface $securityContext A SecurityContext instance
* @param AuthenticationManagerInterface $authenticationManager An AuthenticationManagerInterface instance
* @param string $providerKey
* @param SimplePreAuthenticatorInterface $simpleAuthenticator A SimplePreAuthenticatorInterface instance
* @param LoggerInterface $logger A LoggerInterface instance
* @param EventDispatcherInterface $dispatcher An EventDispatcherInterface instance
*/
public function __construct(SecurityContextInterface $securityContext, AuthenticationManagerInterface $authenticationManager, $providerKey, SimplePreAuthenticatorInterface $simpleAuthenticator, LoggerInterface $logger = null)
public function __construct(SecurityContextInterface $securityContext, AuthenticationManagerInterface $authenticationManager, $providerKey, SimplePreAuthenticatorInterface $simpleAuthenticator, LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null)
{
if (empty($providerKey)) {
throw new \InvalidArgumentException('$providerKey must not be empty.');
@ -55,6 +60,7 @@ class SimplePreAuthenticationListener implements ListenerInterface
$this->providerKey = $providerKey;
$this->simpleAuthenticator = $simpleAuthenticator;
$this->logger = $logger;
$this->dispatcher = $dispatcher;
}
/**
@ -84,6 +90,11 @@ class SimplePreAuthenticationListener implements ListenerInterface
$token = $this->authenticationManager->authenticate($token);
$this->securityContext->setToken($token);
if (null !== $this->dispatcher) {
$loginEvent = new InteractiveLoginEvent($request, $token);
$this->dispatcher->dispatch(SecurityEvents::INTERACTIVE_LOGIN, $loginEvent);
}
} catch (AuthenticationException $e) {
$this->securityContext->setToken(null);

View File

@ -47,7 +47,7 @@ class SessionAuthenticationStrategy implements SessionAuthenticationStrategyInte
return;
case self::MIGRATE:
$request->getSession()->migrate();
$request->getSession()->migrate(true);
return;

View File

@ -0,0 +1,136 @@
<?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\Http\Tests\Firewall;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Symfony\Component\Security\Http\Firewall\SimplePreAuthenticationListener;
use Symfony\Component\Security\Http\SecurityEvents;
class SimplePreAuthenticationListenerTest extends \PHPUnit_Framework_TestCase
{
private $authenticationManager;
private $dispatcher;
private $event;
private $logger;
private $request;
private $securityContext;
private $token;
public function testHandle()
{
$this->securityContext
->expects($this->once())
->method('setToken')
->with($this->equalTo($this->token))
;
$this->authenticationManager
->expects($this->once())
->method('authenticate')
->with($this->equalTo($this->token))
->will($this->returnValue($this->token))
;
$simpleAuthenticator = $this->getMock('Symfony\Component\Security\Core\Authentication\SimplePreAuthenticatorInterface');
$simpleAuthenticator
->expects($this->once())
->method('createToken')
->with($this->equalTo($this->request), $this->equalTo('secured_area'))
->will($this->returnValue($this->token))
;
$loginEvent = new InteractiveLoginEvent($this->request, $this->token);
$this->dispatcher
->expects($this->once())
->method('dispatch')
->with($this->equalTo(SecurityEvents::INTERACTIVE_LOGIN), $this->equalTo($loginEvent))
;
$listener = new SimplePreAuthenticationListener($this->securityContext, $this->authenticationManager, 'secured_area', $simpleAuthenticator, $this->logger, $this->dispatcher);
$listener->handle($this->event);
}
public function testHandlecatchAuthenticationException()
{
$exception = new AuthenticationException('Authentication failed.');
$this->authenticationManager
->expects($this->once())
->method('authenticate')
->with($this->equalTo($this->token))
->will($this->throwException($exception))
;
$this->securityContext->expects($this->once())
->method('setToken')
->with($this->equalTo(null))
;
$simpleAuthenticator = $this->getMock('Symfony\Component\Security\Core\Authentication\SimplePreAuthenticatorInterface');
$simpleAuthenticator
->expects($this->once())
->method('createToken')
->with($this->equalTo($this->request), $this->equalTo('secured_area'))
->will($this->returnValue($this->token))
;
$listener = new SimplePreAuthenticationListener($this->securityContext, $this->authenticationManager, 'secured_area', $simpleAuthenticator, $this->logger, $this->dispatcher);
$listener->handle($this->event);
}
public function setUp()
{
$this->authenticationManager = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\AuthenticationProviderManager')
->disableOriginalConstructor()
->getMock()
;
$this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
$this->request = new Request(array(), array(), array(), array(), array(), array());
$this->event = $this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array(), array(), '', false);
$this->event
->expects($this->any())
->method('getRequest')
->will($this->returnValue($this->request))
;
$this->logger = $this->getMockBuilder('Symfony\Bridge\Monolog\Logger')
->disableOriginalConstructor()
->getMock()
;
$this->securityContext = $this->getMockBuilder('Symfony\Component\Security\Core\SecurityContext')
->disableOriginalConstructor()
->getMock()
;
$this->token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
}
public function tearDown()
{
$this->authenticationManager = null;
$this->dispatcher = null;
$this->event = null;
$this->logger = null;
$this->request = null;
$this->securityContext = null;
$this->token = null;
}
}

View File

@ -40,7 +40,7 @@ class SessionAuthenticationStrategyTest extends \PHPUnit_Framework_TestCase
public function testSessionIsMigrated()
{
$session = $this->getMock('Symfony\Component\HttpFoundation\Session\SessionInterface');
$session->expects($this->once())->method('migrate');
$session->expects($this->once())->method('migrate')->with($this->equalTo(true));
$strategy = new SessionAuthenticationStrategy(SessionAuthenticationStrategy::MIGRATE);
$strategy->onAuthentication($this->getRequest($session), $this->getToken());

View File

@ -11,7 +11,6 @@
<!-- php -r 'echo -1 & ~E_USER_DEPRECATED;' -->
<ini name="error_reporting" value="-16385"/>
</php>
<testsuites>
<testsuite name="Symfony Templating Component Test Suite">
<directory>./Tests/</directory>

View File

@ -11,7 +11,6 @@
<!-- php -r 'echo -1 & ~E_USER_DEPRECATED;' -->
<ini name="error_reporting" value="-16385"/>
</php>
<testsuites>
<testsuite name="Symfony Translation Component Test Suite">
<directory>./Tests/</directory>

View File

@ -11,7 +11,6 @@
<!-- php -r 'echo -1 & ~E_USER_DEPRECATED;' -->
<ini name="error_reporting" value="-16385"/>
</php>
<testsuites>
<testsuite name="Symfony Validator Component Test Suite">
<directory>./Tests/</directory>