Verzeichnisstruktur phpBB-3.3.16


Veröffentlicht
27.04.2026

So funktioniert es


Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück

Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

      (Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

PhpDumper.php

Zuletzt modifiziert: 01.05.2026, 11:27 - Dateigröße: 75.66 KiB


 0001  <?php
 0002   
 0003  /*
 0004   * This file is part of the Symfony package.
 0005   *
 0006   * (c) Fabien Potencier <fabien@symfony.com>
 0007   *
 0008   * For the full copyright and license information, please view the LICENSE
 0009   * file that was distributed with this source code.
 0010   */
 0011   
 0012  namespace Symfony\Component\DependencyInjection\Dumper;
 0013   
 0014  use Symfony\Component\DependencyInjection\Argument\ArgumentInterface;
 0015  use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
 0016  use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
 0017  use Symfony\Component\DependencyInjection\Compiler\AnalyzeServiceReferencesPass;
 0018  use Symfony\Component\DependencyInjection\Compiler\CheckCircularReferencesPass;
 0019  use Symfony\Component\DependencyInjection\Container;
 0020  use Symfony\Component\DependencyInjection\ContainerBuilder;
 0021  use Symfony\Component\DependencyInjection\ContainerInterface;
 0022  use Symfony\Component\DependencyInjection\Definition;
 0023  use Symfony\Component\DependencyInjection\Exception\EnvParameterException;
 0024  use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
 0025  use Symfony\Component\DependencyInjection\Exception\RuntimeException;
 0026  use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
 0027  use Symfony\Component\DependencyInjection\ExpressionLanguage;
 0028  use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\DumperInterface as ProxyDumper;
 0029  use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\NullDumper;
 0030  use Symfony\Component\DependencyInjection\Parameter;
 0031  use Symfony\Component\DependencyInjection\Reference;
 0032  use Symfony\Component\DependencyInjection\TypedReference;
 0033  use Symfony\Component\DependencyInjection\Variable;
 0034  use Symfony\Component\ExpressionLanguage\Expression;
 0035  use Symfony\Component\HttpKernel\Kernel;
 0036   
 0037  /**
 0038   * PhpDumper dumps a service container as a PHP class.
 0039   *
 0040   * @author Fabien Potencier <fabien@symfony.com>
 0041   * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 0042   */
 0043  class PhpDumper extends Dumper
 0044  {
 0045      /**
 0046       * Characters that might appear in the generated variable name as first character.
 0047       */
 0048      const FIRST_CHARS = 'abcdefghijklmnopqrstuvwxyz';
 0049   
 0050      /**
 0051       * Characters that might appear in the generated variable name as any but the first character.
 0052       */
 0053      const NON_FIRST_CHARS = 'abcdefghijklmnopqrstuvwxyz0123456789_';
 0054   
 0055      private $definitionVariables;
 0056      private $referenceVariables;
 0057      private $variableCount;
 0058      private $inlinedDefinitions;
 0059      private $serviceCalls;
 0060      private $reservedVariables = ['instance', 'class', 'this'];
 0061      private $expressionLanguage;
 0062      private $targetDirRegex;
 0063      private $targetDirMaxMatches;
 0064      private $docStar;
 0065      private $serviceIdToMethodNameMap;
 0066      private $usedMethodNames;
 0067      private $namespace;
 0068      private $asFiles;
 0069      private $hotPathTag;
 0070      private $inlineRequires;
 0071      private $inlinedRequires = [];
 0072      private $circularReferences = [];
 0073   
 0074      /**
 0075       * @var ProxyDumper
 0076       */
 0077      private $proxyDumper;
 0078   
 0079      /**
 0080       * {@inheritdoc}
 0081       */
 0082      public function __construct(ContainerBuilder $container)
 0083      {
 0084          if (!$container->isCompiled()) {
 0085              @trigger_error('Dumping an uncompiled ContainerBuilder is deprecated since Symfony 3.3 and will not be supported anymore in 4.0. Compile the container beforehand.', \E_USER_DEPRECATED);
 0086          }
 0087   
 0088          parent::__construct($container);
 0089      }
 0090   
 0091      /**
 0092       * Sets the dumper to be used when dumping proxies in the generated container.
 0093       */
 0094      public function setProxyDumper(ProxyDumper $proxyDumper)
 0095      {
 0096          $this->proxyDumper = $proxyDumper;
 0097      }
 0098   
 0099      /**
 0100       * Dumps the service container as a PHP class.
 0101       *
 0102       * Available options:
 0103       *
 0104       *  * class:      The class name
 0105       *  * base_class: The base class name
 0106       *  * namespace:  The class namespace
 0107       *  * as_files:   To split the container in several files
 0108       *
 0109       * @return string|array A PHP class representing the service container or an array of PHP files if the "as_files" option is set
 0110       *
 0111       * @throws EnvParameterException When an env var exists but has not been dumped
 0112       */
 0113      public function dump(array $options = [])
 0114      {
 0115          $this->targetDirRegex = null;
 0116          $this->inlinedRequires = [];
 0117          $options = array_merge([
 0118              'class' => 'ProjectServiceContainer',
 0119              'base_class' => 'Container',
 0120              'namespace' => '',
 0121              'as_files' => false,
 0122              'debug' => true,
 0123              'hot_path_tag' => 'container.hot_path',
 0124              'inline_class_loader_parameter' => 'container.dumper.inline_class_loader',
 0125              'build_time' => time(),
 0126          ], $options);
 0127   
 0128          $this->namespace = $options['namespace'];
 0129          $this->asFiles = $options['as_files'];
 0130          $this->hotPathTag = $options['hot_path_tag'];
 0131          $this->inlineRequires = $options['inline_class_loader_parameter'] && $this->container->hasParameter($options['inline_class_loader_parameter']) && $this->container->getParameter($options['inline_class_loader_parameter']);
 0132   
 0133          if (0 !== strpos($baseClass = $options['base_class'], '\\') && 'Container' !== $baseClass) {
 0134              $baseClass = sprintf('%s\%s', $options['namespace'] ? '\\'.$options['namespace'] : '', $baseClass);
 0135              $baseClassWithNamespace = $baseClass;
 0136          } elseif ('Container' === $baseClass) {
 0137              $baseClassWithNamespace = Container::class;
 0138          } else {
 0139              $baseClassWithNamespace = $baseClass;
 0140          }
 0141   
 0142          $this->initializeMethodNamesMap('Container' === $baseClass ? Container::class : $baseClass);
 0143   
 0144          if ($this->getProxyDumper() instanceof NullDumper) {
 0145              (new AnalyzeServiceReferencesPass(true, false))->process($this->container);
 0146              try {
 0147                  (new CheckCircularReferencesPass())->process($this->container);
 0148              } catch (ServiceCircularReferenceException $e) {
 0149                  $path = $e->getPath();
 0150                  end($path);
 0151                  $path[key($path)] .= '". Try running "composer require symfony/proxy-manager-bridge';
 0152   
 0153                  throw new ServiceCircularReferenceException($e->getServiceId(), $path);
 0154              }
 0155          }
 0156   
 0157          (new AnalyzeServiceReferencesPass(false, !$this->getProxyDumper() instanceof NullDumper))->process($this->container);
 0158          $checkedNodes = [];
 0159          $this->circularReferences = [];
 0160          foreach ($this->container->getCompiler()->getServiceReferenceGraph()->getNodes() as $id => $node) {
 0161              if (!$node->getValue() instanceof Definition) {
 0162                  continue;
 0163              }
 0164              if (!isset($checkedNodes[$id])) {
 0165                  $this->analyzeCircularReferences($id, $node->getOutEdges(), $checkedNodes);
 0166              }
 0167          }
 0168          $this->container->getCompiler()->getServiceReferenceGraph()->clear();
 0169          $checkedNodes = [];
 0170   
 0171          $this->docStar = $options['debug'] ? '*' : '';
 0172   
 0173          if (!empty($options['file']) && is_dir($dir = \dirname($options['file']))) {
 0174              // Build a regexp where the first root dirs are mandatory,
 0175              // but every other sub-dir is optional up to the full path in $dir
 0176              // Mandate at least 1 root dir and not more than 5 optional dirs.
 0177   
 0178              $dir = explode(\DIRECTORY_SEPARATOR, realpath($dir));
 0179              $i = \count($dir);
 0180   
 0181              if (2 + (int) ('\\' === \DIRECTORY_SEPARATOR) <= $i) {
 0182                  $regex = '';
 0183                  $lastOptionalDir = $i > 8 ? $i - 5 : (2 + (int) ('\\' === \DIRECTORY_SEPARATOR));
 0184                  $this->targetDirMaxMatches = $i - $lastOptionalDir;
 0185   
 0186                  while (--$i >= $lastOptionalDir) {
 0187                      $regex = sprintf('(%s%s)?', preg_quote(\DIRECTORY_SEPARATOR.$dir[$i], '#'), $regex);
 0188                  }
 0189   
 0190                  do {
 0191                      $regex = preg_quote(\DIRECTORY_SEPARATOR.$dir[$i], '#').$regex;
 0192                  } while (0 < --$i);
 0193   
 0194                  $this->targetDirRegex = '#(^|file://|[:;, \|\r\n])'.preg_quote($dir[0], '#').$regex.'#';
 0195              }
 0196          }
 0197   
 0198          $code =
 0199              $this->startClass($options['class'], $baseClass, $baseClassWithNamespace).
 0200              $this->addServices().
 0201              $this->addDefaultParametersMethod().
 0202              $this->endClass()
 0203          ;
 0204   
 0205          if ($this->asFiles) {
 0206              $fileStart = <<<EOF
 0207  <?php
 0208   
 0209  use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
 0210   
 0211  // This file has been auto-generated by the Symfony Dependency Injection Component for internal use.
 0212   
 0213  EOF;
 0214   
 0215              $files = [];
 0216   
 0217              if ($ids = array_keys($this->container->getRemovedIds())) {
 0218                  sort($ids);
 0219                  $c = "<?php\n\nreturn [\n";
 0220                  foreach ($ids as $id) {
 0221                      $c .= '    '.$this->doExport($id)." => true,\n";
 0222                  }
 0223                  $files['removed-ids.php'] = $c."];\n";
 0224              }
 0225   
 0226              foreach ($this->generateServiceFiles() as $file => $c) {
 0227                  $files[$file] = $fileStart.$c;
 0228              }
 0229              foreach ($this->generateProxyClasses() as $file => $c) {
 0230                  $files[$file] = "<?php\n".$c;
 0231              }
 0232              $files[$options['class'].'.php'] = $code;
 0233              $hash = ucfirst(strtr(ContainerBuilder::hash($files), '._', 'xx'));
 0234              $code = [];
 0235   
 0236              foreach ($files as $file => $c) {
 0237                  $code["Container{$hash}/{$file}"] = $c;
 0238              }
 0239              array_pop($code);
 0240              $code["Container{$hash}/{$options['class']}.php"] = substr_replace($files[$options['class'].'.php'], "<?php\n\nnamespace Container{$hash};\n", 0, 6);
 0241              $namespaceLine = $this->namespace ? "\nnamespace {$this->namespace};\n" : '';
 0242              $time = $options['build_time'];
 0243              $id = hash('crc32', $hash.$time);
 0244   
 0245              $code[$options['class'].'.php'] = <<<EOF
 0246  <?php
 0247  {$namespaceLine}
 0248  // This file has been auto-generated by the Symfony Dependency Injection Component for internal use.
 0249   
 0250  if (\\class_exists(\\Container{$hash}\\{$options['class']}::class, false)) {
 0251      // no-op
 0252  } elseif (!include __DIR__.'/Container{$hash}/{$options['class']}.php') {
 0253      touch(__DIR__.'/Container{$hash}.legacy');
 0254   
 0255      return;
 0256  }
 0257   
 0258  if (!\\class_exists({$options['class']}::class, false)) {
 0259      \\class_alias(\\Container{$hash}\\{$options['class']}::class, {$options['class']}::class, false);
 0260  }
 0261   
 0262  return new \\Container{$hash}\\{$options['class']}([
 0263      'container.build_hash' => '$hash',
 0264      'container.build_id' => '$id',
 0265      'container.build_time' => $time,
 0266  ], __DIR__.\\DIRECTORY_SEPARATOR.'Container{$hash}');
 0267   
 0268  EOF;
 0269   
 0270          } else {
 0271              foreach ($this->generateProxyClasses() as $c) {
 0272                  $code .= $c;
 0273              }
 0274          }
 0275   
 0276          $this->targetDirRegex = null;
 0277          $this->inlinedRequires = [];
 0278          $this->circularReferences = [];
 0279   
 0280          $unusedEnvs = [];
 0281          foreach ($this->container->getEnvCounters() as $env => $use) {
 0282              if (!$use) {
 0283                  $unusedEnvs[] = $env;
 0284              }
 0285          }
 0286          if ($unusedEnvs) {
 0287              throw new EnvParameterException($unusedEnvs, null, 'Environment variables "%s" are never used. Please, check your container\'s configuration.');
 0288          }
 0289   
 0290          return $code;
 0291      }
 0292   
 0293      /**
 0294       * Retrieves the currently set proxy dumper or instantiates one.
 0295       *
 0296       * @return ProxyDumper
 0297       */
 0298      private function getProxyDumper()
 0299      {
 0300          if (!$this->proxyDumper) {
 0301              $this->proxyDumper = new NullDumper();
 0302          }
 0303   
 0304          return $this->proxyDumper;
 0305      }
 0306   
 0307      private function analyzeCircularReferences($sourceId, array $edges, &$checkedNodes, &$currentPath = [], $byConstructor = true)
 0308      {
 0309          $checkedNodes[$sourceId] = true;
 0310          $currentPath[$sourceId] = $byConstructor;
 0311   
 0312          foreach ($edges as $edge) {
 0313              $node = $edge->getDestNode();
 0314              $id = $node->getId();
 0315   
 0316              if (!$node->getValue() instanceof Definition || $sourceId === $id || $edge->isLazy() || $edge->isWeak()) {
 0317                  // no-op
 0318              } elseif (isset($currentPath[$id])) {
 0319                  $this->addCircularReferences($id, $currentPath, $edge->isReferencedByConstructor());
 0320              } elseif (!isset($checkedNodes[$id])) {
 0321                  $this->analyzeCircularReferences($id, $node->getOutEdges(), $checkedNodes, $currentPath, $edge->isReferencedByConstructor());
 0322              } elseif (isset($this->circularReferences[$id])) {
 0323                  $this->connectCircularReferences($id, $currentPath, $edge->isReferencedByConstructor());
 0324              }
 0325          }
 0326          unset($currentPath[$sourceId]);
 0327      }
 0328   
 0329      private function connectCircularReferences($sourceId, &$currentPath, $byConstructor, &$subPath = [])
 0330      {
 0331          $currentPath[$sourceId] = $subPath[$sourceId] = $byConstructor;
 0332   
 0333          foreach ($this->circularReferences[$sourceId] as $id => $byConstructor) {
 0334              if (isset($currentPath[$id])) {
 0335                  $this->addCircularReferences($id, $currentPath, $byConstructor);
 0336              } elseif (!isset($subPath[$id]) && isset($this->circularReferences[$id])) {
 0337                  $this->connectCircularReferences($id, $currentPath, $byConstructor, $subPath);
 0338              }
 0339          }
 0340          unset($currentPath[$sourceId], $subPath[$sourceId]);
 0341      }
 0342   
 0343      private function addCircularReferences($id, $currentPath, $byConstructor)
 0344      {
 0345          $currentPath[$id] = $byConstructor;
 0346          $circularRefs = [];
 0347   
 0348          foreach (array_reverse($currentPath) as $parentId => $v) {
 0349              $byConstructor = $byConstructor && $v;
 0350              $circularRefs[] = $parentId;
 0351   
 0352              if ($parentId === $id) {
 0353                  break;
 0354              }
 0355          }
 0356   
 0357          $currentId = $id;
 0358          foreach ($circularRefs as $parentId) {
 0359              if (empty($this->circularReferences[$parentId][$currentId])) {
 0360                  $this->circularReferences[$parentId][$currentId] = $byConstructor;
 0361              }
 0362   
 0363              $currentId = $parentId;
 0364          }
 0365      }
 0366   
 0367      private function collectLineage($class, array &$lineage)
 0368      {
 0369          if (isset($lineage[$class])) {
 0370              return;
 0371          }
 0372          if (!$r = $this->container->getReflectionClass($class, false)) {
 0373              return;
 0374          }
 0375          if ($this->container instanceof $class) {
 0376              return;
 0377          }
 0378          $file = $r->getFileName();
 0379          if (') : eval()\'d code' === substr($file, -17)) {
 0380              $file = substr($file, 0, strrpos($file, '(', -17));
 0381          }
 0382          if (!$file || $this->doExport($file) === $exportedFile = $this->export($file)) {
 0383              return;
 0384          }
 0385   
 0386          if ($parent = $r->getParentClass()) {
 0387              $this->collectLineage($parent->name, $lineage);
 0388          }
 0389   
 0390          foreach ($r->getInterfaces() as $parent) {
 0391              $this->collectLineage($parent->name, $lineage);
 0392          }
 0393   
 0394          foreach ($r->getTraits() as $parent) {
 0395              $this->collectLineage($parent->name, $lineage);
 0396          }
 0397   
 0398          $lineage[$class] = substr($exportedFile, 1, -1);
 0399      }
 0400   
 0401      private function generateProxyClasses()
 0402      {
 0403          $alreadyGenerated = [];
 0404          $definitions = $this->container->getDefinitions();
 0405          $strip = '' === $this->docStar && method_exists('Symfony\Component\HttpKernel\Kernel', 'stripComments');
 0406          $proxyDumper = $this->getProxyDumper();
 0407          ksort($definitions);
 0408          foreach ($definitions as $definition) {
 0409              if (!$proxyDumper->isProxyCandidate($definition)) {
 0410                  continue;
 0411              }
 0412              if (isset($alreadyGenerated[$class = $definition->getClass()])) {
 0413                  continue;
 0414              }
 0415              $alreadyGenerated[$class] = true;
 0416              // register class' reflector for resource tracking
 0417              $this->container->getReflectionClass($class);
 0418              if ("\n" === $proxyCode = "\n".$proxyDumper->getProxyCode($definition)) {
 0419                  continue;
 0420              }
 0421              if ($strip) {
 0422                  $proxyCode = "<?php\n".$proxyCode;
 0423                  $proxyCode = substr(Kernel::stripComments($proxyCode), 5);
 0424              }
 0425              yield sprintf('%s.php', explode(' ', $proxyCode, 3)[1]) => $proxyCode;
 0426          }
 0427      }
 0428   
 0429      /**
 0430       * Generates the require_once statement for service includes.
 0431       *
 0432       * @return string
 0433       */
 0434      private function addServiceInclude($cId, Definition $definition)
 0435      {
 0436          $code = '';
 0437   
 0438          if ($this->inlineRequires && !$this->isHotPath($definition)) {
 0439              $lineage = [];
 0440              foreach ($this->inlinedDefinitions as $def) {
 0441                  if (!$def->isDeprecated() && \is_string($class = \is_array($factory = $def->getFactory()) && \is_string($factory[0]) ? $factory[0] : $def->getClass())) {
 0442                      $this->collectLineage($class, $lineage);
 0443                  }
 0444              }
 0445   
 0446              foreach ($this->serviceCalls as $id => list($callCount, $behavior)) {
 0447                  if ('service_container' !== $id && $id !== $cId
 0448                      && ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE !== $behavior
 0449                      && $this->container->has($id)
 0450                      && $this->isTrivialInstance($def = $this->container->findDefinition($id))
 0451                      && \is_string($class = \is_array($factory = $def->getFactory()) && \is_string($factory[0]) ? $factory[0] : $def->getClass())
 0452                  ) {
 0453                      $this->collectLineage($class, $lineage);
 0454                  }
 0455              }
 0456   
 0457              foreach (array_diff_key(array_flip($lineage), $this->inlinedRequires) as $file => $class) {
 0458                  $code .= sprintf("        include_once %s;\n", $file);
 0459              }
 0460          }
 0461   
 0462          foreach ($this->inlinedDefinitions as $def) {
 0463              if ($file = $def->getFile()) {
 0464                  $code .= sprintf("        include_once %s;\n", $this->dumpValue($file));
 0465              }
 0466          }
 0467   
 0468          if ('' !== $code) {
 0469              $code .= "\n";
 0470          }
 0471   
 0472          return $code;
 0473      }
 0474   
 0475      /**
 0476       * Generates the service instance.
 0477       *
 0478       * @param string $id
 0479       * @param bool   $isSimpleInstance
 0480       *
 0481       * @return string
 0482       *
 0483       * @throws InvalidArgumentException
 0484       * @throws RuntimeException
 0485       */
 0486      private function addServiceInstance($id, Definition $definition, $isSimpleInstance)
 0487      {
 0488          $class = $this->dumpValue($definition->getClass());
 0489   
 0490          if (0 === strpos($class, "'") && false === strpos($class, '$') && !preg_match('/^\'(?:\\\{2})?[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(?:\\\{2}[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*\'$/', $class)) {
 0491              throw new InvalidArgumentException(sprintf('"%s" is not a valid class name for the "%s" service.', $class, $id));
 0492          }
 0493   
 0494          $isProxyCandidate = $this->getProxyDumper()->isProxyCandidate($definition);
 0495          $instantiation = '';
 0496   
 0497          if (!$isProxyCandidate && $definition->isShared()) {
 0498              $instantiation = sprintf('$this->services[%s] = %s', $this->doExport($id), $isSimpleInstance ? '' : '$instance');
 0499          } elseif (!$isSimpleInstance) {
 0500              $instantiation = '$instance';
 0501          }
 0502   
 0503          $return = '';
 0504          if ($isSimpleInstance) {
 0505              $return = 'return ';
 0506          } else {
 0507              $instantiation .= ' = ';
 0508          }
 0509   
 0510          return $this->addNewInstance($definition, $return, $instantiation, $id);
 0511      }
 0512   
 0513      /**
 0514       * Checks if the definition is a trivial instance.
 0515       *
 0516       * @return bool
 0517       */
 0518      private function isTrivialInstance(Definition $definition)
 0519      {
 0520          if ($definition->isSynthetic() || $definition->getFile() || $definition->getMethodCalls() || $definition->getProperties() || $definition->getConfigurator()) {
 0521              return false;
 0522          }
 0523          if ($definition->isDeprecated() || $definition->isLazy() || $definition->getFactory() || 3 < \count($definition->getArguments())) {
 0524              return false;
 0525          }
 0526   
 0527          foreach ($definition->getArguments() as $arg) {
 0528              if (!$arg || $arg instanceof Parameter) {
 0529                  continue;
 0530              }
 0531              if (\is_array($arg) && 3 >= \count($arg)) {
 0532                  foreach ($arg as $k => $v) {
 0533                      if ($this->dumpValue($k) !== $this->dumpValue($k, false)) {
 0534                          return false;
 0535                      }
 0536                      if (!$v || $v instanceof Parameter) {
 0537                          continue;
 0538                      }
 0539                      if ($v instanceof Reference && $this->container->has($id = (string) $v) && $this->container->findDefinition($id)->isSynthetic()) {
 0540                          continue;
 0541                      }
 0542                      if (!is_scalar($v) || $this->dumpValue($v) !== $this->dumpValue($v, false)) {
 0543                          return false;
 0544                      }
 0545                  }
 0546              } elseif ($arg instanceof Reference && $this->container->has($id = (string) $arg) && $this->container->findDefinition($id)->isSynthetic()) {
 0547                  continue;
 0548              } elseif (!is_scalar($arg) || $this->dumpValue($arg) !== $this->dumpValue($arg, false)) {
 0549                  return false;
 0550              }
 0551          }
 0552   
 0553          return true;
 0554      }
 0555   
 0556      /**
 0557       * Adds method calls to a service definition.
 0558       *
 0559       * @param string $variableName
 0560       *
 0561       * @return string
 0562       */
 0563      private function addServiceMethodCalls(Definition $definition, $variableName = 'instance')
 0564      {
 0565          $calls = '';
 0566          foreach ($definition->getMethodCalls() as $call) {
 0567              $arguments = [];
 0568              foreach ($call[1] as $value) {
 0569                  $arguments[] = $this->dumpValue($value);
 0570              }
 0571   
 0572              $calls .= $this->wrapServiceConditionals($call[1], sprintf("        \$%s->%s(%s);\n", $variableName, $call[0], implode(', ', $arguments)));
 0573          }
 0574   
 0575          return $calls;
 0576      }
 0577   
 0578      private function addServiceProperties(Definition $definition, $variableName = 'instance')
 0579      {
 0580          $code = '';
 0581          foreach ($definition->getProperties() as $name => $value) {
 0582              $code .= sprintf("        \$%s->%s = %s;\n", $variableName, $name, $this->dumpValue($value));
 0583          }
 0584   
 0585          return $code;
 0586      }
 0587   
 0588      /**
 0589       * Adds configurator definition.
 0590       *
 0591       * @param string $variableName
 0592       *
 0593       * @return string
 0594       */
 0595      private function addServiceConfigurator(Definition $definition, $variableName = 'instance')
 0596      {
 0597          if (!$callable = $definition->getConfigurator()) {
 0598              return '';
 0599          }
 0600   
 0601          if (\is_array($callable)) {
 0602              if ($callable[0] instanceof Reference
 0603                  || ($callable[0] instanceof Definition && $this->definitionVariables->contains($callable[0]))
 0604              ) {
 0605                  return sprintf("        %s->%s(\$%s);\n", $this->dumpValue($callable[0]), $callable[1], $variableName);
 0606              }
 0607   
 0608              $class = $this->dumpValue($callable[0]);
 0609              // If the class is a string we can optimize call_user_func away
 0610              if (0 === strpos($class, "'") && false === strpos($class, '$')) {
 0611                  return sprintf("        %s::%s(\$%s);\n", $this->dumpLiteralClass($class), $callable[1], $variableName);
 0612              }
 0613   
 0614              if (0 === strpos($class, 'new ')) {
 0615                  return sprintf("        (%s)->%s(\$%s);\n", $this->dumpValue($callable[0]), $callable[1], $variableName);
 0616              }
 0617   
 0618              return sprintf("        \\call_user_func([%s, '%s'], \$%s);\n", $this->dumpValue($callable[0]), $callable[1], $variableName);
 0619          }
 0620   
 0621          return sprintf("        %s(\$%s);\n", $callable, $variableName);
 0622      }
 0623   
 0624      /**
 0625       * Adds a service.
 0626       *
 0627       * @param string $id
 0628       * @param string &$file
 0629       *
 0630       * @return string
 0631       */
 0632      private function addService($id, Definition $definition, &$file = null)
 0633      {
 0634          $this->definitionVariables = new \SplObjectStorage();
 0635          $this->referenceVariables = [];
 0636          $this->variableCount = 0;
 0637          $this->referenceVariables[$id] = new Variable('instance');
 0638   
 0639          $return = [];
 0640   
 0641          if ($class = $definition->getClass()) {
 0642              $class = $class instanceof Parameter ? '%'.$class.'%' : $this->container->resolveEnvPlaceholders($class);
 0643              $return[] = sprintf(0 === strpos($class, '%') ? '@return object A %1$s instance' : '@return \%s', ltrim($class, '\\'));
 0644          } elseif ($definition->getFactory()) {
 0645              $factory = $definition->getFactory();
 0646              if (\is_string($factory)) {
 0647                  $return[] = sprintf('@return object An instance returned by %s()', $factory);
 0648              } elseif (\is_array($factory) && (\is_string($factory[0]) || $factory[0] instanceof Definition || $factory[0] instanceof Reference)) {
 0649                  $class = $factory[0] instanceof Definition ? $factory[0]->getClass() : (string) $factory[0];
 0650                  $class = $class instanceof Parameter ? '%'.$class.'%' : $this->container->resolveEnvPlaceholders($class);
 0651                  $return[] = sprintf('@return object An instance returned by %s::%s()', $class, $factory[1]);
 0652              }
 0653          }
 0654   
 0655          if ($definition->isDeprecated()) {
 0656              if ($return && 0 === strpos($return[\count($return) - 1], '@return')) {
 0657                  $return[] = '';
 0658              }
 0659   
 0660              $return[] = sprintf('@deprecated %s', $definition->getDeprecationMessage($id));
 0661          }
 0662   
 0663          $return = str_replace("\n     * \n", "\n     *\n", implode("\n     * ", $return));
 0664          $return = $this->container->resolveEnvPlaceholders($return);
 0665   
 0666          $shared = $definition->isShared() ? ' shared' : '';
 0667          $public = $definition->isPublic() ? 'public' : 'private';
 0668          $autowired = $definition->isAutowired() ? ' autowired' : '';
 0669   
 0670          if ($definition->isLazy()) {
 0671              $lazyInitialization = '$lazyLoad = true';
 0672          } else {
 0673              $lazyInitialization = '';
 0674          }
 0675   
 0676          $asFile = $this->asFiles && $definition->isShared() && !$this->isHotPath($definition);
 0677          $methodName = $this->generateMethodName($id);
 0678          if ($asFile) {
 0679              $file = $methodName.'.php';
 0680              $code = "        // Returns the $public '$id'$shared$autowired service.\n\n";
 0681          } else {
 0682              $code = <<<EOF
 0683   
 0684      /*{$this->docStar}
 0685       * Gets the $public '$id'$shared$autowired service.
 0686       *
 0687       * $return
 0688  EOF;
 0689   
 0690              $code = str_replace('*/', ' ', $code).<<<EOF
 0691   
 0692       */
 0693      protected function {$methodName}($lazyInitialization)
 0694      {
 0695   
 0696  EOF;
 0697   
 0698          }
 0699   
 0700          $this->serviceCalls = [];
 0701          $this->inlinedDefinitions = $this->getDefinitionsFromArguments([$definition], null, $this->serviceCalls);
 0702   
 0703          $code .= $this->addServiceInclude($id, $definition);
 0704   
 0705          if ($this->getProxyDumper()->isProxyCandidate($definition)) {
 0706              $factoryCode = $asFile ? "\$this->load('%s.php', false)" : '$this->%s(false)';
 0707              $code .= $this->getProxyDumper()->getProxyFactoryCode($definition, $id, sprintf($factoryCode, $methodName, $this->doExport($id)));
 0708          }
 0709   
 0710          if ($definition->isDeprecated()) {
 0711              $code .= sprintf("        @trigger_error(%s, E_USER_DEPRECATED);\n\n", $this->export($definition->getDeprecationMessage($id)));
 0712          }
 0713   
 0714          $code .= $this->addInlineService($id, $definition);
 0715   
 0716          if ($asFile) {
 0717              $code = implode("\n", array_map(function ($line) { return $line ? substr($line, 8) : $line; }, explode("\n", $code)));
 0718          } else {
 0719              $code .= "    }\n";
 0720          }
 0721   
 0722          $this->definitionVariables = $this->inlinedDefinitions = null;
 0723          $this->referenceVariables = $this->serviceCalls = null;
 0724   
 0725          return $code;
 0726      }
 0727   
 0728      private function addInlineVariables($id, Definition $definition, array $arguments, $forConstructor)
 0729      {
 0730          $code = '';
 0731   
 0732          foreach ($arguments as $argument) {
 0733              if (\is_array($argument)) {
 0734                  $code .= $this->addInlineVariables($id, $definition, $argument, $forConstructor);
 0735              } elseif ($argument instanceof Reference) {
 0736                  $code .= $this->addInlineReference($id, $definition, $this->container->normalizeId($argument), $forConstructor);
 0737              } elseif ($argument instanceof Definition) {
 0738                  $code .= $this->addInlineService($id, $definition, $argument, $forConstructor);
 0739              }
 0740          }
 0741   
 0742          return $code;
 0743      }
 0744   
 0745      private function addInlineReference($id, Definition $definition, $targetId, $forConstructor)
 0746      {
 0747          while ($this->container->hasAlias($targetId)) {
 0748              $targetId = (string) $this->container->getAlias($targetId);
 0749          }
 0750   
 0751          list($callCount, $behavior) = $this->serviceCalls[$targetId];
 0752   
 0753          if ($id === $targetId) {
 0754              return $this->addInlineService($id, $definition, $definition);
 0755          }
 0756   
 0757          if ('service_container' === $targetId || isset($this->referenceVariables[$targetId])) {
 0758              return '';
 0759          }
 0760   
 0761          $hasSelfRef = isset($this->circularReferences[$id][$targetId]) && !isset($this->definitionVariables[$definition]);
 0762   
 0763          if ($hasSelfRef && !$forConstructor && !$forConstructor = !$this->circularReferences[$id][$targetId]) {
 0764              $code = $this->addInlineService($id, $definition, $definition);
 0765          } else {
 0766              $code = '';
 0767          }
 0768   
 0769          if (isset($this->referenceVariables[$targetId]) || (2 > $callCount && (!$hasSelfRef || !$forConstructor))) {
 0770              return $code;
 0771          }
 0772   
 0773          $name = $this->getNextVariableName();
 0774          $this->referenceVariables[$targetId] = new Variable($name);
 0775   
 0776          $reference = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE >= $behavior ? new Reference($targetId, $behavior) : null;
 0777          $code .= sprintf("        \$%s = %s;\n", $name, $this->getServiceCall($targetId, $reference));
 0778   
 0779          if (!$hasSelfRef || !$forConstructor) {
 0780              return $code;
 0781          }
 0782   
 0783          $code .= sprintf(<<<'EOTXT'
 0784   
 0785          if (isset($this->%s[%s])) {
 0786              return $this->%1$s[%2$s];
 0787          }
 0788   
 0789  EOTXT
 0790              ,
 0791              'services',
 0792              $this->doExport($id)
 0793          );
 0794   
 0795          return $code;
 0796      }
 0797   
 0798      private function addInlineService($id, Definition $definition, Definition $inlineDef = null, $forConstructor = true)
 0799      {
 0800          $code = '';
 0801   
 0802          if ($isSimpleInstance = $isRootInstance = null === $inlineDef) {
 0803              foreach ($this->serviceCalls as $targetId => list($callCount, $behavior, $byConstructor)) {
 0804                  if ($byConstructor && isset($this->circularReferences[$id][$targetId]) && !$this->circularReferences[$id][$targetId]) {
 0805                      $code .= $this->addInlineReference($id, $definition, $targetId, $forConstructor);
 0806                  }
 0807              }
 0808          }
 0809   
 0810          if (isset($this->definitionVariables[$inlineDef = $inlineDef ?: $definition])) {
 0811              return $code;
 0812          }
 0813   
 0814          $arguments = [$inlineDef->getArguments(), $inlineDef->getFactory()];
 0815   
 0816          $code .= $this->addInlineVariables($id, $definition, $arguments, $forConstructor);
 0817   
 0818          if ($arguments = array_filter([$inlineDef->getProperties(), $inlineDef->getMethodCalls(), $inlineDef->getConfigurator()])) {
 0819              $isSimpleInstance = false;
 0820          } elseif ($definition !== $inlineDef && 2 > $this->inlinedDefinitions[$inlineDef]) {
 0821              return $code;
 0822          }
 0823   
 0824          if (isset($this->definitionVariables[$inlineDef])) {
 0825              $isSimpleInstance = false;
 0826          } else {
 0827              $name = $definition === $inlineDef ? 'instance' : $this->getNextVariableName();
 0828              $this->definitionVariables[$inlineDef] = new Variable($name);
 0829              $code .= '' !== $code ? "\n" : '';
 0830   
 0831              if ('instance' === $name) {
 0832                  $code .= $this->addServiceInstance($id, $definition, $isSimpleInstance);
 0833              } else {
 0834                  $code .= $this->addNewInstance($inlineDef, '$'.$name, ' = ', $id);
 0835              }
 0836   
 0837              if ('' !== $inline = $this->addInlineVariables($id, $definition, $arguments, false)) {
 0838                  $code .= "\n".$inline."\n";
 0839              } elseif ($arguments && 'instance' === $name) {
 0840                  $code .= "\n";
 0841              }
 0842   
 0843              $code .= $this->addServiceProperties($inlineDef, $name);
 0844              $code .= $this->addServiceMethodCalls($inlineDef, $name);
 0845              $code .= $this->addServiceConfigurator($inlineDef, $name);
 0846          }
 0847   
 0848          if ($isRootInstance && !$isSimpleInstance) {
 0849              $code .= "\n        return \$instance;\n";
 0850          }
 0851   
 0852          return $code;
 0853      }
 0854   
 0855      /**
 0856       * Adds multiple services.
 0857       *
 0858       * @return string
 0859       */
 0860      private function addServices()
 0861      {
 0862          $publicServices = $privateServices = '';
 0863          $definitions = $this->container->getDefinitions();
 0864          ksort($definitions);
 0865          foreach ($definitions as $id => $definition) {
 0866              if ($definition->isSynthetic() || ($this->asFiles && $definition->isShared() && !$this->isHotPath($definition))) {
 0867                  continue;
 0868              }
 0869              if ($definition->isPublic()) {
 0870                  $publicServices .= $this->addService($id, $definition);
 0871              } else {
 0872                  $privateServices .= $this->addService($id, $definition);
 0873              }
 0874          }
 0875   
 0876          return $publicServices.$privateServices;
 0877      }
 0878   
 0879      private function generateServiceFiles()
 0880      {
 0881          $definitions = $this->container->getDefinitions();
 0882          ksort($definitions);
 0883          foreach ($definitions as $id => $definition) {
 0884              if (!$definition->isSynthetic() && $definition->isShared() && !$this->isHotPath($definition)) {
 0885                  $code = $this->addService($id, $definition, $file);
 0886                  yield $file => $code;
 0887              }
 0888          }
 0889      }
 0890   
 0891      private function addNewInstance(Definition $definition, $return, $instantiation, $id)
 0892      {
 0893          $class = $this->dumpValue($definition->getClass());
 0894          $return = '        '.$return.$instantiation;
 0895   
 0896          $arguments = [];
 0897          foreach ($definition->getArguments() as $value) {
 0898              $arguments[] = $this->dumpValue($value);
 0899          }
 0900   
 0901          if (null !== $definition->getFactory()) {
 0902              $callable = $definition->getFactory();
 0903              if (\is_array($callable)) {
 0904                  if (!preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $callable[1])) {
 0905                      throw new RuntimeException(sprintf('Cannot dump definition because of invalid factory method (%s).', $callable[1] ?: 'n/a'));
 0906                  }
 0907   
 0908                  if ($callable[0] instanceof Reference
 0909                      || ($callable[0] instanceof Definition && $this->definitionVariables->contains($callable[0]))) {
 0910                      return $return.sprintf("%s->%s(%s);\n", $this->dumpValue($callable[0]), $callable[1], $arguments ? implode(', ', $arguments) : '');
 0911                  }
 0912   
 0913                  $class = $this->dumpValue($callable[0]);
 0914                  // If the class is a string we can optimize call_user_func away
 0915                  if (0 === strpos($class, "'") && false === strpos($class, '$')) {
 0916                      if ("''" === $class) {
 0917                          throw new RuntimeException(sprintf('Cannot dump definition: The "%s" service is defined to be created by a factory but is missing the service reference, did you forget to define the factory service id or class?', $id));
 0918                      }
 0919   
 0920                      return $return.sprintf("%s::%s(%s);\n", $this->dumpLiteralClass($class), $callable[1], $arguments ? implode(', ', $arguments) : '');
 0921                  }
 0922   
 0923                  if (0 === strpos($class, 'new ')) {
 0924                      return $return.sprintf("(%s)->%s(%s);\n", $class, $callable[1], $arguments ? implode(', ', $arguments) : '');
 0925                  }
 0926   
 0927                  return $return.sprintf("\\call_user_func([%s, '%s']%s);\n", $class, $callable[1], $arguments ? ', '.implode(', ', $arguments) : '');
 0928              }
 0929   
 0930              return $return.sprintf("%s(%s);\n", $this->dumpLiteralClass($this->dumpValue($callable)), $arguments ? implode(', ', $arguments) : '');
 0931          }
 0932   
 0933          if (false !== strpos($class, '$')) {
 0934              return sprintf("        \$class = %s;\n\n%snew \$class(%s);\n", $class, $return, implode(', ', $arguments));
 0935          }
 0936   
 0937          return $return.sprintf("new %s(%s);\n", $this->dumpLiteralClass($class), implode(', ', $arguments));
 0938      }
 0939   
 0940      /**
 0941       * Adds the class headers.
 0942       *
 0943       * @param string $class                  Class name
 0944       * @param string $baseClass              The name of the base class
 0945       * @param string $baseClassWithNamespace Fully qualified base class name
 0946       *
 0947       * @return string
 0948       */
 0949      private function startClass($class, $baseClass, $baseClassWithNamespace)
 0950      {
 0951          $bagClass = $this->container->isCompiled() ? 'use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;' : 'use Symfony\Component\DependencyInjection\ParameterBag\\ParameterBag;';
 0952          $namespaceLine = !$this->asFiles && $this->namespace ? "\nnamespace {$this->namespace};\n" : '';
 0953   
 0954          $code = <<<EOF
 0955  <?php
 0956  $namespaceLine
 0957  use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
 0958  use Symfony\Component\DependencyInjection\ContainerInterface;
 0959  use Symfony\Component\DependencyInjection\Container;
 0960  use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
 0961  use Symfony\Component\DependencyInjection\Exception\LogicException;
 0962  use Symfony\Component\DependencyInjection\Exception\RuntimeException;
 0963  $bagClass
 0964   
 0965  /*{$this->docStar}
 0966   * This class has been auto-generated
 0967   * by the Symfony Dependency Injection Component.
 0968   *
 0969   * @final since Symfony 3.3
 0970   */
 0971  class $class extends $baseClass
 0972  {
 0973      private \$parameters = [];
 0974      private \$targetDirs = [];
 0975   
 0976      public function __construct()
 0977      {
 0978   
 0979  EOF;
 0980   
 0981          if (null !== $this->targetDirRegex) {
 0982              $dir = $this->asFiles ? '$this->targetDirs[0] = \\dirname($containerDir)' : '__DIR__';
 0983              $code .= <<<EOF
 0984          \$dir = {$dir};
 0985          for (\$i = 1; \$i <= {$this->targetDirMaxMatches}; ++\$i) {
 0986              \$this->targetDirs[\$i] = \$dir = \\dirname(\$dir);
 0987          }
 0988   
 0989  EOF;
 0990   
 0991          }
 0992          if ($this->asFiles) {
 0993              $code = str_replace('$parameters', "\$buildParameters;\n    private \$containerDir;\n    private \$parameters", $code);
 0994              $code = str_replace('__construct()', '__construct(array $buildParameters = [], $containerDir = __DIR__)', $code);
 0995              $code .= "        \$this->buildParameters = \$buildParameters;\n";
 0996              $code .= "        \$this->containerDir = \$containerDir;\n";
 0997          }
 0998   
 0999          if ($this->container->isCompiled()) {
 1000              if (Container::class !== $baseClassWithNamespace) {
 1001                  $r = $this->container->getReflectionClass($baseClassWithNamespace, false);
 1002                  if (null !== $r
 1003                      && (null !== $constructor = $r->getConstructor())
 1004                      && 0 === $constructor->getNumberOfRequiredParameters()
 1005                      && Container::class !== $constructor->getDeclaringClass()->name
 1006                  ) {
 1007                      $code .= "        parent::__construct();\n";
 1008                      $code .= "        \$this->parameterBag = null;\n\n";
 1009                  }
 1010              }
 1011   
 1012              if ($this->container->getParameterBag()->all()) {
 1013                  $code .= "        \$this->parameters = \$this->getDefaultParameters();\n\n";
 1014              }
 1015   
 1016              $code .= "        \$this->services = [];\n";
 1017          } else {
 1018              $arguments = $this->container->getParameterBag()->all() ? 'new ParameterBag($this->getDefaultParameters())' : null;
 1019              $code .= "        parent::__construct($arguments);\n";
 1020          }
 1021   
 1022          $code .= $this->addNormalizedIds();
 1023          $code .= $this->addSyntheticIds();
 1024          $code .= $this->addMethodMap();
 1025          $code .= $this->asFiles ? $this->addFileMap() : '';
 1026          $code .= $this->addPrivateServices();
 1027          $code .= $this->addAliases();
 1028          $code .= $this->addInlineRequires();
 1029          $code .= <<<'EOF'
 1030      }
 1031   
 1032  EOF;
 1033   
 1034          $code .= $this->addRemovedIds();
 1035   
 1036          if ($this->container->isCompiled()) {
 1037              $code .= <<<EOF
 1038   
 1039      public function compile()
 1040      {
 1041          throw new LogicException('You cannot compile a dumped container that was already compiled.');
 1042      }
 1043   
 1044      public function isCompiled()
 1045      {
 1046          return true;
 1047      }
 1048   
 1049      public function isFrozen()
 1050      {
 1051          @trigger_error(sprintf('The %s() method is deprecated since Symfony 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED);
 1052   
 1053          return true;
 1054      }
 1055   
 1056  EOF;
 1057   
 1058          }
 1059   
 1060          if ($this->asFiles) {
 1061              $code .= <<<EOF
 1062   
 1063      protected function load(\$file, \$lazyLoad = true)
 1064      {
 1065          return require \$this->containerDir.\\DIRECTORY_SEPARATOR.\$file;
 1066      }
 1067   
 1068  EOF;
 1069   
 1070          }
 1071   
 1072          $proxyDumper = $this->getProxyDumper();
 1073          foreach ($this->container->getDefinitions() as $definition) {
 1074              if (!$proxyDumper->isProxyCandidate($definition)) {
 1075                  continue;
 1076              }
 1077              if ($this->asFiles) {
 1078                  $proxyLoader = '$this->load("{$class}.php")';
 1079              } elseif ($this->namespace) {
 1080                  $proxyLoader = 'class_alias("'.$this->namespace.'\\\\{$class}", $class, false)';
 1081              } else {
 1082                  $proxyLoader = '';
 1083              }
 1084              if ($proxyLoader) {
 1085                  $proxyLoader = "class_exists(\$class, false) || {$proxyLoader};\n\n        ";
 1086              }
 1087              $code .= <<<EOF
 1088   
 1089      protected function createProxy(\$class, \Closure \$factory)
 1090      {
 1091          {$proxyLoader}return \$factory();
 1092      }
 1093   
 1094  EOF;
 1095   
 1096              break;
 1097          }
 1098   
 1099          return $code;
 1100      }
 1101   
 1102      /**
 1103       * Adds the normalizedIds property definition.
 1104       *
 1105       * @return string
 1106       */
 1107      private function addNormalizedIds()
 1108      {
 1109          $code = '';
 1110          $normalizedIds = $this->container->getNormalizedIds();
 1111          ksort($normalizedIds);
 1112          foreach ($normalizedIds as $id => $normalizedId) {
 1113              if ($this->container->has($normalizedId)) {
 1114                  $code .= '            '.$this->doExport($id).' => '.$this->doExport($normalizedId).",\n";
 1115              }
 1116          }
 1117   
 1118          return $code ? "        \$this->normalizedIds = [\n".$code."        ];\n" : '';
 1119      }
 1120   
 1121      /**
 1122       * Adds the syntheticIds definition.
 1123       *
 1124       * @return string
 1125       */
 1126      private function addSyntheticIds()
 1127      {
 1128          $code = '';
 1129          $definitions = $this->container->getDefinitions();
 1130          ksort($definitions);
 1131          foreach ($definitions as $id => $definition) {
 1132              if ($definition->isSynthetic() && 'service_container' !== $id) {
 1133                  $code .= '            '.$this->doExport($id)." => true,\n";
 1134              }
 1135          }
 1136   
 1137          return $code ? "        \$this->syntheticIds = [\n{$code}        ];\n" : '';
 1138      }
 1139   
 1140      /**
 1141       * Adds the removedIds definition.
 1142       *
 1143       * @return string
 1144       */
 1145      private function addRemovedIds()
 1146      {
 1147          if (!$ids = $this->container->getRemovedIds()) {
 1148              return '';
 1149          }
 1150          if ($this->asFiles) {
 1151              $code = "require \$this->containerDir.\\DIRECTORY_SEPARATOR.'removed-ids.php'";
 1152          } else {
 1153              $code = '';
 1154              $ids = array_keys($ids);
 1155              sort($ids);
 1156              foreach ($ids as $id) {
 1157                  if (preg_match('/^\d+_[^~]++~[._a-zA-Z\d]{7}$/', $id)) {
 1158                      continue;
 1159                  }
 1160                  $code .= '            '.$this->doExport($id)." => true,\n";
 1161              }
 1162   
 1163              $code = "[\n{$code}        ]";
 1164          }
 1165   
 1166          return <<<EOF
 1167   
 1168      public function getRemovedIds()
 1169      {
 1170          return {$code};
 1171      }
 1172   
 1173  EOF;
 1174   
 1175      }
 1176   
 1177      /**
 1178       * Adds the methodMap property definition.
 1179       *
 1180       * @return string
 1181       */
 1182      private function addMethodMap()
 1183      {
 1184          $code = '';
 1185          $definitions = $this->container->getDefinitions();
 1186          ksort($definitions);
 1187          foreach ($definitions as $id => $definition) {
 1188              if (!$definition->isSynthetic() && (!$this->asFiles || !$definition->isShared() || $this->isHotPath($definition))) {
 1189                  $code .= '            '.$this->doExport($id).' => '.$this->doExport($this->generateMethodName($id)).",\n";
 1190              }
 1191          }
 1192   
 1193          return $code ? "        \$this->methodMap = [\n{$code}        ];\n" : '';
 1194      }
 1195   
 1196      /**
 1197       * Adds the fileMap property definition.
 1198       *
 1199       * @return string
 1200       */
 1201      private function addFileMap()
 1202      {
 1203          $code = '';
 1204          $definitions = $this->container->getDefinitions();
 1205          ksort($definitions);
 1206          foreach ($definitions as $id => $definition) {
 1207              if (!$definition->isSynthetic() && $definition->isShared() && !$this->isHotPath($definition)) {
 1208                  $code .= sprintf("            %s => '%s.php',\n", $this->doExport($id), $this->generateMethodName($id));
 1209              }
 1210          }
 1211   
 1212          return $code ? "        \$this->fileMap = [\n{$code}        ];\n" : '';
 1213      }
 1214   
 1215      /**
 1216       * Adds the privates property definition.
 1217       *
 1218       * @return string
 1219       */
 1220      private function addPrivateServices()
 1221      {
 1222          $code = '';
 1223   
 1224          $aliases = $this->container->getAliases();
 1225          ksort($aliases);
 1226          foreach ($aliases as $id => $alias) {
 1227              if ($alias->isPrivate()) {
 1228                  $code .= '            '.$this->doExport($id)." => true,\n";
 1229              }
 1230          }
 1231   
 1232          $definitions = $this->container->getDefinitions();
 1233          ksort($definitions);
 1234          foreach ($definitions as $id => $definition) {
 1235              if (!$definition->isPublic()) {
 1236                  $code .= '            '.$this->doExport($id)." => true,\n";
 1237              }
 1238          }
 1239   
 1240          if (empty($code)) {
 1241              return '';
 1242          }
 1243   
 1244          $out = "        \$this->privates = [\n";
 1245          $out .= $code;
 1246          $out .= "        ];\n";
 1247   
 1248          return $out;
 1249      }
 1250   
 1251      /**
 1252       * Adds the aliases property definition.
 1253       *
 1254       * @return string
 1255       */
 1256      private function addAliases()
 1257      {
 1258          if (!$aliases = $this->container->getAliases()) {
 1259              return $this->container->isCompiled() ? "\n        \$this->aliases = [];\n" : '';
 1260          }
 1261   
 1262          $code = "        \$this->aliases = [\n";
 1263          ksort($aliases);
 1264          foreach ($aliases as $alias => $id) {
 1265              $id = $this->container->normalizeId($id);
 1266              while (isset($aliases[$id])) {
 1267                  $id = $this->container->normalizeId($aliases[$id]);
 1268              }
 1269              $code .= '            '.$this->doExport($alias).' => '.$this->doExport($id).",\n";
 1270          }
 1271   
 1272          return $code."        ];\n";
 1273      }
 1274   
 1275      private function addInlineRequires()
 1276      {
 1277          if (!$this->hotPathTag || !$this->inlineRequires) {
 1278              return '';
 1279          }
 1280   
 1281          $lineage = [];
 1282   
 1283          foreach ($this->container->findTaggedServiceIds($this->hotPathTag) as $id => $tags) {
 1284              $definition = $this->container->getDefinition($id);
 1285              $inlinedDefinitions = $this->getDefinitionsFromArguments([$definition]);
 1286   
 1287              foreach ($inlinedDefinitions as $def) {
 1288                  if (\is_string($class = \is_array($factory = $def->getFactory()) && \is_string($factory[0]) ? $factory[0] : $def->getClass())) {
 1289                      $this->collectLineage($class, $lineage);
 1290                  }
 1291              }
 1292          }
 1293   
 1294          $code = '';
 1295   
 1296          foreach ($lineage as $file) {
 1297              if (!isset($this->inlinedRequires[$file])) {
 1298                  $this->inlinedRequires[$file] = true;
 1299                  $code .= sprintf("\n            include_once %s;", $file);
 1300              }
 1301          }
 1302   
 1303          return $code ? sprintf("\n        \$this->privates['service_container'] = function () {%s\n        };\n", $code) : '';
 1304      }
 1305   
 1306      /**
 1307       * Adds default parameters method.
 1308       *
 1309       * @return string
 1310       */
 1311      private function addDefaultParametersMethod()
 1312      {
 1313          if (!$this->container->getParameterBag()->all()) {
 1314              return '';
 1315          }
 1316   
 1317          $php = [];
 1318          $dynamicPhp = [];
 1319          $normalizedParams = [];
 1320   
 1321          foreach ($this->container->getParameterBag()->all() as $key => $value) {
 1322              if ($key !== $resolvedKey = $this->container->resolveEnvPlaceholders($key)) {
 1323                  throw new InvalidArgumentException(sprintf('Parameter name cannot use env parameters: "%s".', $resolvedKey));
 1324              }
 1325              if ($key !== $lcKey = strtolower($key)) {
 1326                  $normalizedParams[] = sprintf('        %s => %s,', $this->export($lcKey), $this->export($key));
 1327              }
 1328              $export = $this->exportParameters([$value]);
 1329              $export = explode('0 => ', substr(rtrim($export, " ]\n"), 2, -1), 2);
 1330   
 1331              if (preg_match("/\\\$this->(?:getEnv\('(?:\w++:)*+\w++'\)|targetDirs\[\d++\])/", $export[1])) {
 1332                  $dynamicPhp[$key] = sprintf('%scase %s: $value = %s; break;', $export[0], $this->export($key), $export[1]);
 1333              } else {
 1334                  $php[] = sprintf('%s%s => %s,', $export[0], $this->export($key), $export[1]);
 1335              }
 1336          }
 1337   
 1338          $parameters = sprintf("[\n%s\n%s]", implode("\n", $php), str_repeat(' ', 8));
 1339   
 1340          $code = '';
 1341          if ($this->container->isCompiled()) {
 1342              $code .= <<<'EOF'
 1343   
 1344      public function getParameter($name)
 1345      {
 1346          $name = (string) $name;
 1347          if (isset($this->buildParameters[$name])) {
 1348              return $this->buildParameters[$name];
 1349          }
 1350          if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) {
 1351              $name = $this->normalizeParameterName($name);
 1352   
 1353              if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) {
 1354                  throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name));
 1355              }
 1356          }
 1357          if (isset($this->loadedDynamicParameters[$name])) {
 1358              return $this->loadedDynamicParameters[$name] ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name);
 1359          }
 1360   
 1361          return $this->parameters[$name];
 1362      }
 1363   
 1364      public function hasParameter($name)
 1365      {
 1366          $name = (string) $name;
 1367          if (isset($this->buildParameters[$name])) {
 1368              return true;
 1369          }
 1370          $name = $this->normalizeParameterName($name);
 1371   
 1372          return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters);
 1373      }
 1374   
 1375      public function setParameter($name, $value)
 1376      {
 1377          throw new LogicException('Impossible to call set() on a frozen ParameterBag.');
 1378      }
 1379   
 1380      public function getParameterBag()
 1381      {
 1382          if (null === $this->parameterBag) {
 1383              $parameters = $this->parameters;
 1384              foreach ($this->loadedDynamicParameters as $name => $loaded) {
 1385                  $parameters[$name] = $loaded ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name);
 1386              }
 1387              foreach ($this->buildParameters as $name => $value) {
 1388                  $parameters[$name] = $value;
 1389              }
 1390              $this->parameterBag = new FrozenParameterBag($parameters);
 1391          }
 1392   
 1393          return $this->parameterBag;
 1394      }
 1395   
 1396  EOF;
 1397   
 1398              if (!$this->asFiles) {
 1399                  $code = preg_replace('/^.*buildParameters.*\n.*\n.*\n/m', '', $code);
 1400              }
 1401   
 1402              if ($dynamicPhp) {
 1403                  $loadedDynamicParameters = $this->exportParameters(array_combine(array_keys($dynamicPhp), array_fill(0, \count($dynamicPhp), false)), '', 8);
 1404                  $getDynamicParameter = <<<'EOF'
 1405          switch ($name) {
 1406  %s
 1407              default: throw new InvalidArgumentException(sprintf('The dynamic parameter "%%s" must be defined.', $name));
 1408          }
 1409          $this->loadedDynamicParameters[$name] = true;
 1410   
 1411          return $this->dynamicParameters[$name] = $value;
 1412  EOF;
 1413   
 1414                  $getDynamicParameter = sprintf($getDynamicParameter, implode("\n", $dynamicPhp));
 1415              } else {
 1416                  $loadedDynamicParameters = '[]';
 1417                  $getDynamicParameter = str_repeat(' ', 8).'throw new InvalidArgumentException(sprintf(\'The dynamic parameter "%s" must be defined.\', $name));';
 1418              }
 1419   
 1420              $code .= <<<EOF
 1421   
 1422      private \$loadedDynamicParameters = {$loadedDynamicParameters};
 1423      private \$dynamicParameters = [];
 1424   
 1425      /*{$this->docStar}
 1426       * Computes a dynamic parameter.
 1427       *
 1428       * @param string \$name The name of the dynamic parameter to load
 1429       *
 1430       * @return mixed The value of the dynamic parameter
 1431       *
 1432       * @throws InvalidArgumentException When the dynamic parameter does not exist
 1433       */
 1434      private function getDynamicParameter(\$name)
 1435      {
 1436  {$getDynamicParameter}
 1437      }
 1438   
 1439   
 1440  EOF;
 1441   
 1442   
 1443              $code .= '    private $normalizedParameterNames = '.($normalizedParams ? sprintf("[\n%s\n    ];", implode("\n", $normalizedParams)) : '[];')."\n";
 1444              $code .= <<<'EOF'
 1445   
 1446      private function normalizeParameterName($name)
 1447      {
 1448          if (isset($this->normalizedParameterNames[$normalizedName = strtolower($name)]) || isset($this->parameters[$normalizedName]) || array_key_exists($normalizedName, $this->parameters)) {
 1449              $normalizedName = isset($this->normalizedParameterNames[$normalizedName]) ? $this->normalizedParameterNames[$normalizedName] : $normalizedName;
 1450              if ((string) $name !== $normalizedName) {
 1451                  @trigger_error(sprintf('Parameter names will be made case sensitive in Symfony 4.0. Using "%s" instead of "%s" is deprecated since Symfony 3.4.', $name, $normalizedName), E_USER_DEPRECATED);
 1452              }
 1453          } else {
 1454              $normalizedName = $this->normalizedParameterNames[$normalizedName] = (string) $name;
 1455          }
 1456   
 1457          return $normalizedName;
 1458      }
 1459   
 1460  EOF;
 1461   
 1462          } elseif ($dynamicPhp) {
 1463              throw new RuntimeException('You cannot dump a not-frozen container with dynamic parameters.');
 1464          }
 1465   
 1466          $code .= <<<EOF
 1467   
 1468      /*{$this->docStar}
 1469       * Gets the default parameters.
 1470       *
 1471       * @return array An array of the default parameters
 1472       */
 1473      protected function getDefaultParameters()
 1474      {
 1475          return $parameters;
 1476      }
 1477   
 1478  EOF;
 1479   
 1480   
 1481          return $code;
 1482      }
 1483   
 1484      /**
 1485       * Exports parameters.
 1486       *
 1487       * @param string $path
 1488       * @param int    $indent
 1489       *
 1490       * @return string
 1491       *
 1492       * @throws InvalidArgumentException
 1493       */
 1494      private function exportParameters(array $parameters, $path = '', $indent = 12)
 1495      {
 1496          $php = [];
 1497          foreach ($parameters as $key => $value) {
 1498              if (\is_array($value)) {
 1499                  $value = $this->exportParameters($value, $path.'/'.$key, $indent + 4);
 1500              } elseif ($value instanceof ArgumentInterface) {
 1501                  throw new InvalidArgumentException(sprintf('You cannot dump a container with parameters that contain special arguments. "%s" found in "%s".', \get_class($value), $path.'/'.$key));
 1502              } elseif ($value instanceof Variable) {
 1503                  throw new InvalidArgumentException(sprintf('You cannot dump a container with parameters that contain variable references. Variable "%s" found in "%s".', $value, $path.'/'.$key));
 1504              } elseif ($value instanceof Definition) {
 1505                  throw new InvalidArgumentException(sprintf('You cannot dump a container with parameters that contain service definitions. Definition for "%s" found in "%s".', $value->getClass(), $path.'/'.$key));
 1506              } elseif ($value instanceof Reference) {
 1507                  throw new InvalidArgumentException(sprintf('You cannot dump a container with parameters that contain references to other services (reference to service "%s" found in "%s").', $value, $path.'/'.$key));
 1508              } elseif ($value instanceof Expression) {
 1509                  throw new InvalidArgumentException(sprintf('You cannot dump a container with parameters that contain expressions. Expression "%s" found in "%s".', $value, $path.'/'.$key));
 1510              } else {
 1511                  $value = $this->export($value);
 1512              }
 1513   
 1514              $php[] = sprintf('%s%s => %s,', str_repeat(' ', $indent), $this->export($key), $value);
 1515          }
 1516   
 1517          return sprintf("[\n%s\n%s]", implode("\n", $php), str_repeat(' ', $indent - 4));
 1518      }
 1519   
 1520      /**
 1521       * Ends the class definition.
 1522       *
 1523       * @return string
 1524       */
 1525      private function endClass()
 1526      {
 1527          return <<<'EOF'
 1528  }
 1529   
 1530  EOF;
 1531   
 1532      }
 1533   
 1534      /**
 1535       * Wraps the service conditionals.
 1536       *
 1537       * @param string $value
 1538       * @param string $code
 1539       *
 1540       * @return string
 1541       */
 1542      private function wrapServiceConditionals($value, $code)
 1543      {
 1544          if (!$condition = $this->getServiceConditionals($value)) {
 1545              return $code;
 1546          }
 1547   
 1548          // re-indent the wrapped code
 1549          $code = implode("\n", array_map(function ($line) { return $line ? '    '.$line : $line; }, explode("\n", $code)));
 1550   
 1551          return sprintf("        if (%s) {\n%s        }\n", $condition, $code);
 1552      }
 1553   
 1554      /**
 1555       * Get the conditions to execute for conditional services.
 1556       *
 1557       * @param string $value
 1558       *
 1559       * @return string|null
 1560       */
 1561      private function getServiceConditionals($value)
 1562      {
 1563          $conditions = [];
 1564          foreach (ContainerBuilder::getInitializedConditionals($value) as $service) {
 1565              if (!$this->container->hasDefinition($service)) {
 1566                  return 'false';
 1567              }
 1568              $conditions[] = sprintf('isset($this->services[%s])', $this->doExport($service));
 1569          }
 1570          foreach (ContainerBuilder::getServiceConditionals($value) as $service) {
 1571              if ($this->container->hasDefinition($service) && !$this->container->getDefinition($service)->isPublic()) {
 1572                  continue;
 1573              }
 1574   
 1575              $conditions[] = sprintf('$this->has(%s)', $this->doExport($service));
 1576          }
 1577   
 1578          if (!$conditions) {
 1579              return '';
 1580          }
 1581   
 1582          return implode(' && ', $conditions);
 1583      }
 1584   
 1585      private function getDefinitionsFromArguments(array $arguments, \SplObjectStorage $definitions = null, array &$calls = [], $byConstructor = null)
 1586      {
 1587          if (null === $definitions) {
 1588              $definitions = new \SplObjectStorage();
 1589          }
 1590   
 1591          foreach ($arguments as $argument) {
 1592              if (\is_array($argument)) {
 1593                  $this->getDefinitionsFromArguments($argument, $definitions, $calls, $byConstructor);
 1594              } elseif ($argument instanceof Reference) {
 1595                  $id = $this->container->normalizeId($argument);
 1596   
 1597                  while ($this->container->hasAlias($id)) {
 1598                      $id = (string) $this->container->getAlias($id);
 1599                  }
 1600   
 1601                  if (!isset($calls[$id])) {
 1602                      $calls[$id] = [0, $argument->getInvalidBehavior(), $byConstructor];
 1603                  } else {
 1604                      $calls[$id][1] = min($calls[$id][1], $argument->getInvalidBehavior());
 1605                  }
 1606   
 1607                  ++$calls[$id][0];
 1608              } elseif (!$argument instanceof Definition) {
 1609                  // no-op
 1610              } elseif (isset($definitions[$argument])) {
 1611                  $definitions[$argument] = 1 + $definitions[$argument];
 1612              } else {
 1613                  $definitions[$argument] = 1;
 1614                  $arguments = [$argument->getArguments(), $argument->getFactory()];
 1615                  $this->getDefinitionsFromArguments($arguments, $definitions, $calls, null === $byConstructor || $byConstructor);
 1616                  $arguments = [$argument->getProperties(), $argument->getMethodCalls(), $argument->getConfigurator()];
 1617                  $this->getDefinitionsFromArguments($arguments, $definitions, $calls, null !== $byConstructor && $byConstructor);
 1618              }
 1619          }
 1620   
 1621          return $definitions;
 1622      }
 1623   
 1624      /**
 1625       * Dumps values.
 1626       *
 1627       * @param mixed $value
 1628       * @param bool  $interpolate
 1629       *
 1630       * @return string
 1631       *
 1632       * @throws RuntimeException
 1633       */
 1634      private function dumpValue($value, $interpolate = true)
 1635      {
 1636          if (\is_array($value)) {
 1637              if ($value && $interpolate && false !== $param = array_search($value, $this->container->getParameterBag()->all(), true)) {
 1638                  return $this->dumpValue("%$param%");
 1639              }
 1640              $code = [];
 1641              foreach ($value as $k => $v) {
 1642                  $code[] = sprintf('%s => %s', $this->dumpValue($k, $interpolate), $this->dumpValue($v, $interpolate));
 1643              }
 1644   
 1645              return sprintf('[%s]', implode(', ', $code));
 1646          } elseif ($value instanceof ArgumentInterface) {
 1647              $scope = [$this->definitionVariables, $this->referenceVariables];
 1648              $this->definitionVariables = $this->referenceVariables = null;
 1649   
 1650              try {
 1651                  if ($value instanceof ServiceClosureArgument) {
 1652                      $value = $value->getValues()[0];
 1653                      $code = $this->dumpValue($value, $interpolate);
 1654   
 1655                      if ($value instanceof TypedReference) {
 1656                          $code = sprintf('$f = function (\\%s $v%s) { return $v; }; return $f(%s);', $value->getType(), ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $value->getInvalidBehavior() ? ' = null' : '', $code);
 1657                      } else {
 1658                          $code = sprintf('return %s;', $code);
 1659                      }
 1660   
 1661                      return sprintf("function () {\n            %s\n        }", $code);
 1662                  }
 1663   
 1664                  if ($value instanceof IteratorArgument) {
 1665                      $operands = [0];
 1666                      $code = [];
 1667                      $code[] = 'new RewindableGenerator(function () {';
 1668   
 1669                      if (!$values = $value->getValues()) {
 1670                          $code[] = '            return new \EmptyIterator();';
 1671                      } else {
 1672                          $countCode = [];
 1673                          $countCode[] = 'function () {';
 1674   
 1675                          foreach ($values as $k => $v) {
 1676                              ($c = $this->getServiceConditionals($v)) ? $operands[] = "(int) ($c)" : ++$operands[0];
 1677                              $v = $this->wrapServiceConditionals($v, sprintf("        yield %s => %s;\n", $this->dumpValue($k, $interpolate), $this->dumpValue($v, $interpolate)));
 1678                              foreach (explode("\n", $v) as $v) {
 1679                                  if ($v) {
 1680                                      $code[] = '    '.$v;
 1681                                  }
 1682                              }
 1683                          }
 1684   
 1685                          $countCode[] = sprintf('            return %s;', implode(' + ', $operands));
 1686                          $countCode[] = '        }';
 1687                      }
 1688   
 1689                      $code[] = sprintf('        }, %s)', \count($operands) > 1 ? implode("\n", $countCode) : $operands[0]);
 1690   
 1691                      return implode("\n", $code);
 1692                  }
 1693              } finally {
 1694                  list($this->definitionVariables, $this->referenceVariables) = $scope;
 1695              }
 1696          } elseif ($value instanceof Definition) {
 1697              if (null !== $this->definitionVariables && $this->definitionVariables->contains($value)) {
 1698                  return $this->dumpValue($this->definitionVariables[$value], $interpolate);
 1699              }
 1700              if ($value->getMethodCalls()) {
 1701                  throw new RuntimeException('Cannot dump definitions which have method calls.');
 1702              }
 1703              if ($value->getProperties()) {
 1704                  throw new RuntimeException('Cannot dump definitions which have properties.');
 1705              }
 1706              if (null !== $value->getConfigurator()) {
 1707                  throw new RuntimeException('Cannot dump definitions which have a configurator.');
 1708              }
 1709   
 1710              $arguments = [];
 1711              foreach ($value->getArguments() as $argument) {
 1712                  $arguments[] = $this->dumpValue($argument);
 1713              }
 1714   
 1715              if (null !== $value->getFactory()) {
 1716                  $factory = $value->getFactory();
 1717   
 1718                  if (\is_string($factory)) {
 1719                      return sprintf('%s(%s)', $this->dumpLiteralClass($this->dumpValue($factory)), implode(', ', $arguments));
 1720                  }
 1721   
 1722                  if (\is_array($factory)) {
 1723                      if (!preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $factory[1])) {
 1724                          throw new RuntimeException(sprintf('Cannot dump definition because of invalid factory method (%s).', $factory[1] ?: 'n/a'));
 1725                      }
 1726   
 1727                      $class = $this->dumpValue($factory[0]);
 1728                      if (\is_string($factory[0])) {
 1729                          return sprintf('%s::%s(%s)', $this->dumpLiteralClass($class), $factory[1], implode(', ', $arguments));
 1730                      }
 1731   
 1732                      if ($factory[0] instanceof Definition) {
 1733                          if (0 === strpos($class, 'new ')) {
 1734                              return sprintf('(%s)->%s(%s)', $class, $factory[1], implode(', ', $arguments));
 1735                          }
 1736   
 1737                          return sprintf("\\call_user_func([%s, '%s']%s)", $class, $factory[1], \count($arguments) > 0 ? ', '.implode(', ', $arguments) : '');
 1738                      }
 1739   
 1740                      if ($factory[0] instanceof Reference) {
 1741                          return sprintf('%s->%s(%s)', $class, $factory[1], implode(', ', $arguments));
 1742                      }
 1743                  }
 1744   
 1745                  throw new RuntimeException('Cannot dump definition because of invalid factory.');
 1746              }
 1747   
 1748              $class = $value->getClass();
 1749              if (null === $class) {
 1750                  throw new RuntimeException('Cannot dump definitions which have no class nor factory.');
 1751              }
 1752   
 1753              return sprintf('new %s(%s)', $this->dumpLiteralClass($this->dumpValue($class)), implode(', ', $arguments));
 1754          } elseif ($value instanceof Variable) {
 1755              return '$'.$value;
 1756          } elseif ($value instanceof Reference) {
 1757              $id = $this->container->normalizeId($value);
 1758   
 1759              while ($this->container->hasAlias($id)) {
 1760                  $id = (string) $this->container->getAlias($id);
 1761              }
 1762   
 1763              if (null !== $this->referenceVariables && isset($this->referenceVariables[$id])) {
 1764                  return $this->dumpValue($this->referenceVariables[$id], $interpolate);
 1765              }
 1766   
 1767              return $this->getServiceCall($id, $value);
 1768          } elseif ($value instanceof Expression) {
 1769              return $this->getExpressionLanguage()->compile((string) $value, ['this' => 'container']);
 1770          } elseif ($value instanceof Parameter) {
 1771              return $this->dumpParameter($value);
 1772          } elseif (true === $interpolate && \is_string($value)) {
 1773              if (preg_match('/^%([^%]+)%$/', $value, $match)) {
 1774                  // we do this to deal with non string values (Boolean, integer, ...)
 1775                  // the preg_replace_callback converts them to strings
 1776                  return $this->dumpParameter($match[1]);
 1777              } else {
 1778                  $replaceParameters = function ($match) {
 1779                      return "'.".$this->dumpParameter($match[2]).".'";
 1780                  };
 1781   
 1782                  $code = str_replace('%%', '%', preg_replace_callback('/(?<!%)(%)([^%]+)\1/', $replaceParameters, $this->export($value)));
 1783   
 1784                  return $code;
 1785              }
 1786          } elseif (\is_object($value) || \is_resource($value)) {
 1787              throw new RuntimeException('Unable to dump a service container if a parameter is an object or a resource.');
 1788          }
 1789   
 1790          return $this->export($value);
 1791      }
 1792   
 1793      /**
 1794       * Dumps a string to a literal (aka PHP Code) class value.
 1795       *
 1796       * @param string $class
 1797       *
 1798       * @return string
 1799       *
 1800       * @throws RuntimeException
 1801       */
 1802      private function dumpLiteralClass($class)
 1803      {
 1804          if (false !== strpos($class, '$')) {
 1805              return sprintf('${($_ = %s) && false ?: "_"}', $class);
 1806          }
 1807          if (0 !== strpos($class, "'") || !preg_match('/^\'(?:\\\{2})?[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(?:\\\{2}[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*\'$/', $class)) {
 1808              throw new RuntimeException(sprintf('Cannot dump definition because of invalid class name (%s).', $class ?: 'n/a'));
 1809          }
 1810   
 1811          $class = substr(str_replace('\\\\', '\\', $class), 1, -1);
 1812   
 1813          return 0 === strpos($class, '\\') ? $class : '\\'.$class;
 1814      }
 1815   
 1816      /**
 1817       * Dumps a parameter.
 1818       *
 1819       * @param string $name
 1820       *
 1821       * @return string
 1822       */
 1823      private function dumpParameter($name)
 1824      {
 1825          $name = (string) $name;
 1826   
 1827          if ($this->container->isCompiled() && $this->container->hasParameter($name)) {
 1828              $value = $this->container->getParameter($name);
 1829              $dumpedValue = $this->dumpValue($value, false);
 1830   
 1831              if (!$value || !\is_array($value)) {
 1832                  return $dumpedValue;
 1833              }
 1834   
 1835              if (!preg_match("/\\\$this->(?:getEnv\('(?:\w++:)*+\w++'\)|targetDirs\[\d++\])/", $dumpedValue)) {
 1836                  return sprintf('$this->parameters[%s]', $this->doExport($name));
 1837              }
 1838          }
 1839   
 1840          return sprintf('$this->getParameter(%s)', $this->doExport($name));
 1841      }
 1842   
 1843      /**
 1844       * Gets a service call.
 1845       *
 1846       * @param string    $id
 1847       * @param Reference $reference
 1848       *
 1849       * @return string
 1850       */
 1851      private function getServiceCall($id, Reference $reference = null)
 1852      {
 1853          while ($this->container->hasAlias($id)) {
 1854              $id = (string) $this->container->getAlias($id);
 1855          }
 1856          $id = $this->container->normalizeId($id);
 1857   
 1858          if ('service_container' === $id) {
 1859              return '$this';
 1860          }
 1861   
 1862          if ($this->container->hasDefinition($id) && $definition = $this->container->getDefinition($id)) {
 1863              if ($definition->isSynthetic()) {
 1864                  $code = sprintf('$this->get(%s%s)', $this->doExport($id), null !== $reference ? ', '.$reference->getInvalidBehavior() : '');
 1865              } elseif (null !== $reference && ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $reference->getInvalidBehavior()) {
 1866                  $code = 'null';
 1867                  if (!$definition->isShared()) {
 1868                      return $code;
 1869                  }
 1870              } elseif ($this->isTrivialInstance($definition)) {
 1871                  $code = substr($this->addNewInstance($definition, '', '', $id), 8, -2);
 1872                  if ($definition->isShared()) {
 1873                      $code = sprintf('$this->services[%s] = %s', $this->doExport($id), $code);
 1874                  }
 1875                  $code = "($code)";
 1876              } elseif ($this->asFiles && $definition->isShared() && !$this->isHotPath($definition)) {
 1877                  $code = sprintf("\$this->load('%s.php')", $this->generateMethodName($id));
 1878              } else {
 1879                  $code = sprintf('$this->%s()', $this->generateMethodName($id));
 1880              }
 1881          } elseif (null !== $reference && ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $reference->getInvalidBehavior()) {
 1882              return 'null';
 1883          } elseif (null !== $reference && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $reference->getInvalidBehavior()) {
 1884              $code = sprintf('$this->get(%s, /* ContainerInterface::NULL_ON_INVALID_REFERENCE */ %d)', $this->doExport($id), ContainerInterface::NULL_ON_INVALID_REFERENCE);
 1885          } else {
 1886              $code = sprintf('$this->get(%s)', $this->doExport($id));
 1887          }
 1888   
 1889          // The following is PHP 5.5 syntax for what could be written as "(\$this->services['$id'] ?? $code)" on PHP>=7.0
 1890   
 1891          return sprintf("\${(\$_ = isset(\$this->services[%s]) ? \$this->services[%1\$s] : %s) && false ?: '_'}", $this->doExport($id), $code);
 1892      }
 1893   
 1894      /**
 1895       * Initializes the method names map to avoid conflicts with the Container methods.
 1896       *
 1897       * @param string $class the container base class
 1898       */
 1899      private function initializeMethodNamesMap($class)
 1900      {
 1901          $this->serviceIdToMethodNameMap = [];
 1902          $this->usedMethodNames = [];
 1903   
 1904          if ($reflectionClass = $this->container->getReflectionClass($class)) {
 1905              foreach ($reflectionClass->getMethods() as $method) {
 1906                  $this->usedMethodNames[strtolower($method->getName())] = true;
 1907              }
 1908          }
 1909      }
 1910   
 1911      /**
 1912       * Convert a service id to a valid PHP method name.
 1913       *
 1914       * @param string $id
 1915       *
 1916       * @return string
 1917       *
 1918       * @throws InvalidArgumentException
 1919       */
 1920      private function generateMethodName($id)
 1921      {
 1922          if (isset($this->serviceIdToMethodNameMap[$id])) {
 1923              return $this->serviceIdToMethodNameMap[$id];
 1924          }
 1925   
 1926          $i = strrpos($id, '\\');
 1927          $name = Container::camelize(false !== $i && isset($id[1 + $i]) ? substr($id, 1 + $i) : $id);
 1928          $name = preg_replace('/[^a-zA-Z0-9_\x7f-\xff]/', '', $name);
 1929          $methodName = 'get'.$name.'Service';
 1930          $suffix = 1;
 1931   
 1932          while (isset($this->usedMethodNames[strtolower($methodName)])) {
 1933              ++$suffix;
 1934              $methodName = 'get'.$name.$suffix.'Service';
 1935          }
 1936   
 1937          $this->serviceIdToMethodNameMap[$id] = $methodName;
 1938          $this->usedMethodNames[strtolower($methodName)] = true;
 1939   
 1940          return $methodName;
 1941      }
 1942   
 1943      /**
 1944       * Returns the next name to use.
 1945       *
 1946       * @return string
 1947       */
 1948      private function getNextVariableName()
 1949      {
 1950          $firstChars = self::FIRST_CHARS;
 1951          $firstCharsLength = \strlen($firstChars);
 1952          $nonFirstChars = self::NON_FIRST_CHARS;
 1953          $nonFirstCharsLength = \strlen($nonFirstChars);
 1954   
 1955          while (true) {
 1956              $name = '';
 1957              $i = $this->variableCount;
 1958   
 1959              if ('' === $name) {
 1960                  $name .= $firstChars[$i % $firstCharsLength];
 1961                  $i = (int) ($i / $firstCharsLength);
 1962              }
 1963   
 1964              while ($i > 0) {
 1965                  --$i;
 1966                  $name .= $nonFirstChars[$i % $nonFirstCharsLength];
 1967                  $i = (int) ($i / $nonFirstCharsLength);
 1968              }
 1969   
 1970              ++$this->variableCount;
 1971   
 1972              // check that the name is not reserved
 1973              if (\in_array($name, $this->reservedVariables, true)) {
 1974                  continue;
 1975              }
 1976   
 1977              return $name;
 1978          }
 1979      }
 1980   
 1981      private function getExpressionLanguage()
 1982      {
 1983          if (null === $this->expressionLanguage) {
 1984              if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) {
 1985                  throw new RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.');
 1986              }
 1987              $providers = $this->container->getExpressionLanguageProviders();
 1988              $this->expressionLanguage = new ExpressionLanguage(null, $providers, function ($arg) {
 1989                  $id = '""' === substr_replace($arg, '', 1, -1) ? stripcslashes(substr($arg, 1, -1)) : null;
 1990   
 1991                  if (null !== $id && ($this->container->hasAlias($id) || $this->container->hasDefinition($id))) {
 1992                      return $this->getServiceCall($id);
 1993                  }
 1994   
 1995                  return sprintf('$this->get(%s)', $arg);
 1996              });
 1997   
 1998              if ($this->container->isTrackingResources()) {
 1999                  foreach ($providers as $provider) {
 2000                      $this->container->addObjectResource($provider);
 2001                  }
 2002              }
 2003          }
 2004   
 2005          return $this->expressionLanguage;
 2006      }
 2007   
 2008      private function isHotPath(Definition $definition)
 2009      {
 2010          return $this->hotPathTag && $definition->hasTag($this->hotPathTag) && !$definition->isDeprecated();
 2011      }
 2012   
 2013      private function export($value)
 2014      {
 2015          if (null !== $this->targetDirRegex && \is_string($value) && preg_match($this->targetDirRegex, $value, $matches, \PREG_OFFSET_CAPTURE)) {
 2016              $suffix = $matches[0][1] + \strlen($matches[0][0]);
 2017              $matches[0][1] += \strlen($matches[1][0]);
 2018              $prefix = $matches[0][1] ? $this->doExport(substr($value, 0, $matches[0][1]), true).'.' : '';
 2019              $suffix = isset($value[$suffix]) ? '.'.$this->doExport(substr($value, $suffix), true) : '';
 2020              $dirname = $this->asFiles ? '$this->containerDir' : '__DIR__';
 2021              $offset = 2 + $this->targetDirMaxMatches - \count($matches);
 2022   
 2023              if ($this->asFiles || 0 < $offset) {
 2024                  $dirname = sprintf('$this->targetDirs[%d]', $offset);
 2025              }
 2026   
 2027              if ($prefix || $suffix) {
 2028                  return sprintf('(%s%s%s)', $prefix, $dirname, $suffix);
 2029              }
 2030   
 2031              return $dirname;
 2032          }
 2033   
 2034          return $this->doExport($value, true);
 2035      }
 2036   
 2037      private function doExport($value, $resolveEnv = false)
 2038      {
 2039          if (\is_string($value) && false !== strpos($value, "\n")) {
 2040              $cleanParts = explode("\n", $value);
 2041              $cleanParts = array_map(function ($part) { return var_export($part, true); }, $cleanParts);
 2042              $export = implode('."\n".', $cleanParts);
 2043          } else {
 2044              $export = var_export($value, true);
 2045          }
 2046   
 2047          if ($resolveEnv && "'" === $export[0] && $export !== $resolvedExport = $this->container->resolveEnvPlaceholders($export, "'.\$this->getEnv('string:%s').'")) {
 2048              $export = $resolvedExport;
 2049              if (".''" === substr($export, -3)) {
 2050                  $export = substr($export, 0, -3);
 2051                  if ("'" === $export[1]) {
 2052                      $export = substr_replace($export, '', 18, 7);
 2053                  }
 2054              }
 2055              if ("'" === $export[1]) {
 2056                  $export = substr($export, 3);
 2057              }
 2058          }
 2059   
 2060          return $export;
 2061      }
 2062  }
 2063