diff --git a/src/Symfony/Bridge/Doctrine/ManagerRegistry.php b/src/Symfony/Bridge/Doctrine/ManagerRegistry.php index b30fd0691b1a8..c353e36e66282 100644 --- a/src/Symfony/Bridge/Doctrine/ManagerRegistry.php +++ b/src/Symfony/Bridge/Doctrine/ManagerRegistry.php @@ -59,8 +59,12 @@ function (&$wrappedInstance, LazyLoadingInterface $manager) use ($name) { if (isset($this->aliases[$name])) { $name = $this->aliases[$name]; } - $method = !isset($this->methodMap[$name]) ? 'get'.strtr($name, $this->underscoreMap).'Service' : $this->methodMap[$name]; - $wrappedInstance = $this->{$method}(false); + if (isset($this->fileMap[$name])) { + $wrappedInstance = $this->load($this->fileMap[$name], false); + } else { + $method = !isset($this->methodMap[$name]) ? 'get'.strtr($name, $this->underscoreMap).'Service' : $this->methodMap[$name]; + $wrappedInstance = $this->{$method}(false); + } $manager->setProxyInitializer(null); diff --git a/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php b/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php index 29133e762d659..22ed2b05f188e 100644 --- a/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php +++ b/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php @@ -81,24 +81,21 @@ public function getProxyFactoryCode(Definition $definition, $id, $factoryCode = } $proxyClass = $this->getProxyClassName($definition); - $generatedClass = $this->generateProxyClass($definition); + $hasStaticConstructor = $this->generateProxyClass($definition)->hasMethod('staticProxyConstructor'); - $constructorCall = $generatedClass->hasMethod('staticProxyConstructor') - ? $proxyClass.'::staticProxyConstructor' - : 'new '.$proxyClass; + $constructorCall = sprintf($hasStaticConstructor ? '%s::staticProxyConstructor' : 'new %s', '\\'.$proxyClass); return <<createProxy('$proxyClass', function () { + return $constructorCall(function (&\$wrappedInstance, \ProxyManager\Proxy\LazyLoadingInterface \$proxy) { \$wrappedInstance = $factoryCode; \$proxy->setProxyInitializer(null); return true; - } - ); + }); + }); } @@ -122,7 +119,7 @@ public function getProxyCode(Definition $definition) */ private function getProxyClassName(Definition $definition) { - return str_replace('\\', '', $definition->getClass()).'_'.spl_object_hash($definition).$this->salt; + return preg_replace('/^.*\\\\/', '', $definition->getClass()).'_'.substr(hash('sha256', spl_object_hash($definition).$this->salt), -7); } /** diff --git a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Fixtures/php/lazy_service_structure.txt b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Fixtures/php/lazy_service_structure.txt index 88e2933cd9015..574041b89bbb4 100644 --- a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Fixtures/php/lazy_service_structure.txt +++ b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Fixtures/php/lazy_service_structure.txt @@ -3,19 +3,18 @@ use %a class LazyServiceProjectServiceContainer extends Container {%a - p%s function getFooService($lazyLoad = true) + protected function getFooService($lazyLoad = true) { if ($lazyLoad) { - - return $this->services['foo'] =%sstdClass_%s( - function (&$wrappedInstance, \ProxyManager\Proxy\LazyLoadingInterface $proxy) { + return $this->services['foo'] = $this->createProxy('stdClass_%s', function () { + return %S\stdClass_%s(function (&$wrappedInstance, \ProxyManager\Proxy\LazyLoadingInterface $proxy) { $wrappedInstance = $this->getFooService(false); $proxy->setProxyInitializer(null); return true; - } - ); + }); + }); } return new \stdClass(); diff --git a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/PhpDumper/ProxyDumperTest.php b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/PhpDumper/ProxyDumperTest.php index 58de413674fa5..640290e2b45a2 100644 --- a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/PhpDumper/ProxyDumperTest.php +++ b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/PhpDumper/ProxyDumperTest.php @@ -55,13 +55,13 @@ public function testGetProxyCode() $code = $this->dumper->getProxyCode($definition); $this->assertStringMatchesFormat( - '%Aclass SymfonyBridgeProxyManagerTestsLazyProxyPhpDumperProxyDumperTest%aextends%w' + '%Aclass ProxyDumperTest%aextends%w' .'\Symfony\Bridge\ProxyManager\Tests\LazyProxy\PhpDumper\ProxyDumperTest%a', $code ); } - public function testGetProxyFactoryCodeWithCustomMethod() + public function testGetProxyFactoryCode() { $definition = new Definition(__CLASS__); @@ -70,19 +70,15 @@ public function testGetProxyFactoryCodeWithCustomMethod() $code = $this->dumper->getProxyFactoryCode($definition, 'foo', '$this->getFoo2Service(false)'); $this->assertStringMatchesFormat( - '%wif ($lazyLoad) {%wreturn $this->services[\'foo\'] =%s' - .'SymfonyBridgeProxyManagerTestsLazyProxyPhpDumperProxyDumperTest_%s(%wfunction ' - .'(&$wrappedInstance, \ProxyManager\Proxy\LazyLoadingInterface $proxy) {' - .'%w$wrappedInstance = $this->getFoo2Service(false);%w$proxy->setProxyInitializer(null);' - .'%wreturn true;%w}%w);%w}%w', - $code + '%A$wrappedInstance = $this->getFoo2Service(false);%w$proxy->setProxyInitializer(null);%A', + $code ); } /** * @group legacy */ - public function testGetProxyFactoryCode() + public function testLegacyGetProxyFactoryCode() { $definition = new Definition(__CLASS__); @@ -91,11 +87,7 @@ public function testGetProxyFactoryCode() $code = $this->dumper->getProxyFactoryCode($definition, 'foo'); $this->assertStringMatchesFormat( - '%wif ($lazyLoad) {%wreturn $this->services[\'foo\'] =%s' - .'SymfonyBridgeProxyManagerTestsLazyProxyPhpDumperProxyDumperTest_%s(%wfunction ' - .'(&$wrappedInstance, \ProxyManager\Proxy\LazyLoadingInterface $proxy) {' - .'%w$wrappedInstance = $this->getFooService(false);%w$proxy->setProxyInitializer(null);' - .'%wreturn true;%w}%w);%w}%w', + '%A$wrappedInstance = $this->getFooService(false);%w$proxy->setProxyInitializer(null);%A', $code ); } diff --git a/src/Symfony/Bridge/ProxyManager/composer.json b/src/Symfony/Bridge/ProxyManager/composer.json index c9fe094094dcb..7e34cd90b5139 100644 --- a/src/Symfony/Bridge/ProxyManager/composer.json +++ b/src/Symfony/Bridge/ProxyManager/composer.json @@ -17,7 +17,7 @@ ], "require": { "php": "^5.5.9|>=7.0.8", - "symfony/dependency-injection": "~2.8|~3.0|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", "ocramius/proxy-manager": "~0.4|~1.0|~2.0" }, "require-dev": { diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php index c3a7bf450ed0f..77ae66867c660 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php @@ -15,6 +15,7 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\SymfonyStyle; +use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\HttpKernel\CacheClearer\CacheClearerInterface; use Symfony\Component\HttpKernel\KernelInterface; @@ -125,6 +126,9 @@ protected function execute(InputInterface $input, OutputInterface $output) $this->filesystem->remove($oldCacheDir); + // The current event dispatcher is stale, let's not use it anymore + $this->getApplication()->setDispatcher(new EventDispatcher()); + if ($output->isVerbose()) { $io->comment('Finished'); } @@ -213,13 +217,19 @@ protected function warmup($warmupDir, $realCacheDir, $enableOptionalWarmers = tr } // fix references to container's class - $tempContainerClass = get_class($tempKernel->getContainer()); - $realContainerClass = get_class($realKernel->getContainer()); + $tempContainerClass = $tempKernel->getContainerClass(); + $realContainerClass = $tempKernel->getRealContainerClass(); foreach (Finder::create()->files()->depth('<2')->name($tempContainerClass.'*')->in($warmupDir) as $file) { $content = str_replace($tempContainerClass, $realContainerClass, file_get_contents($file)); file_put_contents($file, $content); rename($file, str_replace(DIRECTORY_SEPARATOR.$tempContainerClass, DIRECTORY_SEPARATOR.$realContainerClass, $file)); } + if (is_dir($tempContainerDir = $warmupDir.'/'.get_class($tempKernel->getContainer()))) { + foreach (Finder::create()->files()->in($tempContainerDir) as $file) { + $content = str_replace($tempContainerClass, $realContainerClass, file_get_contents($file)); + file_put_contents($file, $content); + } + } // remove temp kernel file after cache warmed up @unlink($tempKernelFile); @@ -245,7 +255,9 @@ protected function getTempKernel(KernelInterface $parent, $namespace, $parentCla // to avoid the many problems in serialized resources files $class = substr($parentClass, 0, -1).'_'; // the temp container class must be changed too - $containerClass = var_export(substr(get_class($parent->getContainer()), 0, -1).'_', true); + $container = $parent->getContainer(); + $realContainerClass = var_export($container->hasParameter('kernel.container_class') ? $container->getParameter('kernel.container_class') : get_class($parent->getContainer()), true); + $containerClass = substr_replace($realContainerClass, '_', -2, 1); if (method_exists($parent, 'getProjectDir')) { $projectDir = var_export(realpath($parent->getProjectDir()), true); @@ -281,7 +293,12 @@ public function getLogDir() return $logDir; } - protected function getContainerClass() + public function getRealContainerClass() + { + return $realContainerClass; + } + + public function getContainerClass() { return $containerClass; } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/CacheClearCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/CacheClearCommandTest.php index b9fe63ec5bbab..f3392995ae93d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/CacheClearCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/CacheClearCommandTest.php @@ -68,8 +68,9 @@ public function testCacheIsFreshAfterCacheClearedWithWarmup() } // check that app kernel file present in meta file of container's cache - $containerRef = new \ReflectionObject($this->kernel->getContainer()); - $containerFile = $containerRef->getFileName(); + $containerClass = $this->kernel->getContainer()->getParameter('kernel.container_class'); + $containerRef = new \ReflectionClass($containerClass); + $containerFile = dirname(dirname($containerRef->getFileName())).'/'.$containerClass.'.php'; $containerMetaFile = $containerFile.'.meta'; $kernelRef = new \ReflectionObject($this->kernel); $kernelFile = $kernelRef->getFileName(); @@ -83,6 +84,12 @@ public function testCacheIsFreshAfterCacheClearedWithWarmup() } } $this->assertTrue($found, 'Kernel file should present as resource'); - $this->assertRegExp(sprintf('/\'kernel.container_class\'\s*=>\s*\'%s\'/', get_class($this->kernel->getContainer())), file_get_contents($containerFile), 'kernel.container_class is properly set on the dumped container'); + + if (defined('HHVM_VERSION')) { + return; + } + $containerRef = new \ReflectionClass(require $containerFile); + $containerFile = str_replace('tes_'.DIRECTORY_SEPARATOR, 'test'.DIRECTORY_SEPARATOR, $containerRef->getFileName()); + $this->assertRegExp(sprintf('/\'kernel.container_class\'\s*=>\s*\'%s\'/', $containerClass), file_get_contents($containerFile), 'kernel.container_class is properly set on the dumped container'); } } diff --git a/src/Symfony/Component/DependencyInjection/Container.php b/src/Symfony/Component/DependencyInjection/Container.php index e3e66308e65cb..187571e9765dd 100644 --- a/src/Symfony/Component/DependencyInjection/Container.php +++ b/src/Symfony/Component/DependencyInjection/Container.php @@ -55,6 +55,7 @@ class Container implements ResettableContainerInterface protected $parameterBag; protected $services = array(); + protected $fileMap = array(); protected $methodMap = array(); protected $aliases = array(); protected $loading = array(); @@ -203,7 +204,7 @@ public function set($id, $service) } else { @trigger_error(sprintf('Setting the "%s" private service is deprecated since Symfony 3.2 and won\'t be supported anymore in Symfony 4.0.', $id), E_USER_DEPRECATED); } - } elseif (isset($this->methodMap[$id])) { + } elseif (isset($this->fileMap[$id]) || isset($this->methodMap[$id])) { if (null === $service) { @trigger_error(sprintf('Unsetting the "%s" pre-defined service is deprecated since Symfony 3.3 and won\'t be supported anymore in Symfony 4.0.', $id), E_USER_DEPRECATED); } else { @@ -235,7 +236,7 @@ public function has($id) return true; } - if (isset($this->methodMap[$id])) { + if (isset($this->fileMap[$id]) || isset($this->methodMap[$id])) { return true; } @@ -299,40 +300,25 @@ public function get($id, $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE throw new ServiceCircularReferenceException($id, array_keys($this->loading)); } - if (isset($this->methodMap[$id])) { - $method = $this->methodMap[$id]; - } elseif (--$i && $id !== $normalizedId = $this->normalizeId($id)) { - $id = $normalizedId; - continue; - } elseif (!$this->methodMap && !$this instanceof ContainerBuilder && __CLASS__ !== static::class && method_exists($this, $method = 'get'.strtr($id, $this->underscoreMap).'Service')) { - // We only check the convention-based factory in a compiled container (i.e. a child class other than a ContainerBuilder, - // and only when the dumper has not generated the method map (otherwise the method map is considered to be fully populated by the dumper) - @trigger_error('Generating a dumped container without populating the method map is deprecated since 3.2 and will be unsupported in 4.0. Update your dumper to generate the method map.', E_USER_DEPRECATED); - // $method is set to the right value, proceed - } else { - if (self::EXCEPTION_ON_INVALID_REFERENCE === $invalidBehavior) { - if (!$id) { - throw new ServiceNotFoundException($id); - } - - $alternatives = array(); - foreach ($this->getServiceIds() as $knownId) { - $lev = levenshtein($id, $knownId); - if ($lev <= strlen($id) / 3 || false !== strpos($knownId, $id)) { - $alternatives[] = $knownId; - } - } - - throw new ServiceNotFoundException($id, null, null, $alternatives); - } - - return; - } - $this->loading[$id] = true; try { - $service = $this->$method(); + if (isset($this->fileMap[$id])) { + return $this->load($this->fileMap[$id]); + } elseif (isset($this->methodMap[$id])) { + return $this->{$this->methodMap[$id]}(); + } elseif (--$i && $id !== $normalizedId = $this->normalizeId($id)) { + $id = $normalizedId; + continue; + } elseif (!$this->methodMap && !$this instanceof ContainerBuilder && __CLASS__ !== static::class && method_exists($this, $method = 'get'.strtr($id, $this->underscoreMap).'Service')) { + // We only check the convention-based factory in a compiled container (i.e. a child class other than a ContainerBuilder, + // and only when the dumper has not generated the method map (otherwise the method map is considered to be fully populated by the dumper) + @trigger_error('Generating a dumped container without populating the method map is deprecated since 3.2 and will be unsupported in 4.0. Update your dumper to generate the method map.', E_USER_DEPRECATED); + + return $this->{$method}(); + } + + break; } catch (\Exception $e) { unset($this->services[$id]); @@ -340,8 +326,22 @@ public function get($id, $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE } finally { unset($this->loading[$id]); } + } + + if (self::EXCEPTION_ON_INVALID_REFERENCE === $invalidBehavior) { + if (!$id) { + throw new ServiceNotFoundException($id); + } + + $alternatives = array(); + foreach ($this->getServiceIds() as $knownId) { + $lev = levenshtein($id, $knownId); + if ($lev <= strlen($id) / 3 || false !== strpos($knownId, $id)) { + $alternatives[] = $knownId; + } + } - return $service; + throw new ServiceNotFoundException($id, null, null, $alternatives); } } @@ -401,7 +401,7 @@ public function getServiceIds() } $ids[] = 'service_container'; - return array_unique(array_merge($ids, array_keys($this->methodMap), array_keys($this->services))); + return array_unique(array_merge($ids, array_keys($this->methodMap), array_keys($this->fileMap), array_keys($this->services))); } /** @@ -428,6 +428,16 @@ public static function underscore($id) return strtolower(preg_replace(array('/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'), array('\\1_\\2', '\\1_\\2'), str_replace('_', '.', $id))); } + /** + * Creates a service by requiring its factory file. + * + * @return object The service created by the file + */ + protected function load($file) + { + return require $file; + } + /** * Fetches a variable from the environment. * diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index 03d8f9babf100..cdcea02ed19d0 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -65,6 +65,8 @@ class PhpDumper extends Dumper private $docStar; private $serviceIdToMethodNameMap; private $usedMethodNames; + private $namespace; + private $asFiles; /** * @var \Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\DumperInterface @@ -103,10 +105,11 @@ public function setProxyDumper(ProxyDumper $proxyDumper) * * class: The class name * * base_class: The base class name * * namespace: The class namespace + * * as_files: To split the container in several files * * @param array $options An array of options * - * @return string A PHP class representing of the service container + * @return string|array A PHP class representing the service container or an array of PHP files if the "as_files" option is set * * @throws EnvParameterException When an env var exists but has not been dumped */ @@ -117,9 +120,12 @@ public function dump(array $options = array()) 'class' => 'ProjectServiceContainer', 'base_class' => 'Container', 'namespace' => '', + 'as_files' => false, 'debug' => true, ), $options); + $this->namespace = $options['namespace']; + $this->asFiles = $options['as_files']; $this->initializeMethodNamesMap($options['base_class']); $this->docStar = $options['debug'] ? '*' : ''; @@ -149,22 +155,62 @@ public function dump(array $options = array()) } } - $code = $this->startClass($options['class'], $options['base_class'], $options['namespace']); + $code = + $this->startClass($options['class'], $options['base_class']). + $this->addServices(). + $this->addDefaultParametersMethod(). + $this->endClass() + ; - if ($this->container->isCompiled()) { - $code .= $this->addFrozenConstructor(); - $code .= $this->addFrozenCompile(); - $code .= $this->addFrozenIsCompiled(); + if ($this->asFiles) { + $fileStart = <<generateServiceFiles() as $file => $c) { + $files[$file] = $fileStart.$c; + } + foreach ($this->generateProxyClasses() as $file => $c) { + $files[$file] = " $c) { + $code["Container{$hash}/{$file}"] = $c; + } + array_pop($code); + $code["Container{$hash}/Container.php"] = implode("\nclass Container{$hash}", explode("\nclass {$options['class']}", $files['Container.php'], 2)); + $namespaceLine = $this->namespace ? "\nnamespace {$this->namespace};\n" : ''; + + $code[$options['class'].'.php'] = <<addConstructor(); + foreach ($this->generateProxyClasses() as $c) { + $code .= $c; + } } - $code .= - $this->addServices(). - $this->addDefaultParametersMethod(). - $this->endClass(). - $this->addProxyClasses() - ; $this->targetDirRegex = null; $unusedEnvs = array(); @@ -244,30 +290,27 @@ private function addServiceLocalTempVariables($cId, Definition $definition, arra } /** - * Generates code for the proxies to be attached after the container class. + * Generates code for the proxies. * * @return string */ - private function addProxyClasses() + private function generateProxyClasses() { - /* @var $definitions Definition[] */ - $definitions = array_filter( - $this->container->getDefinitions(), - array($this->getProxyDumper(), 'isProxyCandidate') - ); - $code = ''; + $definitions = $this->container->getDefinitions(); $strip = '' === $this->docStar && method_exists('Symfony\Component\HttpKernel\Kernel', 'stripComments'); - + $proxyDumper = $this->getProxyDumper(); + ksort($definitions); foreach ($definitions as $definition) { - $proxyCode = "\n".$this->getProxyDumper()->getProxyCode($definition); + if (!$proxyDumper->isProxyCandidate($definition)) { + continue; + } + $proxyCode = "\n".$proxyDumper->getProxyCode($definition); if ($strip) { $proxyCode = " $proxyCode; } - - return $code; } /** @@ -364,23 +407,6 @@ private function addServiceInlinedDefinitions($id, array $inlinedDefinitions) return $code; } - /** - * Adds the service return statement. - * - * @param string $id - * @param bool $isSimpleInstance - * - * @return string - */ - private function addServiceReturn($id, $isSimpleInstance) - { - if ($isSimpleInstance) { - return " }\n"; - } - - return "\n return \$instance;\n }\n"; - } - /** * Generates the service instance. * @@ -569,14 +595,12 @@ private function addServiceConfigurator(Definition $definition, $variableName = * * @param string $id * @param Definition $definition + * @param string &$file * * @return string */ - private function addService($id, Definition $definition) + private function addService($id, Definition $definition, &$file = null) { - if ($definition->isSynthetic()) { - return ''; - } $this->definitionVariables = new \SplObjectStorage(); $this->referenceVariables = array(); $this->variableCount = 0; @@ -620,23 +644,29 @@ private function addService($id, Definition $definition) $lazyInitialization = ''; } - // with proxies, for 5.3.3 compatibility, the getter must be public to be accessible to the initializer - $isProxyCandidate = $this->getProxyDumper()->isProxyCandidate($definition); - $visibility = $isProxyCandidate ? 'public' : 'protected'; + $asFile = $this->asFiles && $definition->isShared(); $methodName = $this->generateMethodName($id); - $code = <<docStar} * Gets the $public '$id'$shared$autowired service. * * $return */ - {$visibility} function {$methodName}($lazyInitialization) + protected function {$methodName}($lazyInitialization) { EOF; + } - $code .= $isProxyCandidate ? $this->getProxyDumper()->getProxyFactoryCode($definition, $id, "\$this->$methodName(false)") : ''; + if ($this->getProxyDumper()->isProxyCandidate($definition)) { + $factoryCode = $asFile ? "\$this->load(__DIR__.'/%s.php', false)" : '$this->%s(false)'; + $code .= $this->getProxyDumper()->getProxyFactoryCode($definition, $id, sprintf($factoryCode, $methodName)); + } if ($definition->isDeprecated()) { $code .= sprintf(" @trigger_error(%s, E_USER_DEPRECATED);\n\n", $this->export($definition->getDeprecationMessage($id))); @@ -654,9 +684,15 @@ private function addService($id, Definition $definition) $this->addServiceProperties($definition). $this->addServiceMethodCalls($definition). $this->addServiceConfigurator($definition). - $this->addServiceReturn($id, $isSimpleInstance) + (!$isSimpleInstance ? "\n return \$instance;\n" : '') ; + if ($asFile) { + $code = implode("\n", array_map(function ($line) { return $line ? substr($line, 8) : $line; }, explode("\n", $code))); + } else { + $code .= " }\n"; + } + $this->definitionVariables = null; $this->referenceVariables = null; @@ -674,6 +710,9 @@ private function addServices() $definitions = $this->container->getDefinitions(); ksort($definitions); foreach ($definitions as $id => $definition) { + if ($definition->isSynthetic() || ($this->asFiles && $definition->isShared())) { + continue; + } if ($definition->isPublic()) { $publicServices .= $this->addService($id, $definition); } else { @@ -684,6 +723,18 @@ private function addServices() return $publicServices.$privateServices; } + private function generateServiceFiles() + { + $definitions = $this->container->getDefinitions(); + ksort($definitions); + foreach ($definitions as $id => $definition) { + if (!$definition->isSynthetic() && $definition->isShared()) { + $code = $this->addService($id, $definition, $file); + yield $file => $code; + } + } + } + private function addNewInstance(Definition $definition, $return, $instantiation, $id) { $class = $this->dumpValue($definition->getClass()); @@ -737,16 +788,15 @@ private function addNewInstance(Definition $definition, $return, $instantiation, * * @param string $class Class name * @param string $baseClass The name of the base class - * @param string $namespace The class namespace * * @return string */ - private function startClass($class, $baseClass, $namespace) + private function startClass($class, $baseClass) { $bagClass = $this->container->isCompiled() ? 'use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;' : 'use Symfony\Component\DependencyInjection\ParameterBag\\ParameterBag;'; - $namespaceLine = $namespace ? "\nnamespace $namespace;\n" : ''; + $namespaceLine = $this->namespace ? "\nnamespace {$this->namespace};\n" : ''; - return <<exportTargetDirs(); - $arguments = $this->container->getParameterBag()->all() ? 'new ParameterBag($this->getDefaultParameters())' : null; - - $code = <<docStar} * Constructor. */ public function __construct() - {{$targetDirs} - parent::__construct($arguments); - -EOF; - - $code .= $this->addNormalizedIds(); - $code .= $this->addMethodMap(); - $code .= $this->addPrivateServices(); - $code .= $this->addAliases(); - - $code .= <<<'EOF' - } - -EOF; - - return $code; - } - - /** - * Adds the constructor for a compiled container. - * - * @return string - */ - private function addFrozenConstructor() { - $targetDirs = $this->exportTargetDirs(); - $code = <<targetDirRegex) { + $dir = $this->asFiles ? '$this->targetDirs[0] = dirname(__DIR__)' : '__DIR__'; + $code .= <<targetDirMaxMatches}; ++\$i) { + \$this->targetDirs[\$i] = \$dir = dirname(\$dir); + } - /*{$this->docStar} - * Constructor. - */ - public function __construct() - {{$targetDirs} EOF; + } - if ($this->container->getParameterBag()->all()) { - $code .= "\n \$this->parameters = \$this->getDefaultParameters();\n"; + if ($this->container->isCompiled()) { + if ($this->container->getParameterBag()->all()) { + $code .= " \$this->parameters = \$this->getDefaultParameters();\n\n"; + } + $code .= " \$this->services = array();\n"; + } else { + $arguments = $this->container->getParameterBag()->all() ? 'new ParameterBag($this->getDefaultParameters())' : null; + $code .= " parent::__construct($arguments);\n"; } - $code .= "\n \$this->services = array();\n"; $code .= $this->addNormalizedIds(); $code .= $this->addMethodMap(); + $code .= $this->asFiles ? $this->addFileMap() : ''; $code .= $this->addPrivateServices(); $code .= $this->addAliases(); - $code .= <<<'EOF' } EOF; - - return $code; - } - - /** - * Adds the compile method for a compiled container. - * - * @return string - */ - private function addFrozenCompile() - { - return <<container->isCompiled()) { + $code .= <<docStar} * {@inheritdoc} @@ -860,18 +868,6 @@ public function compile() throw new LogicException('You cannot compile a dumped container that was already compiled.'); } -EOF; - } - - /** - * Adds the isCompiled method for a compiled container. - * - * @return string - */ - private function addFrozenIsCompiled() - { - return <<docStar} * {@inheritdoc} */ @@ -891,6 +887,49 @@ public function isFrozen() } EOF; + } + + if ($this->asFiles) { + $code .= <<docStar} + * {@inheritdoc} + */ + protected function load(\$file, \$lazyLoad = true) + { + return require \$file; + } + +EOF; + } + + $proxyDumper = $this->getProxyDumper(); + foreach ($this->container->getDefinitions() as $definition) { + if (!$proxyDumper->isProxyCandidate($definition)) { + continue; + } + if ($this->asFiles) { + $proxyLoader = '$this->load(__DIR__."/{$class}.php")'; + } elseif ($this->namespace) { + $proxyLoader = 'class_alias("'.$this->namespace.'\\\\{$class}", $class, false)'; + } else { + $proxyLoader = ''; + } + if ($proxyLoader) { + $proxyLoader = "class_exists(\$class, false) || {$proxyLoader};\n\n "; + } + $code .= <<container->getDefinitions(); - if (!$definitions || !$definitions = array_filter($definitions, function ($def) { return !$def->isSynthetic(); })) { - return ''; + ksort($definitions); + foreach ($definitions as $id => $definition) { + if (!$definition->isSynthetic() && (!$this->asFiles || !$definition->isShared())) { + $code .= ' '.$this->export($id).' => '.$this->export($this->generateMethodName($id)).",\n"; + } } - $code = " \$this->methodMap = array(\n"; + return $code ? " \$this->methodMap = array(\n{$code} );\n" : ''; + } + + /** + * Adds the fileMap property definition. + * + * @return string + */ + private function addFileMap() + { + $code = ''; + $definitions = $this->container->getDefinitions(); ksort($definitions); foreach ($definitions as $id => $definition) { - $code .= ' '.$this->export($id).' => '.$this->export($this->generateMethodName($id)).",\n"; + if (!$definition->isSynthetic() && $definition->isShared()) { + $code .= sprintf(" %s => __DIR__.'/%s.php',\n", $this->export($id), $this->generateMethodName($id)); + } } - return $code." );\n"; + return $code ? " \$this->fileMap = array(\n{$code} );\n" : ''; } /** @@ -1584,7 +1640,13 @@ private function getServiceCall($id, Reference $reference = null) return '$this'; } - if ($this->container->hasDefinition($id) && !$this->container->getDefinition($id)->isPublic()) { + if ($this->asFiles && $this->container->hasDefinition($id)) { + if ($this->container->getDefinition($id)->isShared()) { + $code = sprintf("\$this->load(__DIR__.'/%s.php')", $this->generateMethodName($id)); + } else { + $code = sprintf('$this->%s()', $this->generateMethodName($id)); + } + } elseif ($this->container->hasDefinition($id) && !$this->container->getDefinition($id)->isPublic()) { $code = sprintf('$this->%s()', $this->generateMethodName($id)); } elseif (null !== $reference && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $reference->getInvalidBehavior()) { $code = sprintf('$this->get(\'%s\', ContainerInterface::NULL_ON_INVALID_REFERENCE)', $id); @@ -1715,17 +1777,6 @@ private function getExpressionLanguage() return $this->expressionLanguage; } - private function exportTargetDirs() - { - return null === $this->targetDirRegex ? '' : <<targetDirMaxMatches}; ++\$i) { - \$this->targetDirs[\$i] = \$dir = dirname(\$dir); - } -EOF; - } - private function export($value) { if (null !== $this->targetDirRegex && is_string($value) && preg_match($this->targetDirRegex, $value, $matches, PREG_OFFSET_CAPTURE)) { @@ -1733,8 +1784,9 @@ private function export($value) $suffix = $matches[0][1] + strlen($matches[0][0]); $suffix = isset($value[$suffix]) ? '.'.$this->doExport(substr($value, $suffix)) : ''; $dirname = '__DIR__'; + $offset = 1 + $this->targetDirMaxMatches - count($matches); - if (0 < $offset = 1 + $this->targetDirMaxMatches - count($matches)) { + if ($this->asFiles || 0 < $offset) { $dirname = sprintf('$this->targetDirs[%d]', $offset); } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php index 4afb445c68ca8..fc5a950af4709 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php @@ -162,6 +162,18 @@ public function testAddService() } } + public function testDumpAsFiles() + { + $container = include self::$fixturesPath.'/containers/container9.php'; + $container->compile(); + $dumper = new PhpDumper($container); + $dump = print_r($dumper->dump(array('as_files' => true, 'file' => __DIR__)), true); + if ('\\' === DIRECTORY_SEPARATOR) { + $dump = str_replace('\\\\Fixtures\\\\includes\\\\foo.php', '/Fixtures/includes/foo.php', $dump); + } + $this->assertStringMatchesFormatFile(self::$fixturesPath.'/php/services9_as_files.txt', $dump); + } + public function testServicesWithAnonymousFactories() { $container = include self::$fixturesPath.'/containers/container19.php'; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php index 13b45fda07a70..6445e0f427e06 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php @@ -34,6 +34,7 @@ ; $container ->register('foo_bar', '%foo_class%') + ->addArgument(new Reference('deprecated_service')) ->setShared(false) ; $container->getParameterBag()->clear(); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services9.dot b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services9.dot index b316b93c1576b..df9a1cae7ce73 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services9.dot +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services9.dot @@ -38,6 +38,7 @@ digraph sc { node_foo -> node_foo_baz [label="" style="dashed"]; node_foo -> node_bar [label="setBar()" style="dashed"]; node_bar -> node_foo_baz [label="" style="filled"]; + node_foo_bar -> node_deprecated_service [label="" style="filled"]; node_method_call1 -> node_foo [label="setBar()" style="dashed"]; node_method_call1 -> node_foo2 [label="setBar()" style="dashed"]; node_method_call1 -> node_foo3 [label="setBar()" style="dashed"]; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php index 4998b60f4c719..f1ba88974a66c 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php @@ -238,7 +238,7 @@ protected function getFooBarService() { $class = $this->getParameter('foo_class'); - return new $class(); + return new $class(${($_ = isset($this->services['deprecated_service']) ? $this->services['deprecated_service'] : $this->get('deprecated_service')) && false ?: '_'}); } /** diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt new file mode 100644 index 0000000000000..3b80a904d3e9d --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt @@ -0,0 +1,434 @@ +Array +( + [Container%s/getBarService.php] => services['foo.baz']) ? $this->services['foo.baz'] : $this->load(__DIR__.'/getFoo_BazService.php')) && false ?: '_'}; + +$this->services['bar'] = $instance = new \Bar\FooClass('foo', $a, $this->getParameter('foo_bar')); + +$a->configure($instance); + +return $instance; + + [Container%s/getBazService.php] => services['baz'] = $instance = new \Baz(); + +$instance->setFoo(${($_ = isset($this->services['foo_with_inline']) ? $this->services['foo_with_inline'] : $this->load(__DIR__.'/getFooWithInlineService.php')) && false ?: '_'}); + +return $instance; + + [Container%s/getConfiguredServiceService.php] => setFoo(${($_ = isset($this->services['baz']) ? $this->services['baz'] : $this->load(__DIR__.'/getBazService.php')) && false ?: '_'}); + +$this->services['configured_service'] = $instance = new \stdClass(); + +$a->configureStdClass($instance); + +return $instance; + + [Container%s/getConfiguredServiceSimpleService.php] => services['configured_service_simple'] = $instance = new \stdClass(); + +(new \ConfClass('bar'))->configureStdClass($instance); + +return $instance; + + [Container%s/getDecoratorServiceService.php] => services['decorator_service'] = new \stdClass(); + + [Container%s/getDecoratorServiceWithNameService.php] => services['decorator_service_with_name'] = new \stdClass(); + + [Container%s/getDeprecatedServiceService.php] => services['deprecated_service'] = new \stdClass(); + + [Container%s/getFactoryServiceService.php] => services['factory_service'] = ${($_ = isset($this->services['foo.baz']) ? $this->services['foo.baz'] : $this->load(__DIR__.'/getFoo_BazService.php')) && false ?: '_'}->getInstance(); + + [Container%s/getFactoryServiceSimpleService.php] => services['factory_service_simple'] = (new \SimpleFactoryClass('foo'))->getInstance(); + + [Container%s/getFooService.php] => services['foo.baz']) ? $this->services['foo.baz'] : $this->load(__DIR__.'/getFoo_BazService.php')) && false ?: '_'}; + +$this->services['foo'] = $instance = \Bar\FooClass::getInstance('foo', $a, array('bar' => 'foo is bar', 'foobar' => 'bar'), true, $this); + +$instance->foo = 'bar'; +$instance->moo = $a; +$instance->qux = array('bar' => 'foo is bar', 'foobar' => 'bar'); +$instance->setBar(${($_ = isset($this->services['bar']) ? $this->services['bar'] : $this->load(__DIR__.'/getBarService.php')) && false ?: '_'}); +$instance->initialize(); +sc_configure($instance); + +return $instance; + + [Container%s/getFoo_BazService.php] => services['foo.baz'] = $instance = \BazClass::getInstance(); + +\BazClass::configureStatic1($instance); + +return $instance; + + [Container%s/getFooWithInlineService.php] => services['foo_with_inline'] = $instance = new \Foo(); + +$a->pub = 'pub'; +$a->setBaz(${($_ = isset($this->services['baz']) ? $this->services['baz'] : $this->load(__DIR__.'/getBazService.php')) && false ?: '_'}); + +$instance->setBar($a); + +return $instance; + + [Container%s/getLazyContextService.php] => services['lazy_context'] = new \LazyContext(new RewindableGenerator(function () { + yield 'k1' => ${($_ = isset($this->services['foo.baz']) ? $this->services['foo.baz'] : $this->load(__DIR__.'/getFoo_BazService.php')) && false ?: '_'}; + yield 'k2' => $this; +}, 2), new RewindableGenerator(function () { + return new \EmptyIterator(); +}, 0)); + + [Container%s/getLazyContextIgnoreInvalidRefService.php] => services['lazy_context_ignore_invalid_ref'] = new \LazyContext(new RewindableGenerator(function () { + yield 0 => ${($_ = isset($this->services['foo.baz']) ? $this->services['foo.baz'] : $this->load(__DIR__.'/getFoo_BazService.php')) && false ?: '_'}; +}, 1), new RewindableGenerator(function () { + return new \EmptyIterator(); +}, 0)); + + [Container%s/getMethodCall1Service.php] => targetDirs[0].'/Fixtures/includes/foo.php'); + +$this->services['method_call1'] = $instance = new \Bar\FooClass(); + +$instance->setBar(${($_ = isset($this->services['foo']) ? $this->services['foo'] : $this->load(__DIR__.'/getFooService.php')) && false ?: '_'}); +$instance->setBar(NULL); +$instance->setBar((${($_ = isset($this->services['foo']) ? $this->services['foo'] : $this->load(__DIR__.'/getFooService.php')) && false ?: '_'}->foo() . (($this->hasParameter("foo")) ? ($this->getParameter("foo")) : ("default")))); + +return $instance; + + [Container%s/getNewFactoryServiceService.php] => foo = 'bar'; + +$this->services['new_factory_service'] = $instance = $a->getInstance(); + +$instance->foo = 'bar'; + +return $instance; + + [Container%s/getServiceFromStaticMethodService.php] => services['service_from_static_method'] = \Bar\FooClass::getInstance(); + + [Container%s/Container.php] => targetDirs[0] = dirname(__DIR__); + for ($i = 1; $i <= 5; ++$i) { + $this->targetDirs[$i] = $dir = dirname($dir); + } + $this->parameters = $this->getDefaultParameters(); + + $this->services = array(); + $this->methodMap = array( + 'foo_bar' => 'getFooBarService', + ); + $this->fileMap = array( + 'bar' => __DIR__.'/getBarService.php', + 'baz' => __DIR__.'/getBazService.php', + 'configured_service' => __DIR__.'/getConfiguredServiceService.php', + 'configured_service_simple' => __DIR__.'/getConfiguredServiceSimpleService.php', + 'decorator_service' => __DIR__.'/getDecoratorServiceService.php', + 'decorator_service_with_name' => __DIR__.'/getDecoratorServiceWithNameService.php', + 'deprecated_service' => __DIR__.'/getDeprecatedServiceService.php', + 'factory_service' => __DIR__.'/getFactoryServiceService.php', + 'factory_service_simple' => __DIR__.'/getFactoryServiceSimpleService.php', + 'foo' => __DIR__.'/getFooService.php', + 'foo.baz' => __DIR__.'/getFoo_BazService.php', + 'foo_with_inline' => __DIR__.'/getFooWithInlineService.php', + 'lazy_context' => __DIR__.'/getLazyContextService.php', + 'lazy_context_ignore_invalid_ref' => __DIR__.'/getLazyContextIgnoreInvalidRefService.php', + 'method_call1' => __DIR__.'/getMethodCall1Service.php', + 'new_factory_service' => __DIR__.'/getNewFactoryServiceService.php', + 'service_from_static_method' => __DIR__.'/getServiceFromStaticMethodService.php', + ); + $this->aliases = array( + 'alias_for_alias' => 'foo', + 'alias_for_foo' => 'foo', + 'decorated' => 'decorator_service_with_name', + ); + } + + /** + * {@inheritdoc} + */ + public function compile() + { + throw new LogicException('You cannot compile a dumped container that was already compiled.'); + } + + /** + * {@inheritdoc} + */ + public function isCompiled() + { + return true; + } + + /** + * {@inheritdoc} + */ + 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; + } + + /** + * {@inheritdoc} + */ + protected function load($file, $lazyLoad = true) + { + return require $file; + } + + /** + * Gets the public 'foo_bar' service. + * + * @return \Bar\FooClass + */ + protected function getFooBarService() + { + return new \Bar\FooClass(${($_ = isset($this->services['deprecated_service']) ? $this->services['deprecated_service'] : $this->load(__DIR__.'/getDeprecatedServiceService.php')) && false ?: '_'}); + } + + /** + * {@inheritdoc} + */ + public function getParameter($name) + { + if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { + $name = strtolower($name); + + if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { + throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); + } + } + if (isset($this->loadedDynamicParameters[$name])) { + return $this->loadedDynamicParameters[$name] ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name); + } + + return $this->parameters[$name]; + } + + /** + * {@inheritdoc} + */ + public function hasParameter($name) + { + $name = strtolower($name); + + return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters); + } + + /** + * {@inheritdoc} + */ + public function setParameter($name, $value) + { + throw new LogicException('Impossible to call set() on a frozen ParameterBag.'); + } + + /** + * {@inheritdoc} + */ + public function getParameterBag() + { + if (null === $this->parameterBag) { + $parameters = $this->parameters; + foreach ($this->loadedDynamicParameters as $name => $loaded) { + $parameters[$name] = $loaded ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name); + } + $this->parameterBag = new FrozenParameterBag($parameters); + } + + return $this->parameterBag; + } + + private $loadedDynamicParameters = array(); + private $dynamicParameters = array(); + + /** + * Computes a dynamic parameter. + * + * @param string The name of the dynamic parameter to load + * + * @return mixed The value of the dynamic parameter + * + * @throws InvalidArgumentException When the dynamic parameter does not exist + */ + private function getDynamicParameter($name) + { + throw new InvalidArgumentException(sprintf('The dynamic parameter "%s" must be defined.', $name)); + } + + /** + * Gets the default parameters. + * + * @return array An array of the default parameters + */ + protected function getDefaultParameters() + { + return array( + 'baz_class' => 'BazClass', + 'foo_class' => 'Bar\\FooClass', + 'foo' => 'bar', + ); + } +} + + [ProjectServiceContainer.php] => services['deprecated_service']) ? $this->services['deprecated_service'] : $this->get('deprecated_service')) && false ?: '_'}); } /** diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml index 100a23a9c5b7e..fb2050ab6191f 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml @@ -41,7 +41,9 @@ %foo_bar% - + + + %path%foo.php diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml index a7a9cc28fd61b..984f2136700c0 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml @@ -31,6 +31,7 @@ services: foo_bar: class: '%foo_class%' shared: false + arguments: ['@deprecated_service'] method_call1: class: Bar\FooClass file: '%path%foo.php' diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 4b065f56a0fc0..a6c31e8a3f821 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -22,6 +22,7 @@ use Symfony\Component\DependencyInjection\Loader\PhpFileLoader; use Symfony\Component\DependencyInjection\Loader\DirectoryLoader; use Symfony\Component\DependencyInjection\Loader\ClosureLoader; +use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Bundle\BundleInterface; @@ -588,9 +589,7 @@ protected function initializeContainer() $fresh = false; } - require_once $cache->getPath(); - - $this->container = new $class(); + $this->container = require $cache->getPath(); $this->container->set('kernel', $this); if (!$fresh && $this->container->has('cache_warmer')) { @@ -757,9 +756,24 @@ protected function dumpContainer(ConfigCache $cache, ContainerBuilder $container $dumper->setProxyDumper(new ProxyDumper(substr(hash('sha256', $cache->getPath()), 0, 7))); } - $content = $dumper->dump(array('class' => $class, 'base_class' => $baseClass, 'file' => $cache->getPath(), 'debug' => $this->debug)); + $content = $dumper->dump(array( + 'class' => $class, + 'base_class' => $baseClass, + 'file' => $cache->getPath(), + 'as_files' => true, + 'debug' => $this->debug, + )); + + $rootCode = array_pop($content); + $dir = dirname($cache->getPath()).'/'; + $fs = new Filesystem(); + + foreach ($content as $file => $code) { + $fs->dumpFile($dir.$file, $code, null); + @chmod($dir.$file, 0666 & ~umask()); + } - $cache->write($content, $container->getResources()); + $cache->write($rootCode, $container->getResources()); } /** diff --git a/src/Symfony/Component/HttpKernel/composer.json b/src/Symfony/Component/HttpKernel/composer.json index 053ea74b27c48..3c051bb5f7b33 100644 --- a/src/Symfony/Component/HttpKernel/composer.json +++ b/src/Symfony/Component/HttpKernel/composer.json @@ -28,7 +28,7 @@ "symfony/config": "~2.8|~3.0|~4.0", "symfony/console": "~2.8|~3.0|~4.0", "symfony/css-selector": "~2.8|~3.0|~4.0", - "symfony/dependency-injection": "~3.3|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", "symfony/dom-crawler": "~2.8|~3.0|~4.0", "symfony/expression-language": "~2.8|~3.0|~4.0", "symfony/finder": "~2.8|~3.0|~4.0", @@ -42,7 +42,7 @@ }, "conflict": { "symfony/config": "<2.8", - "symfony/dependency-injection": "<3.3", + "symfony/dependency-injection": "<3.4", "symfony/var-dumper": "<3.3", "twig/twig": "<1.34|<2.4,>=2" },