diff --git a/src/Symfony/Bridge/Doctrine/Form/ChoiceList/EntityChoiceList.php b/src/Symfony/Bridge/Doctrine/Form/ChoiceList/EntityChoiceList.php index c2fa9daebf..9cf636df95 100644 --- a/src/Symfony/Bridge/Doctrine/Form/ChoiceList/EntityChoiceList.php +++ b/src/Symfony/Bridge/Doctrine/Form/ChoiceList/EntityChoiceList.php @@ -329,7 +329,7 @@ class EntityChoiceList extends ObjectChoiceList protected function createIndex($entity) { if ($this->idAsIndex) { - return current($this->getIdentifierValues($entity)); + return $this->fixIndex(current($this->getIdentifierValues($entity))); } return parent::createIndex($entity); @@ -355,6 +355,23 @@ class EntityChoiceList extends ObjectChoiceList return parent::createValue($entity); } + /** + * {@inheritdoc} + */ + protected function fixIndex($index) + { + $index = parent::fixIndex($index); + + // If the ID is a single-field integer identifier, it is used as + // index. Replace any leading minus by underscore to make it a valid + // form name. + if ($this->idAsIndex && $index < 0) { + $index = strtr($index, '-', '_'); + } + + return $index; + } + /** * Loads the list with entities. */ diff --git a/src/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/EntityChoiceListTest.php b/src/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/EntityChoiceListTest.php index f928f1f385..a3ce750343 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/EntityChoiceListTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/EntityChoiceListTest.php @@ -312,4 +312,47 @@ class EntityChoiceListTest extends DoctrineOrmTestCase $this->assertSame(array(0 => $entity1, 1 => $entity2), $choiceList->getChoices()); } + + public function testMinusReplacedByUnderscoreInNegativeIntIds() + { + $entity1 = new SingleIdentEntity(-1, 'Foo'); + $entity2 = new SingleIdentEntity(1, 'Bar'); + + // Persist for managed state + $this->em->persist($entity1); + $this->em->persist($entity2); + $this->em->flush(); + + $choiceList = new EntityChoiceList( + $this->em, + self::SINGLE_IDENT_CLASS, + 'name' + ); + + $this->assertSame(array('_1' => $entity1, 1 => $entity2), $choiceList->getChoices()); + $this->assertSame(array('_1', 1), $choiceList->getIndicesForChoices(array($entity1, $entity2))); + $this->assertSame(array('_1', 1), $choiceList->getIndicesForValues(array('-1', '1'))); + } + + public function testMinusReplacedByUnderscoreIfNotLoaded() + { + $entity1 = new SingleIdentEntity(-1, 'Foo'); + $entity2 = new SingleIdentEntity(1, 'Bar'); + + // Persist for managed state + $this->em->persist($entity1); + $this->em->persist($entity2); + $this->em->flush(); + + $choiceList = new EntityChoiceList( + $this->em, + self::SINGLE_IDENT_CLASS, + 'name' + ); + + // no getChoices()! + + $this->assertSame(array('_1', 1), $choiceList->getIndicesForChoices(array($entity1, $entity2))); + $this->assertSame(array('_1', 1), $choiceList->getIndicesForValues(array('-1', '1'))); + } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/esi.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/esi.xml index 9e1d57f921..3038f40e97 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/esi.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/esi.xml @@ -13,8 +13,8 @@ - - + + diff --git a/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/trace.html.twig b/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/trace.html.twig index 37b2ecc2b4..d4a11e1e50 100644 --- a/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/trace.html.twig +++ b/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/trace.html.twig @@ -12,8 +12,8 @@ in {{ trace.file|format_file(trace.line) }}  {% spaceless %} - - - + + - + + {% endspaceless %}
diff --git a/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/traces.html.twig b/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/traces.html.twig index e9359959d2..e0f1a0db13 100644 --- a/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/traces.html.twig +++ b/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/traces.html.twig @@ -5,8 +5,8 @@ {{ exception.class|abbr_class }}: {{ exception.message|nl2br|format_file_from_text }}  {% spaceless %} - - - + + - + + {% endspaceless %} diff --git a/src/Symfony/Component/Console/Formatter/OutputFormatter.php b/src/Symfony/Component/Console/Formatter/OutputFormatter.php index a7ac648af1..642590dcbc 100644 --- a/src/Symfony/Component/Console/Formatter/OutputFormatter.php +++ b/src/Symfony/Component/Console/Formatter/OutputFormatter.php @@ -23,7 +23,7 @@ class OutputFormatter implements OutputFormatterInterface /** * The pattern to phrase the format. */ - const FORMAT_PATTERN = '#(\\\\?)<(/?)([a-z][a-z0-9_=;-]+)?>((?:(?!\\\\?<).)*)#is'; + const FORMAT_PATTERN = '#(\\\\?)<(/?)([a-z][a-z0-9_=;-]+)?>((?: [^<\\\\]+ | (?!<(?:/?[a-z]|/>)). | .(?<=\\\\<) )*)#isx'; private $decorated; private $styles = array(); diff --git a/src/Symfony/Component/Console/Tests/Formatter/OutputFormatterTest.php b/src/Symfony/Component/Console/Tests/Formatter/OutputFormatterTest.php index 33187a7d26..497630e87c 100644 --- a/src/Symfony/Component/Console/Tests/Formatter/OutputFormatterTest.php +++ b/src/Symfony/Component/Console/Tests/Formatter/OutputFormatterTest.php @@ -73,6 +73,26 @@ class FormatterStyleTest extends \PHPUnit_Framework_TestCase ); } + public function testStyleMatchingNotGreedy() + { + $formatter = new OutputFormatter(true); + + $this->assertEquals( + "(\033[32m>=2.0,<2.3\033[0m)", + $formatter->format('(>=2.0,<2.3)') + ); + } + + public function testStyleEscaping() + { + $formatter = new OutputFormatter(true); + + $this->assertEquals( + "(\033[32mz>=2.0,format('('.$formatter->escape('z>=2.0,)') + ); + } + public function testDeepNestedStyles() { $formatter = new OutputFormatter(true); diff --git a/src/Symfony/Component/CssSelector/Tests/TokenizerTest.php b/src/Symfony/Component/CssSelector/Tests/TokenizerTest.php index b15de9dca1..e0e00d8ed3 100644 --- a/src/Symfony/Component/CssSelector/Tests/TokenizerTest.php +++ b/src/Symfony/Component/CssSelector/Tests/TokenizerTest.php @@ -34,6 +34,7 @@ class TokenizerTest extends \PHPUnit_Framework_TestCase { $this->assertEquals('foo[class=foo bar ]', $this->tokensToString($this->tokenizer->tokenize('foo[class="foo bar"]')), '->tokenize() lexes an input string and returns an array of tokens'); $this->assertEquals("foo[class=foo Abar ]", $this->tokensToString($this->tokenizer->tokenize('foo[class="foo \\65 bar"]')), '->tokenize() lexes an input string and returns an array of tokens'); + $this->assertEquals("img[alt= ]", $this->tokensToString($this->tokenizer->tokenize('img[alt=""]')), '->tokenize() lexes an input string and returns an array of tokens'); } /** diff --git a/src/Symfony/Component/CssSelector/Tokenizer.php b/src/Symfony/Component/CssSelector/Tokenizer.php index 67d5b67470..34e8ac580a 100644 --- a/src/Symfony/Component/CssSelector/Tokenizer.php +++ b/src/Symfony/Component/CssSelector/Tokenizer.php @@ -129,7 +129,7 @@ class Tokenizer } $result = substr($s, $start, $next - $start); - if ('\\' === $result[strlen($result) - 1]) { + if (strlen($result) > 0 && '\\' === $result[strlen($result) - 1]) { // next quote character is escaped $pos = $next + 1; continue; diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveInvalidReferencesPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveInvalidReferencesPass.php index c69d078e8b..6fad9a2841 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ResolveInvalidReferencesPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveInvalidReferencesPass.php @@ -89,7 +89,7 @@ class ResolveInvalidReferencesPass implements CompilerPassInterface // resolve invalid behavior if ($exists && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $invalidBehavior) { - $arguments[$k] = new Reference($id); + $arguments[$k] = new Reference($id, ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, $argument->isStrict()); } elseif (!$exists && ContainerInterface::NULL_ON_INVALID_REFERENCE === $invalidBehavior) { $arguments[$k] = null; } elseif (!$exists && ContainerInterface::IGNORE_ON_INVALID_REFERENCE === $invalidBehavior) { diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index a0740a964c..22aabf2745 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -229,24 +229,7 @@ class PhpDumper extends Dumper throw new ServiceCircularReferenceException($id, array($id)); } - $arguments = array(); - foreach ($sDefinition->getArguments() as $argument) { - $arguments[] = $this->dumpValue($argument); - } - - if (null !== $sDefinition->getFactoryMethod()) { - if (null !== $sDefinition->getFactoryClass()) { - $code .= sprintf(" \$%s = call_user_func(array(%s, '%s')%s);\n", $name, $this->dumpValue($sDefinition->getFactoryClass()), $sDefinition->getFactoryMethod(), count($arguments) > 0 ? ', '.implode(', ', $arguments) : ''); - } elseif (null !== $sDefinition->getFactoryService()) { - $code .= sprintf(" \$%s = %s->%s(%s);\n", $name, $this->getServiceCall($sDefinition->getFactoryService()), $sDefinition->getFactoryMethod(), implode(', ', $arguments)); - } else { - throw new RuntimeException('Factory service or factory class must be defined in service definition for '.$id); - } - } elseif (false !== strpos($class, '$')) { - $code .= sprintf(" \$class = %s;\n \$%s = new \$class(%s);\n", $class, $name, implode(', ', $arguments)); - } else { - $code .= sprintf(" \$%s = new \\%s(%s);\n", $name, substr(str_replace('\\\\', '\\', $class), 1, -1), implode(', ', $arguments)); - } + $code .= $this->addNewInstance($id, $sDefinition, '$'.$name, ' = '); if (!$this->hasReference($id, $sDefinition->getMethodCalls(), true) && !$this->hasReference($id, $sDefinition->getProperties(), true)) { $code .= $this->addServiceMethodCalls(null, $sDefinition, $name); @@ -297,11 +280,6 @@ class PhpDumper extends Dumper throw new InvalidArgumentException(sprintf('"%s" is not a valid class name for the "%s" service.', $class, $id)); } - $arguments = array(); - foreach ($definition->getArguments() as $value) { - $arguments[] = $this->dumpValue($value); - } - $simple = $this->isSimpleInstance($id, $definition); $instantiation = ''; @@ -320,19 +298,7 @@ class PhpDumper extends Dumper $instantiation .= ' = '; } - if (null !== $definition->getFactoryMethod()) { - if (null !== $definition->getFactoryClass()) { - $code = sprintf(" $return{$instantiation}call_user_func(array(%s, '%s')%s);\n", $this->dumpValue($definition->getFactoryClass()), $definition->getFactoryMethod(), $arguments ? ', '.implode(', ', $arguments) : ''); - } elseif (null !== $definition->getFactoryService()) { - $code = sprintf(" $return{$instantiation}%s->%s(%s);\n", $this->getServiceCall($definition->getFactoryService()), $definition->getFactoryMethod(), implode(', ', $arguments)); - } else { - throw new RuntimeException('Factory method requires a factory service or factory class in service definition for '.$id); - } - } elseif (false !== strpos($class, '$')) { - $code = sprintf(" \$class = %s;\n\n $return{$instantiation}new \$class(%s);\n", $class, implode(', ', $arguments)); - } else { - $code = sprintf(" $return{$instantiation}new \\%s(%s);\n", substr(str_replace('\\\\', '\\', $class), 1, -1), implode(', ', $arguments)); - } + $code = $this->addNewInstance($id, $definition, $return, $instantiation); if (!$simple) { $code .= "\n"; @@ -611,6 +577,34 @@ EOF; return $publicServices.$aliasServices.$privateServices; } + private function addNewInstance($id, Definition $definition, $return, $instantiation) + { + $class = $this->dumpValue($definition->getClass()); + + $arguments = array(); + foreach ($definition->getArguments() as $value) { + $arguments[] = $this->dumpValue($value); + } + + if (null !== $definition->getFactoryMethod()) { + if (null !== $definition->getFactoryClass()) { + return sprintf(" $return{$instantiation}call_user_func(array(%s, '%s')%s);\n", $this->dumpValue($definition->getFactoryClass()), $definition->getFactoryMethod(), $arguments ? ', '.implode(', ', $arguments) : ''); + } + + if (null !== $definition->getFactoryService()) { + return sprintf(" $return{$instantiation}%s->%s(%s);\n", $this->getServiceCall($definition->getFactoryService()), $definition->getFactoryMethod(), implode(', ', $arguments)); + } + + throw new RuntimeException('Factory method requires a factory service or factory class in service definition for '.$id); + } + + if (false !== strpos($class, '$')) { + return sprintf(" \$class = %s;\n\n $return{$instantiation}new \$class(%s);\n", $class, implode(', ', $arguments)); + } + + return sprintf(" $return{$instantiation}new \\%s(%s);\n", substr(str_replace('\\\\', '\\', $class), 1, -1), implode(', ', $arguments)); + } + /** * Adds the class headers. * diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveInvalidReferencesPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveInvalidReferencesPassTest.php index a18ba73862..72058868d4 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveInvalidReferencesPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveInvalidReferencesPassTest.php @@ -61,6 +61,20 @@ class ResolveInvalidReferencesPassTest extends \PHPUnit_Framework_TestCase $this->assertEquals(array(), $def->getProperties()); } + public function testStrictFlagIsPreserved() + { + $container = new ContainerBuilder(); + $container->register('bar'); + $def = $container + ->register('foo') + ->addArgument(new Reference('bar', ContainerInterface::NULL_ON_INVALID_REFERENCE, false)) + ; + + $this->process($container); + + $this->assertFalse($def->getArgument(0)->isStrict()); + } + protected function process(ContainerBuilder $container) { $pass = new ResolveInvalidReferencesPass(); diff --git a/src/Symfony/Component/Form/FormBuilder.php b/src/Symfony/Component/Form/FormBuilder.php index 0cec9b9426..9d11b5f750 100644 --- a/src/Symfony/Component/Form/FormBuilder.php +++ b/src/Symfony/Component/Form/FormBuilder.php @@ -204,6 +204,21 @@ class FormBuilder extends FormConfigBuilder implements \IteratorAggregate, FormB return count($this->children); } + /** + * {@inheritdoc} + */ + public function getFormConfig() + { + $config = parent::getFormConfig(); + + $config->factory = null; + $config->parent = null; + $config->children = array(); + $config->unresolvedChildren = array(); + + return $config; + } + /** * {@inheritdoc} */ diff --git a/src/Symfony/Component/Form/Resources/translations/validators.da.xlf b/src/Symfony/Component/Form/Resources/translations/validators.da.xlf index 9663cb6f17..c2dd4601f9 100644 --- a/src/Symfony/Component/Form/Resources/translations/validators.da.xlf +++ b/src/Symfony/Component/Form/Resources/translations/validators.da.xlf @@ -11,7 +11,7 @@ Den oploadede fil var for stor. Opload venligst en mindre fil. - The CSRF token is invalid. + The CSRF token is invalid. Please try to resubmit the form. CSRF nøglen er ugyldig. diff --git a/src/Symfony/Component/Form/Tests/FormBuilderTest.php b/src/Symfony/Component/Form/Tests/FormBuilderTest.php index 96e1d63c7c..6836ea140d 100644 --- a/src/Symfony/Component/Form/Tests/FormBuilderTest.php +++ b/src/Symfony/Component/Form/Tests/FormBuilderTest.php @@ -239,6 +239,30 @@ class FormBuilderTest extends \PHPUnit_Framework_TestCase $this->builder->create('bar', 'text'); } + public function testGetFormConfigErasesReferences() + { + $builder = new FormBuilder('name', null, $this->dispatcher, $this->factory); + $builder->setParent(new FormBuilder('parent', null, $this->dispatcher, $this->factory)); + $builder->add(new FormBuilder('child', null, $this->dispatcher, $this->factory)); + + $config = $builder->getFormConfig(); + $reflClass = new \ReflectionClass($config); + $factory = $reflClass->getProperty('factory'); + $parent = $reflClass->getProperty('parent'); + $children = $reflClass->getProperty('children'); + $unresolvedChildren = $reflClass->getProperty('unresolvedChildren'); + + $factory->setAccessible(true); + $parent->setAccessible(true); + $children->setAccessible(true); + $unresolvedChildren->setAccessible(true); + + $this->assertNull($factory->getValue($config)); + $this->assertNull($parent->getValue($config)); + $this->assertEmpty($children->getValue($config)); + $this->assertEmpty($unresolvedChildren->getValue($config)); + } + private function getFormBuilder($name = 'name') { $mock = $this->getMockBuilder('Symfony\Component\Form\FormBuilder') diff --git a/src/Symfony/Component/HttpFoundation/File/MimeType/FileBinaryMimeTypeGuesser.php b/src/Symfony/Component/HttpFoundation/File/MimeType/FileBinaryMimeTypeGuesser.php index 3da63dd483..958e84cbae 100644 --- a/src/Symfony/Component/HttpFoundation/File/MimeType/FileBinaryMimeTypeGuesser.php +++ b/src/Symfony/Component/HttpFoundation/File/MimeType/FileBinaryMimeTypeGuesser.php @@ -45,7 +45,7 @@ class FileBinaryMimeTypeGuesser implements MimeTypeGuesserInterface */ public static function isSupported() { - return !defined('PHP_WINDOWS_VERSION_BUILD'); + return !defined('PHP_WINDOWS_VERSION_BUILD') && function_exists('passthru') && function_exists('escapeshellarg'); } /** diff --git a/src/Symfony/Component/HttpFoundation/Request.php b/src/Symfony/Component/HttpFoundation/Request.php index 3b5d1448a0..d886df1ef7 100644 --- a/src/Symfony/Component/HttpFoundation/Request.php +++ b/src/Symfony/Component/HttpFoundation/Request.php @@ -1404,7 +1404,8 @@ class Request * Returns true if the request is a XMLHttpRequest. * * It works if your JavaScript library set an X-Requested-With HTTP header. - * It is known to work with Prototype, Mootools, jQuery. + * It is known to work with common JavaScript frameworks: + * @link http://en.wikipedia.org/wiki/List_of_Ajax_frameworks#JavaScript * * @return Boolean true if the request is an XMLHttpRequest, false otherwise * diff --git a/src/Symfony/Component/HttpFoundation/Session/Flash/FlashBag.php b/src/Symfony/Component/HttpFoundation/Session/Flash/FlashBag.php index 9796653985..5bb43bc53a 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Flash/FlashBag.php +++ b/src/Symfony/Component/HttpFoundation/Session/Flash/FlashBag.php @@ -177,6 +177,11 @@ class FlashBag implements FlashBagInterface, \IteratorAggregate, \Countable /** * Returns the number of flashes. * + * This method does not work. + * + * @deprecated in 2.2, removed in 2.3 + * @see https://github.com/symfony/symfony/issues/6408 + * * @return int The number of flashes */ public function count() diff --git a/src/Symfony/Component/Security/Tests/Core/Util/ClassUtilsTest.php b/src/Symfony/Component/Security/Tests/Core/Util/ClassUtilsTest.php index edfd779a8e..8359236f65 100644 --- a/src/Symfony/Component/Security/Tests/Core/Util/ClassUtilsTest.php +++ b/src/Symfony/Component/Security/Tests/Core/Util/ClassUtilsTest.php @@ -15,7 +15,7 @@ namespace Symfony\Component\Security\Tests\Core\Util class ClassUtilsTest extends \PHPUnit_Framework_TestCase { - static public function dataGetClass() + public static function dataGetClass() { return array( array('stdClass', 'stdClass'),