diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index b5e3744de6f0e..6ddc9b375b1af 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -32,6 +32,7 @@ use Symfony\Component\Config\Loader\DelegatingLoader; use Symfony\Component\Config\ConfigCache; use Symfony\Component\ClassLoader\ClassCollectionLoader; +use Symfony\Component\Filesystem\Filesystem; /** * The Kernel is the heart of the Symfony system. @@ -52,6 +53,7 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $bundleMap; protected $container; protected $rootDir; + protected $realRootDir; protected $environment; protected $debug; protected $booted = false; @@ -714,9 +716,67 @@ protected function dumpContainer(ConfigCache $cache, ContainerBuilder $container $content = static::stripComments($content); } + $content = $this->removeAbsolutePathsFromContainer($content); + $cache->write($content, $container->getResources()); } + /** + * Converts absolute paths to relative ones in the dumped container. + */ + private function removeAbsolutePathsFromContainer($content) + { + if (!class_exists('Symfony\Component\Filesystem\Filesystem')) { + return $content; + } + + $rootDir = $this->getRealRootDir(); + if (!$rootDir) { + return $content; + } + + $rootDir = rtrim($rootDir, '/'); + $cacheDir = $this->getCacheDir(); + $filesystem = new Filesystem(); + + return preg_replace_callback("{'([^']*?)(".preg_quote($rootDir)."[^']*)'}", function ($match) use ($filesystem, $cacheDir) { + $prefix = !empty($match[1]) ? "'$match[1]'.__DIR__" : "__DIR__"; + + if ('.' === $relativePath = rtrim($filesystem->makePathRelative($match[2], $cacheDir), '/')) { + return $prefix; + } + + return $prefix.".'/".$relativePath."'"; + }, $content); + } + + /** + * Find the "real" root dir (by finding the composer.json file) + * + * @return null|string + */ + private function getRealRootDir() + { + if (null !== $this->realRootDir) { + return $this->realRootDir; + } + + $rootDir = $this->getRootDir(); + $previous = $rootDir; + while (!file_exists($rootDir.'/composer.json')) { + if ($previous === $rootDir = realpath($rootDir.'/..')) { + // unable to detect the project root, give up + return $this->realRootDir = false; + } + + $previous = $rootDir; + } + + $this->realRootDir = $rootDir; + + return $this->realRootDir; + } + /** * Returns a loader for the container. * diff --git a/src/Symfony/Component/HttpKernel/Tests/Fixtures/DumpedContainers/app/cache/dev/withAbsolutePaths.php b/src/Symfony/Component/HttpKernel/Tests/Fixtures/DumpedContainers/app/cache/dev/withAbsolutePaths.php new file mode 100644 index 0000000000000..b8644ecb9fe00 --- /dev/null +++ b/src/Symfony/Component/HttpKernel/Tests/Fixtures/DumpedContainers/app/cache/dev/withAbsolutePaths.php @@ -0,0 +1,8 @@ +'ROOT_DIR/app/cache/dev/foo' +'ROOT_DIR/app/cache/foo' +'ROOT_DIR/foo/bar.php' +'ROOT_DIR/app/cache/dev' + +'/some/where/else/foo' + +'file:ROOT_DIR/app/cache/dev/profiler' diff --git a/src/Symfony/Component/HttpKernel/Tests/Fixtures/DumpedContainers/app/cache/dev/withoutAbsolutePaths.php b/src/Symfony/Component/HttpKernel/Tests/Fixtures/DumpedContainers/app/cache/dev/withoutAbsolutePaths.php new file mode 100644 index 0000000000000..36823dfc160c8 --- /dev/null +++ b/src/Symfony/Component/HttpKernel/Tests/Fixtures/DumpedContainers/app/cache/dev/withoutAbsolutePaths.php @@ -0,0 +1,8 @@ +__DIR__.'/foo' +__DIR__.'/../foo' +__DIR__.'/../../../foo/bar.php' +__DIR__ + +'/some/where/else/foo' + +'file:'.__DIR__.'/profiler' diff --git a/src/Symfony/Component/HttpKernel/Tests/Fixtures/DumpedContainers/composer.json b/src/Symfony/Component/HttpKernel/Tests/Fixtures/DumpedContainers/composer.json new file mode 100644 index 0000000000000..0967ef424bce6 --- /dev/null +++ b/src/Symfony/Component/HttpKernel/Tests/Fixtures/DumpedContainers/composer.json @@ -0,0 +1 @@ +{} diff --git a/src/Symfony/Component/HttpKernel/Tests/Fixtures/KernelForTest.php b/src/Symfony/Component/HttpKernel/Tests/Fixtures/KernelForTest.php index 5fd61bbc7e7ce..000f823c6ada3 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Fixtures/KernelForTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Fixtures/KernelForTest.php @@ -16,6 +16,11 @@ class KernelForTest extends Kernel { + public function setRootDir($dir) + { + $this->rootDir = $dir; + } + public function getBundleMap() { return $this->bundleMap; @@ -34,4 +39,9 @@ public function isBooted() { return $this->booted; } + + public function setRealRootDir($dir) + { + $this->realRootDir = $dir; + } } diff --git a/src/Symfony/Component/HttpKernel/Tests/KernelTest.php b/src/Symfony/Component/HttpKernel/Tests/KernelTest.php index bc9876df3b12c..8571dddd87a97 100644 --- a/src/Symfony/Component/HttpKernel/Tests/KernelTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/KernelTest.php @@ -722,6 +722,39 @@ public function testTerminateDelegatesTerminationOnlyForTerminableInterface() $kernel->terminate(Request::create('/'), new Response()); } + /** + * @dataProvider getRemoveAbsolutePathsFromContainerData + */ + public function testRemoveAbsolutePathsFromContainer($symfonyRootDir, $realRootDir, $replacement, $replaced) + { + $kernel = new KernelForTest('dev', true); + $kernel->setRootDir($symfonyRootDir); + if (null !== $realRootDir) { + $kernel->setRealRootDir($realRootDir); + } + + $content = file_get_contents(__DIR__.'/Fixtures/DumpedContainers/app/cache/dev/withAbsolutePaths.php'); + $content = str_replace('ROOT_DIR', $replacement, $content); + + $m = new \ReflectionMethod($kernel, 'removeAbsolutePathsFromContainer'); + $m->setAccessible(true); + $newContent = $m->invoke($kernel, $content); + if ($replaced) { + $this->assertEquals(file_get_contents(__DIR__.'/Fixtures/DumpedContainers/app/cache/dev/withoutAbsolutePaths.php'), $newContent); + } else { + $this->assertEquals($newContent, $content); + } + } + + public function getRemoveAbsolutePathsFromContainerData() + { + return array( + array(__DIR__.'/Fixtures/DumpedContainers/app', null, __DIR__.'/Fixtures/DumpedContainers', true), + array(sys_get_temp_dir(), null, __DIR__.'/Fixtures/DumpedContainers', false), + array('/app/app', '/app', '/app', true), + ); + } + /** * Returns a mock for the BundleInterface * diff --git a/src/Symfony/Component/HttpKernel/composer.json b/src/Symfony/Component/HttpKernel/composer.json index 24bed4a2d1df2..7105b5cb12817 100644 --- a/src/Symfony/Component/HttpKernel/composer.json +++ b/src/Symfony/Component/HttpKernel/composer.json @@ -29,6 +29,7 @@ "symfony/console": "~2.2", "symfony/dependency-injection": "~2.0", "symfony/finder": "~2.0", + "symfony/filesystem": "~2.4", "symfony/process": "~2.0", "symfony/routing": "~2.2", "symfony/stopwatch": "~2.2", @@ -40,7 +41,8 @@ "symfony/config": "", "symfony/console": "", "symfony/dependency-injection": "", - "symfony/finder": "" + "symfony/finder": "", + "symfony/filesystem": "" }, "autoload": { "psr-0": { "Symfony\\Component\\HttpKernel\\": "" }