Merge branch '2.8' into 3.0

* 2.8:
  fixed test
  [Request] Ignore invalid IP addresses sent by proxies
  [EventDispatcher] TraceableEventDispatcher resets listener priorities
  Throw for missing container extensions
  [TwigBridge] add missing unit tests (AppVariable)
  Able to load big xml files with DomCrawler
  fixed typo
  [Form] Fix constraints could be null if not set
  [Finder] Check PHP version before applying a workaround for a PHP bug
  fixed CS
  add defaultNull to version
  sort bundles in config:dump-reference command
  Fixer findings.
  Profiler CSS position conflicts with JS detection
  [Translation][Writer] avoid calling setBackup if the dumper is not an instance of FileDumper.
  [FrameworkBundle] Compute the kernel root hash only one time
This commit is contained in:
Fabien Potencier 2016-01-25 10:56:57 +01:00
commit 107765142e
26 changed files with 320 additions and 36 deletions

View File

@ -0,0 +1,150 @@
<?php
namespace Symfony\Bridge\Twig\Tests;
use Symfony\Bridge\Twig\AppVariable;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Session\Session;
class AppVariableTest extends \PHPUnit_Framework_TestCase
{
/**
* @var AppVariable
*/
protected $appVariable;
public function setUp()
{
$this->appVariable = new AppVariable();
}
/**
* @dataProvider debugDataProvider
*/
public function testDebug($debugFlag)
{
$this->appVariable->setDebug($debugFlag);
$this->assertEquals($debugFlag, $this->appVariable->getDebug());
}
public function debugDataProvider()
{
return array(
'debug on' => array(true),
'debug off' => array(false),
);
}
public function testEnvironment()
{
$this->appVariable->setEnvironment('dev');
$this->assertEquals('dev', $this->appVariable->getEnvironment());
}
public function testGetSession()
{
$request = $this->getMock('Symfony\Component\HttpFoundation\Request');
$request->method('getSession')->willReturn($session = new Session());
$this->setRequestStack($request);
$this->assertEquals($session, $this->appVariable->getSession());
}
public function testGetSessionWithNoRequest()
{
$this->setRequestStack(null);
$this->assertNull($this->appVariable->getSession());
}
public function testGetRequest()
{
$this->setRequestStack($request = new Request());
$this->assertEquals($request, $this->appVariable->getRequest());
}
public function testGetUser()
{
$this->setTokenStorage($user = $this->getMock('Symfony\Component\Security\Core\User\UserInterface'));
$this->assertEquals($user, $this->appVariable->getUser());
}
public function testGetUserWithUsernameAsTokenUser()
{
$this->setTokenStorage($user = 'username');
$this->assertNull($this->appVariable->getUser());
}
public function testGetUserWithNoToken()
{
$tokenStorage = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface');
$this->appVariable->setTokenStorage($tokenStorage);
$this->assertNull($this->appVariable->getUser());
}
/**
* @expectedException \RuntimeException
*/
public function testEnvironmentNotSet()
{
$this->appVariable->getEnvironment();
}
/**
* @expectedException \RuntimeException
*/
public function testDebugNotSet()
{
$this->appVariable->getDebug();
}
/**
* @expectedException \RuntimeException
*/
public function testGetUserWithTokenStorageNotSet()
{
$this->appVariable->getUser();
}
/**
* @expectedException \RuntimeException
*/
public function testGetRequestWithRequestStackNotSet()
{
$this->appVariable->getRequest();
}
/**
* @expectedException \RuntimeException
*/
public function testGetSessionWithRequestStackNotSet()
{
$this->appVariable->getSession();
}
protected function setRequestStack($request)
{
$requestStackMock = $this->getMock('Symfony\Component\HttpFoundation\RequestStack');
$requestStackMock->method('getCurrentRequest')->willReturn($request);
$this->appVariable->setRequestStack($requestStackMock);
}
protected function setTokenStorage($user)
{
$tokenStorage = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface');
$this->appVariable->setTokenStorage($tokenStorage);
$token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
$tokenStorage->method('getToken')->willReturn($token);
$token->method('getUser')->willReturn($user);
}
}

View File

@ -36,6 +36,7 @@ class TransNodeTest extends \PHPUnit_Framework_TestCase
trim($compiler->compile($node)->getSource())
);
}
protected function getVariableGetterWithoutStrictCheck($name)
{
return sprintf('(isset($context["%s"]) ? $context["%s"] : null)', $name, $name);

View File

@ -54,6 +54,10 @@ abstract class AbstractConfigCommand extends ContainerDebugCommand
$bundles = $this->initializeBundles();
foreach ($bundles as $bundle) {
if ($name === $bundle->getName()) {
if (!$bundle->getContainerExtension()) {
throw new \LogicException(sprintf('Bundle "%s" does not have a container extension.', $name));
}
return $bundle->getContainerExtension();
}

View File

@ -392,6 +392,7 @@ class Configuration implements ConfigurationInterface
->fixXmlConfig('base_url')
->children()
->scalarNode('version')
->defaultNull()
->beforeNormalization()
->ifTrue(function ($v) { return '' === $v; })
->then(function ($v) { return; })

View File

@ -38,6 +38,11 @@ class FrameworkExtension extends Extension
private $translationConfigEnabled = false;
private $sessionConfigEnabled = false;
/**
* @var string|null
*/
private $kernelRootHash;
/**
* Responds to the app.config configuration parameter.
*
@ -767,7 +772,7 @@ class FrameworkExtension extends Extension
if (isset($config['cache'])) {
$container->setParameter(
'validator.mapping.cache.prefix',
'validator_'.hash('sha256', $container->getParameter('kernel.root_dir'))
'validator_'.$this->getKernelRootHash($container)
);
$validatorBuilder->addMethodCall('setMetadataCache', array(new Reference($config['cache'])));
@ -943,7 +948,7 @@ class FrameworkExtension extends Extension
if (isset($config['cache']) && $config['cache']) {
$container->setParameter(
'serializer.mapping.cache.prefix',
'serializer_'.hash('sha256', $container->getParameter('kernel.root_dir'))
'serializer_'.$this->getKernelRootHash($container)
);
$container->getDefinition('serializer.mapping.class_metadata_factory')->replaceArgument(
@ -978,6 +983,22 @@ class FrameworkExtension extends Extension
}
}
/**
* Gets a hash of the kernel root directory.
*
* @param ContainerBuilder $container
*
* @return string
*/
private function getKernelRootHash(ContainerBuilder $container)
{
if (!$this->kernelRootHash) {
$this->kernelRootHash = hash('sha256', $container->getParameter('kernel.root_dir'));
}
return $this->kernelRootHash;
}
/**
* Returns the base path for the XSD files.
*

View File

@ -424,9 +424,6 @@
.sf-toolbar-block .sf-toolbar-icon svg {
top: 6px;
}
.sf-toolbar-block-config:hover .sf-toolbar-info {
right: 0;
}
.sf-toolbar-block-time .sf-toolbar-icon svg,
.sf-toolbar-block-memory .sf-toolbar-icon svg {
display: none;

View File

@ -83,6 +83,7 @@ abstract class AbstractDescriptorTest extends \PHPUnit_Framework_TestCase
}
abstract protected function getDescriptor();
abstract protected function getFormat();
private function getDescriptionTestData(array $objects)

View File

@ -28,5 +28,6 @@ abstract class AbstractNodeTest extends \PHPUnit_Framework_TestCase
}
abstract public function getToStringConversionTestData();
abstract public function getSpecificityValueTestData();
}

View File

@ -43,7 +43,9 @@ abstract class AbstractHandlerTest extends \PHPUnit_Framework_TestCase
}
abstract public function getHandleValueTestData();
abstract public function getDontHandleValueTestData();
abstract protected function generateHandler();
protected function assertStreamEmpty(TokenStream $stream)

View File

@ -235,7 +235,7 @@ class Crawler implements \Countable, \IteratorAggregate
$dom->validateOnParse = true;
if ('' !== trim($content)) {
@$dom->loadXML($content, LIBXML_NONET);
@$dom->loadXML($content, LIBXML_NONET | (defined('LIBXML_PARSEHUGE') ? LIBXML_PARSEHUGE : 0));
}
libxml_use_internal_errors($internalErrors);

View File

@ -235,12 +235,12 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface
private function preProcess($eventName)
{
foreach ($this->dispatcher->getListeners($eventName) as $listener) {
$this->dispatcher->removeListener($eventName, $listener);
$info = $this->getListenerInfo($listener, $eventName);
$name = isset($info['class']) ? $info['class'] : $info['type'];
$wrappedListener = new WrappedListener($listener, $name, $this->stopwatch, $this);
$this->wrappedListeners[$eventName][] = $wrappedListener;
$this->dispatcher->addListener($eventName, $wrappedListener);
$this->dispatcher->removeListener($eventName, $listener);
$this->dispatcher->addListener($eventName, $wrappedListener, $info['priority']);
}
}
@ -253,8 +253,9 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface
continue;
}
// Unwrap listener
$priority = $this->getListenerPriority($eventName, $listener);
$this->dispatcher->removeListener($eventName, $listener);
$this->dispatcher->addListener($eventName, $listener->getWrappedListener());
$this->dispatcher->addListener($eventName, $listener->getWrappedListener(), $priority);
$info = $this->getListenerInfo($listener->getWrappedListener(), $eventName);
if ($listener->wasCalled()) {

View File

@ -56,6 +56,23 @@ class TraceableEventDispatcherTest extends \PHPUnit_Framework_TestCase
$this->assertTrue($tdispatcher->hasListeners('foo'));
}
public function testGetListenerPriority()
{
$dispatcher = new EventDispatcher();
$tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch());
$tdispatcher->addListener('foo', function () {}, 123);
$listeners = $dispatcher->getListeners('foo');
$this->assertSame(123, $tdispatcher->getListenerPriority('foo', $listeners[0]));
// Verify that priority is preserved when listener is removed and re-added
// in preProcess() and postProcess().
$tdispatcher->dispatch('foo', new Event());
$listeners = $dispatcher->getListeners('foo');
$this->assertSame(123, $tdispatcher->getListenerPriority('foo', $listeners[0]));
}
public function testAddRemoveSubscriber()
{
$dispatcher = new EventDispatcher();
@ -138,12 +155,12 @@ class TraceableEventDispatcherTest extends \PHPUnit_Framework_TestCase
$dispatcher = new EventDispatcher();
$tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch());
$tdispatcher->addListener('foo', $listener1 = function () use (&$called) { $called[] = 'foo1'; });
$tdispatcher->addListener('foo', $listener2 = function () use (&$called) { $called[] = 'foo2'; });
$tdispatcher->addListener('foo', function () use (&$called) { $called[] = 'foo1'; }, 10);
$tdispatcher->addListener('foo', function () use (&$called) { $called[] = 'foo2'; }, 20);
$tdispatcher->dispatch('foo');
$this->assertEquals(array('foo1', 'foo2'), $called);
$this->assertSame(array('foo2', 'foo1'), $called);
}
public function testDispatchNested()

View File

@ -12,9 +12,10 @@
namespace Symfony\Component\Finder\Iterator;
/**
* This iterator just overrides the rewind method in order to correct a PHP bug.
* This iterator just overrides the rewind method in order to correct a PHP bug,
* which existed before version 5.5.23/5.6.7.
*
* @see https://bugs.php.net/bug.php?id=49104
* @see https://bugs.php.net/68557
*
* @author Alex Bogomazov
*/
@ -28,18 +29,19 @@ abstract class FilterIterator extends \FilterIterator
*/
public function rewind()
{
if (PHP_VERSION_ID > 50607 || (PHP_VERSION_ID > 50523 && PHP_VERSION_ID < 50600)) {
parent::rewind();
return;
}
$iterator = $this;
while ($iterator instanceof \OuterIterator) {
$innerIterator = $iterator->getInnerIterator();
if ($innerIterator instanceof RecursiveDirectoryIterator) {
if ($innerIterator->isRewindable()) {
$innerIterator->next();
$innerIterator->rewind();
}
} elseif ($iterator->getInnerIterator() instanceof \FilesystemIterator) {
$iterator->getInnerIterator()->next();
$iterator->getInnerIterator()->rewind();
if ($innerIterator instanceof \FilesystemIterator) {
$innerIterator->next();
$innerIterator->rewind();
}
$iterator = $iterator->getInnerIterator();
}

View File

@ -118,8 +118,10 @@ class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator
return;
}
// @see https://bugs.php.net/bug.php?id=49104
parent::next();
// @see https://bugs.php.net/68557
if (PHP_VERSION_ID < 50523 || PHP_VERSION_ID >= 50600 && PHP_VERSION_ID < 50607) {
parent::next();
}
parent::rewind();
}

View File

@ -462,7 +462,7 @@ class FinderTest extends Iterator\RealIteratorTestCase
* Searching in multiple locations involves AppendIterator which does an unnecessary rewind which leaves FilterIterator
* with inner FilesystemIterator in an invalid state.
*
* @see https://bugs.php.net/bug.php?id=49104
* @see https://bugs.php.net/68557
*/
public function testMultipleLocations()
{
@ -472,8 +472,12 @@ class FinderTest extends Iterator\RealIteratorTestCase
);
// it is expected that there are test.py test.php in the tmpDir
$finder = $this->buildFinder();
$finder->in($locations)->depth('< 1')->name('test.php');
$finder = new Finder();
$finder->in($locations)
// the default flag IGNORE_DOT_FILES fixes the problem indirectly
// so we set it to false for better isolation
->ignoreDotFiles(false)
->depth('< 1')->name('test.php');
$this->assertCount(1, $finder);
}
@ -483,7 +487,7 @@ class FinderTest extends Iterator\RealIteratorTestCase
* AppendIterator which does an unnecessary rewind which leaves
* FilterIterator with inner FilesystemIterator in an invalid state.
*
* @see https://bugs.php.net/bug.php?id=49104
* @see https://bugs.php.net/68557
*/
public function testMultipleLocationsWithSubDirectories()
{

View File

@ -43,8 +43,9 @@ class FilterIteratorTest extends RealIteratorTestCase
++$c;
}
// This would fail with \FilterIterator but works with Symfony\Component\Finder\Iterator\FilterIterator
// see https://bugs.php.net/bug.php?id=49104
// This would fail in php older than 5.5.23/5.6.7 with \FilterIterator
// but works with Symfony\Component\Finder\Iterator\FilterIterator
// see https://bugs.php.net/68557
$this->assertEquals(1, $c);
}
}

View File

@ -62,7 +62,7 @@ class FormValidator extends ConstraintValidator
// Validate the data against the constraints defined
// in the form
$constraints = $config->getOption('constraints');
$constraints = $config->getOption('constraints', array());
foreach ($constraints as $constraint) {
// For the "Valid" constraint, validate the data in all groups
if ($constraint instanceof Valid) {

View File

@ -28,6 +28,7 @@ class HttpFoundationRequestHandlerTest extends AbstractRequestHandlerTest
{
$this->requestHandler->handleRequest($this->getMockForm('name', 'GET'));
}
/**
* @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException
*/

View File

@ -170,6 +170,17 @@ class FormValidatorTest extends AbstractConstraintValidatorTest
$this->assertNoViolation();
}
public function testMissingConstraintIndex()
{
$object = new \stdClass();
$form = new FormBuilder('name', '\stdClass', $this->dispatcher, $this->factory);
$form = $form->setData($object)->getForm();
$this->validator->validate($form, new Form());
$this->assertNoViolation();
}
public function testValidateConstraintsEvenIfNoCascadeValidation()
{
$object = $this->getMock('\stdClass');

View File

@ -807,7 +807,7 @@ class Request
}
$clientIps[] = $ip; // Complete the IP chain with the IP the request actually came from
$ip = $clientIps[0]; // Fallback to this when the client IP falls into the range of trusted proxies
$firstTrustedIp = null;
foreach ($clientIps as $key => $clientIp) {
// Remove port (unfortunately, it does happen)
@ -815,13 +815,22 @@ class Request
$clientIps[$key] = $clientIp = $match[1];
}
if (!filter_var($clientIp, FILTER_VALIDATE_IP)) {
unset($clientIps[$key]);
}
if (IpUtils::checkIp($clientIp, self::$trustedProxies)) {
unset($clientIps[$key]);
// Fallback to this when the client IP falls into the range of trusted proxies
if (null === $firstTrustedIp) {
$firstTrustedIp = $clientIp;
}
}
}
// Now the IP chain contains only untrusted proxies and the client IP
return $clientIps ? array_reverse($clientIps) : array($ip);
return $clientIps ? array_reverse($clientIps) : array($firstTrustedIp);
}
/**

View File

@ -1023,11 +1023,12 @@ class Response
return $notModified;
}
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
/**
* Is response invalid?
*
* @return bool
*
* @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
*/
public function isInvalid()
{

View File

@ -853,7 +853,7 @@ class RequestTest extends \PHPUnit_Framework_TestCase
// $expected $remoteAddr $httpForwarded $trustedProxies
return array(
array(array('127.0.0.1'), '127.0.0.1', 'for="_gazonk"', null),
array(array('_gazonk'), '127.0.0.1', 'for="_gazonk"', array('127.0.0.1')),
array(array('127.0.0.1'), '127.0.0.1', 'for="_gazonk"', array('127.0.0.1')),
array(array('88.88.88.88'), '127.0.0.1', 'for="88.88.88.88:80"', array('127.0.0.1')),
array(array('192.0.2.60'), '::1', 'for=192.0.2.60;proto=http;by=203.0.113.43', array('::1')),
array(array('2620:0:1cfe:face:b00c::3', '192.0.2.43'), '::1', 'for=192.0.2.43, for=2620:0:1cfe:face:b00c::3', array('::1')),
@ -909,6 +909,9 @@ class RequestTest extends \PHPUnit_Framework_TestCase
// client IP with port
array(array('88.88.88.88'), '127.0.0.1', '88.88.88.88:12345, 127.0.0.1', array('127.0.0.1')),
// invalid forwarded IP is ignored
array(array('88.88.88.88'), '127.0.0.1', 'unknown,88.88.88.88', array('127.0.0.1')),
);
}

View File

@ -139,15 +139,19 @@ class SomeUser implements UserInterface
public function getRoles()
{
}
public function getPassword()
{
}
public function getSalt()
{
}
public function getUsername()
{
}
public function eraseCredentials()
{
}

View File

@ -0,0 +1,47 @@
<?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\Translation\Tests\Writer;
use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Translation\Writer\TranslationWriter;
class TranslationWriterTest extends \PHPUnit_Framework_TestCase
{
public function testWriteTranslations()
{
$dumper = $this->getMock('Symfony\Component\Translation\Dumper\DumperInterface');
$dumper
->expects($this->once())
->method('dump');
$writer = new TranslationWriter();
$writer->addDumper('test', $dumper);
$writer->writeTranslations(new MessageCatalogue(array()), 'test');
}
public function testDisableBackup()
{
$dumper = $this->getMock('Symfony\Component\Translation\Dumper\DumperInterface');
$dumper
->expects($this->never())
->method('setBackup');
$phpDumper = $this->getMock('Symfony\Component\Translation\Dumper\PhpFileDumper');
$phpDumper
->expects($this->once())
->method('setBackup');
$writer = new TranslationWriter();
$writer->addDumper('test', $dumper);
$writer->addDumper('php', $phpDumper);
$writer->disableBackup();
}
}

View File

@ -45,7 +45,9 @@ class TranslationWriter
public function disableBackup()
{
foreach ($this->dumpers as $dumper) {
$dumper->setBackup(false);
if (method_exists($dumper, 'setBackup')) {
$dumper->setBackup(false);
}
}
}

View File

@ -94,6 +94,7 @@ class AnnotationLoaderTest extends \PHPUnit_Framework_TestCase
$this->assertEquals($expected_parent, $parent_metadata);
}
/**
* Test MetaData merge with parent annotation.
*/