From 31dd6ae8b56be4935213f6f3b19d709dbe9238b2 Mon Sep 17 00:00:00 2001 From: Artur Eshenbrener Date: Wed, 11 Oct 2017 16:02:31 +0300 Subject: [PATCH 1/4] [DependencyInjection] fixed PhpDumper Handle the case, when exporting string contains new line, which cause incorrect php code together with `as_files` option fixes #24470 --- .../DependencyInjection/Dumper/PhpDumper.php | 8 +- .../Tests/Dumper/PhpDumperTest.php | 9 ++ .../containers/container_nl_in_argument.php | 13 +++ .../php/container_nl_in_argument_as_files.txt | 96 +++++++++++++++++++ 4 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container_nl_in_argument.php create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/container_nl_in_argument_as_files.txt diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index f12d813890615..f28b01f4f635b 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -1917,7 +1917,13 @@ private function export($value) private function doExport($value) { - $export = var_export($value, true); + if (is_string($value) && false !== strpos($value, "\n")) { + $cleanParts = explode("\n", $value); + $cleanParts = array_map(function($part) { return var_export($part, true); }, $cleanParts); + $export = implode(' . "\n" . ', $cleanParts); + } else { + $export = var_export($value, true); + } if ("'" === $export[0] && $export !== $resolvedExport = $this->container->resolveEnvPlaceholders($export, "'.\$this->getEnv('string:%s').'")) { $export = $resolvedExport; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php index 014ce3c16f885..70203bd4d9a1a 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php @@ -187,6 +187,15 @@ public function testServicesWithAnonymousFactories() $this->assertStringEqualsFile(self::$fixturesPath.'/php/services19.php', $dumper->dump(), '->dump() dumps services with anonymous factories'); } + public function testDumpAsFilesWhenServicePropertiesContainSpaces() + { + $container = include self::$fixturesPath.'/containers/container_nl_in_argument.php'; + $container->compile(); + $dumper = new PhpDumper($container); + $dump = print_r($dumper->dump(array('as_files' => true, 'file' => __DIR__)), true); + $this->assertStringMatchesFormatFile(self::$fixturesPath.'/php/container_nl_in_argument_as_files.txt', $dump); + } + public function testAddServiceIdWithUnsupportedCharacters() { $class = 'Symfony_DI_PhpDumper_Test_Unsupported_Characters'; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container_nl_in_argument.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container_nl_in_argument.php new file mode 100644 index 0000000000000..0fe95723e9089 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container_nl_in_argument.php @@ -0,0 +1,13 @@ +register('foo', 'Foo') + ->addArgument("string with\nnew line") + ->setPublic(true) +; + +return $container; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/container_nl_in_argument_as_files.txt b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/container_nl_in_argument_as_files.txt new file mode 100644 index 0000000000000..02cff779bd3bb --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/container_nl_in_argument_as_files.txt @@ -0,0 +1,96 @@ +Array +( + [Container49hcjyk/removed-ids.php] => true, + 'Symfony\\Component\\DependencyInjection\\ContainerInterface' => true, +); + + [Container49hcjyk/getFooService.php] => services['foo'] = new \Foo('string with' . "\n" . 'new line'); + + [Container49hcjyk/Container.php] => targetDirs[0] = dirname(__DIR__); + for ($i = 1; $i <= 5; ++$i) { + $this->targetDirs[$i] = $dir = dirname($dir); + } + $this->services = array(); + $this->fileMap = array( + 'foo' => __DIR__.'/getFooService.php', + ); + + $this->aliases = array(); + } + + public function getRemovedIds() + { + return require __DIR__.'/removed-ids.php'; + } + + public function compile() + { + throw new LogicException('You cannot compile a dumped container that was already compiled.'); + } + + public function isCompiled() + { + return true; + } + + public function isFrozen() + { + @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED); + + return true; + } + + protected function load($file, $lazyLoad = true) + { + return require $file; + } +} + + [ProjectServiceContainer.php] => Date: Wed, 11 Oct 2017 16:05:54 +0300 Subject: [PATCH 2/4] fixed coding style --- src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index f28b01f4f635b..d8dfaabbe009d 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -1919,7 +1919,7 @@ private function doExport($value) { if (is_string($value) && false !== strpos($value, "\n")) { $cleanParts = explode("\n", $value); - $cleanParts = array_map(function($part) { return var_export($part, true); }, $cleanParts); + $cleanParts = array_map(function ($part) { return var_export($part, true); }, $cleanParts); $export = implode(' . "\n" . ', $cleanParts); } else { $export = var_export($value, true); From 1a0a5913741dc1cbd2b24bcafb455f71afc24749 Mon Sep 17 00:00:00 2001 From: Artur Eshenbrener Date: Thu, 12 Oct 2017 13:36:25 +0300 Subject: [PATCH 3/4] Added a test case, when broken PhpDumper generates invalid php code --- .../containers/container_nl_in_argument.php | 6 +++++ .../php/container_nl_in_argument_as_files.txt | 26 +++++++++++++------ 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container_nl_in_argument.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container_nl_in_argument.php index 0fe95723e9089..5b0f9ebd76474 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container_nl_in_argument.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container_nl_in_argument.php @@ -10,4 +10,10 @@ ->setPublic(true) ; +$container + ->register('foo2', 'Foo') + ->addArgument("string with\nnl") + ->setPublic(true) +; + return $container; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/container_nl_in_argument_as_files.txt b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/container_nl_in_argument_as_files.txt index 02cff779bd3bb..f63e5df4f4fbc 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/container_nl_in_argument_as_files.txt +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/container_nl_in_argument_as_files.txt @@ -1,13 +1,13 @@ Array ( - [Container49hcjyk/removed-ids.php] => true, 'Symfony\\Component\\DependencyInjection\\ContainerInterface' => true, ); - [Container49hcjyk/getFooService.php] => services['foo'] = new \Foo('string with' . "\n" . 'new line'); - [Container49hcjyk/Container.php] => services['foo2'] = new \Foo('string with' . "\n" . 'nl'); + + [ContainerQug0xcu/Container.php] => services = array(); $this->fileMap = array( 'foo' => __DIR__.'/getFooService.php', + 'foo2' => __DIR__.'/getFoo2Service.php', ); $this->aliases = array(); @@ -83,14 +93,14 @@ class Container49hcjyk extends Container // This file has been auto-generated by the Symfony Dependency Injection Component for internal use. -if (!class_exists(Container49hcjyk::class, false)) { - require __DIR__.'/Container49hcjyk/Container.php'; +if (!class_exists(ContainerQug0xcu::class, false)) { + require __DIR__.'/ContainerQug0xcu/Container.php'; } if (!class_exists(ProjectServiceContainer::class, false)) { - class_alias(Container49hcjyk::class, ProjectServiceContainer::class, false); + class_alias(ContainerQug0xcu::class, ProjectServiceContainer::class, false); } -return new Container49hcjyk(); +return new ContainerQug0xcu(); ) From e6e649b7dc69522be076300dedce305e09d4e6f1 Mon Sep 17 00:00:00 2001 From: Artur Eshenbrener Date: Thu, 12 Oct 2017 15:46:44 +0300 Subject: [PATCH 4/4] [DI] PhpDumper. Make generated code compatible with coding standards --- .../DependencyInjection/Dumper/PhpDumper.php | 2 +- .../php/container_nl_in_argument_as_files.txt | 22 +++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index d8dfaabbe009d..16c319fe7644d 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -1920,7 +1920,7 @@ private function doExport($value) if (is_string($value) && false !== strpos($value, "\n")) { $cleanParts = explode("\n", $value); $cleanParts = array_map(function ($part) { return var_export($part, true); }, $cleanParts); - $export = implode(' . "\n" . ', $cleanParts); + $export = implode('."\n".', $cleanParts); } else { $export = var_export($value, true); } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/container_nl_in_argument_as_files.txt b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/container_nl_in_argument_as_files.txt index f63e5df4f4fbc..de17e9af62628 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/container_nl_in_argument_as_files.txt +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/container_nl_in_argument_as_files.txt @@ -1,31 +1,31 @@ Array ( - [ContainerQug0xcu/removed-ids.php] => true, 'Symfony\\Component\\DependencyInjection\\ContainerInterface' => true, ); - [ContainerQug0xcu/getFooService.php] => services['foo'] = new \Foo('string with' . "\n" . 'new line'); +return $this->services['foo'] = new \Foo('string with'."\n".'new line'); - [ContainerQug0xcu/getFoo2Service.php] => services['foo2'] = new \Foo('string with' . "\n" . 'nl'); +return $this->services['foo2'] = new \Foo('string with'."\n".'nl'); - [ContainerQug0xcu/Container.php] =>