8000 From 6c50013b12aed899f17eebf374b3b1cf77e12e71 Mon Sep 17 00:00:00 2001 From: WouterJ Date: Sun, 30 Nov 2014 21:23:32 +0100 Subject: [PATCH 0001/2143] Allowed extensions to inline compiler passes --- .../Compiler/ExtensionCompilerPass.php | 28 +++++++++++ .../Compiler/PassConfig.php | 1 + .../Compiler/ExtensionCompilerPassTest.php | 46 +++++++++++++++++++ 3 files changed, 75 insertions(+) create mode 100644 src/Symfony/Component/DependencyInjection/Compiler/ExtensionCompilerPass.php create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Compiler/ExtensionCompilerPassTest.php diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ExtensionCompilerPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ExtensionCompilerPass.php new file mode 100644 index 0000000000000..a9b418d497bed --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Compiler/ExtensionCompilerPass.php @@ -0,0 +1,28 @@ + + */ +class ExtensionCompilerPass implements CompilerPassInterface +{ + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + foreach ($container->getExtensions() as $extension) { + if (!$extension instanceof CompilerPassInterface) { + continue; + } + + $extension->process($container); + } + } +} diff --git a/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php b/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php index 044529eb6d7c0..d6dee26fda766 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php @@ -45,6 +45,7 @@ public function __construct() $this->mergePass = new MergeExtensionConfigurationPass(); $this->optimizationPasses = array( + new ExtensionCompilerPass(), new ResolveDefinitionTemplatesPass(), new DecoratorServicePass(), new ResolveParameterPlaceHoldersPass(), diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ExtensionCompilerPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ExtensionCompilerPassTest.php new file mode 100644 index 0000000000000..ef690da16329e --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ExtensionCompilerPassTest.php @@ -0,0 +1,46 @@ + + */ +class ExtensionCompilerPassTest extends \PHPUnit_Framework_TestCase +{ + private $container; + private $pass; + + public function setUp() + { + $this->container = $this->getMock('Symfony\Component\DependencyInjection\ContainerBuilder'); + $this->pass = new ExtensionCompilerPass(); + } + + public function testProcess() + { + $extension1 = $this->createExtensionMock(true); + $extension1->expects($this->once())->method('process'); + $extension2 = $this->createExtensionMock(false); + $extension3 = $this->createExtensionMock(false); + $extension4 = $this->createExtensionMock(true); + $extension4->expects($this->once())->method('process'); + + $this->container->expects($this->any()) + ->method('getExtensions') + ->will($this->returnValue(array($extension1, $extension2, $extension3, $extension4))) + ; + + $this->pass->process($this->container); + } + + private function createExtensionMock($hasInlineCompile) + { + return $this->getMock('Symfony\Component\DependencyInjection\\'.( + $hasInlineCompile + ? 'Compiler\CompilerPassInterface' + : 'Extension\ExtensionInterface' + )); + } +} From cd42e2de93c7ea1394aa2b83367756a3affee03e Mon Sep 17 00:00:00 2001 From: Jakub Zalas Date: Tue, 14 Jul 2015 14:59:01 +0100 Subject: [PATCH 0002/2143] [FrameworkBundle] Add path verification to the template parsing test cases --- .../Templating/TemplateNameParserTest.php | 33 ++++++++++--------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/TemplateNameParserTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/TemplateNameParserTest.php index ca10c3a8fe861..d8e69a6a73f81 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/TemplateNameParserTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/TemplateNameParserTest.php @@ -43,30 +43,31 @@ protected function tearDown() } /** - * @dataProvider getLogicalNameToTemplateProvider + * @dataProvider parseProvider */ - public function testParse($name, $ref) + public function testParse($name, $logicalName, $path, $ref) { $template = $this->parser->parse($name); - $this->assertEquals($template->getLogicalName(), $ref->getLogicalName()); - $this->assertEquals($template->getLogicalName(), $name); + $this->assertSame($ref->getLogicalName(), $template->getLogicalName()); + $this->assertSame($logicalName, $template->getLogicalName()); + $this->assertSame($path, $template->getPath()); } - public function getLogicalNameToTemplateProvider() + public function parseProvider() { return array( - array('FooBundle:Post:index.html.php', new TemplateReference('FooBundle', 'Post', 'index', 'html', 'php')), - array('FooBundle:Post:index.html.twig', new TemplateReference('FooBundle', 'Post', 'index', 'html', 'twig')), - array('FooBundle:Post:index.xml.php', new TemplateReference('FooBundle', 'Post', 'index', 'xml', 'php')), - array('SensioFooBundle:Post:index.html.php', new TemplateReference('SensioFooBundle', 'Post', 'index', 'html', 'php')), - array('SensioCmsFooBundle:Post:index.html.php', new TemplateReference('SensioCmsFooBundle', 'Post', 'index', 'html', 'php')), - array(':Post:index.html.php', new TemplateReference('', 'Post', 'index', 'html', 'php')), - array('::index.html.php', new TemplateReference('', '', 'index', 'html', 'php')), - array('FooBundle:Post:foo.bar.index.html.php', new TemplateReference('FooBundle', 'Post', 'foo.bar.index', 'html', 'php')), - array('/path/to/section/name.php', new BaseTemplateReference('/path/to/section/name.php', 'php')), - array('name.twig', new BaseTemplateReference('name.twig', 'twig')), - array('name', new BaseTemplateReference('name')), + array('FooBundle:Post:index.html.php', 'FooBundle:Post:index.html.php', '@FooBundle/Resources/views/Post/index.html.php', new TemplateReference('FooBundle', 'Post', 'index', 'html', 'php')), + array('FooBundle:Post:index.html.twig', 'FooBundle:Post:index.html.twig', '@FooBundle/Resources/views/Post/index.html.twig', new TemplateReference('FooBundle', 'Post', 'index', 'html', 'twig')), + array('FooBundle:Post:index.xml.php', 'FooBundle:Post:index.xml.php', '@FooBundle/Resources/views/Post/index.xml.php', new TemplateReference('FooBundle', 'Post', 'index', 'xml', 'php')), + array('SensioFooBundle:Post:index.html.php', 'SensioFooBundle:Post:index.html.php', '@SensioFooBundle/Resources/views/Post/index.html.php', new TemplateReference('SensioFooBundle', 'Post', 'index', 'html', 'php')), + array('SensioCmsFooBundle:Post:index.html.php', 'SensioCmsFooBundle:Post:index.html.php', '@SensioCmsFooBundle/Resources/views/Post/index.html.php', new TemplateReference('SensioCmsFooBundle', 'Post', 'index', 'html', 'php')), + array(':Post:index.html.php', ':Post:index.html.php', 'views/Post/index.html.php', new TemplateReference('', 'Post', 'index', 'html', 'php')), + array('::index.html.php', '::index.html.php', 'views/index.html.php', new TemplateReference('', '', 'index', 'html', 'php')), + array('FooBundle:Post:foo.bar.index.html.php', 'FooBundle:Post:foo.bar.index.html.php', '@FooBundle/Resources/views/Post/foo.bar.index.html.php', new TemplateReference('FooBundle', 'Post', 'foo.bar.index', 'html', 'php')), + array('/path/to/section/name.php', '/path/to/section/name.php', '/path/to/section/name.php', new BaseTemplateReference('/path/to/section/name.php', 'php')), + array('name.twig', 'name.twig', 'name.twig', new BaseTemplateReference('name.twig', 'twig')), + array('name', 'name', 'name', new BaseTemplateReference('name')), ); } From 132a4e4b6fb8382b41032f6f7b7eb2b35f2790c5 Mon Sep 17 00:00:00 2001 From: Jakub Zalas Date: Wed, 15 Jul 2015 08:00:45 +0100 Subject: [PATCH 0003/2143] [FrameworkBundle] Fix template location for PHP templates --- .../Bundle/FrameworkBundle/Templating/TemplateNameParser.php | 2 +- .../FrameworkBundle/Tests/Templating/TemplateNameParserTest.php | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/TemplateNameParser.php b/src/Symfony/Bundle/FrameworkBundle/Templating/TemplateNameParser.php index 4777fbeadbb49..46e2983f5deab 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Templating/TemplateNameParser.php +++ b/src/Symfony/Bundle/FrameworkBundle/Templating/TemplateNameParser.php @@ -56,7 +56,7 @@ public function parse($name) throw new \RuntimeException(sprintf('Template name "%s" contains invalid characters.', $name)); } - if (!preg_match('/^([^:]*):([^:]*):(.+)\.([^\.]+)\.([^\.]+)$/', $name, $matches)) { + if (!preg_match('/^(?:([^:]*):)?(?:([^:]*):)?(.+)\.([^\.]+)\.([^\.]+)$/', $name, $matches)) { return parent::parse($name); } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/TemplateNameParserTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/TemplateNameParserTest.php index d8e69a6a73f81..4ff824bf7ca82 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/TemplateNameParserTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/TemplateNameParserTest.php @@ -64,10 +64,12 @@ public function parseProvider() array('SensioCmsFooBundle:Post:index.html.php', 'SensioCmsFooBundle:Post:index.html.php', '@SensioCmsFooBundle/Resources/views/Post/index.html.php', new TemplateReference('SensioCmsFooBundle', 'Post', 'index', 'html', 'php')), array(':Post:index.html.php', ':Post:index.html.php', 'views/Post/index.html.php', new TemplateReference('', 'Post', 'index', 'html', 'php')), array('::index.html.php', '::index.html.php', 'views/index.html.php', new TemplateReference('', '', 'index', 'html', 'php')), + array('index.html.php', '::index.html.php', 'views/index.html.php', new TemplateReference('', '', 'index', 'html', 'php')), array('FooBundle:Post:foo.bar.index.html.php', 'FooBundle:Post:foo.bar.index.html.php', '@FooBundle/Resources/views/Post/foo.bar.index.html.php', new TemplateReference('FooBundle', 'Post', 'foo.bar.index', 'html', 'php')), array('/path/to/section/name.php', '/path/to/section/name.php', '/path/to/section/name.php', new BaseTemplateReference('/path/to/section/name.php', 'php')), array('name.twig', 'name.twig', 'name.twig', new BaseTemplateReference('name.twig', 'twig')), array('name', 'name', 'name', new BaseTemplateReference('name')), + array('default/index.html.php', '::default/index.html.php', 'views/default/index.html.php', new TemplateReference(null, null, 'default/index', 'html', 'php')), ); } From 729902a33f2b956a4c1ab14885c52eba97bb5342 Mon Sep 17 00:00:00 2001 From: "Issei.M" Date: Sat, 7 Feb 2015 21:55:43 +0900 Subject: [PATCH 0004/2143] [Security] InMemoryUserProvider now concerns whether user's password is changed when refreshing --- .../Core/User/InMemoryUserProvider.php | 37 +++++++++++++------ .../Core/User/InMemoryUserProviderTest.php | 33 ++++++++++++++--- 2 files changed, 53 insertions(+), 17 deletions(-) diff --git a/src/Symfony/Component/Security/Core/User/InMemoryUserProvider.php b/src/Symfony/Component/Security/Core/User/InMemoryUserProvider.php index 624eb3d5d54a2..9aa39cad4849a 100644 --- a/src/Symfony/Component/Security/Core/User/InMemoryUserProvider.php +++ b/src/Symfony/Component/Security/Core/User/InMemoryUserProvider.php @@ -67,17 +67,9 @@ public function createUser(UserInterface $user) */ public function loadUserByUsername($username) { - if (!isset($this->users[strtolower($username)])) { - $ex = new UsernameNotFoundException(sprintf('Username "%s" does not exist.', $username)); - $ex->setUsername($username); - - throw $ex; - } + $user = $this->getUser($username); - $user = $this->users[strtolower($username)]; - - return new User($user->getUsername(), $user->getPassword(), $user->getRoles(), $user->isEnabled(), $user->isAccountNonExpired(), - $user->isCredentialsNonExpired(), $user->isAccountNonLocked()); + return new User($user->getUsername(), $user->getPassword(), $user->getRoles(), $user->isEnabled(), $user->isAccountNonExpired(), $user->isCredentialsNonExpired(), $user->isAccountNonLocked()); } /** @@ -89,7 +81,9 @@ public function refreshUser(UserInterface $user) throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', get_class($user))); } - return $this->loadUserByUsername($user->getUsername()); + $storedUser = $this->getUser($user->getUsername()); + + return new User($storedUser->getUsername(), $storedUser->getPassword(), $storedUser->getRoles(), $storedUser->isEnabled(), $storedUser->isAccountNonExpired(), $storedUser->isCredentialsNonExpired() && $storedUser->getPassword() === $user->getPassword(), $storedUser->isAccountNonLocked()); } /** @@ -99,4 +93,25 @@ public function supportsClass($class) { return $class === 'Symfony\Component\Security\Core\User\User'; } + + /** + * Returns the user by given username. + * + * @param string $username The username. + * + * @return User + * + * @throws UsernameNotFoundException If user whose given username does not exist. + */ + private function getUser($username) + { + if (!isset($this->users[strtolower($username)])) { + $ex = new UsernameNotFoundException(sprintf('Username "%s" does not exist.', $username)); + $ex->setUsername($username); + + throw $ex; + } + + return $this->users[strtolower($username)]; + } } diff --git a/src/Symfony/Component/Security/Tests/Core/User/InMemoryUserProviderTest.php b/src/Symfony/Component/Security/Tests/Core/User/InMemoryUserProviderTest.php index 826e3908bb4f6..266d397039005 100644 --- a/src/Symfony/Component/Security/Tests/Core/User/InMemoryUserProviderTest.php +++ b/src/Symfony/Component/Security/Tests/Core/User/InMemoryUserProviderTest.php @@ -18,18 +18,39 @@ class InMemoryUserProviderTest extends \PHPUnit_Framework_TestCase { public function testConstructor() { - $provider = new InMemoryUserProvider(array( + $provider = $this->createProvider(); + + $user = $provider->loadUserByUsername('fabien'); + $this->assertEquals('foo', $user->getPassword()); + $this->assertEquals(array('ROLE_USER'), $user->getRoles()); + $this->assertFalse($user->isEnabled()); + } + + public function testRefresh() + { + $user = new User('fabien', 'bar'); + + $provider = $this->createProvider(); + + $refreshedUser = $provider->refreshUser($user); + $this->assertEquals('foo', $refreshedUser->getPassword()); + $this->assertEquals(array('ROLE_USER'), $refreshedUser->getRoles()); + $this->assertFalse($refreshedUser->isEnabled()); + $this->assertFalse($refreshedUser->isCredentialsNonExpired()); + } + + /** + * @return InMemoryUserProvider + */ + protected function createProvider() + { + return new InMemoryUserProvider(array( 'fabien' => array( 'password' => 'foo', 'enabled' => false, 'roles' => array('ROLE_USER'), ), )); - - $user = $provider->loadUserByUsername('fabien'); - $this->assertEquals('foo', $user->getPassword()); - $this->assertEquals(array('ROLE_USER'), $user->getRoles()); - $this->assertFalse($user->isEnabled()); } public function testCreateUser() From 73366d528157414c6d84b84cd9d2beea24f20c13 Mon Sep 17 00:00:00 2001 From: Teoh Han Hui Date: Fri, 7 Aug 2015 05:28:03 +0000 Subject: [PATCH 0005/2143] [Yaml] Improve newline handling in folded scalar blocks --- src/Symfony/Component/Yaml/Parser.php | 40 +++++++++++-------- .../Component/Yaml/Tests/Fixtures/sfTests.yml | 18 ++++++++- 2 files changed, 40 insertions(+), 18 deletions(-) diff --git a/src/Symfony/Component/Yaml/Parser.php b/src/Symfony/Component/Yaml/Parser.php index 3c20c8662fb02..caf373e396132 100644 --- a/src/Symfony/Component/Yaml/Parser.php +++ b/src/Symfony/Component/Yaml/Parser.php @@ -20,7 +20,9 @@ */ class Parser { - const FOLDED_SCALAR_PATTERN = '(?P\||>)(?P\+|\-|\d+|\+\d+|\-\d+|\d+\+|\d+\-)?(?P +#.*)?'; + const BLOCK_SCALAR_HEADER_PATTERN = '(?P\||>)(?P\+|\-|\d+|\+\d+|\-\d+|\d+\+|\d+\-)?(?P +#.*)?'; + // BC - wrongly named + const FOLDED_SCALAR_PATTERN = self::BLOCK_SCALAR_HEADER_PATTERN; private $offset = 0; private $lines = array(); @@ -332,8 +334,8 @@ private function getNextEmbedBlock($indentation = null, $inSequence = false) $isItUnindentedCollection = $this->isStringUnIndentedCollectionItem($this->currentLine); - // Comments must not be removed inside a string block (ie. after a line ending with "|") - $removeCommentsPattern = '~'.self::FOLDED_SCALAR_PATTERN.'$~'; + // Comments must not be removed inside a block scalar + $removeCommentsPattern = '~'.self::BLOCK_SCALAR_HEADER_PATTERN.'$~'; $removeComments = !preg_match($removeCommentsPattern, $this->currentLine); while ($this->moveToNextLine()) { @@ -422,10 +424,10 @@ private function parseValue($value, $exceptionOnInvalidType, $objectSupport) return $this->refs[$value]; } - if (preg_match('/^'.self::FOLDED_SCALAR_PATTERN.'$/', $value, $matches)) { + if (preg_match('/^'.self::BLOCK_SCALAR_HEADER_PATTERN.'$/', $value, $matches)) { $modifiers = isset($matches['modifiers']) ? $matches['modifiers'] : ''; - return $this->parseFoldedScalar($matches['separator'], preg_replace('#\d+#', '', $modifiers), (int) abs($modifiers)); + return $this->parseBlockScalar($matches['separator'], preg_replace('#\d+#', '', $modifiers), (int) abs($modifiers)); } try { @@ -439,15 +441,15 @@ private function parseValue($value, $exceptionOnInvalidType, $objectSupport) } /** - * Parses a folded scalar. + * Parses a block scalar. * - * @param string $separator The separator that was used to begin this folded scalar (| or >) - * @param string $indicator The indicator that was used to begin this folded scalar (+ or -) - * @param int $indentation The indentation that was used to begin this folded scalar + * @param string $style The style indicator that was used to begin this block scalar (| or >) + * @param string $chomping The chomping indicator that was used to begin this block scalar (+ or -) + * @param int $indentation The indentation indicator that was used to begin this block scalar * * @return string The text value */ - private function parseFoldedScalar($separator, $indicator = '', $indentation = 0) + private function parseBlockScalar($style, $chomping = '', $indentation = 0) { $notEOF = $this->moveToNextLine(); if (!$notEOF) { @@ -502,17 +504,23 @@ private function parseFoldedScalar($separator, $indicator = '', $indentation = 0 $this->moveToPreviousLine(); } - // replace all non-trailing single newlines with spaces in folded blocks - if ('>' === $separator) { + // folded style + if ('>' === $style) { + // folded lines + // replace all non-leading/non-trailing single newlines with spaces preg_match('/(\n*)$/', $text, $matches); - $text = preg_replace('/(? - Empty lines in folded blocks + Empty lines in literal blocks yaml: | foo: bar: | @@ -65,6 +65,20 @@ yaml: | php: | array('foo' => array('bar' => "foo\n\n\n \nbar\n")) --- +test: Empty lines in folded blocks +brief: > + Empty lines in folded blocks +yaml: | + foo: + bar: > + + foo + + + bar +php: | + array('foo' => array('bar' => "\nfoo\n\nbar\n")) +--- test: IP addresses brief: > IP addresses From 166e1750bcdabb3b674543c20b2f397790833a6d Mon Sep 17 00:00:00 2001 From: Michael Lee Date: Thu, 13 Aug 2015 19:30:11 +0800 Subject: [PATCH 0006/2143] [expression-language] Code Cleanup for GetAttrNode Use ``$this->nodes['attribute']->attributes['value']`` to replace ``$this->nodes['attribute']->evaluate($functions, $values)`` for method call and property call. | Q | A | ------------- | --- | Bug fix? | no | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | n/a | License | MIT | Doc PR | n/a --- src/Symfony/Component/ExpressionLanguage/Node/GetAttrNode.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/ExpressionLanguage/Node/GetAttrNode.php b/src/Symfony/Component/ExpressionLanguage/Node/GetAttrNode.php index c7f9c411135b9..b3f98bf565f08 100644 --- a/src/Symfony/Component/ExpressionLanguage/Node/GetAttrNode.php +++ b/src/Symfony/Component/ExpressionLanguage/Node/GetAttrNode.php @@ -78,7 +78,7 @@ public function evaluate($functions, $values) throw new \RuntimeException('Unable to get a property on a non-object.'); } - return call_user_func_array(array($obj, $this->nodes['attribute']->evaluate($functions, $values)), $this->nodes['arguments']->evaluate($functions, $values)); + return call_user_func_array(array($obj, $this->nodes['attribute']->attributes['value']), $this->nodes['arguments']->evaluate($functions, $values)); case self::ARRAY_CALL: $array = $this->nodes['node']->evaluate($functions, $values); From e5d3f2567d6d04fceac19c6ed5d2be439bcc7d6e Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Mon, 24 Aug 2015 15:16:17 +0200 Subject: [PATCH 0007/2143] [console] Use the description when no help is available --- src/Symfony/Component/Console/Command/Command.php | 2 +- src/Symfony/Component/Console/Tests/Command/CommandTest.php | 2 ++ .../Component/Console/Tests/Fixtures/application_asxml1.txt | 2 +- .../Component/Console/Tests/Fixtures/application_asxml2.txt | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Console/Command/Command.php b/src/Symfony/Component/Console/Command/Command.php index 29625a26dacf9..f169b6eb8702e 100644 --- a/src/Symfony/Component/Console/Command/Command.php +++ b/src/Symfony/Component/Console/Command/Command.php @@ -484,7 +484,7 @@ public function setHelp($help) */ public function getHelp() { - return $this->help; + return $this->help ?: $this->description; } /** diff --git a/src/Symfony/Component/Console/Tests/Command/CommandTest.php b/src/Symfony/Component/Console/Tests/Command/CommandTest.php index 1ae12874ba84f..a0c8d78deb275 100644 --- a/src/Symfony/Component/Console/Tests/Command/CommandTest.php +++ b/src/Symfony/Component/Console/Tests/Command/CommandTest.php @@ -131,6 +131,8 @@ public function testGetSetHelp() $ret = $command->setHelp('help1'); $this->assertEquals($command, $ret, '->setHelp() implements a fluent interface'); $this->assertEquals('help1', $command->getHelp(), '->setHelp() sets the help'); + $command->setHelp(''); + $this->assertEquals('description', $command->getHelp(), '->getHelp() fallback to the description'); } public function testGetProcessedHelp() diff --git a/src/Symfony/Component/Console/Tests/Fixtures/application_asxml1.txt b/src/Symfony/Component/Console/Tests/Fixtures/application_asxml1.txt index 71d2fcba35405..3652d6613d38b 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/application_asxml1.txt +++ b/src/Symfony/Component/Console/Tests/Fixtures/application_asxml1.txt @@ -97,7 +97,7 @@ foo:bar The foo:bar command - + The foo:bar command afoobar diff --git a/src/Symfony/Component/Console/Tests/Fixtures/application_asxml2.txt b/src/Symfony/Component/Console/Tests/Fixtures/application_asxml2.txt index 0b30b201f2ff7..3205f9cb5f029 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/application_asxml2.txt +++ b/src/Symfony/Component/Console/Tests/Fixtures/application_asxml2.txt @@ -4,7 +4,7 @@ foo:bar The foo:bar command - + The foo:bar command afoobar From 1f3ea0f8af641782ab1a1e58f4c9ffc53e0f36c0 Mon Sep 17 00:00:00 2001 From: "Nathanael d. Noblet" Date: Thu, 27 Aug 2015 13:00:40 -0600 Subject: [PATCH 0008/2143] Use ObjectManager interface instead of EntityManager If you use the EntityManager Decorator pattern that doctrine provides then simply specifying a query_builder closure where your decorated em is used fails as it isn't an instance of Doctrine\ORM\EntityManager. Testing against the ObjectManager interface fixes the issue. --- .../Doctrine/Form/ChoiceList/ORMQueryBuilderLoader.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Bridge/Doctrine/Form/ChoiceList/ORMQueryBuilderLoader.php b/src/Symfony/Bridge/Doctrine/Form/ChoiceList/ORMQueryBuilderLoader.php index 8f135d62582d7..30263ea7e3b87 100644 --- a/src/Symfony/Bridge/Doctrine/Form/ChoiceList/ORMQueryBuilderLoader.php +++ b/src/Symfony/Bridge/Doctrine/Form/ChoiceList/ORMQueryBuilderLoader.php @@ -14,7 +14,7 @@ use Symfony\Component\Form\Exception\UnexpectedTypeException; use Doctrine\ORM\QueryBuilder; use Doctrine\DBAL\Connection; -use Doctrine\ORM\EntityManager; +use Doctrine\Common\Persistence\ObjectManager; /** * Getting Entities through the ORM QueryBuilder. @@ -35,7 +35,7 @@ class ORMQueryBuilderLoader implements EntityLoaderInterface * Construct an ORM Query Builder Loader. * * @param QueryBuilder|\Closure $queryBuilder - * @param EntityManager $manager + * @param ObjectManager $manager * @param string $class * * @throws UnexpectedTypeException @@ -49,8 +49,8 @@ public function __construct($queryBuilder, $manager = null, $class = null) } if ($queryBuilder instanceof \Closure) { - if (!$manager instanceof EntityManager) { - throw new UnexpectedTypeException($manager, 'Doctrine\ORM\EntityManager'); + if (!$manager instanceof ObjectManager) { + throw new UnexpectedTypeException($manager, 'Doctrine\Common\Persistence\ObjectManager'); } $queryBuilder = $queryBuilder($manager->getRepository($class)); From de7d4a7225c9444b6a8e389709943c864156688b Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sat, 29 Aug 2015 20:06:03 +0200 Subject: [PATCH 0009/2143] [FrameworkBundle] Fix templating.helper.code.file_link_format when defined by ini setting --- .../FrameworkBundle/DependencyInjection/FrameworkExtension.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 75e45202deac9..c6801f56e2181 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -364,7 +364,7 @@ private function registerTemplatingConfiguration(array $config, $ide, ContainerB 'sublime' => 'subl://open?url=file://%%f&line=%%l', ); - $container->setParameter('templating.helper.code.file_link_format', ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format') ?: (isset($links[$ide]) ? $links[$ide] : $ide)); + $container->setParameter('templating.helper.code.file_link_format', str_replace('%', '%%', ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format')) ?: (isset($links[$ide]) ? $links[$ide] : $ide)); } $container->setParameter('templating.helper.form.resources', $config['form']['resources']); $container->setParameter('fragment.renderer.hinclude.global_template', $config['hinclude_default_template']); From 0f2256e85a792409ce0071bcf16286bef1092243 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 31 Aug 2015 16:18:45 +0200 Subject: [PATCH 0010/2143] [appveyor] PHP 5.3.11 for Symfony 2.7 --- appveyor.yml | 4 ++-- src/Symfony/Component/Console/Descriptor/JsonDescriptor.php | 4 ++-- .../Component/Console/Descriptor/MarkdownDescriptor.php | 4 ++-- src/Symfony/Component/Console/Descriptor/TextDescriptor.php | 4 ++-- .../Tests/Normalizer/GetSetMethodNormalizerTest.php | 3 +++ .../Serializer/Tests/Normalizer/ObjectNormalizerTest.php | 3 +++ 6 files changed, 14 insertions(+), 8 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 2eefdb1ce89e5..2e4d1cce40218 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -22,8 +22,8 @@ init: install: - IF EXIST c:\php (SET PHP=0) ELSE (mkdir c:\php) - cd c:\php - - IF %PHP%==1 appveyor DownloadFile http://windows.php.net/downloads/releases/archives/php-5.3.3-nts-Win32-VC9-x86.zip - - IF %PHP%==1 7z x php-5.3.3-nts-Win32-VC9-x86.zip -y > 7z.log + - IF %PHP%==1 appveyor DownloadFile http://windows.php.net/downloads/releases/archives/php-5.3.11-nts-Win32-VC9-x86.zip + - IF %PHP%==1 7z x php-5.3.11-nts-Win32-VC9-x86.zip -y > 7z.log - IF %PHP%==1 appveyor DownloadFile http://nebm.ist.utl.pt/~glopes/misc/intl_win/ 8000 ICU-51.2-dlls.zip - IF %PHP%==1 7z x ICU-51.2-dlls.zip -y > 7z.log - IF %PHP%==1 cd ext diff --git a/src/Symfony/Component/Console/Descriptor/JsonDescriptor.php b/src/Symfony/Component/Console/Descriptor/JsonDescriptor.php index 8649d3ac456f3..87e38fdb89071 100644 --- a/src/Symfony/Component/Console/Descriptor/JsonDescriptor.php +++ b/src/Symfony/Component/Console/Descriptor/JsonDescriptor.php @@ -102,7 +102,7 @@ private function getInputArgumentData(InputArgument $argument) 'name' => $argument->getName(), 'is_required' => $argument->isRequired(), 'is_array' => $argument->isArray(), - 'description' => preg_replace('/\s*\R\s*/', ' ', $argument->getDescription()), + 'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $argument->getDescription()), 'default' => $argument->getDefault(), ); } @@ -120,7 +120,7 @@ private function getInputOptionData(InputOption $option) 'accept_value' => $option->acceptValue(), 'is_value_required' => $option->isValueRequired(), 'is_multiple' => $option->isArray(), - 'description' => preg_replace('/\s*\R\s*/', ' ', $option->getDescription()), + 'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $option->getDescription()), 'default' => $option->getDefault(), ); } diff --git a/src/Symfony/Component/Console/Descriptor/MarkdownDescriptor.php b/src/Symfony/Component/Console/Descriptor/MarkdownDescriptor.php index 10f05168d47d0..d3d76a4201025 100644 --- a/src/Symfony/Component/Console/Descriptor/MarkdownDescriptor.php +++ b/src/Symfony/Component/Console/Descriptor/MarkdownDescriptor.php @@ -36,7 +36,7 @@ protected function describeInputArgument(InputArgument $argument, array $options .'* Name: '.($argument->getName() ?: '')."\n" .'* Is required: '.($argument->isRequired() ? 'yes' : 'no')."\n" .'* Is array: '.($argument->isArray() ? 'yes' : 'no')."\n" - .'* Description: '.preg_replace('/\s*\R\s*/', PHP_EOL.' ', $argument->getDescription() ?: '')."\n" + .'* Description: '.preg_replace('/\s*[\r\n]\s*/', "\n ", $argument->getDescription() ?: '')."\n" .'* Default: `'.str_replace("\n", '', var_export($argument->getDefault(), true)).'`' ); } @@ -53,7 +53,7 @@ protected function describeInputOption(InputOption $option, array $options = arr .'* Accept value: '.($option->acceptValue() ? 'yes' : 'no')."\n" .'* Is value required: '.($option->isValueRequired() ? 'yes' : 'no')."\n" .'* Is multiple: '.($option->isArray() ? 'yes' : 'no')."\n" - .'* Description: '.preg_replace('/\s*\R\s*/', PHP_EOL.' ', $option->getDescription() ?: '')."\n" + .'* Description: '.preg_replace('/\s*[\r\n]\s*/', "\n ", $option->getDescription() ?: '')."\n" .'* Default: `'.str_replace("\n", '', var_export($option->getDefault(), true)).'`' ); } diff --git a/src/Symfony/Component/Console/Descriptor/TextDescriptor.php b/src/Symfony/Component/Console/Descriptor/TextDescriptor.php index 212796a3edcc8..57e09e4d81c36 100644 --- a/src/Symfony/Component/Console/Descriptor/TextDescriptor.php +++ b/src/Symfony/Component/Console/Descriptor/TextDescriptor.php @@ -44,7 +44,7 @@ protected function describeInputArgument(InputArgument $argument, array $options $argument->getName(), str_repeat(' ', $spacingWidth), // + 17 = 2 spaces + + + 2 spaces - preg_replace('/\s*\R\s*/', PHP_EOL.str_repeat(' ', $totalWidth + 17), $argument->getDescription()), + preg_replace('/\s*[\r\n]\s*/', "\n".str_repeat(' ', $totalWidth + 17), $argument->getDescription()), $default ), $options); } @@ -81,7 +81,7 @@ protected function describeInputOption(InputOption $option, array $options = arr $synopsis, str_repeat(' ', $spacingWidth), // + 17 = 2 spaces + + + 2 spaces - preg_replace('/\s*\R\s*/', "\n".str_repeat(' ', $totalWidth + 17), $option->getDescription()), + preg_replace('/\s*[\r\n]\s*/', "\n".str_repeat(' ', $totalWidth + 17), $option->getDescription()), $default, $option->isArray() ? ' (multiple values allowed)' : '' ), $options); diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/GetSetMethodNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/GetSetMethodNormalizerTest.php index 24036292caceb..53369629e6fe7 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/GetSetMethodNormalizerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/GetSetMethodNormalizerTest.php @@ -209,6 +209,9 @@ public function testConstructorDenormalizeWithMissingOptionalArgument() public function testConstructorDenormalizeWithOptionalDefaultArgument() { + if (PHP_VERSION_ID <= 50316) { + $this->markTestSkipped('See https://bugs.php.net/62715'); + } $obj = $this->normalizer->denormalize( array('bar' => 'test'), __NAMESPACE__.'\GetConstructorArgsWithDefaultValueDummy', 'any'); diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php index 7d9da645c4f4e..3080c8df80e95 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php @@ -157,6 +157,9 @@ public function testConstructorDenormalizeWithMissingOptionalArgument() public function testConstructorDenormalizeWithOptionalDefaultArgument() { + if (PHP_VERSION_ID <= 50316) { + $this->markTestSkipped('See https://bugs.php.net/62715'); + } $obj = $this->normalizer->denormalize( array('bar' => 'test'), __NAMESPACE__.'\ObjectConstructorArgsWithDefaultValueDummy', 'any'); From cd167f49dd09a5eb39e2f2b888e7ee0008e8129a Mon Sep 17 00:00:00 2001 From: Christophe Coevoet Date: Mon, 31 Aug 2015 21:21:38 +0200 Subject: [PATCH 0011/2143] Mark deprecated Twig functions as deprecated with the Twig feature --- src/Symfony/Bridge/Twig/AppVariable.php | 2 +- src/Symfony/Bridge/Twig/Extension/AssetExtension.php | 2 +- src/Symfony/Bridge/Twig/Extension/FormExtension.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Bridge/Twig/AppVariable.php b/src/Symfony/Bridge/Twig/AppVariable.php index bffa6a674d247..88d9835ce2399 100644 --- a/src/Symfony/Bridge/Twig/AppVariable.php +++ b/src/Symfony/Bridge/Twig/AppVariable.php @@ -14,8 +14,8 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpFoundation\Session\Session; -use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; +use Symfony\Component\Security\Core\SecurityContext; use Symfony\Component\DependencyInjection\ContainerInterface; /** diff --git a/src/Symfony/Bridge/Twig/Extension/AssetExtension.php b/src/Symfony/Bridge/Twig/Extension/AssetExtension.php index f7b9c8750089b..d90d13f6fd3d4 100644 --- a/src/Symfony/Bridge/Twig/Extension/AssetExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/AssetExtension.php @@ -42,7 +42,7 @@ public function getFunctions() return array( new \Twig_SimpleFunction('asset', array($this, 'getAssetUrl')), new \Twig_SimpleFunction('asset_version', array($this, 'getAssetVersion')), - new \Twig_SimpleFunction('assets_version', array($this, 'getAssetsVersion')), + new \Twig_SimpleFunction('assets_version', array($this, 'getAssetsVersion'), array('deprecated' => true, 'alternative' => 'asset_version')), ); } diff --git a/src/Symfony/Bridge/Twig/Extension/FormExtension.php b/src/Symfony/Bridge/Twig/Extension/FormExtension.php index 9c7339f70295f..924d49d581863 100644 --- a/src/Symfony/Bridge/Twig/Extension/FormExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/FormExtension.php @@ -61,7 +61,7 @@ public function getTokenParsers() public function getFunctions() { return array( - new \Twig_SimpleFunction('form_enctype', null, array('node_class' => 'Symfony\Bridge\Twig\Node\FormEnctypeNode', 'is_safe' => array('html'))), + new \Twig_SimpleFunction('form_enctype', null, array('node_class' => 'Symfony\Bridge\Twig\Node\FormEnctypeNode', 'is_safe' => array('html'), 'deprecated' => true, 'alternative' => 'form_start')), new \Twig_SimpleFunction('form_widget', null, array('node_class' => 'Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', 'is_safe' => array('html'))), new \Twig_SimpleFunction('form_errors', null, array('node_class' => 'Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', 'is_safe' => array('html'))), new \Twig_SimpleFunction('form_label', null, array('node_class' => 'Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', 'is_safe' => array('html'))), From 835aa788d46b1b91e69610837116ecd2f8ec7aa6 Mon Sep 17 00:00:00 2001 From: Abdellatif Ait boudad Date: Mon, 31 Aug 2015 16:16:04 +0000 Subject: [PATCH 0012/2143] [Form][2.7][ Choice type] fixed groups with empty array. --- .../Form/ChoiceList/Factory/DefaultChoiceListFactory.php | 4 ++++ .../Tests/ChoiceList/Factory/DefaultChoiceListFactoryTest.php | 1 + 2 files changed, 5 insertions(+) diff --git a/src/Symfony/Component/Form/ChoiceList/Factory/DefaultChoiceListFactory.php b/src/Symfony/Component/Form/ChoiceList/Factory/DefaultChoiceListFactory.php index 9e54fa0857f9e..b227180100d7b 100644 --- a/src/Symfony/Component/Form/ChoiceList/Factory/DefaultChoiceListFactory.php +++ b/src/Symfony/Component/Form/ChoiceList/Factory/DefaultChoiceListFactory.php @@ -172,6 +172,10 @@ private static function addChoiceView($choice, $value, $label, $keys, &$index, $ private static function addChoiceViewsGroupedBy($groupBy, $label, $choices, $keys, &$index, $attr, $isPreferred, &$preferredViews, &$otherViews) { foreach ($groupBy as $key => $value) { + if (null === $value) { + continue; + } + // Add the contents of groups to new ChoiceGroupView instances if (is_array($value)) { $preferredViewsForGroup = array(); diff --git a/src/Symfony/Component/Form/Tests/ChoiceList/Factory/DefaultChoiceListFactoryTest.php b/src/Symfony/Component/Form/Tests/ChoiceList/Factory/DefaultChoiceListFactoryTest.php index 1738aaff0ff3c..9210bc3d70ede 100644 --- a/src/Symfony/Component/Form/Tests/ChoiceList/Factory/DefaultChoiceListFactoryTest.php +++ b/src/Symfony/Component/Form/Tests/ChoiceList/Factory/DefaultChoiceListFactoryTest.php @@ -536,6 +536,7 @@ public function testCreateViewFlatGroupByOriginalStructure() $list = new ArrayChoiceList(array( 'Group 1' => array('A' => $this->obj1, 'B' => $this->obj2), 'Group 2' => array('C' => $this->obj3, 'D' => $this->obj4), + 'Group empty' => array(), )); $view = $this->factory->createView( From 2c4860877d13652e9c424629ec9a51a4ab876fa6 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 1 Sep 2015 15:39:59 +0200 Subject: [PATCH 0013/2143] Require symfony/intl ~2.4 when Locale::setDefault() is used --- src/Symfony/Component/Form/composer.json | 2 +- src/Symfony/Component/Translation/composer.json | 2 +- src/Symfony/Component/Validator/composer.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Form/composer.json b/src/Symfony/Component/Form/composer.json index 21c6af679971e..3894b6b45dda9 100644 --- a/src/Symfony/Component/Form/composer.json +++ b/src/Symfony/Component/Form/composer.json @@ -18,7 +18,7 @@ "require": { "php": ">=5.3.9", "symfony/event-dispatcher": "~2.1", - "symfony/intl": "~2.3", + "symfony/intl": "~2.4", "symfony/options-resolver": "~2.6", "symfony/property-access": "~2.3" }, diff --git a/src/Symfony/Component/Translation/composer.json b/src/Symfony/Component/Translation/composer.json index 6f1053e66caf0..e2e1587e0a4f3 100644 --- a/src/Symfony/Component/Translation/composer.json +++ b/src/Symfony/Component/Translation/composer.json @@ -21,7 +21,7 @@ "require-dev": { "symfony/phpunit-bridge": "~2.7", "symfony/config": "~2.7", - "symfony/intl": "~2.3", + "symfony/intl": "~2.4", "symfony/yaml": "~2.2", "psr/log": "~1.0" }, diff --git a/src/Symfony/Component/Validator/composer.json b/src/Symfony/Component/Validator/composer.json index b89fe1b134515..5881064ea4950 100644 --- a/src/Symfony/Component/Validator/composer.json +++ b/src/Symfony/Component/Validator/composer.json @@ -22,7 +22,7 @@ "require-dev": { "symfony/phpunit-bridge": "~2.7", "symfony/http-foundation": "~2.1", - "symfony/intl": "~2.3", + "symfony/intl": "~2.4", "symfony/yaml": "~2.0,>=2.0.5", "symfony/config": "~2.2", "symfony/property-access": "~2.3", From 7c87baab77068c0f8893286b5cdd3614372c2100 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 1 Sep 2015 17:38:42 +0200 Subject: [PATCH 0014/2143] updated CHANGELOG for 2.3.32 --- CHANGELOG-2.3.md | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/CHANGELOG-2.3.md b/CHANGELOG-2.3.md index e261767b557f0..c3b5656102cc4 100644 --- a/CHANGELOG-2.3.md +++ b/CHANGELOG-2.3.md @@ -7,6 +7,38 @@ in 2.3 minor versions. To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v2.3.0...v2.3.1 +* 2.3.32 (2015-09-01) + + * bug #15601 [console] Use the description when no help is available (Nicofuma) + * bug #15603 [HttpKernel] Do not normalize the kernel root directory path #15567 (leofeyer) + * bug #15428 Fix the validation of form resources to register the default theme (stof) + * bug #15619 [Translation] Fix the string casting in the XliffFileLoader (stof) + * bug #15575 Add appveyor.yml for C.I. on Windows (nicolas-grekas) + * bug #15611 [Translation][Xliff Loader] Support omitting the node in an .xlf file. (leofeyer) + * bug #15549 [FrameworkBundle] Fix precedence of xdebug.file_link_format (nicolas-grekas) + * bug #15589 made Symfony compatible with both Twig 1.x and 2.x (fabpot) + * bug #15535 made Symfony compatible with both Twig 1.x and 2.x (fabpot) + * bug #14372 [DoctrineBridge][Form] fix EntityChoiceList when indexing by primary foreign key (giosh94mhz) + * bug #15489 Implement the support of timezone objects in the stub IntlDateFormatter (stof) + * bug #15426 [Serializer] Add support for variadic arguments in the GetSetNormalizer (stof) + * bug #15480 [Yaml] Nested merge keys (mathroc) + * bug #15445 do not remove space between attributes (greg0ire) + * bug #15263 [HttpFoundation] fixed the check of 'proxy-revalidate' in Response::mustRevalidate() (axiac) + * bug #15425 [Routing] Fix the retrieval of the default value for variadic arguments in the annotation loader (wdalmut, stof) + * bug #15074 Fixing DbalSessionHandler to work with a Oracle "limitation" or bug? (nuncanada) + * bug #15380 do not dump leading backslashes in class names (xabbuh) + * bug #15376 [ClassMapGenerator] Skip ::class constant (WouterJ) + * bug #15170 [Config] type specific check for emptiness (xabbuh) + * bug #15411 Fix the handling of null as locale in the stub intl classes (stof) + * bug #15413 Fix the return value on error for intl methods returning arrays (stof) + * bug #15392 Fix missing _route parameter notice in RouterListener logging case (Haehnchen) + * bug #15386 [php7] Fix for substr() always returning a string (nicolas-grekas) + * bug #15355 [Security] Do not save the target path in the session for a stateless firewall (lyrixx) + * bug #15330 [Console] Fix console output with closed stdout (jakzal) + * bug #15326 [Security] fix check for empty usernames (xabbuh) + * bug #15249 [HttpFoundation] [PSR-7] Allow to use resources as content body and to return resources from string content (dunglas) + * bug #15282 [HttpFoundation] Behaviour change in PHP7 for substr (Nicofuma) + * 2.3.31 (2015-07-13) * bug #15248 Added 'default' color (jaytaph) From a988449e4e32512f714cc5f6f3a28b07eca3bc11 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 1 Sep 2015 17:39:15 +0200 Subject: [PATCH 0015/2143] update CONTRIBUTORS for 2.3.32 --- CONTRIBUTORS.md | 61 +++++++++++++++++++++++++++++++------------------ 1 file changed, 39 insertions(+), 22 deletions(-) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index af5724f4a7af9..3ce8e41098571 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -14,8 +14,8 @@ Symfony is the result of the work of many people who made the code better - Kris Wallsmith (kriswallsmith) - Christophe Coevoet (stof) - Jakub Zalas (jakubzalas) - - Pascal Borreli (pborreli) - Christian Flothmann (xabbuh) + - Pascal Borreli (pborreli) - Hugo Hamon (hhamon) - Joseph Bielawski (stloyd) - Karma Dordrak (drak) @@ -26,15 +26,16 @@ Symfony is the result of the work of many people who made the code better - Jean-François Simon (jfsimon) - Benjamin Eberlei (beberlei) - Igor Wiedler (igorw) - - Martin Hasoň (hason) - Abdellatif Ait boudad (aitboudad) + - Martin Hasoň (hason) - Eriksen Costa (eriksencosta) - Grégoire Pineau (lyrixx) - Wouter De Jong (wouterj) - Jonathan Wage (jwage) + - Javier Eguiluz (javier.eguiluz) + - Kévin Dunglas (dunglas) - Alexandre Salomé (alexandresalome) - William Durand (couac) - - Kévin Dunglas (dunglas) - ornicar - stealth35 ‏ (stealth35) - Alexander Mols (asm89) @@ -84,43 +85,42 @@ Symfony is the result of the work of many people who made the code better - excelwebzone - Jacob Dreesen (jdreesen) - Matthias Pigulla (mpdude) - - Javier Eguiluz (javier.eguiluz) - Fabien Pennequin (fabienpennequin) - Peter Rehm (rpet) - Peter Kokot (maastermedia) - Gordon Franke (gimler) - Robert Schönthal (digitalkaoz) + - Jérémy DERUSSÉ (jderusse) - Dariusz Ruminski - Michal Piotrowski (eventhorizon) - Stefano Sala (stefano.sala) + - David Buchmann (dbu) - Juti Noppornpitak (shiroyuki) - Sebastian Hörl (blogsh) - Daniel Gomes (danielcsgomes) - Hidenori Goto (hidenorigoto) - - David Buchmann (dbu) + - Alexander Schwenn (xelaris) - Guilherme Blanco (guilhermeblanco) - - Jérémy DERUSSÉ (jderusse) - Pablo Godel (pgodel) - Eric GELOEN (gelo) + - Vladimir Reznichenko (kalessil) - Jérémie Augustin (jaugustin) - - Alexander Schwenn (xelaris) + - Issei Murasawa (issei_m) - Rafael Dohms (rdohms) - Arnaud Kleinpeter (nanocom) + - Iltar van der Berg (kjarli) - Joshua Thijssen - - Vladimir Reznichenko (kalessil) - Tigran Azatyan (tigranazatyan) - - Issei Murasawa (issei_m) + - Sebastiaan Stok (sstok) - Richard Shank (iampersistent) - Clemens Tolboom - Helmer Aaviksoo - - Sebastiaan Stok (sstok) - Hiromi Hishida (77web) - Matthieu Ouellette-Vachon (maoueh) - Michał Pipa (michal.pipa) - Amal Raghav (kertz) - Jonathan Ingram (jonathaningram) - Artur Kotyrba - - Iltar van der Berg - Rouven Weßling (realityking) - Andréia Bohner (andreia) - Dmitrii Chekaliuk (lazyhammer) @@ -146,6 +146,7 @@ Symfony is the result of the work of many people who made the code better - fivestar - Dominique Bongiraud - Leszek Prabucki (l3l0) + - Alexander M. Turek (derrabus) - François Zaninotto (fzaninotto) - Dustin Whittle (dustinwhittle) - jeff @@ -164,7 +165,6 @@ Symfony is the result of the work of many people who made the code better - Francois Zaninotto - Alexander Kotynia (olden) - Daniel Tschinder - - Alexander M. Turek (derrabus) - Elnur Abdurrakhimov (elnur) - John Kary (johnkary) - Manuel Reinhard (sprain) @@ -197,6 +197,7 @@ Symfony is the result of the work of many people who made the code better - Robert Kiss (kepten) - Ruben Gonzalez (rubenrua) - Kim Hemsø Rasmussen (kimhemsoe) + - Diego Saint Esteben (dosten) - Florian Lonqueu-Brochard (florianlb) - Tom Van Looy (tvlooy) - Wouter Van Hecke @@ -212,6 +213,7 @@ Symfony is the result of the work of many people who made the code better - Andrew Moore (finewolf) - Bertrand Zuchuat (garfield-fr) - Gabor Toth (tgabi333) + - Grégoire Paris (greg0ire) - Alex Pott - realmfoo - Thomas Tourlourat (armetiz) @@ -232,8 +234,11 @@ Symfony is the result of the work of many people who made the code better - Thomas Schulz (king2500) - Marco Pivetta (ocramius) - Ricard Clau (ricardclau) + - Lorenz Schori + - Giorgio Premi - Erin Millard - Matthew Lewinski (lewinski) + - Marcos Sánchez - alquerci - Francesco Levorato - Vitaliy Zakharov (zakharovvi) @@ -260,13 +265,13 @@ Symfony is the result of the work of many people who made the code better - Kirill chEbba Chebunin (chebba) - Greg Thornton (xdissent) - Baptiste Clavié (talus) - - Grégoire Paris (greg0ire) - Costin Bereveanu (schniper) - Loïc Chardonnet (gnusat) - Marek Kalnik (marekkalnik) - Vyacheslav Salakhutdinov (megazoll) - Hassan Amouhzi - Tamas Szijarto + - Michaël Perrin (michael.perrin) - Pavel Volokitin (pvolok) - Endre Fejes - Tobias Naumann (tna) @@ -297,8 +302,8 @@ Symfony is the result of the work of many people who made the code better - Brian King - Michel Salib (michelsalib) - geoffrey - - Lorenz Schori - Jeanmonod David (jeanmonod) + - Thomas Lallement (raziel057) - Jan Schumann - Niklas Fiekas - lancergr @@ -370,6 +375,7 @@ Symfony is the result of the work of many people who made the code better - Florian Rey (nervo) - Rodrigo Borrego Bernabé (rodrigobb) - Denis Gorbachev (starfall) + - Titouan Galopin (tgalopin) - Steven Surowiec - Kevin Saliou (kbsali) - Daniel Tschinder @@ -393,7 +399,6 @@ Symfony is the result of the work of many people who made the code better - Mantas Var (mvar) - Sebastian Krebs - Christopher Davis (chrisguitarguy) - - Thomas Lallement (raziel057) - alcaeus - vitaliytv - Markus Bachmann (baachi) @@ -449,6 +454,7 @@ Symfony is the result of the work of many people who made the code better - Simon Schick (simonsimcity) - redstar504 - Hossein Bukhamsin + - origaminal - Paweł Wacławczyk (pwc) - Oleg Zinchenko (cystbear) - Johannes Klauss (cloppy) @@ -538,6 +544,7 @@ Symfony is the result of the work of many people who made the code better - Tony Malzhacker - Cyril Quintin (cyqui) - Gerard van Helden (drm) + - Johnny Peck (johnnypeck) - David Romaní - Patrick Allaert - Gustavo Falco (gfalco) @@ -545,6 +552,7 @@ Symfony is the result of the work of many people who made the code better - Aleksey Podskrebyshev - David Marín Carreño (davefx) - Jörn Lang (j.lang) + - Leo Feyer - mwsaz - Benoît Bourgeois - corphi @@ -562,7 +570,6 @@ Symfony is the result of the work of many people who made the code better - Christian Morgan - Alexander Miehe (engerim) - Morgan Auchede (mauchede) - - Titouan Galopin (tgalopin) - Don Pinkster - Maksim Muruev - Emil Einarsson @@ -595,6 +602,7 @@ Symfony is the result of the work of many people who made the code better - Reece Fowell (reecefowell) - stefan.r - Matthieu Napoli (mnapoli) + - Alexandru Furculita (afurculita) - Ben Ramsey (ramsey) - Christian Jul Jensen - The Whole Life to Learn @@ -610,7 +618,6 @@ Symfony is the result of the work of many people who made the code better - Sander Marechal - Radosław Benkel - Gennady Telegin (gtelegin) - - Marcos Sánchez - ttomor - Mei Gwilym (meigwilym) - Michael H. Arieli (excelwebzone) @@ -647,6 +654,7 @@ Symfony is the result of the work of many people who made the code better - Per Sandström (per) - Goran Juric - Laurent Ghirardotti (laurentg) + - Nicolas Macherey - Jan Rosier (rosier) - Lin Clark - Jeremy David (jeremy.david) @@ -695,7 +703,6 @@ Symfony is the result of the work of many people who made the code better - Jochen Bayer (jocl) - Jeremy Bush - wizhippo - - Diego Saint Esteben (dosten) - rpg600 - Péter Buri (burci) - Davide Borsatto (davide.borsatto) @@ -750,7 +757,6 @@ Symfony is the result of the work of many people who made the code better - Jakub Kulhan - Mo Di (modi) - Jeroen van den Enden (stoefke) - - origaminal - Quique Porta (quiqueporta) - Tomasz Szymczyk (karion) - ConneXNL @@ -782,8 +788,10 @@ Symfony is the result of the work of many people who made the code better - Adrien Gallou (agallou) - Karol Sójko (karolsojko) - sl_toto (sl_toto) + - Walter Dal Mut (wdalmut) - Sébastien HOUZÉ - Jingyu Wang + - Daniel Espendiller - steveYeah - Samy Dindane (dinduks) - Keri Henare (kerihenare) @@ -823,10 +831,12 @@ Symfony is the result of the work of many people who made the code better - Tadcka - Beth Binkovitz - Romain Geissler + - Tomaz Ahlin - Benjamin Cremer (bcremer) - Marcus Stöhr (dafish) - Emmanuel Vella (emmanuel.vella) - Carsten Nielsen (phreaknerd) + - Mathieu Rochette - Jay Severson - René Kerner - Nathaniel Catchpole @@ -861,6 +871,7 @@ Symfony is the result of the work of many people who made the code better - Sebastian Ionescu - Thomas Ploch - Simon Neidhold + - Valentin VALCIU - Kevin Dew - James Cowgill - Nicolas Schwartz (nicoschwartz) @@ -911,6 +922,7 @@ Symfony is the result of the work of many people who made the code better - 2manypeople - Wing - Thomas Bibb + - Matt Farmer - catch - Alexandre Segura - Josef Cech @@ -936,11 +948,11 @@ Symfony is the result of the work of many people who made the code better - Manatsawin Hanmongkolchai - Gunther Konig - Maciej Schmidt + - nuncanada - flack - František Bereň - Christoph Nissle (derstoffel) - Ionel Scutelnicu (ionelscutelnicu) - - Johnny Peck (johnnypeck) - Nicolas Tallefourtané (nicolab) - Botond Dani (picur) - Thierry Marianne (thierrymarianne) @@ -1035,6 +1047,7 @@ Symfony is the result of the work of many people who made the code better - Florian Pfitzer (marmelatze) - Martin Mayer (martin) - Grzegorz Łukaszewicz (newicz) + - Veres Lajos - grifx - Robert Campbell - Matt Lehner @@ -1095,11 +1108,11 @@ Symfony is the result of the work of many people who made the code better - Kevin Herrera (kherge) - Luis Ramón López López (lrlopez) - Muriel (metalmumu) - - Michaël Perrin (michael.perrin) - Michael Pohlers (mick_the_big) - Cayetano Soriano Gallego (neoshadybeat) - Pablo Monterde Perez (plebs) - Jimmy Leger (redpanda) + - Pavel Batanov (scaytrase) - Cyrille Jouineau (tuxosaurus) - Yorkie Chadwick (yorkie76) - Yanick Witschi @@ -1123,6 +1136,7 @@ Symfony is the result of the work of many people who made the code better - Ismail Asci (ismailasci) - Simon CONSTANS (kosssi) - Kristof Van Cauwenbergh (kristofvc) + - Tristan Darricau (nicofuma) - Ramon Henrique Ornelas (ramonornela) - Markus S. (staabm) - Till Klampaeckel (till) @@ -1180,6 +1194,7 @@ Symfony is the result of the work of many people who made the code better - Skorney - mieszko4 - Neophy7e + - bokonet - Arrilot - Markus Staab - Pierre-Louis LAUNAY @@ -1190,6 +1205,7 @@ Symfony is the result of the work of many people who made the code better - Abdulkadir N. A. - Yevgen Kovalienia - Sema + - Elan Ruusamäe - Thorsten Hallwas - Michael Squires - Norman Soetbeer @@ -1203,7 +1219,6 @@ Symfony is the result of the work of many people who made the code better - Penny Leach - Richard Trebichavský - g123456789l - - Giorgio Premi - oscartv - DanSync - Peter Zwosta @@ -1261,6 +1276,7 @@ Symfony is the result of the work of many people who made the code better - samuel laulhau (lalop) - Laurent Bachelier (laurentb) - Jérôme Parmentier (lctrs) + - Florent Viel (luxifer) - Matthieu Moquet (mattketmo) - Moritz Borgmann (mborgmann) - Matt Drollette (mdrollette) @@ -1279,6 +1295,7 @@ Symfony is the result of the work of many people who made the code better - Rich Sage (richsage) - Ruud Kamphuis (ruudk) - Bart Ruysseveldt (ruyss) + - Sascha Dens (saschadens) - scourgen hung (scourgen) - Sebastian Busch (sebu) - André Filipe Gonçalves Neves (seven) From 221da6edaf6514eca8efd728c74bf3dbf133a6fd Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 1 Sep 2015 17:40:52 +0200 Subject: [PATCH 0016/2143] updated VERSION for 2.3.32 --- src/Symfony/Component/HttpKernel/Kernel.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index cf3510047df8f..80e1567d2f8b0 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -60,12 +60,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '2.3.32-DEV'; + const VERSION = '2.3.32'; const VERSION_ID = '20332'; const MAJOR_VERSION = '2'; const MINOR_VERSION = '3'; const RELEASE_VERSION = '32'; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = ''; /** * Constructor. From fedbf711a1c76bb2a9ff80e50a07526bedd6a639 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 1 Sep 2015 18:03:57 +0200 Subject: [PATCH 0017/2143] bumped Symfony version to 2.3.33 --- src/Symfony/Component/HttpKernel/Kernel.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 80e1567d2f8b0..5da1e8f716509 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -60,12 +60,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '2.3.32'; - const VERSION_ID = '20332'; + const VERSION = '2.3.33-DEV'; + const VERSION_ID = '20333'; const MAJOR_VERSION = '2'; const MINOR_VERSION = '3'; - const RELEASE_VERSION = '32'; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = '33'; + const EXTRA_VERSION = 'DEV'; /** * Constructor. From 79e29c1f2366caec387bdf4f760f336c87167873 Mon Sep 17 00:00:00 2001 From: Abdellatif Ait boudad Date: Wed, 2 Sep 2015 09:56:25 +0000 Subject: [PATCH 0018/2143] [Translator][fallback catalogues] fixed circular reference. --- .../Translation/MessageCatalogue.php | 7 +++++++ .../Tests/MessageCatalogueTest.php | 20 ++++++++++++++++--- .../Component/Translation/Translator.php | 5 +++-- 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Component/Translation/MessageCatalogue.php b/src/Symfony/Component/Translation/MessageCatalogue.php index aa92a587fbc86..35beb3d94739a 100644 --- a/src/Symfony/Component/Translation/MessageCatalogue.php +++ b/src/Symfony/Component/Translation/MessageCatalogue.php @@ -190,6 +190,13 @@ public function addCatalogue(MessageCatalogueInterface $catalogue) public function addFallbackCatalogue(MessageCatalogueInterface $catalogue) { // detect circular references + $c = $catalogue; + while ($c = $c->getFallbackCatalogue()) { + if ($c->getLocale() === $this->getLocale()) { + throw new \LogicException(sprintf('Circular reference detected when adding a fallback catalogue for locale "%s".', $catalogue->getLocale())); + } + } + $c = $this; do { if ($c->getLocale() === $catalogue->getLocale()) { diff --git a/src/Symfony/Component/Translation/Tests/MessageCatalogueTest.php b/src/Symfony/Component/Translation/Tests/MessageCatalogueTest.php index 7d956553d98c6..6f55b8cc5e8fb 100644 --- a/src/Symfony/Component/Translation/Tests/MessageCatalogueTest.php +++ b/src/Symfony/Compone 8000 nt/Translation/Tests/MessageCatalogueTest.php @@ -127,7 +127,7 @@ public function testAddFallbackCatalogue() /** * @expectedException \LogicException */ - public function testAddFallbackCatalogueWithCircularReference() + public function testAddFallbackCatalogueWithParentCircularReference() { $main = new MessageCatalogue('en_US'); $fallback = new MessageCatalogue('fr_FR'); @@ -136,6 +136,20 @@ public function testAddFallbackCatalogueWithCircularReference() $main->addFallbackCatalogue($fallback); } + /** + * @expectedException \LogicException + */ + public function testAddFallbackCatalogueWithFallbackCircularReference() + { + $fr = new MessageCatalogue('fr'); + $en = new MessageCatalogue('en'); + $es = new MessageCatalogue('es'); + + $fr->addFallbackCatalogue($en); + $es->addFallbackCatalogue($en); + $en->addFallbackCatalogue($fr); + } + /** * @expectedException \LogicException */ @@ -178,10 +192,10 @@ public function testMetadataSetGetDelete() $this->assertEquals(array(), $catalogue->getMetadata('key2', 'messages'), 'Metadata key2 is array'); $catalogue->deleteMetadata('key2', 'messages'); - $this->assertEquals(null, $catalogue->getMetadata('key2', 'messages'), 'Metadata key2 should is deleted.'); + $this->assertNull($catalogue->getMetadata('key2', 'messages'), 'Metadata key2 should is deleted.'); $catalogue->deleteMetadata('key2', 'domain'); - $this->assertEquals(null, $catalogue->getMetadata('key2', 'domain'), 'Metadata key2 should is deleted.'); + $this->assertNull($catalogue->getMetadata('key2', 'domain'), 'Metadata key2 should is deleted.'); } public function testMetadataMerge() diff --git a/src/Symfony/Component/Translation/Translator.php b/src/Symfony/Component/Translation/Translator.php index 88178f8a83f17..38c5acd7616d6 100644 --- a/src/Symfony/Component/Translation/Translator.php +++ b/src/Symfony/Component/Translation/Translator.php @@ -276,8 +276,9 @@ private function loadFallbackCatalogues($locale) $this->doLoadCatalogue($fallback); } - $current->addFallbackCatalogue($this->catalogues[$fallback]); - $current = $this->catalogues[$fallback]; + $fallbackCatalogue = new MessageCatalogue($fallback, $this->catalogues[$fallback]->all()); + $current->addFallbackCatalogue($fallbackCatalogue); + $current = $fallbackCatalogue; } } From 79695037b0f949a1bee5ddfcdd5123c07a00cfad Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 2 Sep 2015 17:00:49 +0200 Subject: [PATCH 0019/2143] [Intl] Fix test --- .../DateFormat/TimeZoneTransformer.php | 2 +- .../Intl/NumberFormatter/NumberFormatter.php | 6 +++--- .../DateFormatter/AbstractIntlDateFormatterTest.php | 13 ++++++++++--- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Component/Intl/DateFormatter/DateFormat/TimeZoneTransformer.php b/src/Symfony/Component/Intl/DateFormatter/DateFormat/TimeZoneTransformer.php index adca3eeb7dcea..6f9c0d5a02bb5 100644 --- a/src/Symfony/Component/Intl/DateFormatter/DateFormat/TimeZoneTransformer.php +++ b/src/Symfony/Component/Intl/DateFormatter/DateFormat/TimeZoneTransformer.php @@ -29,7 +29,7 @@ public function format(\DateTime $dateTime, $length) { $timeZone = substr($dateTime->getTimezone()->getName(), 0, 3); - if (!in_array($timeZone, array('Etc', 'UTC'))) { + if (!in_array($timeZone, array('Etc', 'UTC', 'GMT'))) { throw new NotImplementedException('Time zone different than GMT or UTC is not supported as a formatting output.'); } diff --git a/src/Symfony/Component/Intl/NumberFormatter/NumberFormatter.php b/src/Symfony/Component/Intl/NumberFormatter/NumberFormatter.php index 07c8e84c861bf..0ee222ee50fd6 100644 --- a/src/Symfony/Component/Intl/NumberFormatter/NumberFormatter.php +++ b/src/Symfony/Component/Intl/NumberFormatter/NumberFormatter.php @@ -773,7 +773,7 @@ private function isInitializedAttribute($attr) * @param mixed $value The value to be converted * @param int $type The type to convert. Can be TYPE_DOUBLE (float) or TYPE_INT32 (int) * - * @return int|float The converted value + * @return int|float|false The converted value */ private function convertValueDataType($value, $type) { @@ -793,7 +793,7 @@ private function convertValueDataType($value, $type) * * @param mixed $value The value to be converted * - * @return int The converted value + * @return int|false The converted value */ private function getInt32Value($value) { @@ -809,7 +809,7 @@ private function getInt32Value($value) * * @param mixed $value The value to be converted * - * @return int|float The converted value + * @return int|float|false The converted value * * @see https://bugs.php.net/bug.php?id=59597 Bug #59597 */ diff --git a/src/Symfony/Component/Intl/Tests/DateFormatter/AbstractIntlDateFormatterTest.php b/src/Symfony/Component/Intl/Tests/DateFormatter/AbstractIntlDateFormatterTest.php index 259f5e5d9d5c4..0603394fe1f6d 100644 --- a/src/Symfony/Component/Intl/Tests/DateFormatter/AbstractIntlDateFormatterTest.php +++ b/src/Symfony/Component/Intl/Tests/DateFormatter/AbstractIntlDateFormatterTest.php @@ -392,14 +392,21 @@ public function testFormatWithConstructorTimezone() ); } - public function testFormatWithDateTimeZone() + public function testFormatWithDateTimeZoneGmt() { if (PHP_VERSION_ID < 50500) { $this->markTestSkipped('Only in PHP 5.5+ IntlDateFormatter allows to use DateTimeZone objects.'); } - if (defined('HHVM_VERSION_ID')) { - $this->markTestSkipped('This test cannot work on HHVM. See https://github.com/facebook/hhvm/issues/5875 for the issue.'); + $formatter = $this->getDateFormatter('en', IntlDateFormatter::MEDIUM, IntlDateFormatter::SHORT, new \DateTimeZone('GMT'), IntlDateFormatter::GREGORIAN, 'zzzz'); + + $this->assertEquals('GMT', $formatter->format(0)); + } + + public function testFormatWithDateTimeZoneGmtOffset() + { + if (defined('HHVM_VERSION_ID') || PHP_VERSION_ID <= 50509) { + $this->markTestSkipped('DateTimeZone GMT offsets are supported since 5.5.10. See https://github.com/facebook/hhvm/issues/5875 for HHVM.'); } $formatter = $this->getDateFormatter('en', IntlDateFormatter::MEDIUM, IntlDateFormatter::SHORT, new \DateTimeZone('GMT+03:00'), IntlDateFormatter::GREGORIAN, 'zzzz'); From 232f6fd534956bf9738489691ad1d2070adbc4c5 Mon Sep 17 00:00:00 2001 From: Michael Lee Date: Thu, 3 Sep 2015 15:05:21 +0800 Subject: [PATCH 0020/2143] [framework-bundle] Add Test for TranslationUpdateCommand Added the test script as per the discussion in PR #15562 | Q | A | ------------- | --- | Bug fix? | no | New feature? | no | BC breaks? | no | Deprecations? | yes | Tests pass? | yes | Fixed tickets | n/a | License | MIT | Doc PR | n/a --- .../Command/TranslationUpdateCommandTest.php | 141 ++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationUpdateCommandTest.php diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationUpdateCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationUpdateCommandTest.php new file mode 100644 index 0000000000000..a04a0cccad77c --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationUpdateCommandTest.php @@ -0,0 +1,141 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Tests\Command; + +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Tester\CommandTester; +use Symfony\Bundle\FrameworkBundle\Command\TranslationUpdateCommand; +use Symfony\Component\Filesystem\Filesystem; +use Symfony\Component\DependencyInjection; +use Symfony\Component\HttpKernel; + +class TranslationUpdateCommandTest extends \PHPUnit_Framework_TestCase +{ + private $fs; + private $translationDir; + + public function testDumpMessagesAndClean() + { + $tester = $this->createCommandTester($this->getContainer(array('foo' => 'foo'))); + $tester->execute(array('command' => 'translation:update', 'locale' => 'en', 'bundle' => 'foo', '--dump-messages' => true, '--clean' => true)); + $this->assertRegExp('/foo/', $tester->getDisplay()); + } + + protected function setUp() + { + $this->fs = new Filesystem(); + $this->translationDir = sys_get_temp_dir().'/'.uniqid('sf2_translation', true); + $this->fs->mkdir($this->translationDir.'/Resources/translations'); + $this->fs->mkdir($this->translationDir.'/Resources/views'); + } + + protected function tearDown() + { + $this->fs->remove($this->translationDir); + } + + /** + * @return CommandTester + */ + private function createCommandTester(DependencyInjection\ContainerInterface $container) + { + $command = new TranslationUpdateCommand(); + $command->setContainer($container); + + $application = new Application(); + $application->add($command); + + return new CommandTester($application->find('translation:update')); + } + + private function getContainer($extractedMessages = array(), $loadedMessages = array(), HttpKernel\KernelInterface $kernel = null) + { + $translator = $this->getMockBuilder('Symfony\Component\Translation\Translator') + ->disableOriginalConstructor() + ->getMock(); + + $translator + ->expects($this->any()) + ->method('getFallbackLocales') + ->will($this->returnValue(array('en'))); + + $extractor = $this->getMock('Symfony\Component\Translation\Extractor\ExtractorInterface'); + $extractor + ->expects($this->any()) + ->method('extract') + ->will( + $this->returnCallback(function ($path, $catalogue) use ($extractedMessages) { + $catalogue->add($extractedMessages); + }) + ); + + $loader = $this->getMock('Symfony\Bundle\FrameworkBundle\Translation\TranslationLoader'); + $loader + ->expects($this->any()) + ->method('loadMessages') + ->will( + $this->returnCallback(function ($path, $catalogue) use ($loadedMessages) { + $catalogue->add($loadedMessages); + }) + ); + + $writer = $this->getMock('Symfony\Component\Translation\Writer\TranslationWriter'); + $writer + ->expects($this->any()) + ->method('getFormats') + ->will( + $this->returnValue(array('xlf', 'yml')) + ); + + if (null === $kernel) { + $kernel = $this->getMock('Symfony\Component\HttpKernel\KernelInterface'); + $kernel + ->expects($this->any()) + ->method('getBundle') + ->will($this->returnValueMap(array( + array('foo', true, $this->getBundle($this->translationDir)), + array('test', true, $this->getBundle('test')), + ))); + } + + $kernel + ->expects($this->any()) + ->method('getRootDir') + ->will($this->returnValue($this->translationDir)); + + $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface'); + $container + ->expects($this->any()) + ->method('get') + ->will($this->returnValueMap(array( + array('translation.extractor', 1, $extractor), + array('translation.loader', 1, $loader), + array('translation.writer', 1, $writer), + array('translator', 1, $translator), + array('kernel', 1, $kernel), + ))); + + return $container; + } + + private function getBundle($path) + { + $bundle = $this->getMock('Symfony\Component\HttpKernel\Bundle\BundleInterface'); + $bundle + ->expects($this->any()) + ->method('getPath') + ->will($this->returnValue($path)) + ; + + return $bundle; + } +} From 57232ef44f5a9d0ecf6dbcf77a705332517bf85d Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 3 Sep 2015 13:24:41 +0200 Subject: [PATCH 0021/2143] [travis] Add PHP 7 to allowed failures until segfaults are fixed --- .travis.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7cc691c2b66a6..e959db0cecd0d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,9 +14,12 @@ matrix: - php: 5.4 - php: 5.5 - php: 5.6 - env: deps=low - - php: 7.0 env: deps=high + - php: 7 + - php: 5.6 + env: deps=low + allow_failures: + - php: 7 fast_finish: true services: mongodb From 12ec734845cb8e07afe2fb18e27110e1cf2261d9 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 3 Sep 2015 14:38:39 +0200 Subject: [PATCH 0022/2143] [Validator] Cleanup a test --- .../Tests/Constraints/NotIdenticalToValidatorTest.php | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/Symfony/Component/Validator/Tests/Constraints/NotIdenticalToValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/NotIdenticalToValidatorTest.php index 1fbd80663fadd..43149847b9c5a 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/NotIdenticalToValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/NotIdenticalToValidatorTest.php @@ -82,11 +82,6 @@ public function provideInvalidComparisons() array($object, '2', $object, '2', __NAMESPACE__.'\ComparisonTest_Class'), ); - if (version_compare(PHP_VERSION, '>=', '5.5')) { - $immutableDate = new \DateTimeImmutable('2000-01-01'); - $comparisons[] = array($immutableDate, 'Jan 1, 2000, 12:00 AM', $immutableDate, 'Jan 1, 2000, 12:00 AM', 'DateTime'); - } - return $comparisons; } } From fa7fe568300fc1a0ffe87db32fb482756d9c6c1c Mon Sep 17 00:00:00 2001 From: JakeFr Date: Thu, 3 Sep 2015 22:53:16 +0200 Subject: [PATCH 0023/2143] use new repo location in some readme.md --- src/Symfony/Component/BrowserKit/README.md | 2 +- src/Symfony/Component/Form/README.md | 2 +- src/Symfony/Component/Translation/README.md | 2 +- src/Symfony/Component/Validator/README.md | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/BrowserKit/README.md b/src/Symfony/Component/BrowserKit/README.md index 3c0ee3a040998..d638329978a5c 100644 --- a/src/Symfony/Component/BrowserKit/README.md +++ b/src/Symfony/Component/BrowserKit/README.md @@ -10,7 +10,7 @@ Resources --------- For a simple implementation of a browser based on an HTTP layer, have a look -at [Goutte](https://github.com/fabpot/Goutte). +at [Goutte](https://github.com/FriendsOfPHP/Goutte). For an implementation based on HttpKernelInterface, have a look at the [Client](https://github.com/symfony/symfony/blob/master/src/Symfony/Component/HttpKernel/Client.php) diff --git a/src/Symfony/Component/Form/README.md b/src/Symfony/Component/Form/README.md index 8f34c7a419932..a2f24777af60b 100644 --- a/src/Symfony/Component/Form/README.md +++ b/src/Symfony/Component/Form/README.md @@ -10,7 +10,7 @@ Resources Silex integration: -https://github.com/fabpot/Silex/blob/master/src/Silex/Provider/FormServiceProvider.php +https://github.com/silexphp/Silex/blob/master/src/Silex/Provider/FormServiceProvider.php Documentation: diff --git a/src/Symfony/Component/Translation/README.md b/src/Symfony/Component/Translation/README.md index 9d904357b28f9..9a9dd80a54c77 100644 --- a/src/Symfony/Component/Translation/README.md +++ b/src/Symfony/Component/Translation/README.md @@ -24,7 +24,7 @@ Resources Silex integration: -https://github.com/fabpot/Silex/blob/master/src/Silex/Provider/TranslationServiceProvider.php +https://github.com/silexphp/Silex/blob/master/src/Silex/Provider/TranslationServiceProvider.php Documentation: diff --git a/src/Symfony/Component/Validator/README.md b/src/Symfony/Component/Validator/README.md index efe1c79a4a877..a1e59c7939712 100644 --- a/src/Symfony/Component/Validator/README.md +++ b/src/Symfony/Component/Validator/README.md @@ -109,7 +109,7 @@ Resources Silex integration: -https://github.com/fabpot/Silex/blob/master/src/Silex/Provider/ValidatorServiceProvider.php +https://github.com/silexphp/Silex/blob/master/src/Silex/Provider/ValidatorServiceProvider.php Documentation: From e49739c469a6cd693c0732f4894d1a804c84e116 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 3 Sep 2015 14:33:45 +0200 Subject: [PATCH 0024/2143] [2.7] Clean deprecated interfaces --- .../ChoiceList/ORMQueryBuilderLoaderTest.php | 1 + .../Form/Type/EntityTypePerformanceTest.php | 6 ++--- .../Factory/CachingFactoryDecorator.php | 4 +-- .../Factory/DefaultChoiceListFactory.php | 6 ++++- .../Factory/PropertyAccessDecorator.php | 4 +-- .../Form/Extension/Core/Type/ChoiceType.php | 2 +- .../Factory/CachingFactoryDecoratorTest.php | 17 ++++++++++++ .../Factory/DefaultChoiceListFactoryTest.php | 27 +++++++++++++++++++ .../Factory/PropertyAccessDecoratorTest.php | 3 +++ .../LegacyChoiceListAdapterTest.php | 1 + .../Extension/Core/Type/ChoiceTypeTest.php | 1 + .../Extension/Core/Type/DateTimeTypeTest.php | 3 +++ .../Extension/Core/Type/DateTypeTest.php | 3 +++ .../Extension/Core/Type/TimeTypeTest.php | 3 +++ .../Validator/ValidatorExtensionTest.php | 4 +++ .../ConstraintViolationInterface.php | 4 +++ .../Constraints/CallbackValidator.php | 5 +++- .../Constraints/CallbackValidatorTest.php | 4 +-- .../Tests/Validator/Abstract2Dot5ApiTest.php | 2 ++ .../Tests/Validator/AbstractLegacyApiTest.php | 1 + 20 files changed, 89 insertions(+), 12 deletions(-) diff --git a/src/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/ORMQueryBuilderLoaderTest.php b/src/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/ORMQueryBuilderLoaderTest.php index 8fec7584e41c3..5af59445e1825 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/ORMQueryBuilderLoaderTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/ORMQueryBuilderLoaderTest.php @@ -19,6 +19,7 @@ class ORMQueryBuilderLoaderTest extends \PHPUnit_Framework_TestCase { /** * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException + * @group legacy */ public function testItOnlyWorksWithQueryBuilderOrClosure() { diff --git a/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypePerformanceTest.php b/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypePerformanceTest.php index 1269812bbf151..57df4195bcec4 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypePerformanceTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypePerformanceTest.php @@ -90,7 +90,7 @@ public function testCollapsedEntityField() $this->setMaxRunningTime(1); for ($i = 0; $i < 40; ++$i) { - $form = $this->factory->create('entity', null, array( + $form = $this->factory->create('Symfony\Bridge\Doctrine\Form\Type\EntityType', null, array( 'class' => self::ENTITY_CLASS, )); @@ -108,7 +108,7 @@ public function testCollapsedEntityFieldWithChoices() $this->setMaxRunningTime(1); for ($i = 0; $i < 40; ++$i) { - $form = $this->factory->create('entity', null, array( + $form = $this->factory->create('Symfony\Bridge\Doctrine\Form\Type\EntityType', null, array( 'class' => self::ENTITY_CLASS, 'choices' => $choices, )); @@ -127,7 +127,7 @@ public function testCollapsedEntityFieldWithPreferredChoices() $this->setMaxRunningTime(1); for ($i = 0; $i < 40; ++$i) { - $form = $this->factory->create('entity', null, array( + $form = $this->factory->create('Symfony\Bridge\Doctrine\Form\Type\EntityType', null, array( 'class' => self::ENTITY_CLASS, 'preferred_choices' => $choices, )); diff --git a/src/Symfony/Component/Form/ChoiceList/Factory/CachingFactoryDecorator.php b/src/Symfony/Component/Form/ChoiceList/Factory/CachingFactoryDecorator.php index 0692781f40ee4..ae7f2375bb896 100644 --- a/src/Symfony/Component/Form/ChoiceList/Factory/CachingFactoryDecorator.php +++ b/src/Symfony/Component/Form/ChoiceList/Factory/CachingFactoryDecorator.php @@ -141,7 +141,7 @@ public function createListFromChoices($choices, $value = null) * @deprecated Added for backwards compatibility in Symfony 2.7, to be * removed in Symfony 3.0. */ - public function createListFromFlippedChoices($choices, $value = null) + public function createListFromFlippedChoices($choices, $value = null, $triggerDeprecationNotice = true) { if ($choices instanceof \Traversable) { $choices = iterator_to_array($choices); @@ -158,7 +158,7 @@ public function createListFromFlippedChoices($choices, $value = null) $hash = self::generateHash(array($flatChoices, $value), 'fromFlippedChoices'); if (!isset($this->lists[$hash])) { - $this->lists[$hash] = $this->decoratedFactory->createListFromFlippedChoices($choices, $value); + $this->lists[$hash] = $this->decoratedFactory->createListFromFlippedChoices($choices, $value, $triggerDeprecationNotice); } return $this->lists[$hash]; diff --git a/src/Symfony/Component/Form/ChoiceList/Factory/DefaultChoiceListFactory.php b/src/Symfony/Component/Form/ChoiceList/Factory/DefaultChoiceListFactory.php index b227180100d7b..ef93ffdd76336 100644 --- a/src/Symfony/Component/Form/ChoiceList/Factory/DefaultChoiceListFactory.php +++ b/src/Symfony/Component/Form/ChoiceList/Factory/DefaultChoiceListFactory.php @@ -43,8 +43,12 @@ public function createListFromChoices($choices, $value = null) * @deprecated Added for backwards compatibility in Symfony 2.7, to be * removed in Symfony 3.0. */ - public function createListFromFlippedChoices($choices, $value = null) + public function createListFromFlippedChoices($choices, $value = null, $triggerDeprecationNotice = true) { + if ($triggerDeprecationNotice) { + @trigger_error('The '.__METHOD__.' is deprecated since version 2.7 and will be removed in 3.0.', E_USER_DEPRECATED); + } + return new ArrayKeyChoiceList($choices, $value); } diff --git a/src/Symfony/Component/Form/ChoiceList/Factory/PropertyAccessDecorator.php b/src/Symfony/Component/Form/ChoiceList/Factory/PropertyAccessDecorator.php index 87a364a5f4d55..1b68fd8924284 100644 --- a/src/Symfony/Component/Form/ChoiceList/Factory/PropertyAccessDecorator.php +++ b/src/Symfony/Component/Form/ChoiceList/Factory/PropertyAccessDecorator.php @@ -116,11 +116,11 @@ public function createListFromChoices($choices, $value = null) * @deprecated Added for backwards compatibility in Symfony 2.7, to be * removed in Symfony 3.0. */ - public function createListFromFlippedChoices($choices, $value = null) + public function createListFromFlippedChoices($choices, $value = null, $triggerDeprecationNotice = true) { // Property paths are not supported here, because array keys can never // be objects - return $this->decoratedFactory->createListFromFlippedChoices($choices, $value); + return $this->decoratedFactory->createListFromFlippedChoices($choices, $value, $triggerDeprecationNotice); } /** diff --git a/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php b/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php index 386f27dbc91a0..5102efb55c9ed 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php @@ -280,7 +280,7 @@ public function configureOptions(OptionsResolver $resolver) // BC when choices are in the keys, not in the values if (!$options['choices_as_values']) { - return $choiceListFactory->createListFromFlippedChoices($choices, $options['choice_value']); + return $choiceListFactory->createListFromFlippedChoices($choices, $options['choice_value'], false); } return $choiceListFactory->createListFromChoices($choices, $options['choice_value']); diff --git a/src/Symfony/Component/Form/Tests/ChoiceList/Factory/CachingFactoryDecoratorTest.php b/src/Symfony/Component/Form/Tests/ChoiceList/Factory/CachingFactoryDecoratorTest.php index 9855c4a708d67..d3d530afb58f8 100644 --- a/src/Symfony/Component/Form/Tests/ChoiceList/Factory/CachingFactoryDecoratorTest.php +++ b/src/Symfony/Component/Form/Tests/ChoiceList/Factory/CachingFactoryDecoratorTest.php @@ -155,6 +155,9 @@ public function testCreateFromChoicesDifferentValueClosure() $this->assertSame($list2, $this->factory->createListFromChoices($choices, $closure2)); } + /** + * @group legacy + */ public function testCreateFromFlippedChoicesEmpty() { $list = new \stdClass(); @@ -168,6 +171,9 @@ public function testCreateFromFlippedChoicesEmpty() $this->assertSame($list, $this->factory->createListFromFlippedChoices(array())); } + /** + * @group legacy + */ public function testCreateFromFlippedChoicesComparesTraversableChoicesAsArray() { // The top-most traversable is converted to an array @@ -184,6 +190,9 @@ public function testCreateFromFlippedChoicesComparesTraversableChoicesAsArray() $this->assertSame($list, $this->factory->createListFromFlippedChoices($choices2)); } + /** + * @group legacy + */ public function testCreateFromFlippedChoicesFlattensChoices() { $choices1 = array('key' => array('a' => 'A')); @@ -201,6 +210,7 @@ public function testCreateFromFlippedChoicesFlattensChoices() /** * @dataProvider provideSameKeyChoices + * @group legacy */ public function testCreateFromFlippedChoicesSameChoices($choice1, $choice2) { @@ -219,6 +229,7 @@ public function testCreateFromFlippedChoicesSameChoices($choice1, $choice2) /** * @dataProvider provideDistinguishedKeyChoices + * @group legacy */ public function testCreateFromFlippedChoicesDifferentChoices($choice1, $choice2) { @@ -240,6 +251,9 @@ public function testCreateFromFlippedChoicesDifferentChoices($choice1, $choice2) $this->assertSame($list2, $this->factory->createListFromFlippedChoices($choices2)); } + /** + * @group legacy + */ public function testCreateFromFlippedChoicesSameValueClosure() { $choices = array(1); @@ -255,6 +269,9 @@ public function testCreateFromFlippedChoicesSameValueClosure() $this->assertSame($list, $this->factory->createListFromFlippedChoices($choices, $closure)); } + /** + * @group legacy + */ public function testCreateFromFlippedChoicesDifferentValueClosure() { $choices = array(1); diff --git a/src/Symfony/Component/Form/Tests/ChoiceList/Factory/DefaultChoiceListFactoryTest.php b/src/Symfony/Component/Form/Tests/ChoiceList/Factory/DefaultChoiceListFactoryTest.php index 9210bc3d70ede..741cde5b43921 100644 --- a/src/Symfony/Component/Form/Tests/ChoiceList/Factory/DefaultChoiceListFactoryTest.php +++ b/src/Symfony/Component/Form/Tests/ChoiceList/Factory/DefaultChoiceListFactoryTest.php @@ -193,6 +193,9 @@ function ($object) { return $object->value; } $this->assertObjectListWithCustomValues($list); } + /** + * @group legacy + */ public function testCreateFromFlippedChoicesEmpty() { $list = $this->factory->createListFromFlippedChoices(array()); @@ -201,6 +204,9 @@ public function testCreateFromFlippedChoicesEmpty() $this->assertSame(array(), $list->getValues()); } + /** + * @group legacy + */ public function testCreateFromFlippedChoicesFlat() { $list = $this->factory->createListFromFlippedChoices( @@ -210,6 +216,9 @@ public function testCreateFromFlippedChoicesFlat() $this->assertScalarListWithChoiceValues($list); } + /** + * @group legacy + */ public function testCreateFromFlippedChoicesFlatTraversable() { $list = $this->factory->createListFromFlippedChoices( @@ -219,6 +228,9 @@ public function testCreateFromFlippedChoicesFlatTraversable() $this->assertScalarListWithChoiceValues($list); } + /** + * @group legacy + */ public function testCreateFromFlippedChoicesFlatValuesAsCallable() { $list = $this->factory->createListFromFlippedChoices( @@ -229,6 +241,9 @@ public function testCreateFromFlippedChoicesFlatValuesAsCallable() $this->assertScalarListWithCustomValues($list); } + /** + * @group legacy + */ public function testCreateFromFlippedChoicesFlatValuesAsClosure() { $list = $this->factory->createListFromFlippedChoices( @@ -246,6 +261,9 @@ function ($choice) { $this->assertScalarListWithCustomValues($list); } + /** + * @group legacy + */ public function testCreateFromFlippedChoicesGrouped() { $list = $this->factory->createListFromFlippedChoices( @@ -258,6 +276,9 @@ public function testCreateFromFlippedChoicesGrouped() $this->assertScalarListWithChoiceValues($list); } + /** + * @group legacy + */ public function testCreateFromFlippedChoicesGroupedTraversable() { $list = $this->factory->createListFromFlippedChoices( @@ -270,6 +291,9 @@ public function testCreateFromFlippedChoicesGroupedTraversable() $this->assertScalarListWithChoiceValues($list); } + /** + * @group legacy + */ public function testCreateFromFlippedChoicesGroupedValuesAsCallable() { $list = $this->factory->createListFromFlippedChoices( @@ -283,6 +307,9 @@ public function testCreateFromFlippedChoicesGroupedValuesAsCallable() $this->assertScalarListWithCustomValues($list); } + /** + * @group legacy + */ public function testCreateFromFlippedChoicesGroupedValuesAsClosure() { $list = $this->factory->createListFromFlippedChoices( diff --git a/src/Symfony/Component/Form/Tests/ChoiceList/Factory/PropertyAccessDecoratorTest.php b/src/Symfony/Component/Form/Tests/ChoiceList/Factory/PropertyAccessDecoratorTest.php index 311db477b1993..44490a686a83d 100644 --- a/src/Symfony/Component/Form/Tests/ChoiceList/Factory/PropertyAccessDecoratorTest.php +++ b/src/Symfony/Component/Form/Tests/ChoiceList/Factory/PropertyAccessDecoratorTest.php @@ -63,6 +63,9 @@ public function testCreateFromChoicesPropertyPathInstance() $this->assertSame(array('value'), $this->factory->createListFromChoices($choices, new PropertyPath('property'))); } + /** + * @group legacy + */ public function testCreateFromFlippedChoices() { // Property paths are not supported here, because array keys can never diff --git a/src/Symfony/Component/Form/Tests/ChoiceList/LegacyChoiceListAdapterTest.php b/src/Symfony/Component/Form/Tests/ChoiceList/LegacyChoiceListAdapterTest.php index 521c950331054..911d8c001e054 100644 --- a/src/Symfony/Component/Form/Tests/ChoiceList/LegacyChoiceListAdapterTest.php +++ b/src/Symfony/Component/Form/Tests/ChoiceList/LegacyChoiceListAdapterTest.php @@ -16,6 +16,7 @@ /** * @author Bernhard Schussek + * @group legacy */ class LegacyChoiceListAdapterTest extends \PHPUnit 8000 _Framework_TestCase { diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php index 61c20c2f67287..215ddac936a54 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php @@ -1529,6 +1529,7 @@ public function testPassPlaceholderToView($multiple, $expanded, $required, $plac /** * @dataProvider getOptionsWithPlaceholder + * @group legacy */ public function testPassEmptyValueBC($multiple, $expanded, $required, $placeholder, $viewValue) { diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTimeTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTimeTypeTest.php index 34889ed321cd9..de12bb1e44a66 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTimeTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTimeTypeTest.php @@ -328,6 +328,9 @@ public function testPassPlaceholderAsString() $this->assertSame('Empty', $view['time']['second']->vars['placeholder']); } + /** + * @group legacy + */ public function testPassEmptyValueBC() { $form = $this->factory->create('datetime', null, array( diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTypeTest.php index f690917cd7acb..5cb542993924a 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTypeTest.php @@ -759,6 +759,9 @@ public function testPassPlaceholderAsString() $this->assertSame('Empty', $view['day']->vars['placeholder']); } + /** + * @group legacy + */ public function testPassEmptyValueBC() { $form = $this->factory->create('date', null, array( diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/TimeTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/TimeTypeTest.php index e0faf4c179e28..520f9f22ef112 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/TimeTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/TimeTypeTest.php @@ -562,6 +562,9 @@ public function testPassPlaceholderAsString() $this->assertSame('Empty', $view['second']->vars['placeholder']); } + /** + * @group legacy + */ public function testPassEmptyValueBC() { $form = $this->factory->create('time', null, array( diff --git a/src/Symfony/Component/Form/Tests/Extension/Validator/ValidatorExtensionTest.php b/src/Symfony/Component/Form/Tests/Extension/Validator/ValidatorExtensionTest.php index ee822316ade37..a4dcc1532a86f 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Validator/ValidatorExtensionTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Validator/ValidatorExtensionTest.php @@ -48,6 +48,9 @@ public function test2Dot5ValidationApi() $this->assertInstanceOf('Symfony\Component\Form\Extension\Validator\ValidatorTypeGuesser', $guesser); } + /** + * @group legacy + */ public function test2Dot4ValidationApi() { $factory = $this->getMock('Symfony\Component\Validator\MetadataFactoryInterface'); @@ -82,6 +85,7 @@ public function test2Dot4ValidationApi() /** * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException + * @group legacy */ public function testInvalidValidatorInterface() { diff --git a/src/Symfony/Component/Validator/ConstraintViolationInterface.php b/src/Symfony/Component/Validator/ConstraintViolationInterface.php index 232fb5513f768..9baee2f37c625 100644 --- a/src/Symfony/Component/Validator/ConstraintViolationInterface.php +++ b/src/Symfony/Component/Validator/ConstraintViolationInterface.php @@ -68,6 +68,8 @@ public function getMessageTemplate(); * @see getMessageTemplate() * * @api + * + * @deprecated since version 2.7, to be replaced by getParameters() in 3.0. */ public function getMessageParameters(); @@ -86,6 +88,8 @@ public function getMessageParameters(); * pluralization form (in this case "choices"). * * @return int|null The number to use to pluralize of the message. + * + * @deprecated since version 2.7, to be replaced by getPlural() in 3.0. */ public function getMessagePluralization(); diff --git a/src/Symfony/Component/Validator/Constraints/CallbackValidator.php b/src/Symfony/Component/Validator/Constraints/CallbackValidator.php index eaf2f3c0114c2..a75e6d2f66dfb 100644 --- a/src/Symfony/Component/Validator/Constraints/CallbackValidator.php +++ b/src/Symfony/Component/Validator/Constraints/CallbackValidator.php @@ -54,7 +54,10 @@ public function validate($object, Constraint $constraint) $method($object, $this->context); } elseif (is_array($method)) { if (!is_callable($method)) { - throw new ConstraintDefinitionException(sprintf('"%s::%s" targeted by Callback constraint is not a valid callable', $method[0], $method[1])); + if (isset($method[0]) && is_object($method[0])) { + $method[0] = get_class($method[0]); + } + throw new ConstraintDefinitionException(sprintf('%s targeted by Callback constraint is not a valid callable', json_encode($method))); } call_user_func($method, $object, $this->context); diff --git a/src/Symfony/Component/Validator/Tests/Constraints/CallbackValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/CallbackValidatorTest.php index b619291665e9d..5ad8276563344 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/CallbackValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/CallbackValidatorTest.php @@ -298,7 +298,7 @@ public function testExpectValidMethods() { $object = new CallbackValidatorTest_Object(); - $this->validator->validate($object, new Callback(array('foobar'))); + $this->validator->validate($object, new Callback(array('callback' => array('foobar')))); } /** @@ -308,7 +308,7 @@ public function testExpectValidCallbacks() { $object = new CallbackValidatorTest_Object(); - $this->validator->validate($object, new Callback(array(array('foo', 'bar')))); + $this->validator->validate($object, new Callback(array('callback' => array('foo', 'bar')))); } /** diff --git a/src/Symfony/Component/Validator/Tests/Validator/Abstract2Dot5ApiTest.php b/src/Symfony/Component/Validator/Tests/Validator/Abstract2Dot5ApiTest.php index a2da68f9f1d30..6995d25817988 100644 --- a/src/Symfony/Component/Validator/Tests/Validator/Abstract2Dot5ApiTest.php +++ b/src/Symfony/Component/Validator/Tests/Validator/Abstract2Dot5ApiTest.php @@ -544,6 +544,7 @@ public function testAddCustomizedViolation() /** * @expectedException \Symfony\Component\Validator\Exception\UnsupportedMetadataException + * @group legacy */ public function testMetadataMustImplementClassMetadataInterface() { @@ -561,6 +562,7 @@ public function testMetadataMustImplementClassMetadataInterface() /** * @expectedException \Symfony\Component\Validator\Exception\UnsupportedMetadataException + * @group legacy */ public function testReferenceMetadataMustImplementClassMetadataInterface() { diff --git a/src/Symfony/Component/Validator/Tests/Validator/AbstractLegacyApiTest.php b/src/Symfony/Component/Validator/Tests/Validator/AbstractLegacyApiTest.php index 22af86e3deb32..d78b67bee7e9a 100644 --- a/src/Symfony/Component/Validator/Tests/Validator/AbstractLegacyApiTest.php +++ b/src/Symfony/Component/Validator/Tests/Validator/AbstractLegacyApiTest.php @@ -26,6 +26,7 @@ * @since 2.5 * * @author Bernhard Schussek + * @group legacy */ abstract class AbstractLegacyApiTest extends AbstractValidatorTest { From 4114a2bd3ef6ef69df40243f5ee82034c0bd2c51 Mon Sep 17 00:00:00 2001 From: Anton Bakai Date: Fri, 14 Aug 2015 15:56:24 +0300 Subject: [PATCH 0025/2143] [ExpressionLanguage] Fixed expressions cache key generation --- .../ExpressionLanguage/ExpressionLanguage.php | 9 ++++- .../Tests/ExpressionLanguageTest.php | 34 +++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/ExpressionLanguage/ExpressionLanguage.php b/src/Symfony/Component/ExpressionLanguage/ExpressionLanguage.php index 42ed9eb1d0e6a..fb3faf79a5484 100644 --- a/src/Symfony/Component/ExpressionLanguage/ExpressionLanguage.php +++ b/src/Symfony/Component/ExpressionLanguage/ExpressionLanguage.php @@ -84,7 +84,14 @@ public function parse($expression, $names) return $expression; } - $key = $expression.'//'.implode('-', $names); + asort($names); + $cacheKeyItems = array(); + + foreach ($names as $nameKey => $name) { + $cacheKeyItems[] = is_int($nameKey) ? $name : $nameKey.':'.$name; + } + + $key = $expression.'//'.implode('|', $cacheKeyItems); if (null === $parsedExpression = $this->cache->fetch($key)) { $nodes = $this->getParser()->parse($this->getLexer()->tokenize((string) $expression), $names); diff --git a/src/Symfony/Component/ExpressionLanguage/Tests/ExpressionLanguageTest.php b/src/Symfony/Component/ExpressionLanguage/Tests/ExpressionLanguageTest.php index 15a0ea648d4b9..5af0c4a8e803f 100644 --- a/src/Symfony/Component/ExpressionLanguage/Tests/ExpressionLanguageTest.php +++ b/src/Symfony/Component/ExpressionLanguage/Tests/ExpressionLanguageTest.php @@ -104,4 +104,38 @@ public function shortCircuitProviderCompile() array('true or foo', array('foo' => 'foo'), true), ); } + + public function testCachingForOverriddenVariableNames() + { + $expressionLanguage = new ExpressionLanguage(); + $expression = 'a + b'; + $expressionLanguage->evaluate($expression, array('a' => 1, 'b' => 1)); + $result = $expressionLanguage->compile($expression, array('a', 'B' => 'b')); + $this->assertSame('($a + $B)', $result); + } + + public function testCachingWithDifferentNamesOrder() + { + $cacheMock = $this->getMock('Symfony\Component\ExpressionLanguage\ParserCache\ParserCacheInterface'); + $expressionLanguage = new ExpressionLanguage($cacheMock); + $savedParsedExpressions = array(); + $cacheMock + ->expects($this->exactly(2)) + ->method('fetch') + ->will($this->returnCallback(function ($key) use (&$savedParsedExpressions) { + return isset($savedParsedExpressions[$key]) ? $savedParsedExpressions[$key] : null; + })) + ; + $cacheMock + ->expects($this->exactly(1)) + ->method('save') + ->will($this->returnCallback(function ($key, $expression) use (&$savedParsedExpressions) { + $savedParsedExpressions[$key] = $expression; + })) + ; + + $expression = 'a + b'; + $expressionLanguage->compile($expression, array('a', 'B' => 'b')); + $expressionLanguage->compile($expression, array('B' => 'b', 'a')); + } } From 78023458244e6cee5c8062f8fa39170333a091f8 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Tue, 8 Sep 2015 10:52:13 +0100 Subject: [PATCH 0026/2143] Dispatch console.terminate *after* console.exception --- src/Symfony/Component/Console/Application.php | 10 ++++++---- .../Component/Console/Tests/ApplicationTest.php | 8 ++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/Symfony/Component/Console/Application.php b/src/Symfony/Component/Console/Application.php index 0d6659820497c..3989b0ec83648 100644 --- a/src/Symfony/Component/Console/Application.php +++ b/src/Symfony/Component/Console/Application.php @@ -899,13 +899,15 @@ protected function doRunCommand(Command $command, InputInterface $input, OutputI try { $exitCode = $command->run($input, $output); } catch (\Exception $e) { + $event = new ConsoleExceptionEvent($command, $input, $output, $e, $e->getCode()); + $this->dispatcher->dispatch(ConsoleEvents::EXCEPTION, $event); + + $e = $event->getException(); + $event = new ConsoleTerminateEvent($command, $input, $output, $e->getCode()); $this->dispatcher->dispatch(ConsoleEvents::TERMINATE, $event); - $event = new ConsoleExceptionEvent($command, $input, $output, $e, $event->getExitCode()); - $this->dispatcher->dispatch(ConsoleEvents::EXCEPTION, $event); - - throw $event->getException(); + throw $e; } $event = new ConsoleTerminateEvent($command, $input, $output, $exitCode); diff --git a/src/Symfony/Component/Console/Tests/ApplicationTest.php b/src/Symfony/Component/Console/Tests/ApplicationTest.php index c7798bf2c5573..713f8647153e1 100644 --- a/src/Symfony/Component/Console/Tests/ApplicationTest.php +++ b/src/Symfony/Component/Console/Tests/ApplicationTest.php @@ -799,7 +799,7 @@ public function testRunWithDispatcher() $tester = new ApplicationTester($application); $tester->run(array('command' => 'foo')); - $this->assertEquals('before.foo.after.', $tester->getDisplay()); + $this->assertEquals('before.foo.after.'.PHP_EOL, $tester->getDisplay()); } /** @@ -835,7 +835,7 @@ public function testRunDispatchesAllEventsWithException() $tester = new ApplicationTester($application); $tester->run(array('command' => 'foo')); - $this->assertContains('before.foo.after.caught.', $tester->getDisplay()); + $this->assertContains('before.foo.caught.after.', $tester->getDisplay()); } protected function getDispatcher() @@ -845,12 +845,12 @@ protected function getDispatcher() $event->getOutput()->write('before.'); }); $dispatcher->addListener('console.terminate', function (ConsoleTerminateEvent $event) { - $event->getOutput()->write('after.'); + $event->getOutput()->writeln('after.'); $event->setExitCode(128); }); $dispatcher->addListener('console.exception', function (ConsoleExceptionEvent $event) { - $event->getOutput()->writeln('caught.'); + $event->getOutput()->write('caught.'); $event->setException(new \LogicException('caught.', $event->getExitCode(), $event->getException())); }); From d788cc57438babeef4395296a919c22bcb1f549c Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 8 Sep 2015 16:26:10 +0200 Subject: [PATCH 0027/2143] updated CHANGELOG for 2.7.4 --- CHANGELOG-2.7.md | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/CHANGELOG-2.7.md b/CHANGELOG-2.7.md index 86a2e432667a2..b73a020a1dea9 100644 --- a/CHANGELOG-2.7.md +++ b/CHANGELOG-2.7.md @@ -7,6 +7,49 @@ in 2.7 minor versions. To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v2.7.0...v2.7.1 +* 2.7.4 (2015-09-08) + + * bug #15552 [ExpressionLanguage] Fixed expressions cache key generation (inso) + * bug #15527 [Translator][fallback catalogues] fixed circular reference. (aitboudad) + * bug #15662 [Form][ Choice type] fixed groups with empty array. (aitboudad) + * bug #15601 [console] Use the description when no help is available (Nicofuma) + * bug #15649 [VarDumper] Fix missing support for dumping PHP7 return type (nicolas-grekas) + * bug #15603 [HttpKernel] Do not normalize the kernel root directory path #15567 (leofeyer) + * bug #15647 [Debug] Ignore silencing for deprecations (nicolas-grekas) + * bug #15625 Various fixes esp. on Windows (nicolas-grekas) + * bug #15428 Fix the validation of form resources to register the default theme (stof) + * bug #15623 Fix the retrieval of the value with property path when using a loader (stof) + * bug #15619 [Translation] Fix the string casting in the XliffFileLoader (stof) + * bug #15575 Add appveyor.yml for C.I. on Windows (nicolas-grekas) + * bug #15493 [VarDumper] fixed HtmlDumper to target specific the head tag (SaschaDens) + * bug #15611 [Translation][Xliff Loader] Support omitting the node in an .xlf file. (leofeyer) + * bug #15608 [Form] Fix the handling of values for multiple choice types (stof) + * bug #15549 [FrameworkBundle] Fix precedence of xdebug.file_link_format (nicolas-grekas) + * bug #15589 made Symfony compatible with both Twig 1.x and 2.x (fabpot) + * bug #15590 Made Symfony 2.7 compatible with Twig 2.0 (fabpot) + * bug #15535 made Symfony compatible with both Twig 1.x and 2.x (fabpot) + * bug #15561 [Form] only use PropertyPath if not already callable (Tobion) + * bug #15588 [WebProfilerBundle] add import for Twig macro (xabbuh) + * bug #15546 [Form] fixed BC-break on grouped choice lists (origaminal) + * bug #15515 [Console] Fixed warning when command alias is longer than command name (dosten) + * bug #15251 [DoctrineBridge][Form] Fix IdReader when indexing by primary foreign key (giosh94mhz) + * bug #14372 [DoctrineBridge][Form] fix EntityChoiceList when indexing by primary foreign key (giosh94mhz) + * bug #15514 removed _self usage when not needed (fabpot) + * bug #15489 Implement the support of timezone objects in the stub IntlDateFormatter (stof) + * bug #15426 [Serializer] Add support for variadic arguments in the GetSetNormalizer (stof) + * bug #15480 [Yaml] Nested merge keys (mathroc) + * bug #15443 [Debug] Enhance DebugClassLoader performance on MacOSX (nicolas-grekas) + * bug #15445 do not remove space between attributes (greg0ire) + * bug #15263 [HttpFoundation] fixed the check of 'proxy-revalidate' in Response::mustRevalidate() (axiac) + * bug #15425 [Routing] Fix the retrieval of the default value for variadic arguments in the annotation loader (wdalmut, stof) + * bug #15074 Fixing DbalSessionHandler to work with a Oracle "limitation" or bug? (nuncanada) + * bug #13828 [Validator] Improve Iban Validation (afurculita) + * bug #15380 do not dump leading backslashes in class names (xabbuh) + * bug #15376 [ClassMapGenerator] Skip ::class constant (WouterJ) + * bug #15389 [securityBundle] Compare roles strictly when computing inherited roles (bokonet) + * bug #15170 [Config] type specific check for emptiness (xabbuh) + * bug #15411 Fix the handling of null as locale in the stub intl classes (stof) + * 2.7.3 (2015-07-31) * bug #15413 Fix the return value on error for intl methods returning arrays (stof) From 1fdf23fe28876844b887b0e1935c9adda43ee645 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 8 Sep 2015 16:26:39 +0200 Subject: [PATCH 0028/2143] updated VERSION for 2.7.4 --- src/Symfony/Component/HttpKernel/Kernel.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 3f8b4cd91ec15..5511a08a46ed7 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -60,12 +60,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '2.7.4-DEV'; + const VERSION = '2.7.4'; const VERSION_ID = '20704'; const MAJOR_VERSION = '2'; const MINOR_VERSION = '7'; const RELEASE_VERSION = '4'; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '05/2018'; const END_OF_LIFE = '05/2019'; From 6b08d3eb164e5ba5e02eb0f497591bcdc6d5ef16 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 8 Sep 2015 20:12:26 +0200 Subject: [PATCH 0029/2143] bumped Symfony version to 2.7.5 --- src/Symfony/Component/HttpKernel/Kernel.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 5511a08a46ed7..f9888261dcf81 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -60,12 +60,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '2.7.4'; - const VERSION_ID = '20704'; + const VERSION = '2.7.5-DEV'; + const VERSION_ID = '20705'; const MAJOR_VERSION = '2'; const MINOR_VERSION = '7'; - const RELEASE_VERSION = '4'; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = '5'; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '05/2018'; const END_OF_LIFE = '05/2019'; From 4b45bb91abac20cc05d325c9a2c6a34145be4276 Mon Sep 17 00:00:00 2001 From: Tobias Schultze Date: Tue, 8 Sep 2015 21:33:18 +0200 Subject: [PATCH 0030/2143] Kernel version constants are integers to actually be comparable numerically --- src/Symfony/Component/HttpKernel/Kernel.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 5da1e8f716509..fa31455251ed7 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -61,10 +61,10 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $loadClassCache; const VERSION = '2.3.33-DEV'; - const VERSION_ID = '20333'; - const MAJOR_VERSION = '2'; - const MINOR_VERSION = '3'; - const RELEASE_VERSION = '33'; + const VERSION_ID = 20333; + const MAJOR_VERSION = 2; + const MINOR_VERSION = 3; + const RELEASE_VERSION = 33; const EXTRA_VERSION = 'DEV'; /** From 3849cd80b9fa68baaed0c0b8da1302443162ecd2 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Tue, 8 Sep 2015 21:57:35 +0200 Subject: [PATCH 0031/2143] improve exceptions when parsing malformed files --- .../DependencyInjection/Loader/YamlFileLoader.php | 9 ++++++++- src/Symfony/Component/Routing/Loader/YamlFileLoader.php | 7 ++++++- .../Validator/Mapping/Loader/YamlFileLoader.php | 7 ++++++- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php index fc1fff2032469..28adaa4580487 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php @@ -19,6 +19,7 @@ use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Exception\RuntimeException; use Symfony\Component\Config\Resource\FileResource; +use Symfony\Component\Yaml\Exception\ParseException; use Symfony\Component\Yaml\Parser as YamlParser; /** @@ -286,7 +287,13 @@ protected function loadFile($file) $this->yamlParser = new YamlParser(); } - return $this->validate($this->yamlParser->parse(file_get_contents($file)), $file); + try { + $configuration = $this->yamlParser->parse(file_get_contents($file)); + } catch (ParseException $e) { + throw new \InvalidArgumentException(sprintf('The file "%s" does not contain valid YAML.', $file), 0, $e); + } + + return $this->validate($configuration, $file); } /** diff --git a/src/Symfony/Component/Routing/Loader/YamlFileLoader.php b/src/Symfony/Component/Routing/Loader/YamlFileLoader.php index 3653eaa55078d..f5438f256f13f 100644 --- a/src/Symfony/Component/Routing/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/Routing/Loader/YamlFileLoader.php @@ -14,6 +14,7 @@ use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\Route; use Symfony\Component\Config\Resource\FileResource; +use Symfony\Component\Yaml\Exception\ParseException; use Symfony\Component\Yaml\Parser as YamlParser; use Symfony\Component\Config\Loader\FileLoader; @@ -60,7 +61,11 @@ public function load($file, $type = null) $this->yamlParser = new YamlParser(); } - $config = $this->yamlParser->parse(file_get_contents($path)); + try { + $config = $this->yamlParser->parse(file_get_contents($path)); + } catch (ParseException $e) { + throw new \InvalidArgumentException(sprintf('The file "%s" does not contain valid YAML.', $path), 0, $e); + } $collection = new RouteCollection(); $collection->addResource(new FileResource($path)); diff --git a/src/Symfony/Component/Validator/Mapping/Loader/YamlFileLoader.php b/src/Symfony/Component/Validator/Mapping/Loader/YamlFileLoader.php index 6075b270baa6b..ea4e2641a6fc7 100644 --- a/src/Symfony/Component/Validator/Mapping/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/Validator/Mapping/Loader/YamlFileLoader.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Validator\Mapping\Loader; use Symfony\Component\Validator\Mapping\ClassMetadata; +use Symfony\Component\Yaml\Exception\ParseException; use Symfony\Component\Yaml\Parser as YamlParser; /** @@ -117,7 +118,11 @@ protected function parseNodes(array $nodes) */ private function parseFile($path) { - $classes = $this->yamlParser->parse(file_get_contents($path)); + try { + $classes = $this->yamlParser->parse(file_get_contents($path)); + } catch (ParseException $e) { + throw new \InvalidArgumentException(sprintf('The file "%s" does not contain valid.', $path), 0, $e); + } // empty file if (null === $classes) { From 0ffcc4f53d62384efd8c90178df8729a666a84ee Mon Sep 17 00:00:00 2001 From: Evgeniy Sokolov Date: Wed, 9 Sep 2015 00:56:24 +0200 Subject: [PATCH 0032/2143] drop unused private methods --- .../Extension/Core/DataMapper/PropertyPathMapperTest.php | 8 -------- src/Symfony/Component/Form/Tests/FormFactoryTest.php | 5 ----- 2 files changed, 13 deletions(-) diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php index 05497fceaa0ba..94eaa34d0e224 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php @@ -76,14 +76,6 @@ private function getForm(FormConfigInterface $config, $synchronized = true, $sub return $form; } - /** - * @return \PHPUnit_Framework_MockObject_MockObject - */ - private function getDataMapper() - { - return $this->getMock('Symfony\Component\Form\DataMapperInterface'); - } - public function testMapDataToFormsPassesObjectRefIfByReference() { $car = new \stdClass(); diff --git a/src/Symfony/Component/Form/Tests/FormFactoryTest.php b/src/Symfony/Component/Form/Tests/FormFactoryTest.php index 546f6bd6c0eca..1c6acf4344cda 100644 --- a/src/Symfony/Component/Form/Tests/FormFactoryTest.php +++ b/src/Symfony/Component/Form/Tests/FormFactoryTest.php @@ -489,11 +489,6 @@ private function getMockResolvedType() return $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface'); } - private function getMockType() - { - return $this->getMock('Symfony\Component\Form\FormTypeInterface'); - } - private function getMockFormBuilder() { return $this->getMock('Symfony\Component\Form\Test\FormBuilderInterface'); From 36e09da4b9e75b7a47e9aa51aa3d5376dbcb0c35 Mon Sep 17 00:00:00 2001 From: Christophe Coevoet Date: Wed, 9 Sep 2015 14:19:27 +0200 Subject: [PATCH 0033/2143] Fix the injection of the container in invokable controllers --- .../Controller/ControllerResolver.php | 15 +++++++++------ .../Tests/Controller/ControllerResolverTest.php | 16 ++++++++++++++++ 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerResolver.php b/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerResolver.php index c6ef277be384b..6804ded30d0e5 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerResolver.php +++ b/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerResolver.php @@ -70,17 +70,20 @@ protected function createController($controller) } } - list($class, $method) = explode('::', $controller, 2); + return parent::createController($controller); + } - if (!class_exists($class)) { - throw new \InvalidArgumentException(sprintf('Class "%s" does not exist.', $class)); - } + /** + * {@inheritdoc} + */ + protected function instantiateController($class) + { + $controller = parent::instantiateController($class); - $controller = $this->instantiateController($class); if ($controller instanceof ContainerAwareInterface) { $controller->setContainer($this->container); } - return array($controller, $method); + return $controller; } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerResolverTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerResolverTest.php index 4e804bf079701..76a3489fe1551 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerResolverTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerResolverTest.php @@ -33,6 +33,18 @@ public function testGetControllerOnContainerAware() $this->assertSame('testAction', $controller[1]); } + public function testGetControllerOnContainerAwareInvokable() + { + $resolver = $this->createControllerResolver(); + $request = Request::create('/'); + $request->attributes->set('_controller', 'Symfony\Bundle\FrameworkBundle\Tests\Controller\ContainerAwareController'); + + $controller = $resolver->getController($request); + + $this->assertInstanceOf('Symfony\Bundle\FrameworkBundle\Tests\Controller\ContainerAwareController', $controller); + $this->assertInstanceOf('Symfony\Component\DependencyInjection\ContainerInterface', $controller->getContainer()); + } + public function testGetControllerWithBundleNotation() { $shortName = 'FooBundle:Default:test'; @@ -161,4 +173,8 @@ public function getContainer() public function testAction() { } + + public function __invoke() + { + } } From cade65191531dc6fb30600f274554905b712b85a Mon Sep 17 00:00:00 2001 From: Abdellatif Ait boudad Date: Wed, 12 Aug 2015 10:54:13 +0000 Subject: [PATCH 0034/2143] [Translator][warmup][fallback locales] fixed missing cache file generation. --- .../FrameworkBundle/Tests/Translation/TranslatorTest.php | 3 ++- .../Bundle/FrameworkBundle/Translation/Translator.php | 8 +++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php index c7b61cb88170e..043cd11518a67 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php @@ -273,7 +273,7 @@ public function testWarmup() // prime the cache $translator = $this->getTranslator($loader, array('cache_dir' => $this->tmpDir, 'resource_files' => $resourceFiles), 'yml'); - $translator->setLocale('fr'); + $translator->setFallbackLocales(array('fr')); $translator->warmup($this->tmpDir); $loader = $this->getMock('Symfony\Component\Translation\Loader\LoaderInterface'); @@ -283,6 +283,7 @@ public function testWarmup() $translator = $this->getTranslator($loader, array('cache_dir' => $this->tmpDir, 'resource_files' => $resourceFiles), 'yml'); $t 8000 ranslator->setLocale('fr'); + $translator->setFallbackLocales(array('fr')); $this->assertEquals('répertoire', $translator->trans('folder')); } diff --git a/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php b/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php index 9cc92f9c2d616..fba6d70d6978b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php +++ b/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php @@ -82,7 +82,13 @@ public function warmUp($cacheDir) return; } - foreach ($this->resourceLocales as $locale) { + $locales = array_merge($this->getFallbackLocales(), array($this->getLocale()), $this->resourceLocales); + foreach (array_unique($locales) as $locale) { + // reset catalogue in case it's already loaded during the dump of the other locales. + if (isset($this->catalogues[$locale])) { + unset($this->catalogues[$locale]); + } + $this->loadCatalogue($locale); } } From f0d40c455910962af1d00571c35d181b3f58ad5f Mon Sep 17 00:00:00 2001 From: Evgeniy Sokolov Date: Wed, 9 Sep 2015 00:15:02 +0200 Subject: [PATCH 0035/2143] fix class use and in phpdoc --- .../Tests/DependencyInjection/DoctrineExtensionTest.php | 4 ++-- .../Bridge/Doctrine/Tests/Form/Type/EntityTypeTest.php | 2 +- .../Compiler/AddConsoleCommandPassTest.php | 6 +++--- .../Tests/DependencyInjection/MainConfigurationTest.php | 2 +- src/Symfony/Component/Console/Helper/ProgressBar.php | 2 +- src/Symfony/Component/Console/Helper/Table.php | 4 ++-- .../Component/DependencyInjection/Tests/ContainerTest.php | 2 +- src/Symfony/Component/DomCrawler/Tests/FormTest.php | 2 +- .../EventDispatcher/Tests/AbstractEventDispatcherTest.php | 1 + src/Symfony/Component/ExpressionLanguage/Parser.php | 2 +- src/Symfony/Component/Filesystem/Tests/LockHandlerTest.php | 4 ++-- .../Tests/Fragment/RoutableFragmentRendererTest.php | 2 +- src/Symfony/Component/HttpKernel/Tests/KernelTest.php | 1 + src/Symfony/Component/Intl/Resources/stubs/Collator.php | 1 - .../Security/Core/Tests/Encoder/EncoderFactoryTest.php | 2 +- .../Component/Validator/Mapping/MetadataInterface.php | 1 + src/Symfony/Component/VarDumper/Caster/Caster.php | 4 ++-- 17 files changed, 22 insertions(+), 20 deletions(-) diff --git a/src/Symfony/Bridge/Doctrine/Tests/DependencyInjection/DoctrineExtensionTest.php b/src/Symfony/Bridge/Doctrine/Tests/DependencyInjection/DoctrineExtensionTest.php index 41899c1c6033f..e37f1476ae78f 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/DependencyInjection/DoctrineExtensionTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/DependencyInjection/DoctrineExtensionTest.php @@ -49,7 +49,7 @@ protected function setUp() } /** - * @expectedException LogicException + * @expectedException \LogicException */ public function testFixManagersAutoMappingsWithTwoAutomappings() { @@ -239,7 +239,7 @@ public function testServiceCacheDriver() } /** - * @expectedException InvalidArgumentException + * @expectedException \InvalidArgumentException * @expectedExceptionMessage "unrecognized_type" is an unrecognized Doctrine cache driver. */ public function testUnrecognizedCacheDriverException() diff --git a/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypeTest.php b/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypeTest.php index 9eb1e30fc4959..78f10848bccbf 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypeTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypeTest.php @@ -117,7 +117,7 @@ public function testClassOptionIsRequired() } /** - * @expectedException Symfony\Component\Form\Exception\RuntimeException + * @expectedException \Symfony\Component\Form\Exception\RuntimeException */ public function testInvalidClassOption() { diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddConsoleCommandPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddConsoleCommandPassTest.php index 52f9b0e394d90..9750744859966 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddConsoleCommandPassTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddConsoleCommandPassTest.php @@ -40,7 +40,7 @@ public function testProcess() } /** - * @expectedException InvalidArgumentException + * @expectedException \InvalidArgumentException * @expectedExceptionMessage The service "my-command" tagged "console.command" must be public. */ public function testProcessThrowAnExceptionIfTheServiceIsNotPublic() @@ -57,7 +57,7 @@ public function testProcessThrowAnExceptionIfTheServiceIsNotPublic() } /** - * @expectedException InvalidArgumentException + * @expectedException \InvalidArgumentException * @expectedExceptionMessage The service "my-command" tagged "console.command" must not be abstract. */ public function testProcessThrowAnExceptionIfTheServiceIsAbstract() @@ -74,7 +74,7 @@ public function testProcessThrowAnExceptionIfTheServiceIsAbstract() } /** - * @expectedException InvalidArgumentException + * @expectedException \InvalidArgumentException * @expectedExceptionMessage The service "my-command" tagged "console.command" must be a subclass of "Symfony\Component\Console\Command\Command". */ public function testProcessThrowAnExceptionIfTheServiceIsNotASubclassOfCommand() diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/MainConfigurationTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/MainConfigurationTest.php index 402b321968739..8d9224673cd77 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/MainConfigurationTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/MainConfigurationTest.php @@ -92,7 +92,7 @@ public function testCsrfAliases() } /** - * @expectedException InvalidArgumentException + * @expectedException \InvalidArgumentException */ public function testCsrfOriginalAndAliasValueCausesException() { diff --git a/src/Symfony/Component/Console/Helper/ProgressBar.php b/src/Symfony/Component/Console/Helper/ProgressBar.php index e5ba92773889d..5bc3de4e7390e 100644 --- a/src/Symfony/Component/Console/Helper/ProgressBar.php +++ b/src/Symfony/Component/Console/Helper/ProgressBar.php @@ -476,7 +476,7 @@ public function clear() /** * Sets the progress bar maximal steps. * - * @param int The progress bar max steps + * @param int $max The progress bar max steps */ private function setMaxSteps($max) { diff --git a/src/Symfony/Component/Console/Helper/Table.php b/src/Symfony/Component/Console/Helper/Table.php index 6da4b7d7a1c30..6f5fbd047cee7 100644 --- a/src/Symfony/Component/Console/Helper/Table.php +++ b/src/Symfony/Component/Console/Helper/Table.php @@ -376,7 +376,7 @@ private function buildTableRows($rows) * fill rows that contains rowspan > 1. * * @param array $rows - * @param array $line + * @param int $line * * @return array */ @@ -429,7 +429,7 @@ private function fillNextRows($rows, $line) * fill cells for a row that contains colspan > 1. * * @param array $row - * @param array $column + * @param int $column * * @return array */ diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php index dd8358e929962..472bd1ff62bcd 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php @@ -539,7 +539,7 @@ public function testHasScope() } /** - * @expectedException Exception + * @expectedException \Exception * @expectedExceptionMessage Something went terribly wrong! */ public function testGetThrowsException() diff --git a/src/Symfony/Component/DomCrawler/Tests/FormTest.php b/src/Symfony/Component/DomCrawler/Tests/FormTest.php index 59c3c76cf0f4e..5bfbfb98245dc 100644 --- a/src/Symfony/Component/DomCrawler/Tests/FormTest.php +++ b/src/Symfony/Component/DomCrawler/Tests/FormTest.php @@ -820,7 +820,7 @@ public function testFormRegistrySetValueOnCompoundField() } /** - * @expectedException InvalidArgumentException + * @expectedException \InvalidArgumentException * @expectedExceptionMessage Unreachable field "0" */ public function testFormRegistrySetArrayOnNotCompoundField() diff --git a/src/Symfony/Component/EventDispatcher/Tests/AbstractEventDispatcherTest.php b/src/Symfony/Component/EventDispatcher/Tests/AbstractEventDispatcherTest.php index 199d2c00715b3..2e4c3fd97ff0f 100644 --- a/src/Symfony/Component/EventDispatcher/Tests/AbstractEventDispatcherTest.php +++ b/src/Symfony/Component/EventDispatcher/Tests/AbstractEventDispatcherTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\EventDispatcher\Tests; use Symfony\Component\EventDispatcher\Event; +use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\EventDispatcher\EventSubscriberInterface; abstract class AbstractEventDispatcherTest extends \PHPUnit_Framework_TestCase diff --git a/src/Symfony/Component/ExpressionLanguage/Parser.php b/src/Symfony/Component/ExpressionLanguage/Parser.php index e761898423da3..f121ad9a9cdd8 100644 --- a/src/Symfony/Component/ExpressionLanguage/Parser.php +++ b/src/Symfony/Component/ExpressionLanguage/Parser.php @@ -88,7 +88,7 @@ public function __construct(array $functions) * @param TokenStream $stream A token stream instance * @param array $names An array of valid names * - * @return Node A node tree + * @return Node\Node A node tree * * @throws SyntaxError */ diff --git a/src/Symfony/Component/Filesystem/Tests/LockHandlerTest.php b/src/Symfony/Component/Filesystem/Tests/LockHandlerTest.php index f229ffd83e0b7..9ab5537451639 100644 --- a/src/Symfony/Component/Filesystem/Tests/LockHandlerTest.php +++ b/src/Symfony/Component/Filesystem/Tests/LockHandlerTest.php @@ -7,7 +7,7 @@ class LockHandlerTest extends \PHPUnit_Framework_TestCase { /** - * @expectedException Symfony\Component\Filesystem\Exception\IOException + * @expectedException \Symfony\Component\Filesystem\Exception\IOException * @expectedExceptionMessage Failed to create "/a/b/c/d/e": mkdir(): Permission denied. */ public function testConstructWhenRepositoryDoesNotExist() @@ -19,7 +19,7 @@ public function testConstructWhenRepositoryDoesNotExist() } /** - * @expectedException Symfony\Component\Filesystem\Exception\IOException + * @expectedException \Symfony\Component\Filesystem\Exception\IOException * @expectedExceptionMessage The directory "/" is not writable. */ public function testConstructWhenRepositoryIsNotWriteable() diff --git a/src/Symfony/Component/HttpKernel/Tests/Fragment/RoutableFragmentRendererTest.php b/src/Symfony/Component/HttpKernel/Tests/Fragment/RoutableFragmentRendererTest.php index 184175cc81aa7..1b5f47119afc6 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Fragment/RoutableFragmentRendererTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Fragment/RoutableFragmentRendererTest.php @@ -55,7 +55,7 @@ public function testGenerateFragmentUriWithARequest() } /** - * @expectedException LogicException + * @expectedException \LogicException * @dataProvider getGenerateFragmentUriDataWithNonScalar */ public function testGenerateFragmentUriWithNonScalar($controller) diff --git a/src/Symfony/Component/HttpKernel/Tests/KernelTest.php b/src/Symfony/Component/HttpKernel/Tests/KernelTest.php index 753125ca8566c..edb31423563db 100644 --- a/src/Symfony/Component/HttpKernel/Tests/KernelTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/KernelTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\HttpKernel\Tests; use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\HttpKernel\Bundle\BundleInterface; use Symfony\Component\HttpKernel\Config\EnvParametersResource; use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\HttpKernel\HttpKernelInterface; diff --git a/src/Symfony/Component/Intl/Resources/stubs/Collator.php b/src/Symfony/Component/Intl/Resources/stubs/Collator.php index 2e73e5aacebf4..ca5a0038f3986 100644 --- a/src/Symfony/Component/Intl/Resources/stubs/Collator.php +++ b/src/Symfony/Component/Intl/Resources/stubs/Collator.php @@ -10,7 +10,6 @@ */ use Symfony\Component\Intl\Collator\Collator as IntlCollator; -use Symfony\Component\Intl\Collator\StubCollator; /** * Stub implementation for the Collator class of the intl extension. diff --git a/src/Symfony/Component/Security/Core/Tests/Encoder/EncoderFactoryTest.php b/src/Symfony/Component/Security/Core/Tests/Encoder/EncoderFactoryTest.php index a8ca2f0bd6705..37cda7204af5c 100644 --- a/src/Symfony/Component/Security/Core/Tests/Encoder/EncoderFactoryTest.php +++ b/src/Symfony/Component/Security/Core/Tests/Encoder/EncoderFactoryTest.php @@ -107,7 +107,7 @@ public function testGetNullNamedEncoderForEncoderAware() } /** - * @expectedException RuntimeException + * @expectedException \RuntimeException */ public function testGetInvalidNamedEncoderForEncoderAware() { diff --git a/src/Symfony/Component/Validator/Mapping/MetadataInterface.php b/src/Symfony/Component/Validator/Mapping/MetadataInterface.php index 991962ceafd2d..e5f09e17edc82 100644 --- a/src/Symfony/Component/Validator/Mapping/MetadataInterface.php +++ b/src/Symfony/Component/Validator/Mapping/MetadataInterface.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Validator\Mapping; +use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\MetadataInterface as LegacyMetadataInterface; /** diff --git a/src/Symfony/Component/VarDumper/Caster/Caster.php b/src/Symfony/Component/VarDumper/Caster/Caster.php index 4ce8cf8a1259c..df677002be4bf 100644 --- a/src/Symfony/Component/VarDumper/Caster/Caster.php +++ b/src/Symfony/Component/VarDumper/Caster/Caster.php @@ -36,8 +36,8 @@ class Caster /** * Casts objects to arrays and adds the dynamic property prefix. * - * @param object $obj The object to cast. - * @param ReflectionClass $reflector The class reflector to use for inspecting the object definition. + * @param object $obj The object to cast. + * @param \ReflectionClass $reflector The class reflector to use for inspecting the object definition. * * @return array The array-cast of the object, with prefixed dynamic properties. */ From b38e448f422eb56d495abe9f68593762b028afe4 Mon Sep 17 00:00:00 2001 From: Tobias Schultze Date: Wed, 9 Sep 2015 19:53:06 +0200 Subject: [PATCH 0036/2143] fix leftover changes from previous merge --- src/Symfony/Component/Intl/Resources/stubs/Collator.php | 2 -- .../Http/Tests/RememberMe/AbstractRememberMeServicesTest.php | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Symfony/Component/Intl/Resources/stubs/Collator.php b/src/Symfony/Component/Intl/Resources/stubs/Collator.php index ca5a0038f3986..1977fdf6173f9 100644 --- a/src/Symfony/Component/Intl/Resources/stubs/Collator.php +++ b/src/Symfony/Component/Intl/Resources/stubs/Collator.php @@ -15,8 +15,6 @@ * Stub implementation for the Collator class of the intl extension. * * @author Bernhard Schussek - * - * @see StubCollator */ class Collator extends IntlCollator { diff --git a/src/Symfony/Component/Security/Http/Tests/RememberMe/AbstractRememberMeServicesTest.php b/src/Symfony/Component/Security/Http/Tests/RememberMe/AbstractRememberMeServicesTest.php index 2225b6c55338e..31ab800c537c3 100644 --- a/src/Symfony/Component/Security/Http/Tests/RememberMe/AbstractRememberMeServicesTest.php +++ b/src/Symfony/Component/Security/Http/Tests/RememberMe/AbstractRememberMeServicesTest.php @@ -250,7 +250,7 @@ public function testEncodeCookieAndDecodeCookieAreInvertible() } /** - * @expectedException InvalidArgumentException + * @expectedException \InvalidArgumentException * @expectedExceptionMessage cookie delimiter */ public function testThereShouldBeNoCookieDelimiterInCookieParts() From 1176d6279a545d4dd4f2387c23b09ff13c966366 Mon Sep 17 00:00:00 2001 From: Tobias Nyholm Date: Mon, 7 Sep 2015 17:07:09 +0200 Subject: [PATCH 0037/2143] [Validator] Added Swedish translations --- .../Resources/translations/validators.sv.xlf | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.sv.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.sv.xlf index 68eac7d0c60b3..31a9da327ea38 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.sv.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.sv.xlf @@ -278,6 +278,38 @@ This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Värdet ska inte vara identiskt med {{ compared_value_type }} {{ compared_value }}. + + The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}. + Förhållandet mellan bildens bredd och höjd är för stort ({{ ratio }}). Högsta tillåtna förhållande är {{ max_ratio }}. + + + The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}. + Förhållandet mellan bildens bredd och höjd är för litet ({{ ratio }}). Minsta tillåtna förhållande är {{ min_ratio }}. + + + The image is square ({{ width }}x{{ height }}px). Square images are not allowed. + Bilden är kvadratisk ({{ width }}x{{ height }}px). Kvadratiska bilder tillåts inte. + + + The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed. + Bilden är landskapsorienterad ({{ width }}x{{ height }}px). Landskapsorienterade bilder tillåts inte. + + + The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed. + Bilden är porträttsorienterad ({{ width }}x{{ height }}px). Porträttsorienterade bilder tillåts inte. + + + An empty file is not allowed. + En tom fil är inte tillåten. + + + The host could not be resolved. + Värddatorn kunde inte hittas. + + + This value does not match the expected {{ charset }} charset. + Detta värde har inte den förväntade teckenkodningen {{ charset }}. + From b95b5e217f4731107e8e966f4c04deae7ebde6f1 Mon Sep 17 00:00:00 2001 From: David Badura Date: Thu, 10 Sep 2015 09:43:17 +0200 Subject: [PATCH 0038/2143] missing "YAML" in the exception message. --- .../Component/Validator/Mapping/Loader/YamlFileLoader.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Validator/Mapping/Loader/YamlFileLoader.php b/src/Symfony/Component/Validator/Mapping/Loader/YamlFileLoader.php index ea4e2641a6fc7..cf6dd92dcad9b 100644 --- a/src/Symfony/Component/Validator/Mapping/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/Validator/Mapping/Loader/YamlFileLoader.php @@ -121,7 +121,7 @@ private function parseFile($path) try { $classes = $this->yamlParser->parse(file_get_contents($path)); } catch (ParseException $e) { - throw new \InvalidArgumentException(sprintf('The file "%s" does not contain valid.', $path), 0, $e); + throw new \InvalidArgumentException(sprintf('The file "%s" does not contain valid YAML.', $path), 0, $e); } // empty file From 53cdb1a420aca8eeac76abb6dc9960d56b42fc57 Mon Sep 17 00:00:00 2001 From: AlberT Date: Tue, 9 Jun 2015 13:04:59 +0200 Subject: [PATCH 0039/2143] [WebProfilerBundle] Added tabindex="-1" to not interfer with normal UX --- .../Resources/views/Profiler/toolbar.html.twig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.html.twig index 9e96dc6d1a63c..f0bcd9eeed4d1 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.html.twig @@ -1,7 +1,7 @@ {% if 'normal' != position %}
- validate($configuration, $file); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/bad_format.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/bad_format.yml new file mode 100644 index 0000000000000..1f58cac6acdb0 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/bad_format.yml @@ -0,0 +1,2 @@ +parameters: + FOO: bar diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php index a6fbbd68bc2fe..7d6b76bce9d44 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php @@ -87,6 +87,7 @@ public function provideInvalidFiles() array('bad_services'), array('bad_service'), array('bad_calls'), + array('bad_format'), ); } diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/bad_format.yml b/src/Symfony/Component/Routing/Tests/Fixtures/bad_format.yml new file mode 100644 index 0000000000000..8ba50e2e42816 --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/bad_format.yml @@ -0,0 +1,3 @@ +blog_show: + path: /blog/{slug} + defaults: { _controller: "MyBundle:Blog:show" } diff --git a/src/Symfony/Component/Routing/Tests/Loader/YamlFileLoaderTest.php b/src/Symfony/Component/Routing/Tests/Loader/YamlFileLoaderTest.php index 167fab00d360d..9cc27628ed8a6 100644 --- a/src/Symfony/Component/Routing/Tests/Loader/YamlFileLoaderTest.php +++ b/src/Symfony/Component/Routing/Tests/Loader/YamlFileLoaderTest.php @@ -51,7 +51,15 @@ public function testLoadThrowsExceptionWithInvalidFile($filePath) public function getPathsToInvalidFiles() { - return array(array('nonvalid.yml'), array('nonvalid2.yml'), array('incomplete.yml'), array('nonvalidkeys.yml'), array('nonesense_resource_plus_path.yml'), array('nonesense_type_without_resource.yml')); + return array( + array('nonvalid.yml'), + array('nonvalid2.yml'), + array('incomplete.yml'), + array('nonvalidkeys.yml'), + array('nonesense_resource_plus_path.yml'), + array('nonesense_type_without_resource.yml'), + array('bad_format.yml'), + ); } public function testLoadSpecialRouteName() diff --git a/src/Symfony/Component/Validator/Tests/Mapping/Loader/YamlFileLoaderTest.php b/src/Symfony/Component/Validator/Tests/Mapping/Loader/YamlFileLoaderTest.php index c5b39173e5683..47961c7c129a3 100644 --- a/src/Symfony/Component/Validator/Tests/Mapping/Loader/YamlFileLoaderTest.php +++ b/src/Symfony/Component/Validator/Tests/Mapping/Loader/YamlFileLoaderTest.php @@ -31,15 +31,26 @@ public function testLoadClassMetadataReturnsFalseIfEmpty() $this->assertFalse($loader->loadClassMetadata($metadata)); } - public function testLoadClassMetadataThrowsExceptionIfNotAnArray() + /** + * @dataProvider provideInvalidYamlFiles + * @expectedException \InvalidArgumentException + */ + public function testInvalidYamlFiles($path) { - $loader = new YamlFileLoader(__DIR__.'/nonvalid-mapping.yml'); + $loader = new YamlFileLoader(__DIR__.'/'.$path); $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity'); - $this->setExpectedException('\InvalidArgumentException'); $loader->loadClassMetadata($metadata); } + public function provideInvalidYamlFiles() + { + return array( + array('nonvalid-mapping.yml'), + array('bad-format.yml'), + ); + } + /** * @see https://github.com/symfony/symfony/pull/12158 */ diff --git a/src/Symfony/Component/Validator/Tests/Mapping/Loader/bad-format.yml b/src/Symfony/Component/Validator/Tests/Mapping/Loader/bad-format.yml new file mode 100644 index 0000000000000..d2b4ad2654d36 --- /dev/null +++ b/src/Symfony/Component/Validator/Tests/Mapping/Loader/bad-format.yml @@ -0,0 +1,9 @@ +namespaces: + custom: Symfony\Component\Validator\Tests\Fixtures\ + +Symfony\Component\Validator\Tests\Fixtures\Entity: + constraints: + # Custom constraint + - Symfony\Component\Validator\Tests\Fixtures\ConstraintA: ~ + # Custom constraint with namespaces prefix + - "custom:ConstraintB": ~ From 92e50a3b14fca600933f73dd2f8201f86182dd1b Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 11 Sep 2015 14:29:54 +0200 Subject: [PATCH 0043/2143] [HttpKernel] fix DumpDataCollector compat with Twig 2.0 --- .../Component/HttpKernel/DataCollector/DumpDataCollector.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/DataCollector/DumpDataCollector.php b/src/Symfony/Component/HttpKernel/DataCollector/DumpDataCollector.php index efb0bb3e6e879..e0d7d50f6b89e 100644 --- a/src/Symfony/Component/HttpKernel/DataCollector/DumpDataCollector.php +++ b/src/Symfony/Component/HttpKernel/DataCollector/DumpDataCollector.php @@ -98,9 +98,9 @@ public function dump(Data $data) } elseif (isset($trace[$i]['object']) && $trace[$i]['object'] instanceof \Twig_Template) { $info = $trace[$i]['object']; $name = $info->getTemplateName(); - $src = $info->getEnvironment()->getLoader()->getSource($name); + $src = method_exists($info, 'getSource') ? $info->getSource() : $info->getEnvironment()->getLoader()->getSource($name); $info = $info->getDebugInfo(); - if (isset($info[$trace[$i - 1]['line']])) { + if (null !== $src && isset($info[$trace[$i - 1]['line']])) { $file = false; $line = $info[$trace[$i - 1]['line']]; $src = explode("\n", $src); From f3d844434b2ad4d88273266fff388854406ec5af Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Sat, 12 Sep 2015 19:34:25 +0100 Subject: [PATCH 0044/2143] [Console] Ensure the console output is only detected as decorated when both stderr and stdout support colors --- src/Symfony/Component/Console/Output/ConsoleOutput.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Symfony/Component/Console/Output/ConsoleOutput.php b/src/Symfony/Component/Console/Output/ConsoleOutput.php index 50ef4df9004ce..04bd51b782aff 100644 --- a/src/Symfony/Component/Console/Output/ConsoleOutput.php +++ b/src/Symfony/Component/Console/Output/ConsoleOutput.php @@ -48,7 +48,12 @@ public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = nu { parent::__construct($this->openOutputStream(), $verbosity, $decorated, $formatter); + $actualDecorated = $this->isDecorated(); $this->stderr = new StreamOutput($this->openErrorStream(), $verbosity, $decorated, $this->getFormatter()); + + if (null === $decorated) { + $this->setDecorated($actualDecorated && $this->stderr->isDecorated()); + } } /** From 520bd26642cec313daac2fd3f51259d6fb96f3ca Mon Sep 17 00:00:00 2001 From: Jose Gonzalez Date: Sat, 12 Sep 2015 16:58:59 +0100 Subject: [PATCH 0045/2143] [Yaml] Fix the parsing of float keys --- src/Symfony/Component/Yaml/Parser.php | 5 +++++ .../Component/Yaml/Tests/ParserTest.php | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/src/Symfony/Component/Yaml/Parser.php b/src/Symfony/Component/Yaml/Parser.php index 3c20c8662fb02..fd7ded094f699 100644 --- a/src/Symfony/Component/Yaml/Parser.php +++ b/src/Symfony/Component/Yaml/Parser.php @@ -133,6 +133,11 @@ public function parse($value, $exceptionOnInvalidType = false, $objectSupport = throw $e; } + // Convert float keys to strings, to avoid being converted to integers by PHP + if (is_float($key)) { + $key = (string) $key; + } + if ('<<' === $key) { if (isset($values['value']) && 0 === strpos($values['value'], '*')) { $isInPlace = substr($values['value'], 1); diff --git a/src/Symfony/Component/Yaml/Tests/ParserTest.php b/src/Symfony/Component/Yaml/Tests/ParserTest.php index d74bf18c1b3c6..3054c807fdd12 100644 --- a/src/Symfony/Component/Yaml/Tests/ParserTest.php +++ b/src/Symfony/Component/Yaml/Tests/ParserTest.php @@ -685,6 +685,24 @@ public function testYamlDirective() EOF; $this->assertEquals(array('foo' => 1, 'bar' => 2), $this->parser->parse($yaml)); } + + public function testFloatKeys() + { + $yaml = << array( + '1.2' => 'bar', + '1.3' => 'baz', + ), + ); + + $this->assertEquals($expected, $this->parser->parse($yaml)); + } } class B From c7acde8024b4ada67c98e6b7a98defab7256b2f5 Mon Sep 17 00:00:00 2001 From: Lukas Kahwe Smith Date: Thu, 13 Aug 2015 16:33:53 +0200 Subject: [PATCH 0046/2143] [FrameworkBundle] add a suggest for the serializer component --- src/Symfony/Bundle/FrameworkBundle/composer.json | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index 1ef5af58a1ed0..68c03a912e4d0 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -45,10 +45,11 @@ "symfony/yaml": "~2.0,>=2.0.5" }, "suggest": { - "symfony/console": "", - "symfony/finder": "", - "symfony/form": "", - "symfony/validator": "" + "symfony/console": "For using the console commands", + "symfony/finder": "For using the translation loader and cache warmer", + "symfony/form": "For using forms", + "symfony/validator": "For using validation", + "symfony/serializer": "For using the serializer service", }, "autoload": { "psr-0": { "Symfony\\Bundle\\FrameworkBundle\\": "" } From 92ad5df5675393f5ddaf0b277b56894d45c0e87e Mon Sep 17 00:00:00 2001 From: Kirill Saksin Date: Wed, 3 Jun 2015 00:50:45 +0300 Subject: [PATCH 0047/2143] [DoctrineBridge] Fixed #14840 --- .../DependencyInjection/AbstractDoctrineExtension.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.php b/src/Symfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.php index 1518361c79f27..7247bd5798eef 100644 --- a/src/Symfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.php +++ b/src/Symfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.php @@ -129,11 +129,15 @@ protected function setMappingDriverAlias($mappingConfig, $mappingName) */ protected function setMappingDriverConfig(array $mappingConfig, $mappingName) { - if (!is_dir($mappingConfig['dir'])) { + $mappingDirectory = $mappingConfig['dir']; + if (!is_dir($mappingDirectory)) { throw new \InvalidArgumentException(sprintf('Invalid Doctrine mapping path given. Cannot load Doctrine mapping/bundle named "%s".', $mappingName)); } - $this->drivers[$mappingConfig['type']][$mappingConfig['prefix']] = realpath($mappingConfig['dir']); + if (substr($mappingDirectory, 0, 7) !== 'phar://') { + $mappingDirectory = realpath($mappingDirectory); + } + $this->drivers[$mappingConfig['type']][$mappingConfig['prefix']] = $mappingDirectory; } /** From 06f97bfbd175ad681492176533cfe5611259b6b8 Mon Sep 17 00:00:00 2001 From: Sebastiaan Stok Date: Sun, 31 May 2015 13:21:21 +0200 Subject: [PATCH 0048/2143] [HttpKernel] fix broken multiline Keep this'." And this"); + $esi->process($request, $response); + + $this->assertEquals(' Keep this And this', $response->getContent()); + } + + public function testCommentTagsAreRemoved() + { + $esi = new Esi(); + + $request = Request::create('/'); + $response = new Response(' Keep this'); + $esi->process($request, $response); + + $this->assertEquals(' Keep this', $response->getContent()); + } + public function testProcess() { $esi = new Esi(); From 18e9f45e8dd9753de5111471e5b4de698beb2fb6 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 14 Sep 2015 09:37:59 +0200 Subject: [PATCH 0049/2143] [Debug] Fix case mismatch detection --- .../Component/Debug/DebugClassLoader.php | 20 ++++++++++++++++--- .../Debug/Tests/DebugClassLoaderTest.php | 2 +- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/Debug/DebugClassLoader.php b/src/Symfony/Component/Debug/DebugClassLoader.php index c8e5d1a83ff4d..37d15d1862a6d 100644 --- a/src/Symfony/Component/Debug/DebugClassLoader.php +++ b/src/Symfony/Component/Debug/DebugClassLoader.php @@ -221,8 +221,22 @@ public function loadClass($class) throw new \RuntimeException(sprintf('The autoloader expected class "%s" to be defined in file "%s". The file was found but the class was not in it, the class name or namespace probably has a typo.', $class, $file)); } - if (self::$caseCheck && preg_match('#(?:[/\\\\][a-zA-Z_\x7F-\xFF][a-zA-Z0-9_\x7F-\xFF]*+)++\.(?:php|hh)$#D', $file, $tail)) { - $tail = $tail[0]; + if (self::$caseCheck) { + $real = explode('\\', $class.strrchr($file, '.')); + $tail = explode(DIRECTORY_SEPARATOR, str_replace('/', DIRECTORY_SEPARATOR, $file)); + + $i = count($tail) - 1; + $j = count($real) - 1; + + while (isset($tail[$i], $real[$j]) && $tail[$i] === $real[$j]) { + --$i; + --$j; + } + + array_splice($tail, 0, $i + 1); + } + if (self::$caseCheck && $tail) { + $tail = DIRECTORY_SEPARATOR.implode(DIRECTORY_SEPARATOR, $tail); $tailLen = strlen($tail); $real = $refl->getFileName(); @@ -289,7 +303,7 @@ public function loadClass($class) if (0 === substr_compare($real, $tail, -$tailLen, $tailLen, true) && 0 !== substr_compare($real, $tail, -$tailLen, $tailLen, false) ) { - throw new \RuntimeException(sprintf('Case mismatch between class and source file names: %s vs %s', $class, $real)); + throw new \RuntimeException(sprintf('Case mismatch between class and real file names: %s vs %s in %s', substr($tail, -$tailLen + 1), substr($real, -$tailLen + 1), substr($real, 0, -$tailLen + 1))); } } diff --git a/src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php b/src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php index a368a7d25704a..1516dbedf9a00 100644 --- a/src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php +++ b/src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php @@ -136,7 +136,7 @@ class_exists(__NAMESPACE__.'\TestingCaseMismatch', true); /** * @expectedException \RuntimeException - * @expectedExceptionMessage Case mismatch between class and source file names + * @expectedExceptionMessage Case mismatch between class and real file names */ public function testFileCaseMismatch() { From f12a4c1aee9796913b8fbe29fadf7a7340aa0a5f Mon Sep 17 00:00:00 2001 From: Jakub Zalas Date: Thu, 13 Aug 2015 08:25:37 +0100 Subject: [PATCH 0050/2143] [Console] Fix input validation when required arguments are missing Previous rule was only working when arguments are passed from command line, as in command line there is no way of skipping an argument. The rule does not work for arguments set on the Input after a command is run. --- src/Symfony/Component/Console/Input/Input.php | 11 +++++++++-- .../Component/Console/Tests/Input/InputTest.php | 13 ++++++++++++- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Console/Input/Input.php b/src/Symfony/Component/Console/Input/Input.php index 05a029f09caaf..8103d193164c2 100644 --- a/src/Symfony/Component/Console/Input/Input.php +++ b/src/Symfony/Component/Console/Input/Input.php @@ -72,8 +72,15 @@ abstract protected function parse(); */ public function validate() { - if (count($this->arguments) < $this->definition->getArgumentRequiredCount()) { - throw new \RuntimeException('Not enough arguments.'); + $definition = $this->definition; + $givenArguments = $this->arguments; + + $missingArguments = array_filter(array_keys($definition->getArguments()), function ($argument) use ($definition, $givenArguments) { + return !array_key_exists($argument, $givenArguments) && $definition->getArgument($argument)->isRequired(); + }); + + if (count($missingArguments) > 0) { + throw new \RuntimeException(sprintf('Not enough arguments (missing: "%s").', implode(', ', $missingArguments))); } } diff --git a/src/Symfony/Component/Console/Tests/Input/InputTest.php b/src/Symfony/Component/Console/Tests/Input/InputTest.php index 0b3e38fb6f4ce..eb1c6617f5644 100644 --- a/src/Symfony/Component/Console/Tests/Input/InputTest.php +++ b/src/Symfony/Component/Console/Tests/Input/InputTest.php @@ -94,7 +94,7 @@ public function testGetInvalidArgument() /** * @expectedException \RuntimeException - * @expectedExceptionMessage Not enough arguments. + * @expectedExceptionMessage Not enough arguments (missing: "name"). */ public function testValidateWithMissingArguments() { @@ -103,6 +103,17 @@ public function testValidateWithMissingArguments() $input->validate(); } + /** + * @expectedException \RuntimeException + * @expectedExceptionMessage Not enough arguments (missing: "name"). + */ + public function testValidateWithMissingRequiredArguments() + { + $input = new ArrayInput(array('bar' => 'baz')); + $input->bind(new InputDefinition(array(new InputArgument('name', InputArgument::REQUIRED), new InputArgument('bar', InputArgument::OPTIONAL)))); + $input->validate(); + } + public function testValidate() { $input = new ArrayInput(array('name' => 'foo')); From d2b3fe4c72a1404359f9878df3015ff1b0737ba9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois-Xavier=20de=20Guillebon?= Date: Fri, 11 Sep 2015 15:18:57 +0200 Subject: [PATCH 0051/2143] Fixed properties not explicitily declared --- .../Command/YamlLintCommand.php | 4 +- .../Compiler/CheckReferenceValidityPass.php | 1 - .../DataCollector/DumpDataCollector.php | 1 + .../Component/HttpKernel/HttpCache/Esi.php | 1 - .../Component/HttpKernel/HttpCache/Ssi.php | 1 - .../Tests/HttpCache/HttpCacheTestCase.php | 1 + .../HttpCache/TestMultipleHttpKernel.php | 4 +- .../Tests/Encoder/JsonEncoderTest.php | 3 + .../Serializer/Tests/SerializerTest.php | 96 +++++++++---------- .../RecursiveContextualValidator.php | 10 ++ 10 files changed, 67 insertions(+), 55 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/YamlLintCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/YamlLintCommand.php index 3f931f54c1e27..c4c4bb9cf1d27 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/YamlLintCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/YamlLintCommand.php @@ -105,9 +105,9 @@ protected function execute(InputInterface $input, OutputInterface $output) private function validate($content, $file = null) { - $this->parser = new Parser(); + $parser = new Parser(); try { - $this->parser->parse($content); + $parser->parse($content); } catch (ParseException $e) { return array('file' => $file, 'valid' => false, 'message' => $e->getMessage()); } diff --git a/src/Symfony/Component/DependencyInjection/Compiler/CheckReferenceValidityPass.php b/src/Symfony/Component/DependencyInjection/Compiler/CheckReferenceValidityPass.php index 3d4988d2e6653..82202a9fb6007 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/CheckReferenceValidityPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/CheckReferenceValidityPass.php @@ -64,7 +64,6 @@ public function process(ContainerBuilder $container) } $this->currentId = $id; - $this->currentDefinition = $definition; $this->currentScope = $scope = $definition->getScope(); if (ContainerInterface::SCOPE_CONTAINER === $scope) { diff --git a/src/Symfony/Component/HttpKernel/DataCollector/DumpDataCollector.php b/src/Symfony/Component/HttpKernel/DataCollector/DumpDataCollector.php index e0d7d50f6b89e..c50bf7a135b39 100644 --- a/src/Symfony/Component/HttpKernel/DataCollector/DumpDataCollector.php +++ b/src/Symfony/Component/HttpKernel/DataCollector/DumpDataCollector.php @@ -34,6 +34,7 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface private $clonesIndex = 0; private $rootRefs; private $charset; + private $requestStack; private $dumper; private $dumperIsInjected; diff --git a/src/Symfony/Component/HttpKernel/HttpCache/Esi.php b/src/Symfony/Component/HttpKernel/HttpCache/Esi.php index e4e0a4be6f1a0..4fe523931dc54 100644 --- a/src/Symfony/Component/HttpKernel/HttpCache/Esi.php +++ b/src/Symfony/Component/HttpKernel/HttpCache/Esi.php @@ -200,7 +200,6 @@ public function renderIncludeTag($uri, $alt = null, $ignoreErrors = true, $comme */ public function process(Request $request, Response $response) { - $this->request = $request; $type = $response->headers->get('Content-Type'); if (empty($type)) { $type = 'text/html'; diff --git a/src/Symfony/Component/HttpKernel/HttpCache/Ssi.php b/src/Symfony/Component/HttpKernel/HttpCache/Ssi.php index 7bb54cff62757..43311b6dc8038 100644 --- a/src/Symfony/Component/HttpKernel/HttpCache/Ssi.php +++ b/src/Symfony/Component/HttpKernel/HttpCache/Ssi.php @@ -113,7 +113,6 @@ public function renderIncludeTag($uri, $alt = null, $ignoreErrors = true, $comme */ public function process(Request $request, Response $response) { - $this->request = $request; $type = $response->headers->get('Content-Type'); if (empty($type)) { $type = 'text/html'; diff --git a/src/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTestCase.php b/src/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTestCase.php index 766e2b1d499a5..1fcd2107519bd 100644 --- a/src/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTestCase.php +++ b/src/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTestCase.php @@ -28,6 +28,7 @@ class HttpCacheTestCase extends \PHPUnit_Framework_TestCase protected $responses; protected $catch; protected $esi; + protected $store; protected function setUp() { diff --git a/src/Symfony/Component/HttpKernel/Tests/HttpCache/TestMultipleHttpKernel.php b/src/Symfony/Component/HttpKernel/Tests/HttpCache/TestMultipleHttpKernel.php index 773e221482bed..5b5209e9a678f 100644 --- a/src/Symfony/Component/HttpKernel/Tests/HttpCache/TestMultipleHttpKernel.php +++ b/src/Symfony/Component/HttpKernel/Tests/HttpCache/TestMultipleHttpKernel.php @@ -23,7 +23,7 @@ class TestMultipleHttpKernel extends HttpKernel implements ControllerResolverInt protected $bodies = array(); protected $statuses = array(); protected $headers = array(); - protected $call = false; + protected $called = false; protected $backendRequest; public function __construct($responses) @@ -75,6 +75,6 @@ public function hasBeenCalled() public function reset() { - $this->call = false; + $this->called = false; } } diff --git a/src/Symfony/Component/Serializer/Tests/Encoder/JsonEncoderTest.php b/src/Symfony/Component/Serializer/Tests/Encoder/JsonEncoderTest.php index c7bd11e7aec7a..c064503430e8a 100644 --- a/src/Symfony/Component/Serializer/Tests/Encoder/JsonEncoderTest.php +++ b/src/Symfony/Component/Serializer/Tests/Encoder/JsonEncoderTest.php @@ -17,6 +17,9 @@ class JsonEncoderTest extends \PHPUnit_Framework_TestCase { + private $encoder; + private $serializer; + protected function setUp() { $this->encoder = new JsonEncoder(); diff --git a/src/Symfony/Component/Serializer/Tests/SerializerTest.php b/src/Symfony/Component/Serializer/Tests/SerializerTest.php index 68f70fcfe51ad..a9713466e942c 100644 --- a/src/Symfony/Component/Serializer/Tests/SerializerTest.php +++ b/src/Symfony/Component/Serializer/Tests/SerializerTest.php @@ -38,21 +38,21 @@ public function testInterface() */ public function testNormalizeNoMatch() { - $this->serializer = new Serializer(array($this->getMock('Symfony\Component\Serializer\Normalizer\CustomNormalizer'))); - $this->serializer->normalize(new \stdClass(), 'xml'); + $serializer = new Serializer(array($this->getMock('Symfony\Component\Serializer\Normalizer\CustomNormalizer'))); + $serializer->normalize(new \stdClass(), 'xml'); } public function testNormalizeTraversable() { - $this->serializer = new Serializer(array(), array('json' => new JsonEncoder())); - $result = $this->serializer->serialize(new TraversableDummy(), 'json'); + $serializer = new Serializer(array(), array('json' => new JsonEncoder())); + $result = $serializer->serialize(new TraversableDummy(), 'json'); $this->assertEquals('{"foo":"foo","bar":"bar"}', $result); } public function testNormalizeGivesPriorityToInterfaceOverTraversable() { - $this->serializer = new Serializer(array(new CustomNormalizer()), array('json' => new JsonEncoder())); - $result = $this->serializer->serialize(new NormalizableTraversableDummy(), 'json'); + $serializer = new Serializer(array(new CustomNormalizer()), array('json' => new JsonEncoder())); + $result = $serializer->serialize(new NormalizableTraversableDummy(), 'json'); $this->assertEquals('{"foo":"normalizedFoo","bar":"normalizedBar"}', $result); } @@ -61,8 +61,8 @@ public function testNormalizeGivesPriorityToInterfaceOverTraversable() */ public function testNormalizeOnDenormalizer() { - $this->serializer = new Serializer(array(new TestDenormalizer()), array()); - $this->assertTrue($this->serializer->normalize(new \stdClass(), 'json')); + $serializer = new Serializer(array(new TestDenormalizer()), array()); + $this->assertTrue($serializer->normalize(new \stdClass(), 'json')); } /** @@ -70,8 +70,8 @@ public function testNormalizeOnDenormalizer() */ public function testDenormalizeNoMatch() { - $this->serializer = new Serializer(array($this->getMock('Symfony\Component\Serializer\Normalizer\CustomNormalizer'))); - $this->serializer->denormalize('foo', 'stdClass'); + $serializer = new Serializer(array($this->getMock('Symfony\Component\Serializer\Normalizer\CustomNormalizer'))); + $serializer->denormalize('foo', 'stdClass'); } /** @@ -79,40 +79,40 @@ public function testDenormalizeNoMatch() */ public function testDenormalizeOnNormalizer() { - $this->serializer = new Serializer(array(new TestNormalizer()), array()); + $serializer = new Serializer(array(new TestNormalizer()), array()); $data = array('title' => 'foo', 'numbers' => array(5, 3)); - $this->assertTrue($this->serializer->denormalize(json_encode($data), 'stdClass', 'json')); + $this->assertTrue($serializer->denormalize(json_encode($data), 'stdClass', 'json')); } public function testCustomNormalizerCanNormalizeCollectionsAndScalar() { - $this->serializer = new Serializer(array(new TestNormalizer()), array()); - $this->assertNull($this->serializer->normalize(array('a', 'b'))); - $this->assertNull($this->serializer->normalize(new \ArrayObject(array('c', 'd')))); - $this->assertNull($this->serializer->normalize(array())); - $this->assertNull($this->serializer->normalize('test')); + $serializer = new Serializer(array(new TestNormalizer()), array()); + $this->assertNull($serializer->normalize(array('a', 'b'))); + $this->assertNull($serializer->normalize(new \ArrayObject(array('c', 'd')))); + $this->assertNull($serializer->normalize(array())); + $this->assertNull($serializer->normalize('test')); } public function testSerialize() { - $this->serializer = new Serializer(array(new GetSetMethodNormalizer()), array('json' => new JsonEncoder())); + $serializer = new Serializer(array(new GetSetMethodNormalizer()), array('json' => new JsonEncoder())); $data = array('title' => 'foo', 'numbers' => array(5, 3)); - $result = $this->serializer->serialize(Model::fromArray($data), 'json'); + $result = $serializer->serialize(Model::fromArray($data), 'json'); $this->assertEquals(json_encode($data), $result); } public function testSerializeScalar() { - $this->serializer = new Serializer(array(), array('json' => new JsonEncoder())); - $result = $this->serializer->serialize('foo', 'json'); + $serializer = new Serializer(array(), array('json' => new JsonEncoder())); + $result = $serializer->serialize('foo', 'json'); $this->assertEquals('"foo"', $result); } public function testSerializeArrayOfScalars() { - $this->serializer = new Serializer(array(), array('json' => new JsonEncoder())); + $serializer = new Serializer(array(), array('json' => new JsonEncoder())); $data = array('foo', array(5, 3)); - $result = $this->serializer->serialize($data, 'json'); + $result = $serializer->serialize($data, 'json'); $this->assertEquals(json_encode($data), $result); } @@ -121,9 +121,9 @@ public function testSerializeArrayOfScalars() */ public function testSerializeNoEncoder() { - $this->serializer = new Serializer(array(), array()); + $serializer = new Serializer(array(), array()); $data = array('title' => 'foo', 'numbers' => array(5, 3)); - $this->serializer->serialize($data, 'json'); + $serializer->serialize($data, 'json'); } /** @@ -131,26 +131,26 @@ public function testSerializeNoEncoder() */ public function testSerializeNoNormalizer() { - $this->serializer = new Serializer(array(), array('json' => new JsonEncoder())); + $serializer = new Serializer(array(), array('json' => new JsonEncoder())); $data = array('title' => 'foo', 'numbers' => array(5, 3)); - $this->serializer->serialize(Model::fromArray($data), 'json'); + $serializer->serialize(Model::fromArray($data), 'json'); } public function testDeserialize() { - $this->serializer = new Serializer(array(new GetSetMethodNormalizer()), array('json' => new JsonEncoder())); + $serializer = new Serializer(array(new GetSetMethodNormalizer()), array('json' => new JsonEncoder())); $data = array('title' => 'foo', 'numbers' => array(5, 3)); - $result = $this->serializer->deserialize(json_encode($data), '\Symfony\Component\Serializer\Tests\Model', 'json'); + $result = $serializer->deserialize(json_encode($data), '\Symfony\Component\Serializer\Tests\Model', 'json'); $this->assertEqu 8000 als($data, $result->toArray()); } public function testDeserializeUseCache() { - $this->serializer = new Serializer(array(new GetSetMethodNormalizer()), array('json' => new JsonEncoder())); + $serializer = new Serializer(array(new GetSetMethodNormalizer()), array('json' => new JsonEncoder())); $data = array('title' => 'foo', 'numbers' => array(5, 3)); - $this->serializer->deserialize(json_encode($data), '\Symfony\Component\Serializer\Tests\Model', 'json'); + $serializer->deserialize(json_encode($data), '\Symfony\Component\Serializer\Tests\Model', 'json'); $data = array('title' => 'bar', 'numbers' => array(2, 8)); - $result = $this->serializer->deserialize(json_encode($data), '\Symfony\Component\Serializer\Tests\Model', 'json'); + $result = $serializer->deserialize(json_encode($data), '\Symfony\Component\Serializer\Tests\Model', 'json'); $this->assertEquals($data, $result->toArray()); } @@ -159,9 +159,9 @@ public function testDeserializeUseCache() */ public function testDeserializeNoNormalizer() { - $this->serializer = new Serializer(array(), array('json' => new JsonEncoder())); + $serializer = new Serializer(array(), array('json' => new JsonEncoder())); $data = array('title' => 'foo', 'numbers' => array(5, 3)); - $this->serializer->deserialize(json_encode($data), '\Symfony\Component\Serializer\Tests\Model', 'json'); + $serializer->deserialize(json_encode($data), '\Symfony\Component\Serializer\Tests\Model', 'json'); } /** @@ -169,9 +169,9 @@ public function testDeserializeNoNormalizer() */ public function testDeserializeWrongNormalizer() { - $this->serializer = new Serializer(array(new CustomNormalizer()), array('json' => new JsonEncoder())); + $serializer = new Serializer(array(new CustomNormalizer()), array('json' => new JsonEncoder())); $data = array('title' => 'foo', 'numbers' => array(5, 3)); - $this->serializer->deserialize(json_encode($data), '\Symfony\Component\Serializer\Tests\Model', 'json'); + $serializer->deserialize(json_encode($data), '\Symfony\Component\Serializer\Tests\Model', 'json'); } /** @@ -179,45 +179,45 @@ public function testDeserializeWrongNormalizer() */ public function testDeserializeNoEncoder() { - $this->serializer = new Serializer(array(), array()); + $serializer = new Serializer(array(), array()); $data = array('title' => 'foo', 'numbers' => array(5, 3)); - $this->serializer->deserialize(json_encode($data), '\Symfony\Component\Serializer\Tests\Model', 'json'); + $serializer->deserialize(json_encode($data), '\Symfony\Component\Serializer\Tests\Model', 'json'); } public function testDeserializeSupported() { - $this->serializer = new Serializer(array(new GetSetMethodNormalizer()), array()); + $serializer = new Serializer(array(new GetSetMethodNormalizer()), array()); $data = array('title' => 'foo', 'numbers' => array(5, 3)); - $this->assertTrue($this->serializer->supportsDenormalization(json_encode($data), '\Symfony\Component\Serializer\Tests\Model', 'json')); + $this->assertTrue($serializer->supportsDenormalization(json_encode($data), '\Symfony\Component\Serializer\Tests\Model', 'json')); } public function testDeserializeNotSupported() { - $this->serializer = new Serializer(array(new GetSetMethodNormalizer()), array()); + $serializer = new Serializer(array(new GetSetMethodNormalizer()), array()); $data = array('title' => 'foo', 'numbers' => array(5, 3)); - $this->assertFalse($this->serializer->supportsDenormalization(json_encode($data), 'stdClass', 'json')); + $this->assertFalse($serializer->supportsDenormalization(json_encode($data), 'stdClass', 'json')); } public function testDeserializeNotSupportedMissing() { - $this->serializer = new Serializer(array(), array()); + $serializer = new Serializer(array(), array()); $data = array('title' => 'foo', 'numbers' => array(5, 3)); - $this->assertFalse($this->serializer->supportsDenormalization(json_encode($data), '\Symfony\Component\Serializer\Tests\Model', 'json')); + $this->assertFalse($serializer->supportsDenormalization(json_encode($data), '\Symfony\Component\Serializer\Tests\Model', 'json')); } public function testEncode() { - $this->serializer = new Serializer(array(), array('json' => new JsonEncoder())); + $serializer = new Serializer(array(), array('json' => new JsonEncoder())); $data = array('foo', array(5, 3)); - $result = $this->serializer->encode($data, 'json'); + $result = $serializer->encode($data, 'json'); $this->assertEquals(json_encode($data), $result); } public function testDecode() { - $this->serializer = new Serializer(array(), array('json' => new JsonEncoder())); + $serializer = new Serializer(array(), array('json' => new JsonEncoder())); $data = array('foo', array(5, 3)); - $result = $this->serializer->decode(json_encode($data), 'json'); + $result = $serializer->decode(json_encode($data), 'json'); $this->assertEquals($data, $result); } } diff --git a/src/Symfony/Component/Validator/Validator/RecursiveContextualValidator.php b/src/Symfony/Component/Validator/Validator/RecursiveContextualValidator.php index d632d05d3f4e3..e27f6f637fc36 100644 --- a/src/Symfony/Component/Validator/Validator/RecursiveContextualValidator.php +++ b/src/Symfony/Component/Validator/Validator/RecursiveContextualValidator.php @@ -44,6 +44,16 @@ class RecursiveContextualValidator implements ContextualValidatorInterface */ private $context; + /** + * @var string + */ + private $defaultPropertyPath; + + /** + * @var array + */ + private $defaultGroups; + /** * @var MetadataFactoryInterface */ From c28796ed746cc5d61114cbd41e3cc2601b4311a8 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Tue, 8 Sep 2015 16:34:41 +0100 Subject: [PATCH 0052/2143] Use stderr by default when a specific output is not injected --- .../Bridge/Monolog/Handler/ConsoleHandler.php | 13 ++++----- .../Tests/Handler/ConsoleHandlerTest.php | 27 +------------------ 2 files changed, 8 insertions(+), 32 deletions(-) diff --git a/src/Symfony/Bridge/Monolog/Handler/ConsoleHandler.php b/src/Symfony/Bridge/Monolog/Handler/ConsoleHandler.php index a4c19cdb6af1d..592584ffa4af0 100644 --- a/src/Symfony/Bridge/Monolog/Handler/ConsoleHandler.php +++ b/src/Symfony/Bridge/Monolog/Handler/ConsoleHandler.php @@ -120,7 +120,12 @@ public function close() */ public function onCommand(ConsoleCommandEvent $event) { - $this->setOutput($event->getOutput()); + $output = $event->getOutput(); + if ($output instanceof ConsoleOutputInterface) { + $output = $output->getErrorOutput(); + } + + $this->setOutput($output); } /** @@ -149,11 +154,7 @@ public static function getSubscribedEvents() */ protected function write(array $record) { - if ($record['level'] >= Logger::ERROR && $this->output instanceof ConsoleOutputInterface) { - $this->output->getErrorOutput()->write((string) $record['formatted']); - } else { - $this->output->write((string) $record['formatted']); - } + $this->output->write((string) $record['formatted']); } /** diff --git a/src/Symfony/Bridge/Monolog/Tests/Handler/ConsoleHandlerTest.php b/src/Symfony/Bridge/Monolog/Tests/Handler/ConsoleHandlerTest.php index 65f259693ba3e..6cb315967e4fc 100644 --- a/src/Symfony/Bridge/Monolog/Tests/Handler/ConsoleHandlerTest.php +++ b/src/Symfony/Bridge/Monolog/Tests/Handler/ConsoleHandlerTest.php @@ -110,7 +110,7 @@ public function testGetFormatter() public function testWritingAndFormatting() { - $output = $this->getMock('Symfony\Component\Console\Output\ConsoleOutputInterface'); + $output = $this->getMock('Symfony\Component\Console\Output\OutputInterface'); $output ->expects($this->any()) ->method('getVerbosity') @@ -122,19 +122,6 @@ public function testWritingAndFormatting() ->with('[2013-05-29 16:21:54] app.INFO: My info message '."\n") ; - $errorOutput = $this->getMock('Symfony\Component\Console\Output\OutputInterface'); - $errorOutput - ->expects($this->once()) - ->method('write') - ->with('[2013-05-29 16:21:54] app.ERROR: My error message '."\n") - ; - - $output - ->expects($this->any()) - ->method('getErrorOutput') - ->will($this->returnValue($errorOutput)) - ; - $handler = new ConsoleHandler(null, false); $handler->setOutput($output); @@ -149,18 +136,6 @@ public function testWritingAndFormatting() ); $this->assertTrue($handler->handle($infoRecord), 'The handler finished handling the log as bubble is false.'); - - $errorRecord = array( - 'message' => 'My error message', - 'context' => array(), - 'level' => Logger::ERROR, - 'level_name' => Logger::getLevelName(Logger::ERROR), - 'channel' => 'app', - 'datetime' => new \DateTime('2013-05-29 16:21:54'), - 'extra' => array(), - ); - - $this->assertTrue($handler->handle($errorRecord), 'The handler finished handling the log as bubble is false.'); } public function testLogsFromListeners() From 50afff16471e8c829279548ae5c2b7ab1098bf4a Mon Sep 17 00:00:00 2001 From: Tobias Schultze Date: Mon, 14 Sep 2015 14:10:47 +0200 Subject: [PATCH 0053/2143] [Console] fix typo in OutputInterface --- src/Symfony/Component/Console/Output/OutputInterface.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Console/Output/OutputInterface.php b/src/Symfony/Component/Console/Output/OutputInterface.php index f7f30636feb09..edffb9ca8eac1 100644 --- a/src/Symfony/Component/Console/Output/OutputInterface.php +++ b/src/Symfony/Component/Console/Output/OutputInterface.php @@ -48,7 +48,7 @@ public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL); /** * Writes a message to the output and adds a newline at the end. * - * @param string|array $messages The message as an array of lines of a single string + * @param string|array $messages The message as an array of lines or a single string * @param int $type The type of output (one of the OUTPUT constants) * * @throws \InvalidArgumentException When unknown output type is given From c0363524a987c624f2b1627696c60d77c8bba313 Mon Sep 17 00:00:00 2001 From: Tobias Schultze Date: Mon, 14 Sep 2015 14:22:54 +0200 Subject: [PATCH 0054/2143] [Console] update param type phpdoc for StreamOutput --- src/Symfony/Component/Console/Output/StreamOutput.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Console/Output/StreamOutput.php b/src/Symfony/Component/Console/Output/StreamOutput.php index 6a8305c709654..86fe1827e95fc 100644 --- a/src/Symfony/Component/Console/Output/StreamOutput.php +++ b/src/Symfony/Component/Console/Output/StreamOutput.php @@ -35,7 +35,7 @@ class StreamOutput extends Output /** * Constructor. * - * @param mixed $stream A stream resource + * @param resource $stream A stream resource * @param int $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface) * @param bool|null $decorated Whether to decorate messages (null for auto-guessing) * @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter) From dc57a7a5a7670b3103f1882845bfdb07138422db Mon Sep 17 00:00:00 2001 From: Daniel Tschinder Date: Wed, 25 Feb 2015 22:18:34 +0100 Subject: [PATCH 0055/2143] [DomCrawler] Invalid uri created from forms if base tag present --- src/Symfony/Component/DomCrawler/Crawler.php | 2 +- src/Symfony/Component/DomCrawler/Form.php | 13 ++++++++++++- .../Component/DomCrawler/Tests/CrawlerTest.php | 3 +++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/DomCrawler/Crawler.php b/src/Symfony/Component/DomCrawler/Crawler.php index 823f1352397d1..84ce8f3f8db0f 100644 --- a/src/Symfony/Component/DomCrawler/Crawler.php +++ b/src/Symfony/Component/DomCrawler/Crawler.php @@ -755,7 +755,7 @@ public function form(array $values = null, $method = null) throw new \InvalidArgumentException('The current node list is empty.'); } - $form = new Form($this->getNode(0), $this->uri, $method); + $form = new Form($this->getNode(0), $this->uri, $method, $this->baseHref); if (null !== $values) { $form->setValues($values); diff --git a/src/Symfony/Component/DomCrawler/Form.php b/src/Symfony/Component/DomCrawler/Form.php index b0462f098f817..a447c830d541d 100644 --- a/src/Symfony/Component/DomCrawler/Form.php +++ b/src/Symfony/Component/DomCrawler/Form.php @@ -33,20 +33,27 @@ class Form extends Link implements \ArrayAccess */ private $fields; + /** + * @var string + */ + private $baseHref; + /** * Constructor. * * @param \DOMNode $node A \DOMNode instance * @param string $currentUri The URI of the page where the form is embedded * @param string $method The method to use for the link (if null, it defaults to the method defined by the form) + * @param string $baseHref The URI of the used for relative links, but not for empty action * * @throws \LogicException if the node is not a button inside a form tag * * @api */ - public function __construct(\DOMNode $node, $currentUri, $method = null) + public function __construct(\DOMNode $node, $currentUri, $method = null, $baseHref = null) { parent::__construct($node, $currentUri, $method); + $this->baseHref = $baseHref; $this->initialize(); } @@ -442,6 +449,10 @@ private function initialize() $this->addField($node); } } + + if ($this->baseHref && '' !== $this->node->getAttribute('action')) { + $this->currentUri = $this->baseHref; + } } private function addField(\DOMNode $node) diff --git a/src/Symfony/Component/DomCrawler/Tests/CrawlerTest.php b/src/Symfony/Component/DomCrawler/Tests/CrawlerTest.php index 9906fedc7e209..ca7802d45d4f8 100644 --- a/src/Symfony/Component/DomCrawler/Tests/CrawlerTest.php +++ b/src/Symfony/Component/DomCrawler/Tests/CrawlerTest.php @@ -853,9 +853,12 @@ public function testBaseTagWithForm($baseValue, $actionValue, $expectedUri, $cur public function getBaseTagWithFormData() { return array( + array('https://base.com/', 'link/', 'https://base.com/link/', 'https://base.com/link/', ' tag does work with a path and relative form action'), array('/basepath', '/registration', 'http://domain.com/registration', 'http://domain.com/registration', ' tag does work with a path and form action'), array('/basepath', '', 'http://domain.com/registration', 'http://domain.com/registration', ' tag does work with a path and empty form action'), + array('http://base.com/', '/registration', 'http://base.com/registration', 'http://domain.com/registration', ' tag does work with a URL and form action'), array('http://base.com', '', 'http://domain.com/path/form', 'http://domain.com/path/form', ' tag does work with a URL and an empty form action'), + array('http://base.com/path', '/registration', 'http://base.com/registration', 'http://domain.com/path/form', ' tag does work with a URL and form action'), ); } From fd22d8fa0353f9b7a92fb3b0f6b4a2d95eebfc5d Mon Sep 17 00:00:00 2001 From: Tobias Schultze Date: Mon, 14 Sep 2015 17:16:40 +0200 Subject: [PATCH 0056/2143] [Console] fix phpdoc of DialogHelper --- src/Symfony/Component/Console/Helper/DialogHelper.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Console/Helper/DialogHelper.php b/src/Symfony/Component/Console/Helper/DialogHelper.php index adbf1869c0239..fbb0f06623a84 100644 --- a/src/Symfony/Component/Console/Helper/DialogHelper.php +++ b/src/Symfony/Component/Console/Helper/DialogHelper.php @@ -385,7 +385,7 @@ public function setInputStream($stream) /** * Returns the helper's input stream. * - * @return string + * @return resource|null The input stream or null if the default STDIN is used */ public function getInputStream() { From 68353a6305159210eb5852494b5a7fb786f703b5 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 14 Sep 2015 17:18:35 +0200 Subject: [PATCH 0057/2143] fixed composer.json --- src/Symfony/Bundle/FrameworkBundle/composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index 68c03a912e4d0..9bec22ef534bb 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -49,7 +49,7 @@ "symfony/finder": "For using the translation loader and cache warmer", "symfony/form": "For using forms", "symfony/validator": "For using validation", - "symfony/serializer": "For using the serializer service", + "symfony/serializer": "For using the serializer service" }, "autoload": { "psr-0": { "Symfony\\Bundle\\FrameworkBundle\\": "" } From 90c2a96936435a72bd4ae65cbaedc8cb7dc98050 Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Mon, 14 Sep 2015 19:21:18 +0200 Subject: [PATCH 0058/2143] Default to stderr for console helpers (only merge if #15794 gets merged) --- src/Symfony/Component/Console/Helper/ProcessHelper.php | 9 +++++++++ src/Symfony/Component/Console/Helper/ProgressBar.php | 5 +++++ src/Symfony/Component/Console/Helper/QuestionHelper.php | 5 +++++ 3 files changed, 19 insertions(+) diff --git a/src/Symfony/Component/Console/Helper/ProcessHelper.php b/src/Symfony/Component/Console/Helper/ProcessHelper.php index 0c9da73947623..a811eb48e6798 100644 --- a/src/Symfony/Component/Console/Helper/ProcessHelper.php +++ b/src/Symfony/Component/Console/Helper/ProcessHelper.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Console\Helper; +use Symfony\Component\Console\Output\ConsoleOutputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Process\Exception\ProcessFailedException; use Symfony\Component\Process\Process; @@ -37,6 +38,10 @@ class ProcessHelper extends Helper */ public function run(OutputInterface $output, $cmd, $error = null, $callback = null, $verbosity = OutputInterface::VERBOSITY_VERY_VERBOSE) { + if ($output instanceof ConsoleOutputInterface) { + $output = $output->getErrorOutput(); + } + $formatter = $this->getHelperSet()->get('debug_formatter'); if (is_array($cmd)) { @@ -109,6 +114,10 @@ public function mustRun(OutputInterface $output, $cmd, $error = null, $callback */ public function wrapCallback(OutputInterface $output, Process $process, $callback = null) { + if ($output instanceof ConsoleOutputInterface) { + $output = $output->getErrorOutput(); + } + $formatter = $this->getHelperSet()->get('debug_formatter'); $that = $this; diff --git a/src/Symfony/Component/Console/Helper/ProgressBar.php b/src/Symfony/Component/Console/Helper/ProgressBar.php index 5bc3de4e7390e..7f4b2efb8d5ae 100644 --- a/src/Symfony/Component/Console/Helper/ProgressBar.php +++ b/src/Symfony/Component/Console/Helper/ProgressBar.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Console\Helper; +use Symfony\Component\Console\Output\ConsoleOutputInterface; use Symfony\Component\Console\Output\OutputInterface; /** @@ -54,6 +55,10 @@ class ProgressBar */ public function __construct(OutputInterface $output, $max = 0) { + if ($output instanceof ConsoleOutputInterface) { + $output = $output->getErrorOutput(); + } + $this->output = $output; $this->setMaxSteps($max); diff --git a/src/Symfony/Component/Console/Helper/QuestionHelper.php b/src/Symfony/Component/Console/Helper/QuestionHelper.php index 6584377aad015..a533f8728df3e 100644 --- a/src/Symfony/Component/Console/Helper/QuestionHelper.php +++ b/src/Symfony/Component/Console/Helper/QuestionHelper.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Console\Helper; use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\ConsoleOutputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Formatter\OutputFormatterStyle; use Symfony\Component\Console\Question\Question; @@ -41,6 +42,10 @@ class QuestionHelper extends Helper */ public function ask(InputInterface $input, OutputInterface $output, Question $question) { + if ($output instanceof ConsoleOutputInterface) { + $output = $output->getErrorOutput(); + } + if (!$input->isInteractive()) { return $question->getDefault(); } From e24a798d8f84f71b8d3f34063ca6856d715a1076 Mon Sep 17 00:00:00 2001 From: Michael Lee Date: Mon, 3 Aug 2015 15:13:18 +0800 Subject: [PATCH 0059/2143] [property-access] Improvement for Accessing Reference Chain Improve performance for the following scenarios: - Example 1: ```php $a = array( 'a' => array( 'b' => array( 'c' => 'old-value' ) ) ); $pa->setValue($a, '[a][b][c]', 'new-value'); // The PropertyAccessor will try to set values for // $a['a']['b']['c'], $a['a']['b'] and $a['a'], // but in fact it may terminate the loop // right after the value of $a[a][b][c] is set, // because $a, $[a], $[a][b] and $[a][b][c] // are all passed as reference - the reference chain is not broken. ``` - Example 2 ```php $b = array( 'a' => array( 'b' => array( 'c' => 'old-value' ) ) ) $a = new Foo($b); // In this example, the reference chain of $b is broken, // because it's passed to $a.value as value // But its elements are all passed as reference, // so after setting the value for $b[a][b][c], there is no need // to set value for $b[a][b] and $b[a] $pa->setValue($a, 'value[a][b][c]', 'new-value'); ``` | Q | A | ------------- | --- | Bug fix? | no | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | n/a | License | MIT | Doc PR | n/a --- .../PropertyAccess/PropertyAccessor.php | 45 +++++++++++++++---- 1 file changed, 37 insertions(+), 8 deletions(-) diff --git a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php index d4e8c78a9b408..3b7a50e2fe0f1 100644 --- a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php +++ b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php @@ -25,6 +25,7 @@ class PropertyAccessor implements PropertyAccessorInterface { const VALUE = 0; const IS_REF = 1; + const IS_REF_CHAINED = 2; /** * @var bool @@ -75,6 +76,7 @@ public function setValue(&$objectOrArray, $propertyPath, $value) array_unshift($propertyValues, array( self::VALUE => &$objectOrArray, self::IS_REF => true, + self::IS_REF_CHAINED => true, )); for ($i = count($propertyValues) - 1; $i >= 0; --$i) { @@ -82,14 +84,33 @@ public function setValue(&$objectOrArray, $propertyPath, $value) $property = $propertyPath->getElement($i); - if ($propertyPath->isIndex($i)) { - $this->writeIndex($objectOrArray, $property, $value); - } else { - $this->writeProperty($objectOrArray, $property, $value); - } + // You only need set value for current element if: + // 1. it's the parent of the last index element + // OR + // 2. its child is not passed by reference + // + // This may avoid uncessary value setting process for array elements. + // For example: + // '[a][b][c]' => 'old-value' + // If you want to change its value to 'new-value', + // you only need set value for '[a][b][c]' and it's safe to ignore '[a][b]' and '[a]' + // + if ($i === count($propertyValues) - 1 || !$propertyValues[$i + 1][self::IS_REF]) { + if ($propertyPath->isIndex($i)) { + $this->writeIndex($objectOrArray, $property, $value); + } else { + $this->writeProperty($objectOrArray, $property, $value); + } + + // if current element is an object + // OR + // if current element's reference chain is not broken - current element + // as well as all its ancients in the property path are all passed by reference, + // then there is no need to continue the value setting process + if (is_object($propertyValues[$i][self::VALUE]) || $propertyValues[$i][self::IS_REF_CHAINED]) { + return; + } - if ($propertyValues[$i][self::IS_REF] && is_object($objectOrArray)) { - return; } $value = &$objectOrArray; @@ -132,6 +153,7 @@ public function isWritable($objectOrArray, $propertyPath) array_unshift($propertyValues, array( self::VALUE => $objectOrArray, self::IS_REF => true, + self::IS_REF_CHAINED => true, )); for ($i = count($propertyValues) - 1; $i >= 0; --$i) { @@ -149,7 +171,7 @@ public function isWritable($objectOrArray, $propertyPath) } } - if ($propertyValues[$i][self::IS_REF] && is_object($objectOrArray)) { + if (is_object($propertyValues[$i][self::VALUE]) || $propertyValues[$i][self::IS_REF_CHAINED]) { return true; } } @@ -232,6 +254,13 @@ private function &readPropertiesUntil(&$objectOrArray, PropertyPathInterface $pr throw new UnexpectedTypeException($objectOrArray, $propertyPath, $i + 1); } + // Set the IS_REF_CHAINED flag to true if: + // current property is passed by reference and + // it is the first element in the property path or + // the IS_REF_CHAINED flag of its parent element is true + // Basically, this flag is true only when the reference chain from the top element to current element is not broken + $propertyValue[self::IS_REF_CHAINED] = $propertyValue[self::IS_REF] && ($i == 0 || $propertyValues[$i - 1][self::IS_REF_CHAINED]); + $propertyValues[] = &$propertyValue; } From e5bf0ab8770458e592c096c7ce24a5b270cf5b0b Mon Sep 17 00:00:00 2001 From: Christophe Coevoet Date: Tue, 15 Sep 2015 11:15:55 +0200 Subject: [PATCH 0060/2143] Exclude files based on path before applying the sorting Sorting can be slow, so it is best to applied it after all filtering rules are applied instead of using a bigger list and filtering again after that. --- src/Symfony/Component/Finder/Adapter/PhpAdapter.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/Finder/Adapter/PhpAdapter.php b/src/Symfony/Component/Finder/Adapter/PhpAdapter.php index 378a26acdad14..d8c32dbb4f8ef 100644 --- a/src/Symfony/Component/Finder/Adapter/PhpAdapter.php +++ b/src/Symfony/Component/Finder/Adapter/PhpAdapter.php @@ -68,15 +68,15 @@ public function searchInDirectory($dir) $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters); } + if ($this->paths || $this->notPaths) { + $iterator = new Iterator\PathFilterIterator($iterator, $this->paths, $this->notPaths); + } + if ($this->sort) { $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort); $iterator = $iteratorAggregate->getIterator(); } - if ($this->paths || $this->notPaths) { - $iterator = new Iterator\PathFilterIterator($iterator, $this->paths, $this->notPaths); - } - return $iterator; } From 8c691bd01fe0189df6a118059fe5330733e27930 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 15 Sep 2015 09:27:50 +0200 Subject: [PATCH 0061/2143] [Finder] Handle filtering of recursive iterators and use it to skip looping over excluded directories --- .../Component/Finder/Adapter/PhpAdapter.php | 15 +++++++-------- .../Component/Finder/Iterator/FilterIterator.php | 12 +++++++++++- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/Symfony/Component/Finder/Adapter/PhpAdapter.php b/src/Symfony/Component/Finder/Adapter/PhpAdapter.php index d8c32dbb4f8ef..e8ada3671cfe6 100644 --- a/src/Symfony/Component/Finder/Adapter/PhpAdapter.php +++ b/src/Symfony/Component/Finder/Adapter/PhpAdapter.php @@ -31,10 +31,13 @@ public function searchInDirectory($dir) $flags |= \RecursiveDirectoryIterator::FOLLOW_SYMLINKS; } - $iterator = new \RecursiveIteratorIterator( - new Iterator\RecursiveDirectoryIterator($dir, $flags, $this->ignoreUnreadableDirs), - \RecursiveIteratorIterator::SELF_FIRST - ); + $iterator = new Iterator\RecursiveDirectoryIterator($dir, $flags, $this->ignoreUnreadableDirs); + + if ($this->exclude) { + $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude); + } + + $iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::SELF_FIRST); if ($this->minDepth > 0 || $this->maxDepth < PHP_INT_MAX) { $iterator = new Iterator\DepthRangeFilterIterator($iterator, $this->minDepth, $this->maxDepth); @@ -44,10 +47,6 @@ public function searchInDirectory($dir) $iterator = new Iterator\FileTypeFilterIterator($iterator, $this->mode); } - if ($this->exclude) { - $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude); - } - if ($this->names || $this->notNames) { $iterator = new Iterator\FilenameFilterIterator($iterator, $this->names, $this->notNames); } diff --git a/src/Symfony/Component/Finder/Iterator/FilterIterator.php b/src/Symfony/Component/Finder/Iterator/FilterIterator.php index f4da44c4cdd59..c5290cc80fb82 100644 --- a/src/Symfony/Component/Finder/Iterator/FilterIterator.php +++ b/src/Symfony/Component/Finder/Iterator/FilterIterator.php @@ -18,8 +18,18 @@ * * @author Alex Bogomazov */ -abstract class FilterIterator extends \FilterIterator +abstract class FilterIterator extends \FilterIterator implements \RecursiveIterator { + public function hasChildren() + { + return $this->getInnerIterator() instanceof \RecursiveIterator && $this->getInnerIterator()->hasChildren(); + } + + public function getChildren() + { + return $this->getInnerIterator()->getChildren(); + } + /** * This is a workaround for the problem with \FilterIterator leaving inner \FilesystemIterator in wrong state after * rewind in some cases. From 4c7bb9cd146faa17c24e7e760235fcc5c40ca725 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 15 Sep 2015 14:30:50 +0200 Subject: [PATCH 0062/2143] [VarDumper] Fix HtmlDumper constructor calling CliDumper's --- src/Symfony/Component/VarDumper/Du 8000 mper/HtmlDumper.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php b/src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php index 48d5cffa40889..1c42e763620dd 100644 --- a/src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php +++ b/src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php @@ -50,7 +50,7 @@ class HtmlDumper extends CliDumper */ public function __construct($output = null, $charset = null) { - parent::__construct($output, $charset); + AbstractDumper::__construct($output, $charset); $this->dumpId = 'sf-dump-'.mt_rand(); } From 20f2d03d2eee8f8cc94fbc576efb7d33cd5f40fb Mon Sep 17 00:00:00 2001 From: Christophe Coevoet Date: Tue, 15 Sep 2015 17:55:56 +0200 Subject: [PATCH 0063/2143] Improve the structure of the Finder testsuite Testing against different adapters is now handled by multiple subclasses of a common test case rather than using data providers. This allows tests to be marked as skipped for unsupported adapters instead of making them disappear from the testsuite. --- .../Component/Finder/Tests/BsdFinderTest.php | 28 ++ .../Component/Finder/Tests/FinderTest.php | 448 +++++++----------- .../Component/Finder/Tests/GnuFinderTest.php | 28 ++ .../Tests/Iterator/IteratorTestCase.php | 2 +- 4 files changed, 220 insertions(+), 286 deletions(-) create mode 100644 src/Symfony/Component/Finder/Tests/BsdFinderTest.php create mode 100644 src/Symfony/Component/Finder/Tests/GnuFinderTest.php diff --git a/src/Symfony/Component/Finder/Tests/BsdFinderTest.php b/src/Symfony/Component/Finder/Tests/BsdFinderTest.php new file mode 100644 index 0000000000000..42691a4318531 --- /dev/null +++ b/src/Symfony/Component/Finder/Tests/BsdFinderTest.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Finder\Tests; + +use Symfony\Component\Finder\Adapter\BsdFindAdapter; + +class BsdFinderTest extends FinderTest +{ + protected function getAdapter() + { + $adapter = new BsdFindAdapter(); + + if (!$adapter->isSupported()) { + $this->markTestSkipped(get_class($adapter).' is not supported.'); + } + + return $adapter; + } +} diff --git a/src/Symfony/Component/Finder/Tests/FinderTest.php b/src/Symfony/Component/Finder/Tests/FinderTest.php index 92f38ab94c7fb..337dd9911d9ed 100644 --- a/src/Symfony/Component/Finder/Tests/FinderTest.php +++ b/src/Symfony/Component/Finder/Tests/FinderTest.php @@ -11,8 +11,10 @@ namespace Symfony\Component\Finder\Tests; +use Symfony\Component\Finder\Adapter\AdapterInterface; +use Symfony\Component\Finder\Adapter\GnuFindAdapter; +use Symfony\Component\Finder\Adapter\PhpAdapter; use Symfony\Component\Finder\Finder; -use Symfony\Component\Finder\Adapter; class FinderTest extends Iterator\RealIteratorTestCase { @@ -21,109 +23,94 @@ public function testCreate() $this->assertInstanceOf('Symfony\Component\Finder\Finder', Finder::create()); } - /** - * @dataProvider getAdaptersTestData - */ - public function testDirectories($adapter) + public function testDirectories() { - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $this->assertSame($finder, $finder->directories()); $this->assertIterator($this->toAbsolute(array('foo', 'toto')), $finder->in(self::$tmpDir)->getIterator()); - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $finder->directories(); $finder->files(); $finder->directories(); $this->assertIterator($this->toAbsolute(array('foo', 'toto')), $finder->in(self::$tmpDir)->getIterator()); } - /** - * @dataProvider getAdaptersTestData - */ - public function testFiles($adapter) + public function testFiles() { - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $this->assertSame($finder, $finder->files()); $this->assertIterator($this->toAbsolute(array('foo/bar.tmp', 'test.php', 'test.py', 'foo bar')), $finder->in(self::$tmpDir)->getIterator()); - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $finder->files(); $finder->directories(); $finder->files(); $this->assertIterator($this->toAbsolute(array('foo/bar.tmp', 'test.php', 'test.py', 'foo bar')), $finder->in(self::$tmpDir)->getIterator()); } - /** - * @dataProvider getAdaptersTestData - */ - public function testDepth($adapter) + public function testDepth() { - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $this->assertSame($finder, $finder->depth('< 1')); $this->assertIterator($this->toAbsolute(array('foo', 'test.php', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator()); - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $this->assertSame($finder, $finder->depth('<= 0')); $this->assertIterator($this->toAbsolute(array('foo', 'test.php', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator()); - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $this->assertSame($finder, $finder->depth('>= 1')); $this->assertIterator($this->toAbsolute(array('foo/bar.tmp')), $finder->in(self::$tmpDir)->getIterator()); - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $finder->depth('< 1')->depth('>= 1'); $this->assertIterator(array(), $finder->in(self::$tmpDir)->getIterator()); } - /** - * @dataProvider getAdaptersTestData - */ - public function testName($adapter) + public function testName() { - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $this->assertSame($finder, $finder->name('*.php')); $this->assertIterator($this->toAbsolute(array('test.php')), $finder->in(self::$tmpDir)->getIterator()); - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $finder->name('test.ph*'); $finder->name('test.py'); $this->assertIterator($this->toAbsolute(array('test.php', 'test.py')), $finder->in(self::$tmpDir)->getIterator()); - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $finder->name('~^test~i'); $this->assertIterator($this->toAbsolute(array('test.php', 'test.py')), $finder->in(self::$tmpDir)->getIterator()); - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $finder->name('~\\.php$~i'); $this->assertIterator($this->toAbsolute(array('test.php')), $finder->in(self::$tmpDir)->getIterator()); - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $finder->name('test.p{hp,y}'); $this->assertIterator($this->toAbsolute(array('test.php', 'test.py')), $finder->in(self::$tmpDir)->getIterator()); } - /** - * @dataProvider getAdaptersTestData - */ - public function testNotName($adapter) + public function testNotName() { - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $this->assertSame($finder, $finder->notName('*.php')); $this->assertIterator($this->toAbsolute(array('foo', 'foo/bar.tmp', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator()); - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $finder->notName('*.php'); $finder->notName('*.py'); $this->assertIterator($this->toAbsolute(array('foo', 'foo/bar.tmp', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator()); - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $finder->name('test.ph*'); $finder->name('test.py'); $finder->notName('*.php'); $finder->notName('*.py'); $this->assertIterator(array(), $finder->in(self::$tmpDir)->getIterator()); - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $finder->name('test.ph*'); $finder->name('test.py'); $finder->notName('*.p{hp,y}'); @@ -133,217 +120,177 @@ public function testNotName($adapter) /** * @dataProvider getRegexNameTestData */ - public function testRegexName($adapter, $regex) + public function testRegexName($regex) { - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $finder->name($regex); $this->assertIterator($this->toAbsolute(array('test.py', 'test.php')), $finder->in(self::$tmpDir)->getIterator()); } - /** - * @dataProvider getAdaptersTestData - */ - public function testSize($adapter) + public function testSize() { - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $this->assertSame($finder, $finder->files()->size('< 1K')->size('> 500')); $this->assertIterator($this->toAbsolute(array('test.php')), $finder->in(self::$tmpDir)->getIterator()); } - /** - * @dataProvider getAdaptersTestData - */ - public function testDate($adapter) + public function testDate() { - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $this->assertSame($finder, $finder->files()->date('until last month')); $this->assertIterator($this->toAbsolute(array('foo/bar.tmp', 'test.php')), $finder->in(self::$tmpDir)->getIterator()); } - /** - * @dataProvider getAdaptersTestData - */ - public function testExclude($adapter) + public function testExclude() { - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $this->assertSame($finder, $finder->exclude('foo')); $this->assertIterator($this->toAbsolute(array('test.php', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator()); } - /** - * @dataProvider getAdaptersTestData - */ - public function testIgnoreVCS($adapter) + public function testIgnoreVCS() { - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $this->assertSame($finder, $finder->ignoreVCS(false)->ignoreDotFiles(false)); $this->assertIterator($this->toAbsolute(array('.git', 'foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', '.bar', '.foo', '.foo/.bar', '.foo/bar', 'foo bar')), $finder->in(self::$tmpDir)->getIterator()); - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $finder->ignoreVCS(false)->ignoreVCS(false)->ignoreDotFiles(false); $this->assertIterator($this->toAbsolute(array('.git', 'foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', '.bar', '.foo', '.foo/.bar', '.foo/bar', 'foo bar')), $finder->in(self::$tmpDir)->getIterator()); - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $this->assertSame($finder, $finder->ignoreVCS(true)->ignoreDotFiles(false)); $this->assertIterator($this->toAbsolute(array('foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', '.bar', '.foo', '.foo/.bar', '.foo/bar', 'foo bar')), $finder->in(self::$tmpDir)->getIterator()); } - /** - * @dataProvider getAdaptersTestData - */ - public function testIgnoreDotFiles($adapter) + public function testIgnoreDotFiles() { - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $this->assertSame($finder, $finder->ignoreDotFiles(false)->ignoreVCS(false)); $this->assertIterator($this->toAbsolute(array('.git', '.bar', '.foo', '.foo/.bar', '.foo/bar', 'foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator()); - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $finder->ignoreDotFiles(false)->ignoreDotFiles(false)->ignoreVCS(false); $this->assertIterator($this->toAbsolute(array('.git', '.bar', '.foo', '.foo/.bar', '.foo/bar', 'foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator()); - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $this->assertSame($finder, $finder->ignoreDotFiles(true)->ignoreVCS(false)); $this->assertIterator($this->toAbsolute(array('foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator()); } - /** - * @dataProvider getAdaptersTestData - */ - public function testSortByName($adapter) + public function testSortByName() { - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $this->assertSame($finder, $finder->sortByName()); $this->assertIterator($this->toAbsolute(array('foo', 'foo bar', 'foo/bar.tmp', 'test.php', 'test.py', 'toto')), $finder->in(self::$tmpDir)->getIterator()); } - /** - * @dataProvider getAdaptersTestData - */ - public function testSortByType($adapter) + public function testSortByType() { - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $this->assertSame($finder, $finder->sortByType()); $this->assertIterator($this->toAbsolute(array('foo', 'foo bar', 'toto', 'foo/bar.tmp', 'test.php', 'test.py')), $finder->in(self::$tmpDir)->getIterator()); } - /** - * @dataProvider getAdaptersTestData - */ - public function testSortByAccessedTime($adapter) + public function testSortByAccessedTime() { - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $this->assertSame($finder, $finder->sortByAccessedTime()); $this->assertIterator($this->toAbsolute(array('foo/bar.tmp', 'test.php', 'toto', 'test.py', 'foo', 'foo bar')), $finder->in(self::$tmpDir)->getIterator()); } - /** - * @dataProvider getAdaptersTestData - */ - public function testSortByChangedTime($adapter) + public function testSortByChangedTime() { - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $this->assertSame($finder, $finder->sortByChangedTime()); $this->assertIterator($this->toAbsolute(array('toto', 'test.py', 'test.php', 'foo/bar.tmp', 'foo', 'foo bar')), $finder->in(self::$tmpDir)->getIterator()); } - /** - * @dataProvider getAdaptersTestData - */ - public function testSortByModifiedTime($adapter) + public function testSortByModifiedTime() { - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $this->assertSame($finder, $finder->sortByModifiedTime()); $this->assertIterator($this->toAbsolute(array('foo/bar.tmp', 'test.php', 'toto', 'test.py', 'foo', 'foo bar')), $finder->in(self::$tmpDir)->getIterator()); } - /** - * @dataProvider getAdaptersTestData - */ - public function testSort($adapter) + public function testSort() { - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $this->assertSame($finder, $finder->sort(function (\SplFileInfo $a, \SplFileInfo $b) { return strcmp($a->getRealPath(), $b->getRealPath()); })); $this->assertIterator($this->toAbsolute(array('foo', 'foo bar', 'foo/bar.tmp', 'test.php', 'test.py', 'toto')), $finder->in(self::$tmpDir)->getIterator()); } - /** - * @dataProvider getAdaptersTestData - */ - public function testFilter($adapter) + public function testFilter() { - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $this->assertSame($finder, $finder->filter(function (\SplFileInfo $f) { return false !== strpos($f, 'test'); })); $this->assertIterator($this->toAbsolute(array('test.php', 'test.py')), $finder->in(self::$tmpDir)->getIterator()); } - /** - * @dataProvider getAdaptersTestData - */ - public function testFollowLinks($adapter) + public function testFollowLinks() { if ('\\' == DIRECTORY_SEPARATOR) { - return; + $this->markTestSkipped('symlinks are not supported on Windows'); } - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $this->assertSame($finder, $finder->followLinks()); $this->assertIterator($this->toAbsolute(array('foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator()); } - /** - * @dataProvider getAdaptersTestData - */ - public function testIn($adapter) - { - $finder = $this->buildFinder($adapter); - try { - $finder->in('foobar'); - $this->fail('->in() throws a \InvalidArgumentException if the directory does not exist'); - } catch (\Exception $e) { - $this->assertInstanceOf('InvalidArgumentException', $e, '->in() throws a \InvalidArgumentException if the directory does not exist'); - } - - $finder = $this->buildFinder($adapter); + public function testIn() + { + $finder = $this->buildFinder(); $iterator = $finder->files()->name('*.php')->depth('< 1')->in(array(self::$tmpDir, __DIR__))->getIterator(); - $this->assertIterator(array(self::$tmpDir.DIRECTORY_SEPARATOR.'test.php', __DIR__.DIRECTORY_SEPARATOR.'FinderTest.php'), $iterator); + $expected = array( + self::$tmpDir.DIRECTORY_SEPARATOR.'test.php', + __DIR__.DIRECTORY_SEPARATOR.'BsdFinderTest.php', + __DIR__.DIRECTORY_SEPARATOR.'FinderTest.php', + __DIR__.DIRECTORY_SEPARATOR.'GnuFinderTest.php', + ); + + $this->assertIterator($expected, $iterator); } /** - * @dataProvider getAdaptersTestData + * @expectedException \InvalidArgumentException */ - public function testInWithGlob($adapter) + public function testInWithNonExistentDirectory() { - $finder = $this->buildFinder($adapter); + $finder = new Finder(); + $finder->in('foobar'); + } + + public function testInWithGlob() + { + $finder = $this->buildFinder(); $finder->in(array(__DIR__.'/Fixtures/*/B/C', __DIR__.'/Fixtures/*/*/B/C'))->getIterator(); $this->assertIterator($this->toAbsoluteFixtures(array('A/B/C/abc.dat', 'copy/A/B/C/abc.dat.copy')), $finder); } /** - * @dataProvider getAdaptersTestData * @expectedException \InvalidArgumentException */ - public function testInWithNonDirectoryGlob($adapter) + public function testInWithNonDirectoryGlob() { - $finder = $this->buildFinder($adapter); + $finder = new Finder(); $finder->in(__DIR__.'/Fixtures/A/a*'); } /** - * @dataProvider getAdaptersTestData + * @expectedException \LogicException */ - public function testGetIterator($adapter) - { - $finder = $this->buildFinder($adapter); - try { - $finder->getIterator(); - $this->fail('->getIterator() throws a \LogicException if the in() method has not been called'); - } catch (\Exception $e) { - $this->assertInstanceOf('LogicException', $e, '->getIterator() throws a \LogicException if the in() method has not been called'); - } + public function testGetIteratorWithoutIn() + { + $finder = Finder::create(); + $finder->getIterator(); + } - $finder = $this->buildFinder($adapter); + public function testGetIterator() + { + $finder = $this->buildFinder(); $dirs = array(); foreach ($finder->directories()->in(self::$tmpDir) as $dir) { $dirs[] = (string) $dir; @@ -356,22 +303,19 @@ public function testGetIterator($adapter) $this->assertEquals($expected, $dirs, 'implements the \IteratorAggregate interface'); - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $this->assertEquals(2, iterator_count($finder->directories()->in(self::$tmpDir)), 'implements the \IteratorAggregate interface'); - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $a = iterator_to_array($finder->directories()->in(self::$tmpDir)); $a = array_values(array_map(function ($a) { return (string) $a; }, $a)); sort($a); $this->assertEquals($expected, $a, 'implements the \IteratorAggregate interface'); } - /** - * @dataProvider getAdaptersTestData - */ - public function testRelativePath($adapter) + public function testRelativePath() { - $finder = $this->buildFinder($adapter)->in(self::$tmpDir); + $finder = $this->buildFinder()->in(self::$tmpDir); $paths = array(); @@ -387,12 +331,9 @@ public function testRelativePath($adapter) $this->assertEquals($ref, $paths); } - /** - * @dataProvider getAdaptersTestData - */ - public function testRelativePathname($adapter) + public function testRelativePathname() { - $finder = $this->buildFinder($adapter)->in(self::$tmpDir)->sortByName(); + $finder = $this->buildFinder()->in(self::$tmpDir)->sortByName(); $paths = array(); @@ -408,15 +349,12 @@ public function testRelativePathname($adapter) $this->assertEquals($ref, $paths); } - /** - * @dataProvider getAdaptersTestData - */ - public function testAppendWithAFinder($adapter) + public function testAppendWithAFinder() { - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $finder->files()->in(self::$tmpDir.DIRECTORY_SEPARATOR.'foo'); - $finder1 = $this->buildFinder($adapter); + $finder1 = $this->buildFinder(); $finder1->directories()->in(self::$tmpDir); $finder = $finder->append($finder1); @@ -424,12 +362,9 @@ public function testAppendWithAFinder($adapter) $this->assertIterator($this->toAbsolute(array('foo', 'foo/bar.tmp', 'toto')), $finder->getIterator()); } - /** - * @dataProvider getAdaptersTestData - */ - public function testAppendWithAnArray($adapter) + public function testAppendWithAnArray() { - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $finder->files()->in(self::$tmpDir.DIRECTORY_SEPARATOR.'foo'); $finder->append($this->toAbsolute(array('foo', 'toto'))); @@ -437,20 +372,14 @@ public function testAppendWithAnArray($adapter) $this->assertIterator($this->toAbsolute(array('foo', 'foo/bar.tmp', 'toto')), $finder->getIterator()); } - /** - * @dataProvider getAdaptersTestData - */ - public function testAppendReturnsAFinder($adapter) + public function testAppendReturnsAFinder() { - $this->assertInstanceOf('Symfony\\Component\\Finder\\Finder', $this->buildFinder($adapter)->append(array())); + $this->assertInstanceOf('Symfony\\Component\\Finder\\Finder', Finder::create()->append(array())); } - /** - * @dataProvider getAdaptersTestData - */ - public function testAppendDoesNotRequireIn($adapter) + public function testAppendDoesNotRequireIn() { - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $finder->in(self::$tmpDir.DIRECTORY_SEPARATOR.'foo'); $finder1 = Finder::create()->append($finder); @@ -494,9 +423,9 @@ public function testCountWithoutIn() /** * @dataProvider getContainsTestData */ - public function testContains($adapter, $matchPatterns, $noMatchPatterns, $expected) + public function testContains($matchPatterns, $noMatchPatterns, $expected) { - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $finder->in(__DIR__.DIRECTORY_SEPARATOR.'Fixtures') ->name('*.txt')->sortByName() ->contains($matchPatterns) @@ -505,12 +434,9 @@ public function testContains($adapter, $matchPatterns, $noMatchPatterns, $expect $this->assertIterator($this->toAbsoluteFixtures($expected), $finder); } - /** - * @dataProvider getAdaptersTestData - */ - public function testContainsOnDirectory(Adapter\AdapterInterface $adapter) + public function testContainsOnDirectory() { - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $finder->in(__DIR__) ->directories() ->name('Fixtures') @@ -518,12 +444,9 @@ public function testContainsOnDirectory(Adapter\AdapterInterface $adapter) $this->assertIterator(array(), $finder); } - /** - * @dataProvider getAdaptersTestData - */ - public function testNotContainsOnDirectory(Adapter\AdapterInterface $adapter) + public function testNotContainsOnDirectory() { - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $finder->in(__DIR__) ->directories() ->name('Fixtures') @@ -536,10 +459,8 @@ public function testNotContainsOnDirectory(Adapter\AdapterInterface $adapter) * with inner FilesystemIterator in an invalid state. * * @see https://bugs.php.net/bug.php?id=49104 - * - * @dataProvider getAdaptersTestData */ - public function testMultipleLocations(Adapter\AdapterInterface $adapter) + public function testMultipleLocations() { $locations = array( self::$tmpDir.'/', @@ -547,36 +468,57 @@ public function testMultipleLocations(Adapter\AdapterInterface $adapter) ); // it is expected that there are test.py test.php in the tmpDir - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $finder->in($locations)->depth('< 1')->name('test.php'); $this->assertCount(1, $finder); } /** - * Iterator keys must be the file pathname. + * Searching in multiple locations with sub directories involves + * AppendIterator which does an unnecessary rewind which leaves + * FilterIterator with inner FilesystemIterator in an invalid state. * - * @dataProvider getAdaptersTestData + * @see https://bugs.php.net/bug.php?id=49104 */ - public function testIteratorKeys(Adapter\AdapterInterface $adapter) + public function testMultipleLocationsWithSubDirectories() { - $finder = $this->buildFinder($adapter)->in(self::$tmpDir); + $locations = array( + __DIR__.'/Fixtures/one', + self::$tmpDir.DIRECTORY_SEPARATOR.'toto', + ); + + $finder = $this->buildFinder(); + $finder->in($locations)->depth('< 10')->name('*.neon'); + + $expected = array( + __DIR__.'/Fixtures/one'.DIRECTORY_SEPARATOR.'b'.DIRECTORY_SEPARATOR.'c.neon', + __DIR__.'/Fixtures/one'.DIRECTORY_SEPARATOR.'b'.DIRECTORY_SEPARATOR.'d.neon', + ); + + $this->assertIterator($expected, $finder); + $this->assertIteratorInForeach($expected, $finder); + } + + /** + * Iterator keys must be the file pathname. + */ + public function testIteratorKeys() + { + $finder = $this->buildFinder()->in(self::$tmpDir); foreach ($finder as $key => $file) { $this->assertEquals($file->getPathname(), $key); } } - /** - * @dataProvider getAdaptersTestData - */ - public function testRegexSpecialCharsLocationWithPathRestrictionContainingStartFlag(Adapter\AdapterInterface $adapter) + public function testRegexSpecialCharsLocationWithPathRestrictionContainingStartFlag() { - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $finder->in(__DIR__.DIRECTORY_SEPARATOR.'Fixtures'.DIRECTORY_SEPARATOR.'r+e.gex[c]a(r)s') ->path('/^dir/'); $expected = array('r+e.gex[c]a(r)s'.DIRECTORY_SEPARATOR.'dir', - 'r+e.gex[c]a(r)s'.DIRECTORY_SEPARATOR.'dir'.DIRECTORY_SEPARATOR.'bar.dat',); + 'r+e.gex[c]a(r)s'.DIRECTORY_SEPARATOR.'dir'.DIRECTORY_SEPARATOR.'bar.dat',); $this->assertIterator($this->toAbsoluteFixtures($expected), $finder); } @@ -592,7 +534,7 @@ public function testAdaptersOrdering() $this->assertEquals( array('c', 'e', 'a', 'd', 'b'), - array_map(function (Adapter\AdapterInterface $adapter) { + array_map(function (AdapterInterface $adapter) { return $adapter->getName(); }, $finder->getAdapters()) ); @@ -615,17 +557,9 @@ public function testAdaptersChaining() $this->assertIterator($filenames, $finder->in(sys_get_temp_dir())->getIterator()); } - public function getAdaptersTestData() - { - return array_map( - function ($adapter) { return array($adapter); }, - $this->getValidAdapters() - ); - } - public function getContainsTestData() { - $tests = array( + return array( array('', '', array()), array('foo', 'bar', array()), array('', 'foobar', array('dolor.txt', 'ipsum.txt', 'lorem.txt')), @@ -637,26 +571,22 @@ public function getContainsTestData() array('', 'lorem', array('dolor.txt', 'ipsum.txt')), array('ipsum dolor sit amet', '/^IPSUM/m', array('lorem.txt')), ); - - return $this->buildTestData($tests); } public function getRegexNameTestData() { - $tests = array( + return array( array('~.+\\.p.+~i'), array('~t.*s~i'), ); - - return $this->buildTestData($tests); } /** * @dataProvider getTestPathData */ - public function testPath(Adapter\AdapterInterface $adapter, $matchPatterns, $noMatchPatterns, array $expected) + public function testPath($matchPatterns, $noMatchPatterns, array $expected) { - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $finder->in(__DIR__.DIRECTORY_SEPARATOR.'Fixtures') ->path($matchPatterns) ->notPath($noMatchPatterns); @@ -668,20 +598,20 @@ public function testAdapterSelection() { // test that by default, PhpAdapter is selected $adapters = Finder::create()->getAdapters(); - $this->assertTrue($adapters[0] instanceof Adapter\PhpAdapter); + $this->assertTrue($adapters[0] instanceof PhpAdapter); // test another adapter selection $adapters = Finder::create()->setAdapter('gnu_find')->getAdapters(); - $this->assertTrue($adapters[0] instanceof Adapter\GnuFindAdapter); + $this->assertTrue($adapters[0] instanceof GnuFindAdapter); // test that useBestAdapter method removes selection $adapters = Finder::create()->useBestAdapter()->getAdapters(); - $this->assertFalse($adapters[0] instanceof Adapter\PhpAdapter); + $this->assertFalse($adapters[0] instanceof PhpAdapter); } public function getTestPathData() { - $tests = array( + return array( array('', '', array()), array('/^A\/B\/C/', '/C$/', array('A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C'.DIRECTORY_SEPARATOR.'abc.dat'), @@ -722,20 +652,15 @@ public function getTestPathData() ), ), ); - - return $this->buildTestData($tests); } - /** - * @dataProvider getAdaptersTestData - */ - public function testAccessDeniedException(Adapter\AdapterInterface $adapter) + public function testAccessDeniedException() { if ('\\' === DIRECTORY_SEPARATOR) { $this->markTestSkipped('chmod is not supported on Windows'); } - $finder = $this->buildFinder($adapter); + 8000 $finder = $this->buildFinder(); $finder->files()->in(self::$tmpDir); // make 'foo' directory non-readable @@ -765,16 +690,13 @@ public function testAccessDeniedException(Adapter\AdapterInterface $adapter) } } - /** - * @dataProvider getAdaptersTestData - */ - public function testIgnoredAccessDeniedException(Adapter\AdapterInterface $adapter) + public function testIgnoredAccessDeniedException() { if ('\\' === DIRECTORY_SEPARATOR) { $this->markTestSkipped('chmod is not supported on Windows'); } - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $finder->files()->ignoreUnreadableDirs()->in(self::$tmpDir); // make 'foo' directory non-readable @@ -794,62 +716,18 @@ public function testIgnoredAccessDeniedException(Adapter\AdapterInterface $adapt } } - private function buildTestData(array $tests) + /** + * @return AdapterInterface + */ + protected function getAdapter() { - $data = array(); - foreach ($this->getValidAdapters() as $adapter) { - foreach ($tests as $test) { - $data[] = array_merge(array($adapter), $test); - } - } - - return $data; + return new PhpAdapter(); } - private function buildFinder(Adapter\AdapterInterface $adapter) + private function buildFinder() { return Finder::create() ->removeAdapters() - ->addAdapter($adapter); - } - - private function getValidAdapters() - { - return array_filter( - array( - new Adapter\BsdFindAdapter(), - new Adapter\GnuFindAdapter(), - new Adapter\PhpAdapter(), - ), - function (Adapter\AdapterInterface $adapter) { - return $adapter->isSupported(); - } - ); - } - - /** - * Searching in multiple locations with sub directories 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 - */ - public function testMultipleLocationsWithSubDirectories() - { - $locations = array( - __DIR__.'/Fixtures/one', - self::$tmpDir.DIRECTORY_SEPARATOR.'toto', - ); - - $finder = new Finder(); - $finder->in($locations)->depth('< 10')->name('*.neon'); - - $expected = array( - __DIR__.'/Fixtures/one'.DIRECTORY_SEPARATOR.'b'.DIRECTORY_SEPARATOR.'c.neon', - __DIR__.'/Fixtures/one'.DIRECTORY_SEPARATOR.'b'.DIRECTORY_SEPARATOR.'d.neon', - ); - - $this->assertIterator($expected, $finder); - $this->assertIteratorInForeach($expected, $finder); + ->addAdapter($this->getAdapter()); } } diff --git a/src/Symfony/Component/Finder/Tests/GnuFinderTest.php b/src/Symfony/Component/Finder/Tests/GnuFinderTest.php new file mode 100644 index 0000000000000..5c66723c1bea1 --- /dev/null +++ b/src/Symfony/Component/Finder/Tests/GnuFinderTest.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Finder\Tests; + +use Symfony\Component\Finder\Adapter\GnuFindAdapter; + +class GnuFinderTest extends FinderTest +{ + protected function getAdapter() + { + $adapter = new GnuFindAdapter(); + + if (!$adapter->isSupported()) { + $this->markTestSkipped(get_class($adapter).' is not supported.'); + } + + return $adapter; + } +} diff --git a/src/Symfony/Component/Finder/Tests/Iterator/IteratorTestCase.php b/src/Symfony/Component/Finder/Tests/Iterator/IteratorTestCase.php index 9d2cf5fe45605..2d29efedf1c2f 100644 --- a/src/Symfony/Component/Finder/Tests/Iterator/IteratorTestCase.php +++ b/src/Symfony/Component/Finder/Tests/Iterator/IteratorTestCase.php @@ -16,7 +16,7 @@ abstract class IteratorTestCase extends \PHPUnit_Framework_TestCase protected function assertIterator($expected, \Traversable $iterator) { // set iterator_to_array $use_key to false to avoid values merge - // this made FinderTest::testAppendWithAnArray() failed with GnuFinderAdapter + // this made FinderTest::testAppendWithAnArray() fail with GnuFinderAdapter $values = array_map(function (\SplFileInfo $fileinfo) { return str_replace('/', DIRECTORY_SEPARATOR, $fileinfo->getPathname()); }, iterator_to_array($iterator, false)); $expected = array_map(function ($path) { return str_replace('/', DIRECTORY_SEPARATOR, $path); }, $expected); From 4982b02bdd15fdf2046f426bd108bb3679bee65c Mon Sep 17 00:00:00 2001 From: Jakub Zalas Date: Tue, 15 Sep 2015 08:23:21 +0100 Subject: [PATCH 0064/2143] [Console] Add the command name to input arguments if it's missing --- src/Symfony/Component/Console/Command/Command.php | 7 +++++++ .../Component/Console/Tests/Command/CommandTest.php | 9 +++++++++ 2 files changed, 16 insertions(+) diff --git a/src/Symfony/Component/Console/Command/Command.php b/src/Symfony/Component/Console/Command/Command.php index f169b6eb8702e..bccbc2ff4b8cf 100644 --- a/src/Symfony/Component/Console/Command/Command.php +++ b/src/Symfony/Component/Console/Command/Command.php @@ -241,6 +241,13 @@ public function run(InputInterface $input, OutputInterface $output) $this->interact($input, $output); } + // The command name argument is often omitted when a command is executed directly with its run() method. + // It would fail the validation if we didn't make sure the command argument is present, + // since it's required by the application. + if ($input->hasArgument('command') && null === $input->getArgument('command')) { + $input->setArgument('command', $this->getName()); + } + $input->validate(); if ($this->code) { diff --git a/src/Symfony/Component/Console/Tests/Command/CommandTest.php b/src/Symfony/Component/Console/Tests/Command/CommandTest.php index a0c8d78deb275..a252fe7127794 100644 --- a/src/Symfony/Component/Console/Tests/Command/CommandTest.php +++ b/src/Symfony/Component/Console/Tests/Command/CommandTest.php @@ -267,6 +267,15 @@ public function testRunReturnsIntegerExitCode() $this->assertSame(2, $exitCode, '->run() returns integer exit code (casts numeric to int)'); } + public function testRunWithApplication() + { + $command = new \TestCommand(); + $command->setApplication(new Application()); + $exitCode = $command->run(new StringInput(''), new NullOutput()); + + $this->assertSame(0, $exitCode, '->run() returns an integer exit code'); + } + public function testRunReturnsAlwaysInteger() { $command = new \TestCommand(); From bca67712d0013712a8fa8f986273652bb2bc86d9 Mon Sep 17 00:00:00 2001 From: Richard Quadling Date: Wed, 16 Sep 2015 14:19:29 +0100 Subject: [PATCH 0065/2143] Update Process.php Stop autoruns when shelling on Windows. Original PR was on https://github.com/symfony/Process/pull/9#issuecomment-140721398. --- src/Symfony/Component/Process/Process.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Process/Process.php b/src/Symfony/Component/Process/Process.php index 8c259f5c1fd61..61f37ba59962c 100644 --- a/src/Symfony/Component/Process/Process.php +++ b/src/Symfony/Component/Process/Process.php @@ -232,7 +232,7 @@ public function start($callback = null) $commandline = $this->commandline; if ('\\' === DIRECTORY_SEPARATOR && $this->enhanceWindowsCompatibility) { - $commandline = 'cmd /V:ON /E:ON /C "('.$commandline.')'; + $commandline = 'cmd /V:ON /E:ON /D /C "('.$commandline.')'; foreach ($this->processPipes->getFiles() as $offset => $filename) { $commandline .= ' '.$offset.'>'.ProcessUtils::escapeArgument($filename); } From ec59953f4cb34c15cac4d98f587094556860847c Mon Sep 17 00:00:00 2001 From: Tobias Schultze Date: Thu, 17 Sep 2015 03:14:14 +0200 Subject: [PATCH 0066/2143] [EventDispatcher] fix memory leak in a getListeners --- .../Component/EventDispatcher/EventDispatcher.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/EventDispatcher/EventDispatcher.php b/src/Symfony/Component/EventDispatcher/EventDispatcher.php index a2435e9978b2b..67097e5662bba 100644 --- a/src/Symfony/Component/EventDispatcher/EventDispatcher.php +++ b/src/Symfony/Component/EventDispatcher/EventDispatcher.php @@ -61,6 +61,10 @@ public function dispatch($eventName, Event $event = null) public function getListeners($eventName = null) { if (null !== $eventName) { + if (!isset($this->listeners[$eventName])) { + return array(); + } + if (!isset($this->sorted[$eventName])) { $this->sortListeners($eventName); } @@ -177,9 +181,7 @@ private function sortListeners($eventName) { $this->sorted[$eventName] = array(); - if (isset($this->listeners[$eventName])) { - krsort($this->listeners[$eventName]); - $this->sorted[$eventName] = call_user_func_array('array_merge', $this->listeners[$eventName]); - } + krsort($this->listeners[$eventName]); + $this->sorted[$eventName] = call_user_func_array('array_merge', $this->listeners[$eventName]); } } From a7b7f5479eabfe00c462fc7640d712ec99fdda5f Mon Sep 17 00:00:00 2001 From: Tobias Schultze Date: Thu, 17 Sep 2015 03:42:05 +0200 Subject: [PATCH 0067/2143] [EventDispatcher] skip one lazy loading call --- .../ContainerAwareEventDispatcher.php | 19 ++------------ .../EventDispatcher/EventDispatcher.php | 26 +++++++------------ 2 files changed, 11 insertions(+), 34 deletions(-) diff --git a/src/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php b/src/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php index aedad6ef77036..8782d8e87b17d 100644 --- a/src/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php +++ b/src/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php @@ -103,7 +103,7 @@ public function removeListener($eventName, $listener) } /** - * @see EventDispatcherInterface::hasListeners() + * {@inheritdoc} */ public function hasListeners($eventName = null) { @@ -119,7 +119,7 @@ public function hasListeners($eventName = null) } /** - * @see EventDispatcherInterface::getListeners() + * {@inheritdoc} */ public function getListeners($eventName = null) { @@ -155,21 +155,6 @@ public function addSubscriberService($serviceId, $class) } } - /** - * {@inheritdoc} - * - * Lazily loads listeners for this event from the dependency injection - * container. - * - * @throws \InvalidArgumentException if the service is not defined - */ - public function dispatch($eventName, Event $event = null) - { - $this->lazyLoad($eventName); - - return parent::dispatch($eventName, $event); - } - public function getContainer() { return $this->container; diff --git a/src/Symfony/Component/EventDispatcher/EventDispatcher.php b/src/Symfony/Component/EventDispatcher/EventDispatcher.php index 67097e5662bba..54a279fb403f8 100644 --- a/src/Symfony/Component/EventDispatcher/EventDispatcher.php +++ b/src/Symfony/Component/EventDispatcher/EventDispatcher.php @@ -33,9 +33,7 @@ class EventDispatcher implements EventDispatcherInterface private $sorted = array(); /** - * @see EventDispatcherInterface::dispatch() - * - * @api + * {@inheritdoc} */ public function dispatch($eventName, Event $event = null) { @@ -46,17 +44,15 @@ public function dispatch($eventName, Event $event = null) $event->setDispatcher($this); $event->setName($eventName); - if (!isset($this->listeners[$eventName])) { - return $event; + if ($listeners = $this->getListeners($eventName)) { + $this->doDispatch($listeners, $eventName, $event); } - $this->doDispatch($this->getListeners($eventName), $eventName, $event); - return $event; } /** - * @see EventDispatcherInterface::getListeners() + * {@inheritdoc} */ public function getListeners($eventName = null) { @@ -82,7 +78,7 @@ public function getListeners($eventName = null) } /** - * @see EventDispatcherInterface::hasListeners() + * {@inheritdoc} */ public function hasListeners($eventName = null) { @@ -90,9 +86,7 @@ public function hasListeners($eventName = null) } /** - * @see EventDispatcherInterface::addListener() - * - * @api + * {@inheritdoc} */ public function addListener($eventName, $listener, $priority = 0) { @@ -101,7 +95,7 @@ public function addListener($eventName, $listener, $priority = 0) } /** - * @see EventDispatcherInterface::removeListener() + * {@inheritdoc} */ public function removeListener($eventName, $listener) { @@ -117,9 +111,7 @@ public function removeListener($eventName, $listener) } /** - * @see EventDispatcherInterface::addSubscriber() - * - * @api + * {@inheritdoc} */ public function addSubscriber(EventSubscriberInterface $subscriber) { @@ -137,7 +129,7 @@ public function addSubscriber(EventSubscriberInterface $subscriber) } /** - * @see EventDispatcherInterface::removeSubscriber() + * {@inheritdoc} */ public function removeSubscriber(EventSubscriberInterface $subscriber) { From cf3019bc5a7b8e71880d8f8900c0af6ada9ffe05 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 17 Sep 2015 09:52:41 +0200 Subject: [PATCH 0068/2143] [Finder] Fix recursive filter iterator --- .../Iterator/ExcludeDirectoryFilterIterator.php | 17 ++++++++++++++++- .../Finder/Iterator/FilterIterator.php | 12 +----------- .../Component/Finder/Tests/FinderTest.php | 8 ++++---- .../Iterator/DateRangeFilterIteratorTest.php | 3 +++ .../Iterator/DepthRangeFilterIteratorTest.php | 3 +++ .../ExcludeDirectoryFilterIteratorTest.php | 2 ++ .../Iterator/FileTypeFilterIteratorTest.php | 1 + .../Tests/Iterator/RealIteratorTestCase.php | 1 + .../Iterator/SizeRangeFilterIteratorTest.php | 1 + .../Tests/Iterator/SortableIteratorTest.php | 6 ++++++ 10 files changed, 38 insertions(+), 16 deletions(-) diff --git a/src/Symfony/Component/Finder/Iterator/ExcludeDirectoryFilterIterator.php b/src/Symfony/Component/Finder/Iterator/ExcludeDirectoryFilterIterator.php index 66f8149446b34..836c426f0c837 100644 --- a/src/Symfony/Component/Finder/Iterator/ExcludeDirectoryFilterIterator.php +++ b/src/Symfony/Component/Finder/Iterator/ExcludeDirectoryFilterIterator.php @@ -16,8 +16,9 @@ * * @author Fabien Potencier */ -class ExcludeDirectoryFilterIterator extends FilterIterator +class ExcludeDirectoryFilterIterator extends FilterIterator implements \RecursiveIterator { + private $isRecursive; private $patterns; /** @@ -28,6 +29,7 @@ class ExcludeDirectoryFilterIterator extends FilterIterator */ public function __construct(\Iterator $iterator, array $directories) { + $this->isRecursive = $iterator instanceof \RecursiveIterator; $this->patterns = array(); foreach ($directories as $directory) { $this->patterns[] = '#(^|/)'.preg_quote($directory, '#').'(/|$)#'; @@ -53,4 +55,17 @@ public function accept() return true; } + + public function hasChildren() + { + return $this->isRecursive && $this->getInnerIterator()->hasChildren(); + } + + public function getChildren() + { + $children = new self($this->getInnerIterator()->getChildren(), array()); + $children->patterns = $this->patterns; + + return $children; + } } diff --git a/src/Symfony/Component/Finder/Iterator/FilterIterator.php b/src/Symfony/Component/Finder/Iterator/FilterIterator.php index c5290cc80fb82..f4da44c4cdd59 100644 --- a/src/Symfony/Component/Finder/Iterator/FilterIterator.php +++ b/src/Symfony/Component/Finder/Iterator/FilterIterator.php @@ -18,18 +18,8 @@ * * @author Alex Bogomazov */ -abstract class FilterIterator extends \FilterIterator implements \RecursiveIterator +abstract class FilterIterator extends \FilterIterator { - public function hasChildren() - { - return $this->getInnerIterator() instanceof \RecursiveIterator && $this->getInnerIterator()->hasChildren(); - } - - public function getChildren() - { - return $this->getInnerIterator()->getChildren(); - } - /** * This is a workaround for the problem with \FilterIterator leaving inner \FilesystemIterator in wrong state after * rewind in some cases. diff --git a/src/Symfony/Component/Finder/Tests/FinderTest.php b/src/Symfony/Component/Finder/Tests/FinderTest.php index 337dd9911d9ed..cee8bd7530767 100644 --- a/src/Symfony/Component/Finder/Tests/FinderTest.php +++ b/src/Symfony/Component/Finder/Tests/FinderTest.php @@ -152,11 +152,11 @@ public function testIgnoreVCS() { $finder = $this->buildFinder(); $this->assertSame($finder, $finder->ignoreVCS(false)->ignoreDotFiles(false)); - $this->assertIterator($this->toAbsolute(array('.git', 'foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', '.bar', '.foo', '.foo/.bar', '.foo/bar', 'foo bar')), $finder->in(self::$tmpDir)->getIterator()); + $this->assertIterator($this->toAbsolute(array('.git', 'foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', 'toto/.git', '.bar', '.foo', '.foo/.bar', '.foo/bar', 'foo bar')), $finder->in(self::$tmpDir)->getIterator()); $finder = $this->buildFinder(); $finder->ignoreVCS(false)->ignoreVCS(false)->ignoreDotFiles(false); - $this->assertIterator($this->toAbsolute(array('.git', 'foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', '.bar', '.foo', '.foo/.bar', '.foo/bar', 'foo bar')), $finder->in(self::$tmpDir)->getIterator()); + $this->assertIterator($this->toAbsolute(array('.git', 'foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', 'toto/.git', '.bar', '.foo', '.foo/.bar', '.foo/bar', 'foo bar')), $finder->in(self::$tmpDir)->getIterator()); $finder = $this->buildFinder(); $this->assertSame($finder, $finder->ignoreVCS(true)->ignoreDotFiles(false)); @@ -167,11 +167,11 @@ public function testIgnoreDotFiles() { $finder = $this->buildFinder(); $this->assertSame($finder, $finder->ignoreDotFiles(false)->ignoreVCS(false)); - $this->assertIterator($this->toAbsolute(array('.git', '.bar', '.foo', '.foo/.bar', '.foo/bar', 'foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator()); + $this->assertIterator($this->toAbsolute(array('.git', '.bar', '.foo', '.foo/.bar', '.foo/bar', 'foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', 'toto/.git', 'foo bar')), $finder->in(self::$tmpDir)->getIterator()); $finder = $this->buildFinder(); $finder->ignoreDotFiles(false)->ignoreDotFiles(false)->ignoreVCS(false); - $this->assertIterator($this->toAbsolute(array('.git', '.bar', '.foo', '.foo/.bar', '.foo/bar', 'foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator()); + $this->assertIterator($this->toAbsolute(array('.git', '.bar', '.foo', '.foo/.bar', '.foo/bar', 'foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', 'toto/.git', 'foo bar')), $finder->in(self::$tmpDir)->getIterator()); $finder = $this->buildFinder(); $this->assertSame($finder, $finder->ignoreDotFiles(true)->ignoreVCS(false)); diff --git a/src/Symfony/Component/Finder/Tests/Iterator/DateRangeFilterIteratorTest.php b/src/Symfony/Component/Finder/Tests/Iterator/DateRangeFilterIteratorTest.php index 18896d552891d..8f61124131e8e 100644 --- a/src/Symfony/Component/Finder/Tests/Iterator/DateRangeFilterIteratorTest.php +++ b/src/Symfony/Component/Finder/Tests/Iterator/DateRangeFilterIteratorTest.php @@ -37,6 +37,7 @@ public function getAcceptData() 'foo/bar.tmp', 'test.php', 'toto', + 'toto/.git', '.bar', '.foo', '.foo/.bar', @@ -49,6 +50,7 @@ public function getAcceptData() 'test.py', 'foo', 'toto', + 'toto/.git', '.bar', '.foo', '.foo/.bar', @@ -62,6 +64,7 @@ public function getAcceptData() 'foo/bar.tmp', 'test.php', 'toto', + 'toto/.git', '.foo', ); diff --git a/src/Symfony/Component/Finder/Tests/Iterator/DepthRangeFilterIteratorTest.php b/src/Symfony/Component/Finder/Tests/Iterator/DepthRangeFilterIteratorTest.php index 5ec983247df94..2e90140530cd3 100644 --- a/src/Symfony/Component/Finder/Tests/Iterator/DepthRangeFilterIteratorTest.php +++ b/src/Symfony/Component/Finder/Tests/Iterator/DepthRangeFilterIteratorTest.php @@ -50,6 +50,7 @@ public function getAcceptData() 'foo/bar.tmp', 'test.php', 'toto', + 'toto/.git', '.foo', '.foo/.bar', '.bar', @@ -58,12 +59,14 @@ public function getAcceptData() ); $graterThanOrEqualTo1 = array( + 'toto/.git', 'foo/bar.tmp', '.foo/.bar', '.foo/bar', ); $equalTo1 = array( + 'toto/.git', 'foo/bar.tmp', '.foo/.bar', '.foo/bar', diff --git a/src/Symfony/Component/Finder/Tests/Iterator/ExcludeDirectoryFilterIteratorTest.php b/src/Symfony/Component/Finder/Tests/Iterator/ExcludeDirectoryFilterIteratorTest.php index 693b73319aa17..c5f4ba495a7ca 100644 --- a/src/Symfony/Component/Finder/Tests/Iterator/ExcludeDirectoryFilterIteratorTest.php +++ b/src/Symfony/Component/Finder/Tests/Iterator/ExcludeDirectoryFilterIteratorTest.php @@ -39,6 +39,7 @@ public function getAcceptData() 'test.py', 'test.php', 'toto', + 'toto/.git', 'foo bar', ); @@ -53,6 +54,7 @@ public function getAcceptData() 'foo/bar.tmp', 'test.php', 'toto', + 'toto/.git', 'foo bar', ); diff --git a/src/Symfony/Component/Finder/Tests/Iterator/FileTypeFilterIteratorTest.php b/src/Symfony/Component/Finder/Tests/Iterator/FileTypeFilterIteratorTest.php index cfa8684fdf7df..4350b00ca940a 100644 --- a/src/Symfony/Component/Finder/Tests/Iterator/FileTypeFilterIteratorTest.php +++ b/src/Symfony/Component/Finder/Tests/Iterator/FileTypeFilterIteratorTest.php @@ -43,6 +43,7 @@ public function getAcceptData() '.git', 'foo', 'toto', + 'toto/.git', '.foo', ); diff --git a/src/Symfony/Component/Finder/Tests/Iterator/RealIteratorTestCase.php b/src/Symfony/Component/Finder/Tests/Iterator/RealIteratorTestCase.php index e22476dad2696..94253c7ee7ca2 100644 --- a/src/Symfony/Component/Finder/Tests/Iterator/RealIteratorTestCase.php +++ b/src/Symfony/Component/Finder/Tests/Iterator/RealIteratorTestCase.php @@ -31,6 +31,7 @@ public static function setUpBeforeClass() 'foo/bar.tmp', 'test.php', 'toto/', + 'toto/.git/', 'foo bar', ); diff --git a/src/Symfony/Component/Finder/Tests/Iterator/SizeRangeFilterIteratorTest.php b/src/Symfony/Component/Finder/Tests/Iterator/SizeRangeFilterIteratorTest.php index 8780db4da1ca1..6d75b0f2f0b18 100644 --- a/src/Symfony/Component/Finder/Tests/Iterator/SizeRangeFilterIteratorTest.php +++ b/src/Symfony/Component/Finder/Tests/Iterator/SizeRangeFilterIteratorTest.php @@ -36,6 +36,7 @@ public function getAcceptData() 'foo', 'test.php', 'toto', + 'toto/.git', ); return array( diff --git a/src/Symfony/Component/Finder/Tests/Iterator/SortableIteratorTest.php b/src/Symfony/Component/Finder/Tests/Iterator/SortableIteratorTest.php index ed24f3ea0dca0..6a3124d352a90 100644 --- a/src/Symfony/Component/Finder/Tests/Iterator/SortableIteratorTest.php +++ b/src/Symfony/Component/Finder/Tests/Iterator/SortableIteratorTest.php @@ -85,6 +85,7 @@ public function getAcceptData() 'test.php', 'test.py', 'toto', + 'toto/.git', ); $sortByType = array( @@ -92,6 +93,7 @@ public function getAcceptData() '.git', 'foo', 'toto', + 'toto/.git', '.bar', '.foo/.bar', '.foo/bar', @@ -113,6 +115,7 @@ public function getAcceptData() 'test.php', 'test.py', 'toto', + 'toto/.git', ); $sortByAccessedTime = array( @@ -127,6 +130,7 @@ public function getAcceptData() 'test.py', 'foo', 'toto', + 'toto/.git', 'foo bar', ), // This file was accessed after sleeping for 1 sec @@ -143,6 +147,7 @@ public function getAcceptData() 'foo', 'foo/bar.tmp', 'toto', + 'toto/.git', 'foo bar', ), array('test.php'), @@ -159,6 +164,7 @@ public function getAcceptData() 'foo', 'foo/bar.tmp', 'toto', + 'toto/.git', 'foo bar', ), array('test.php'), From f156de6b71da006bd12642d2f7cec9668d5eb61d Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 17 Sep 2015 14:13:49 +0200 Subject: [PATCH 0069/2143] [Finder] Optimize the hot-path --- .../ExcludeDirectoryFilterIterator.php | 38 +++++++++++++------ .../Iterator/RecursiveDirectoryIterator.php | 25 +++++++++++- 2 files changed, 50 insertions(+), 13 deletions(-) diff --git a/src/Symfony/Component/Finder/Iterator/ExcludeDirectoryFilterIterator.php b/src/Symfony/Component/Finder/Iterator/ExcludeDirectoryFilterIterator.php index 836c426f0c837..b7bb3c4f31310 100644 --- a/src/Symfony/Component/Finder/Iterator/ExcludeDirectoryFilterIterator.php +++ b/src/Symfony/Component/Finder/Iterator/ExcludeDirectoryFilterIterator.php @@ -18,8 +18,10 @@ */ class ExcludeDirectoryFilterIterator extends FilterIterator implements \RecursiveIterator { + private $iterator; private $isRecursive; - private $patterns; + private $excludedDirs = array(); + private $excludedPattern; /** * Constructor. @@ -29,10 +31,18 @@ class ExcludeDirectoryFilterIterator extends FilterIterator implements \Recursiv */ public function __construct(\Iterator $iterator, array $directories) { + $this->iterator = $iterator; $this->isRecursive = $iterator instanceof \RecursiveIterator; - $this->patterns = array(); + $patterns = array(); foreach ($directories as $directory) { - $this->patterns[] = '#(^|/)'.preg_quote($directory, '#').'(/|$)#'; + if (!$this->isRecursive || false !== strpos($directory, '/')) { + $patterns[] = preg_quote($directory, '#'); + } else { + $this->excludedDirs[$directory] = true; + } + } + if ($patterns) { + $this->excludedPattern = '#(?:^|/)(?:'.implode('|', $patterns).')(?:/|$)#'; } parent::__construct($iterator); @@ -45,12 +55,15 @@ public function __construct(\Iterator $iterator, array $directories) */ public function accept() { - $path = $this->isDir() ? $this->current()->getRelativePathname() : $this->current()->getRelativePath(); - $path = str_replace('\\', '/', $path); - foreach ($this->patterns as $pattern) { - if (preg_match($pattern, $path)) { - return false; - } + if ($this->isRecursive && isset($this->excludedDirs[$this->getFilename()]) && $this->isDir()) { + return false; + } + + if ($this->excludedPattern) { + $path = $this->isDir() ? $this->current()->getRelativePathname() : $this->current()->getRelativePath(); + $path = str_replace('\\', '/', $path); + + return !preg_match($this->excludedPattern, $path); } return true; @@ -58,13 +71,14 @@ public function accept() public function hasChildren() { - return $this->isRecursive && $this->getInnerIterator()->hasChildren(); + return $this->isRecursive && $this->iterator->hasChildren(); } public function getChildren() { - $children = new self($this->getInnerIterator()->getChildren(), array()); - $children->patterns = $this->patterns; + $children = new self($this->iterator->getChildren(), array()); + $children->excludedDirs = $this->excludedDirs; + $children->excludedPattern = $this->excludedPattern; return $children; } diff --git a/src/Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.php b/src/Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.php index af824d0e4333c..3f65d69269756 100644 --- a/src/Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.php +++ b/src/Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.php @@ -31,6 +31,11 @@ class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator */ private $rewindable; + // these 3 properties take part of the performance optimization to avoid redoing the same work in all iterations + private $rootPath; + private $subPath; + private $directorySeparator = '/'; + /** * Constructor. * @@ -48,6 +53,10 @@ public function __construct($path, $flags, $ignoreUnreadableDirs = false) parent::__construct($path, $flags); $this->ignoreUnreadableDirs = $ignoreUnreadableDirs; + $this->rootPath = (string) $path; + if ('/' !== DIRECTORY_SEPARATOR && !($flags & self::UNIX_PATHS)) { + $this->directorySeparator = DIRECTORY_SEPARATOR; + } } /** @@ -57,7 +66,17 @@ public function __construct($path, $flags, $ignoreUnreadableDirs = false) */ public function current() { - return new SplFileInfo(parent::current()->getPathname(), $this->getSubPath(), $this->getSubPathname()); + // the logic here avoids redoing the same work in all iterations + + if (null === $subPathname = $this->subPath) { + $subPathname = $this->subPath = (string) $this->getSubPath(); + } + if ('' !== $subPathname) { + $subPathname .= $this->directorySeparator; + } + $subPathname .= $this->getFilename(); + + return new SplFileInfo($this->rootPath.$this->directorySeparator.$subPathname, $this->subPath, $subPathname); } /** @@ -73,6 +92,10 @@ public function getChildren() if ($children instanceof self) { // parent method will call the constructor with default arguments, so unreadable dirs won't be ignored anymore $children->ignoreUnreadableDirs = $this->ignoreUnreadableDirs; + + // performance optimization to avoid redoing the same work in all children + $children->rewindable = &$this->rewindable; + $children->rootPath = $this->rootPath; } return $children; From ba8366e208b5a5df469ac58bf45a4446862d853a Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 18 Sep 2015 11:49:48 +0200 Subject: [PATCH 0070/2143] [travis] Remove PHP 7 from allowed failures --- .travis.yml | 3 --- c 8000 omposer.json | 6 +++--- src/Symfony/Bridge/Doctrine/composer.json | 6 +++--- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/.travis.yml b/.travis.yml index e959db0cecd0d..31ec53de6e375 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,10 +16,7 @@ matrix: - php: 5.6 env: deps=high - php: 7 - - php: 5.6 env: deps=low - allow_failures: - - php: 7 fast_finish: true services: mongodb diff --git a/composer.json b/composer.json index 5e9d19074674e..bf85b666a6547 100644 --- a/composer.json +++ b/composer.json @@ -17,7 +17,7 @@ ], "require": { "php": ">=5.3.3", - "doctrine/common": "~2.3", + "doctrine/common": "~2.4", "twig/twig": "~1.20|~2.0", "psr/log": "~1.0" }, @@ -63,8 +63,8 @@ "require-dev": { "symfony/phpunit-bridge": "~2.7", "doctrine/data-fixtures": "1.0.*", - "doctrine/dbal": "~2.2", - "doctrine/orm": "~2.2,>=2.2.3", + "doctrine/dbal": "~2.4", + "doctrine/orm": "~2.4,>=2.4.5", "monolog/monolog": "~1.3", "propel/propel1": "~1.6", "ircmaxell/password-compat": "~1.0", diff --git a/src/Symfony/Bridge/Doctrine/composer.json b/src/Symfony/Bridge/Doctrine/composer.json index 76e35e1ca6fb8..7c799262275d8 100644 --- a/src/Symfony/Bridge/Doctrine/composer.json +++ b/src/Symfony/Bridge/Doctrine/composer.json @@ -17,7 +17,7 @@ ], "require": { "php": ">=5.3.3", - "doctrine/common": "~2.3" + "doctrine/common": "~2.4" }, "require-dev": { "symfony/phpunit-bridge": "~2.7", @@ -30,8 +30,8 @@ "symfony/validator": "~2.3.0,>=2.3.20", "symfony/translation": "~2.0,>=2.0.5", "doctrine/data-fixtures": "1.0.*", - "doctrine/dbal": "~2.2", - "doctrine/orm": "~2.2,>=2.2.3" + "doctrine/dbal": "~2.4", + "doctrine/orm": "~2.4,>=2.4.5" }, "suggest": { "symfony/form": "", From 1b97c17c301fdeecaad9e0f6b3d96945a92cb440 Mon Sep 17 00:00:00 2001 From: Thomas Landauer Date: Fri, 18 Sep 2015 16:20:21 +0200 Subject: [PATCH 0071/2143] Remove whitespaces between and