Verzeichnisstruktur phpBB-3.2.0


Veröffentlicht
06.01.2017

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: 09.10.2024, 12:56 - Dateigröße: 55.06 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\Variable;
 0015  use Symfony\Component\DependencyInjection\Definition;
 0016  use Symfony\Component\DependencyInjection\ContainerBuilder;
 0017  use Symfony\Component\DependencyInjection\Container;
 0018  use Symfony\Component\DependencyInjection\ContainerInterface;
 0019  use Symfony\Component\DependencyInjection\Reference;
 0020  use Symfony\Component\DependencyInjection\Parameter;
 0021  use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
 0022  use Symfony\Component\DependencyInjection\Exception\RuntimeException;
 0023  use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
 0024  use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\DumperInterface as ProxyDumper;
 0025  use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\NullDumper;
 0026  use Symfony\Component\DependencyInjection\ExpressionLanguage;
 0027  use Symfony\Component\ExpressionLanguage\Expression;
 0028  use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface;
 0029  use Symfony\Component\HttpKernel\Kernel;
 0030   
 0031  /**
 0032   * PhpDumper dumps a service container as a PHP class.
 0033   *
 0034   * @author Fabien Potencier <fabien@symfony.com>
 0035   * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 0036   */
 0037  class PhpDumper extends Dumper
 0038  {
 0039      /**
 0040       * Characters that might appear in the generated variable name as first character.
 0041       *
 0042       * @var string
 0043       */
 0044      const FIRST_CHARS = 'abcdefghijklmnopqrstuvwxyz';
 0045   
 0046      /**
 0047       * Characters that might appear in the generated variable name as any but the first character.
 0048       *
 0049       * @var string
 0050       */
 0051      const NON_FIRST_CHARS = 'abcdefghijklmnopqrstuvwxyz0123456789_';
 0052   
 0053      private $inlinedDefinitions;
 0054      private $definitionVariables;
 0055      private $referenceVariables;
 0056      private $variableCount;
 0057      private $reservedVariables = array('instance', 'class');
 0058      private $expressionLanguage;
 0059      private $targetDirRegex;
 0060      private $targetDirMaxMatches;
 0061      private $docStar;
 0062   
 0063      /**
 0064       * @var ExpressionFunctionProviderInterface[]
 0065       */
 0066      private $expressionLanguageProviders = array();
 0067   
 0068      /**
 0069       * @var \Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\DumperInterface
 0070       */
 0071      private $proxyDumper;
 0072   
 0073      /**
 0074       * {@inheritdoc}
 0075       */
 0076      public function __construct(ContainerBuilder $container)
 0077      {
 0078          parent::__construct($container);
 0079   
 0080          $this->inlinedDefinitions = new \SplObjectStorage();
 0081      }
 0082   
 0083      /**
 0084       * Sets the dumper to be used when dumping proxies in the generated container.
 0085       *
 0086       * @param ProxyDumper $proxyDumper
 0087       */
 0088      public function setProxyDumper(ProxyDumper $proxyDumper)
 0089      {
 0090          $this->proxyDumper = $proxyDumper;
 0091      }
 0092   
 0093      /**
 0094       * Dumps the service container as a PHP class.
 0095       *
 0096       * Available options:
 0097       *
 0098       *  * class:      The class name
 0099       *  * base_class: The base class name
 0100       *  * namespace:  The class namespace
 0101       *
 0102       * @param array $options An array of options
 0103       *
 0104       * @return string A PHP class representing of the service container
 0105       */
 0106      public function dump(array $options = array())
 0107      {
 0108          $this->targetDirRegex = null;
 0109          $options = array_merge(array(
 0110              'class' => 'ProjectServiceContainer',
 0111              'base_class' => 'Container',
 0112              'namespace' => '',
 0113              'debug' => true,
 0114          ), $options);
 0115          $this->docStar = $options['debug'] ? '*' : '';
 0116   
 0117          if (!empty($options['file']) && is_dir($dir = dirname($options['file']))) {
 0118              // Build a regexp where the first root dirs are mandatory,
 0119              // but every other sub-dir is optional up to the full path in $dir
 0120              // Mandate at least 2 root dirs and not more that 5 optional dirs.
 0121   
 0122              $dir = explode(DIRECTORY_SEPARATOR, realpath($dir));
 0123              $i = count($dir);
 0124   
 0125              if (3 <= $i) {
 0126                  $regex = '';
 0127                  $lastOptionalDir = $i > 8 ? $i - 5 : 3;
 0128                  $this->targetDirMaxMatches = $i - $lastOptionalDir;
 0129   
 0130                  while (--$i >= $lastOptionalDir) {
 0131                      $regex = sprintf('(%s%s)?', preg_quote(DIRECTORY_SEPARATOR.$dir[$i], '#'), $regex);
 0132                  }
 0133   
 0134                  do {
 0135                      $regex = preg_quote(DIRECTORY_SEPARATOR.$dir[$i], '#').$regex;
 0136                  } while (0 < --$i);
 0137   
 0138                  $this->targetDirRegex = '#'.preg_quote($dir[0], '#').$regex.'#';
 0139              }
 0140          }
 0141   
 0142          $code = $this->startClass($options['class'], $options['base_class'], $options['namespace']);
 0143   
 0144          if ($this->container->isFrozen()) {
 0145              $code .= $this->addFrozenConstructor();
 0146              $code .= $this->addFrozenCompile();
 0147              $code .= $this->addIsFrozenMethod();
 0148          } else {
 0149              $code .= $this->addConstructor();
 0150          }
 0151   
 0152          $code .=
 0153              $this->addServices().
 0154              $this->addDefaultParametersMethod().
 0155              $this->endClass().
 0156              $this->addProxyClasses()
 0157          ;
 0158          $this->targetDirRegex = null;
 0159   
 0160          return $code;
 0161      }
 0162   
 0163      /**
 0164       * Retrieves the currently set proxy dumper or instantiates one.
 0165       *
 0166       * @return ProxyDumper
 0167       */
 0168      private function getProxyDumper()
 0169      {
 0170          if (!$this->proxyDumper) {
 0171              $this->proxyDumper = new NullDumper();
 0172          }
 0173   
 0174          return $this->proxyDumper;
 0175      }
 0176   
 0177      /**
 0178       * Generates Service local temp variables.
 0179       *
 0180       * @param string $cId
 0181       * @param string $definition
 0182       *
 0183       * @return string
 0184       */
 0185      private function addServiceLocalTempVariables($cId, $definition)
 0186      {
 0187          static $template = "        \$%s = %s;\n";
 0188   
 0189          $localDefinitions = array_merge(
 0190              array($definition),
 0191              $this->getInlinedDefinitions($definition)
 0192          );
 0193   
 0194          $calls = $behavior = array();
 0195          foreach ($localDefinitions as $iDefinition) {
 0196              $this->getServiceCallsFromArguments($iDefinition->getArguments(), $calls, $behavior);
 0197              $this->getServiceCallsFromArguments($iDefinition->getMethodCalls(), $calls, $behavior);
 0198              $this->getServiceCallsFromArguments($iDefinition->getProperties(), $calls, $behavior);
 0199              $this->getServiceCallsFromArguments(array($iDefinition->getConfigurator()), $calls, $behavior);
 0200              $this->getServiceCallsFromArguments(array($iDefinition->getFactory()), $calls, $behavior);
 0201          }
 0202   
 0203          $code = '';
 0204          foreach ($calls as $id => $callCount) {
 0205              if ('service_container' === $id || $id === $cId) {
 0206                  continue;
 0207              }
 0208   
 0209              if ($callCount > 1) {
 0210                  $name = $this->getNextVariableName();
 0211                  $this->referenceVariables[$id] = new Variable($name);
 0212   
 0213                  if (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE === $behavior[$id]) {
 0214                      $code .= sprintf($template, $name, $this->getServiceCall($id));
 0215                  } else {
 0216                      $code .= sprintf($template, $name, $this->getServiceCall($id, new Reference($id, ContainerInterface::NULL_ON_INVALID_REFERENCE)));
 0217                  }
 0218              }
 0219          }
 0220   
 0221          if ('' !== $code) {
 0222              $code .= "\n";
 0223          }
 0224   
 0225          return $code;
 0226      }
 0227   
 0228      /**
 0229       * Generates code for the proxies to be attached after the container class.
 0230       *
 0231       * @return string
 0232       */
 0233      private function addProxyClasses()
 0234      {
 0235          /* @var $definitions Definition[] */
 0236          $definitions = array_filter(
 0237              $this->container->getDefinitions(),
 0238              array($this->getProxyDumper(), 'isProxyCandidate')
 0239          );
 0240          $code = '';
 0241          $strip = '' === $this->docStar && method_exists('Symfony\Component\HttpKernel\Kernel', 'stripComments');
 0242   
 0243          foreach ($definitions as $definition) {
 0244              $proxyCode = "\n".$this->getProxyDumper()->getProxyCode($definition);
 0245              if ($strip) {
 0246                  $proxyCode = "<?php\n".$proxyCode;
 0247                  $proxyCode = substr(Kernel::stripComments($proxyCode), 5);
 0248              }
 0249              $code .= $proxyCode;
 0250          }
 0251   
 0252          return $code;
 0253      }
 0254   
 0255      /**
 0256       * Generates the require_once statement for service includes.
 0257       *
 0258       * @param string     $id         The service id
 0259       * @param Definition $definition
 0260       *
 0261       * @return string
 0262       */
 0263      private function addServiceInclude($id, $definition)
 0264      {
 0265          $template = "        require_once %s;\n";
 0266          $code = '';
 0267   
 0268          if (null !== $file = $definition->getFile()) {
 0269              $code .= sprintf($template, $this->dumpValue($file));
 0270          }
 0271   
 0272          foreach ($this->getInlinedDefinitions($definition) as $definition) {
 0273              if (null !== $file = $definition->getFile()) {
 0274                  $code .= sprintf($template, $this->dumpValue($file));
 0275              }
 0276          }
 0277   
 0278          if ('' !== $code) {
 0279              $code .= "\n";
 0280          }
 0281   
 0282          return $code;
 0283      }
 0284   
 0285      /**
 0286       * Generates the inline definition of a service.
 0287       *
 0288       * @param string     $id
 0289       * @param Definition $definition
 0290       *
 0291       * @return string
 0292       *
 0293       * @throws RuntimeException                  When the factory definition is incomplete
 0294       * @throws ServiceCircularReferenceException When a circular reference is detected
 0295       */
 0296      private function addServiceInlinedDefinitions($id, $definition)
 0297      {
 0298          $code = '';
 0299          $variableMap = $this->definitionVariables;
 0300          $nbOccurrences = new \SplObjectStorage();
 0301          $processed = new \SplObjectStorage();
 0302          $inlinedDefinitions = $this->getInlinedDefinitions($definition);
 0303   
 0304          foreach ($inlinedDefinitions as $definition) {
 0305              if (false === $nbOccurrences->contains($definition)) {
 0306                  $nbOccurrences->offsetSet($definition, 1);
 0307              } else {
 0308                  $i = $nbOccurrences->offsetGet($definition);
 0309                  $nbOccurrences->offsetSet($definition, $i + 1);
 0310              }
 0311          }
 0312   
 0313          foreach ($inlinedDefinitions as $sDefinition) {
 0314              if ($processed->contains($sDefinition)) {
 0315                  continue;
 0316              }
 0317              $processed->offsetSet($sDefinition);
 0318   
 0319              $class = $this->dumpValue($sDefinition->getClass());
 0320              if ($nbOccurrences->offsetGet($sDefinition) > 1 || $sDefinition->getMethodCalls() || $sDefinition->getProperties() || null !== $sDefinition->getConfigurator() || false !== strpos($class, '$')) {
 0321                  $name = $this->getNextVariableName();
 0322                  $variableMap->offsetSet($sDefinition, new Variable($name));
 0323   
 0324                  // a construct like:
 0325                  // $a = new ServiceA(ServiceB $b); $b = new ServiceB(ServiceA $a);
 0326                  // this is an indication for a wrong implementation, you can circumvent this problem
 0327                  // by setting up your service structure like this:
 0328                  // $b = new ServiceB();
 0329                  // $a = new ServiceA(ServiceB $b);
 0330                  // $b->setServiceA(ServiceA $a);
 0331                  if ($this->hasReference($id, $sDefinition->getArguments())) {
 0332                      throw new ServiceCircularReferenceException($id, array($id));
 0333                  }
 0334   
 0335                  $code .= $this->addNewInstance($id, $sDefinition, '$'.$name, ' = ');
 0336   
 0337                  if (!$this->hasReference($id, $sDefinition->getMethodCalls(), true) && !$this->hasReference($id, $sDefinition->getProperties(), true)) {
 0338                      $code .= $this->addServiceMethodCalls(null, $sDefinition, $name);
 0339                      $code .= $this->addServiceProperties(null, $sDefinition, $name);
 0340                      $code .= $this->addServiceConfigurator(null, $sDefinition, $name);
 0341                  }
 0342   
 0343                  $code .= "\n";
 0344              }
 0345          }
 0346   
 0347          return $code;
 0348      }
 0349   
 0350      /**
 0351       * Adds the service return statement.
 0352       *
 0353       * @param string     $id         Service id
 0354       * @param Definition $definition
 0355       *
 0356       * @return string
 0357       */
 0358      private function addServiceReturn($id, $definition)
 0359      {
 0360          if ($this->isSimpleInstance($id, $definition)) {
 0361              return "    }\n";
 0362          }
 0363   
 0364          return "\n        return \$instance;\n    }\n";
 0365      }
 0366   
 0367      /**
 0368       * Generates the service instance.
 0369       *
 0370       * @param string     $id
 0371       * @param Definition $definition
 0372       *
 0373       * @return string
 0374       *
 0375       * @throws InvalidArgumentException
 0376       * @throws RuntimeException
 0377       */
 0378      private function addServiceInstance($id, Definition $definition)
 0379      {
 0380          $class = $definition->getClass();
 0381   
 0382          if ('\\' === substr($class, 0, 1)) {
 0383              $class = substr($class, 1);
 0384          }
 0385   
 0386          $class = $this->dumpValue($class);
 0387   
 0388          if (0 === strpos($class, "'") && !preg_match('/^\'[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(\\\{2}[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*\'$/', $class)) {
 0389              throw new InvalidArgumentException(sprintf('"%s" is not a valid class name for the "%s" service.', $class, $id));
 0390          }
 0391   
 0392          $simple = $this->isSimpleInstance($id, $definition);
 0393          $isProxyCandidate = $this->getProxyDumper()->isProxyCandidate($definition);
 0394          $instantiation = '';
 0395   
 0396          if (!$isProxyCandidate && $definition->isShared() && ContainerInterface::SCOPE_CONTAINER === $definition->getScope(false)) {
 0397              $instantiation = "\$this->services['$id'] = ".($simple ? '' : '$instance');
 0398          } elseif (!$isProxyCandidate && $definition->isShared() && ContainerInterface::SCOPE_PROTOTYPE !== $scope = $definition->getScope(false)) {
 0399              $instantiation = "\$this->services['$id'] = \$this->scopedServices['$scope']['$id'] = ".($simple ? '' : '$instance');
 0400          } elseif (!$simple) {
 0401              $instantiation = '$instance';
 0402          }
 0403   
 0404          $return = '';
 0405          if ($simple) {
 0406              $return = 'return ';
 0407          } else {
 0408              $instantiation .= ' = ';
 0409          }
 0410   
 0411          $code = $this->addNewInstance($id, $definition, $return, $instantiation);
 0412   
 0413          if (!$simple) {
 0414              $code .= "\n";
 0415          }
 0416   
 0417          return $code;
 0418      }
 0419   
 0420      /**
 0421       * Checks if the definition is a simple instance.
 0422       *
 0423       * @param string     $id
 0424       * @param Definition $definition
 0425       *
 0426       * @return bool
 0427       */
 0428      private function isSimpleInstance($id, Definition $definition)
 0429      {
 0430          foreach (array_merge(array($definition), $this->getInlinedDefinitions($definition)) as $sDefinition) {
 0431              if ($definition !== $sDefinition && !$this->hasReference($id, $sDefinition->getMethodCalls())) {
 0432                  continue;
 0433              }
 0434   
 0435              if ($sDefinition->getMethodCalls() || $sDefinition->getProperties() || $sDefinition->getConfigurator()) {
 0436                  return false;
 0437              }
 0438          }
 0439   
 0440          return true;
 0441      }
 0442   
 0443      /**
 0444       * Adds method calls to a service definition.
 0445       *
 0446       * @param string     $id
 0447       * @param Definition $definition
 0448       * @param string     $variableName
 0449       *
 0450       * @return string
 0451       */
 0452      private function addServiceMethodCalls($id, Definition $definition, $variableName = 'instance')
 0453      {
 0454          $calls = '';
 0455          foreach ($definition->getMethodCalls() as $call) {
 0456              $arguments = array();
 0457              foreach ($call[1] as $value) {
 0458                  $arguments[] = $this->dumpValue($value);
 0459              }
 0460   
 0461              $calls .= $this->wrapServiceConditionals($call[1], sprintf("        \$%s->%s(%s);\n", $variableName, $call[0], implode(', ', $arguments)));
 0462          }
 0463   
 0464          return $calls;
 0465      }
 0466   
 0467      private function addServiceProperties($id, Definition $definition, $variableName = 'instance')
 0468      {
 0469          $code = '';
 0470          foreach ($definition->getProperties() as $name => $value) {
 0471              $code .= sprintf("        \$%s->%s = %s;\n", $variableName, $name, $this->dumpValue($value));
 0472          }
 0473   
 0474          return $code;
 0475      }
 0476   
 0477      /**
 0478       * Generates the inline definition setup.
 0479       *
 0480       * @param string     $id
 0481       * @param Definition $definition
 0482       *
 0483       * @return string
 0484       *
 0485       * @throws ServiceCircularReferenceException when the container contains a circular reference
 0486       */
 0487      private function addServiceInlinedDefinitionsSetup($id, Definition $definition)
 0488      {
 0489          $this->referenceVariables[$id] = new Variable('instance');
 0490   
 0491          $code = '';
 0492          $processed = new \SplObjectStorage();
 0493          foreach ($this->getInlinedDefinitions($definition) as $iDefinition) {
 0494              if ($processed->contains($iDefinition)) {
 0495                  continue;
 0496              }
 0497              $processed->offsetSet($iDefinition);
 0498   
 0499              if (!$this->hasReference($id, $iDefinition->getMethodCalls(), true) && !$this->hasReference($id, $iDefinition->getProperties(), true)) {
 0500                  continue;
 0501              }
 0502   
 0503              // if the instance is simple, the return statement has already been generated
 0504              // so, the only possible way to get there is because of a circular reference
 0505              if ($this->isSimpleInstance($id, $definition)) {
 0506                  throw new ServiceCircularReferenceException($id, array($id));
 0507              }
 0508   
 0509              $name = (string) $this->definitionVariables->offsetGet($iDefinition);
 0510              $code .= $this->addServiceMethodCalls(null, $iDefinition, $name);
 0511              $code .= $this->addServiceProperties(null, $iDefinition, $name);
 0512              $code .= $this->addServiceConfigurator(null, $iDefinition, $name);
 0513          }
 0514   
 0515          if ('' !== $code) {
 0516              $code .= "\n";
 0517          }
 0518   
 0519          return $code;
 0520      }
 0521   
 0522      /**
 0523       * Adds configurator definition.
 0524       *
 0525       * @param string     $id
 0526       * @param Definition $definition
 0527       * @param string     $variableName
 0528       *
 0529       * @return string
 0530       */
 0531      private function addServiceConfigurator($id, Definition $definition, $variableName = 'instance')
 0532      {
 0533          if (!$callable = $definition->getConfigurator()) {
 0534              return '';
 0535          }
 0536   
 0537          if (is_array($callable)) {
 0538              if ($callable[0] instanceof Reference
 0539                  || ($callable[0] instanceof Definition && $this->definitionVariables->contains($callable[0]))) {
 0540                  return sprintf("        %s->%s(\$%s);\n", $this->dumpValue($callable[0]), $callable[1], $variableName);
 0541              }
 0542   
 0543              $class = $this->dumpValue($callable[0]);
 0544              // If the class is a string we can optimize call_user_func away
 0545              if (strpos($class, "'") === 0) {
 0546                  return sprintf("        %s::%s(\$%s);\n", $this->dumpLiteralClass($class), $callable[1], $variableName);
 0547              }
 0548   
 0549              return sprintf("        call_user_func(array(%s, '%s'), \$%s);\n", $this->dumpValue($callable[0]), $callable[1], $variableName);
 0550          }
 0551   
 0552          return sprintf("        %s(\$%s);\n", $callable, $variableName);
 0553      }
 0554   
 0555      /**
 0556       * Adds a service.
 0557       *
 0558       * @param string     $id
 0559       * @param Definition $definition
 0560       *
 0561       * @return string
 0562       */
 0563      private function addService($id, Definition $definition)
 0564      {
 0565          $this->definitionVariables = new \SplObjectStorage();
 0566          $this->referenceVariables = array();
 0567          $this->variableCount = 0;
 0568   
 0569          $return = array();
 0570   
 0571          if ($definition->isSynthetic()) {
 0572              $return[] = '@throws RuntimeException always since this service is expected to be injected dynamically';
 0573          } elseif ($class = $definition->getClass()) {
 0574              $return[] = sprintf('@return %s A %s instance', 0 === strpos($class, '%') ? 'object' : '\\'.ltrim($class, '\\'), ltrim($class, '\\'));
 0575          } elseif ($definition->getFactory()) {
 0576              $factory = $definition->getFactory();
 0577              if (is_string($factory)) {
 0578                  $return[] = sprintf('@return object An instance returned by %s()', $factory);
 0579              } elseif (is_array($factory) && (is_string($factory[0]) || $factory[0] instanceof Definition || $factory[0] instanceof Reference)) {
 0580                  if (is_string($factory[0]) || $factory[0] instanceof Reference) {
 0581                      $return[] = sprintf('@return object An instance returned by %s::%s()', (string) $factory[0], $factory[1]);
 0582                  } elseif ($factory[0] instanceof Definition) {
 0583                      $return[] = sprintf('@return object An instance returned by %s::%s()', $factory[0]->getClass(), $factory[1]);
 0584                  }
 0585              }
 0586          } elseif ($definition->getFactoryClass(false)) {
 0587              $return[] = sprintf('@return object An instance returned by %s::%s()', $definition->getFactoryClass(false), $definition->getFactoryMethod(false));
 0588          } elseif ($definition->getFactoryService(false)) {
 0589              $return[] = sprintf('@return object An instance returned by %s::%s()', $definition->getFactoryService(false), $definition->getFactoryMethod(false));
 0590          }
 0591   
 0592          $scope = $definition->getScope(false);
 0593          if (!in_array($scope, array(ContainerInterface::SCOPE_CONTAINER, ContainerInterface::SCOPE_PROTOTYPE))) {
 0594              if ($return && 0 === strpos($return[count($return) - 1], '@return')) {
 0595                  $return[] = '';
 0596              }
 0597              $return[] = sprintf("@throws InactiveScopeException when the '%s' service is requested while the '%s' scope is not active", $id, $scope);
 0598          }
 0599   
 0600          if ($definition->isDeprecated()) {
 0601              if ($return && 0 === strpos($return[count($return) - 1], '@return')) {
 0602                  $return[] = '';
 0603              }
 0604   
 0605              $return[] = sprintf('@deprecated %s', $definition->getDeprecationMessage($id));
 0606          }
 0607   
 0608          $return = str_replace("\n     * \n", "\n     *\n", implode("\n     * ", $return));
 0609   
 0610          $doc = '';
 0611          if ($definition->isShared() && ContainerInterface::SCOPE_PROTOTYPE !== $scope) {
 0612              $doc .= <<<'EOF'
 0613   
 0614       *
 0615       * This service is shared.
 0616       * This method always returns the same instance of the service.
 0617  EOF;
 0618   
 0619          }
 0620   
 0621          if (!$definition->isPublic()) {
 0622              $doc .= <<<'EOF'
 0623   
 0624       *
 0625       * This service is private.
 0626       * If you want to be able to request this service from the container directly,
 0627       * make it public, otherwise you might end up with broken code.
 0628  EOF;
 0629   
 0630          }
 0631   
 0632          if ($definition->isAutowired()) {
 0633              $doc = <<<EOF
 0634   
 0635       *
 0636       * This service is autowired.
 0637  EOF;
 0638   
 0639          }
 0640   
 0641          if ($definition->isLazy()) {
 0642              $lazyInitialization = '$lazyLoad = true';
 0643              $lazyInitializationDoc = "\n     * @param bool    \$lazyLoad whether to try lazy-loading the service with a proxy\n     *";
 0644          } else {
 0645              $lazyInitialization = '';
 0646              $lazyInitializationDoc = '';
 0647          }
 0648   
 0649          // with proxies, for 5.3.3 compatibility, the getter must be public to be accessible to the initializer
 0650          $isProxyCandidate = $this->getProxyDumper()->isProxyCandidate($definition);
 0651          $visibility = $isProxyCandidate ? 'public' : 'protected';
 0652          $code = <<<EOF
 0653   
 0654      /*{$this->docStar}
 0655       * Gets the '$id' service.$doc
 0656       *$lazyInitializationDoc
 0657       * $return
 0658       */
 0659      {$visibility} function get{$this->camelize($id)}Service($lazyInitialization)
 0660      {
 0661   
 0662  EOF;
 0663   
 0664   
 0665          $code .= $isProxyCandidate ? $this->getProxyDumper()->getProxyFactoryCode($definition, $id) : '';
 0666   
 0667          if (!in_array($scope, array(ContainerInterface::SCOPE_CONTAINER, ContainerInterface::SCOPE_PROTOTYPE))) {
 0668              $code .= <<<EOF
 0669          if (!isset(\$this->scopedServices['$scope'])) {
 0670              throw new InactiveScopeException('$id', '$scope');
 0671          }
 0672   
 0673   
 0674  EOF;
 0675   
 0676          }
 0677   
 0678          if ($definition->isSynthetic()) {
 0679              $code .= sprintf("        throw new RuntimeException('You have requested a synthetic service (\"%s\"). The DIC does not know how to construct this service.');\n    }\n", $id);
 0680          } else {
 0681              if ($definition->isDeprecated()) {
 0682                  $code .= sprintf("        @trigger_error(%s, E_USER_DEPRECATED);\n\n", var_export($definition->getDeprecationMessage($id), true));
 0683              }
 0684   
 0685              $code .=
 0686                  $this->addServiceInclude($id, $definition).
 0687                  $this->addServiceLocalTempVariables($id, $definition).
 0688                  $this->addServiceInlinedDefinitions($id, $definition).
 0689                  $this->addServiceInstance($id, $definition).
 0690                  $this->addServiceInlinedDefinitionsSetup($id, $definition).
 0691                  $this->addServiceMethodCalls($id, $definition).
 0692                  $this->addServiceProperties($id, $definition).
 0693                  $this->addServiceConfigurator($id, $definition).
 0694                  $this->addServiceReturn($id, $definition)
 0695              ;
 0696          }
 0697   
 0698          $this->definitionVariables = null;
 0699          $this->referenceVariables = null;
 0700   
 0701          return $code;
 0702      }
 0703   
 0704      /**
 0705       * Adds multiple services.
 0706       *
 0707       * @return string
 0708       */
 0709      private function addServices()
 0710      {
 0711          $publicServices = $privateServices = $synchronizers = '';
 0712          $definitions = $this->container->getDefinitions();
 0713          ksort($definitions);
 0714          foreach ($definitions as $id => $definition) {
 0715              if ($definition->isPublic()) {
 0716                  $publicServices .= $this->addService($id, $definition);
 0717              } else {
 0718                  $privateServices .= $this->addService($id, $definition);
 0719              }
 0720   
 0721              $synchronizers .= $this->addServiceSynchronizer($id, $definition);
 0722          }
 0723   
 0724          return $publicServices.$synchronizers.$privateServices;
 0725      }
 0726   
 0727      /**
 0728       * Adds synchronizer methods.
 0729       *
 0730       * @param string     $id         A service identifier
 0731       * @param Definition $definition A Definition instance
 0732       *
 0733       * @return string|null
 0734       *
 0735       * @deprecated since version 2.7, will be removed in 3.0.
 0736       */
 0737      private function addServiceSynchronizer($id, Definition $definition)
 0738      {
 0739          if (!$definition->isSynchronized(false)) {
 0740              return;
 0741          }
 0742   
 0743          if ('request' !== $id) {
 0744              @trigger_error('Synchronized services were deprecated in version 2.7 and won\'t work anymore in 3.0.', E_USER_DEPRECATED);
 0745          }
 0746   
 0747          $code = '';
 0748          foreach ($this->container->getDefinitions() as $definitionId => $definition) {
 0749              foreach ($definition->getMethodCalls() as $call) {
 0750                  foreach ($call[1] as $argument) {
 0751                      if ($argument instanceof Reference && $id == (string) $argument) {
 0752                          $arguments = array();
 0753                          foreach ($call[1] as $value) {
 0754                              $arguments[] = $this->dumpValue($value);
 0755                          }
 0756   
 0757                          $call = $this->wrapServiceConditionals($call[1], sprintf("\$this->get('%s')->%s(%s);", $definitionId, $call[0], implode(', ', $arguments)));
 0758   
 0759                          $code .= <<<EOF
 0760          if (\$this->initialized('$definitionId')) {
 0761              $call
 0762          }
 0763   
 0764  EOF;
 0765   
 0766                      }
 0767                  }
 0768              }
 0769          }
 0770   
 0771          if (!$code) {
 0772              return;
 0773          }
 0774   
 0775          return <<<EOF
 0776   
 0777      /*{$this->docStar}
 0778       * Updates the '$id' service.
 0779       */
 0780      protected function synchronize{$this->camelize($id)}Service()
 0781      {
 0782  $code    }
 0783   
 0784  EOF;
 0785   
 0786      }
 0787   
 0788      private function addNewInstance($id, Definition $definition, $return, $instantiation)
 0789      {
 0790          $class = $this->dumpValue($definition->getClass());
 0791   
 0792          $arguments = array();
 0793          foreach ($definition->getArguments() as $value) {
 0794              $arguments[] = $this->dumpValue($value);
 0795          }
 0796   
 0797          if (null !== $definition->getFactory()) {
 0798              $callable = $definition->getFactory();
 0799              if (is_array($callable)) {
 0800                  if (!preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $callable[1])) {
 0801                      throw new RuntimeException(sprintf('Cannot dump definition because of invalid factory method (%s)', $callable[1] ?: 'n/a'));
 0802                  }
 0803   
 0804                  if ($callable[0] instanceof Reference
 0805                      || ($callable[0] instanceof Definition && $this->definitionVariables->contains($callable[0]))) {
 0806                      return sprintf("        $return{$instantiation}%s->%s(%s);\n", $this->dumpValue($callable[0]), $callable[1], $arguments ? implode(', ', $arguments) : '');
 0807                  }
 0808   
 0809                  $class = $this->dumpValue($callable[0]);
 0810                  // If the class is a string we can optimize call_user_func away
 0811                  if (strpos($class, "'") === 0) {
 0812                      return sprintf("        $return{$instantiation}%s::%s(%s);\n", $this->dumpLiteralClass($class), $callable[1], $arguments ? implode(', ', $arguments) : '');
 0813                  }
 0814   
 0815                  return sprintf("        $return{$instantiation}call_user_func(array(%s, '%s')%s);\n", $this->dumpValue($callable[0]), $callable[1], $arguments ? ', '.implode(', ', $arguments) : '');
 0816              }
 0817   
 0818              return sprintf("        $return{$instantiation}\\%s(%s);\n", $callable, $arguments ? implode(', ', $arguments) : '');
 0819          } elseif (null !== $definition->getFactoryMethod(false)) {
 0820              if (null !== $definition->getFactoryClass(false)) {
 0821                  $class = $this->dumpValue($definition->getFactoryClass(false));
 0822   
 0823                  // If the class is a string we can optimize call_user_func away
 0824                  if (strpos($class, "'") === 0) {
 0825                      return sprintf("        $return{$instantiation}%s::%s(%s);\n", $this->dumpLiteralClass($class), $definition->getFactoryMethod(false), $arguments ? implode(', ', $arguments) : '');
 0826                  }
 0827   
 0828                  return sprintf("        $return{$instantiation}call_user_func(array(%s, '%s')%s);\n", $this->dumpValue($definition->getFactoryClass(false)), $definition->getFactoryMethod(false), $arguments ? ', '.implode(', ', $arguments) : '');
 0829              }
 0830   
 0831              if (null !== $definition->getFactoryService(false)) {
 0832                  return sprintf("        $return{$instantiation}%s->%s(%s);\n", $this->getServiceCall($definition->getFactoryService(false)), $definition->getFactoryMethod(false), implode(', ', $arguments));
 0833              }
 0834   
 0835              throw new RuntimeException(sprintf('Factory method requires a factory service or factory class in service definition for %s', $id));
 0836          }
 0837   
 0838          if (false !== strpos($class, '$')) {
 0839              return sprintf("        \$class = %s;\n\n        $return{$instantiation}new \$class(%s);\n", $class, implode(', ', $arguments));
 0840          }
 0841   
 0842          return sprintf("        $return{$instantiation}new %s(%s);\n", $this->dumpLiteralClass($class), implode(', ', $arguments));
 0843      }
 0844   
 0845      /**
 0846       * Adds the class headers.
 0847       *
 0848       * @param string $class     Class name
 0849       * @param string $baseClass The name of the base class
 0850       * @param string $namespace The class namespace
 0851       *
 0852       * @return string
 0853       */
 0854      private function startClass($class, $baseClass, $namespace)
 0855      {
 0856          $bagClass = $this->container->isFrozen() ? 'use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;' : 'use Symfony\Component\DependencyInjection\ParameterBag\\ParameterBag;';
 0857          $namespaceLine = $namespace ? "namespace $namespace;\n" : '';
 0858   
 0859          return <<<EOF
 0860  <?php
 0861  $namespaceLine
 0862  use Symfony\Component\DependencyInjection\ContainerInterface;
 0863  use Symfony\Component\DependencyInjection\Container;
 0864  use Symfony\Component\DependencyInjection\Exception\InactiveScopeException;
 0865  use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
 0866  use Symfony\Component\DependencyInjection\Exception\LogicException;
 0867  use Symfony\Component\DependencyInjection\Exception\RuntimeException;
 0868  $bagClass
 0869   
 0870  /*{$this->docStar}
 0871   * $class.
 0872   *
 0873   * This class has been auto-generated
 0874   * by the Symfony Dependency Injection Component.
 0875   */
 0876  class $class extends $baseClass
 0877  {
 0878      private \$parameters;
 0879      private \$targetDirs = array();
 0880   
 0881  EOF;
 0882   
 0883      }
 0884   
 0885      /**
 0886       * Adds the constructor.
 0887       *
 0888       * @return string
 0889       */
 0890      private function addConstructor()
 0891      {
 0892          $targetDirs = $this->exportTargetDirs();
 0893          $arguments = $this->container->getParameterBag()->all() ? 'new ParameterBag($this->getDefaultParameters())' : null;
 0894   
 0895          $code = <<<EOF
 0896   
 0897      /*{$this->docStar}
 0898       * Constructor.
 0899       */
 0900      public function __construct()
 0901      {{$targetDirs}
 0902          parent::__construct($arguments);
 0903   
 0904  EOF;
 0905   
 0906   
 0907          if (count($scopes = $this->container->getScopes(false)) > 0) {
 0908              $code .= "\n";
 0909              $code .= '        $this->scopes = '.$this->dumpValue($scopes).";\n";
 0910              $code .= '        $this->scopeChildren = '.$this->dumpValue($this->container->getScopeChildren(false)).";\n";
 0911          }
 0912   
 0913          $code .= $this->addMethodMap();
 0914          $code .= $this->addAliases();
 0915   
 0916          $code .= <<<'EOF'
 0917      }
 0918   
 0919  EOF;
 0920   
 0921   
 0922          return $code;
 0923      }
 0924   
 0925      /**
 0926       * Adds the constructor for a frozen container.
 0927       *
 0928       * @return string
 0929       */
 0930      private function addFrozenConstructor()
 0931      {
 0932          $targetDirs = $this->exportTargetDirs();
 0933   
 0934          $code = <<<EOF
 0935   
 0936      /*{$this->docStar}
 0937       * Constructor.
 0938       */
 0939      public function __construct()
 0940      {{$targetDirs}
 0941  EOF;
 0942   
 0943   
 0944          if ($this->container->getParameterBag()->all()) {
 0945              $code .= "\n        \$this->parameters = \$this->getDefaultParameters();\n";
 0946          }
 0947   
 0948          $code .= <<<'EOF'
 0949   
 0950          $this->services =
 0951          $this->scopedServices =
 0952          $this->scopeStacks = array();
 0953  EOF;
 0954   
 0955   
 0956          $code .= "\n";
 0957          if (count($scopes = $this->container->getScopes(false)) > 0) {
 0958              $code .= '        $this->scopes = '.$this->dumpValue($scopes).";\n";
 0959              $code .= '        $this->scopeChildren = '.$this->dumpValue($this->container->getScopeChildren(false)).";\n";
 0960          } else {
 0961              $code .= "        \$this->scopes = array();\n";
 0962              $code .= "        \$this->scopeChildren = array();\n";
 0963          }
 0964   
 0965          $code .= $this->addMethodMap();
 0966          $code .= $this->addAliases();
 0967   
 0968          $code .= <<<'EOF'
 0969      }
 0970   
 0971  EOF;
 0972   
 0973   
 0974          return $code;
 0975      }
 0976   
 0977      /**
 0978       * Adds the constructor for a frozen container.
 0979       *
 0980       * @return string
 0981       */
 0982      private function addFrozenCompile()
 0983      {
 0984          return <<<EOF
 0985   
 0986      /*{$this->docStar}
 0987       * {@inheritdoc}
 0988       */
 0989      public function compile()
 0990      {
 0991          throw new LogicException('You cannot compile a dumped frozen container.');
 0992      }
 0993   
 0994  EOF;
 0995   
 0996      }
 0997   
 0998      /**
 0999       * Adds the isFrozen method for a frozen container.
 1000       *
 1001       * @return string
 1002       */
 1003      private function addIsFrozenMethod()
 1004      {
 1005          return <<<EOF
 1006   
 1007      /*{$this->docStar}
 1008       * {@inheritdoc}
 1009       */
 1010      public function isFrozen()
 1011      {
 1012          return true;
 1013      }
 1014   
 1015  EOF;
 1016   
 1017      }
 1018   
 1019      /**
 1020       * Adds the methodMap property definition.
 1021       *
 1022       * @return string
 1023       */
 1024      private function addMethodMap()
 1025      {
 1026          if (!$definitions = $this->container->getDefinitions()) {
 1027              return '';
 1028          }
 1029   
 1030          $code = "        \$this->methodMap = array(\n";
 1031          ksort($definitions);
 1032          foreach ($definitions as $id => $definition) {
 1033              $code .= '            '.var_export($id, true).' => '.var_export('get'.$this->camelize($id).'Service', true).",\n";
 1034          }
 1035   
 1036          return $code."        );\n";
 1037      }
 1038   
 1039      /**
 1040       * Adds the aliases property definition.
 1041       *
 1042       * @return string
 1043       */
 1044      private function addAliases()
 1045      {
 1046          if (!$aliases = $this->container->getAliases()) {
 1047              if ($this->container->isFrozen()) {
 1048                  return "\n        \$this->aliases = array();\n";
 1049              } else {
 1050                  return '';
 1051              }
 1052          }
 1053   
 1054          $code = "        \$this->aliases = array(\n";
 1055          ksort($aliases);
 1056          foreach ($aliases as $alias => $id) {
 1057              $id = (string) $id;
 1058              while (isset($aliases[$id])) {
 1059                  $id = (string) $aliases[$id];
 1060              }
 1061              $code .= '            '.var_export($alias, true).' => '.var_export($id, true).",\n";
 1062          }
 1063   
 1064          return $code."        );\n";
 1065      }
 1066   
 1067      /**
 1068       * Adds default parameters method.
 1069       *
 1070       * @return string
 1071       */
 1072      private function addDefaultParametersMethod()
 1073      {
 1074          if (!$this->container->getParameterBag()->all()) {
 1075              return '';
 1076          }
 1077   
 1078          $parameters = $this->exportParameters($this->container->getParameterBag()->all());
 1079   
 1080          $code = '';
 1081          if ($this->container->isFrozen()) {
 1082              $code .= <<<'EOF'
 1083   
 1084      /**
 1085       * {@inheritdoc}
 1086       */
 1087      public function getParameter($name)
 1088      {
 1089          $name = strtolower($name);
 1090   
 1091          if (!(isset($this->parameters[$name]) || array_key_exists($name, $this->parameters))) {
 1092              throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name));
 1093          }
 1094   
 1095          return $this->parameters[$name];
 1096      }
 1097   
 1098      /**
 1099       * {@inheritdoc}
 1100       */
 1101      public function hasParameter($name)
 1102      {
 1103          $name = strtolower($name);
 1104   
 1105          return isset($this->parameters[$name]) || array_key_exists($name, $this->parameters);
 1106      }
 1107   
 1108      /**
 1109       * {@inheritdoc}
 1110       */
 1111      public function setParameter($name, $value)
 1112      {
 1113          throw new LogicException('Impossible to call set() on a frozen ParameterBag.');
 1114      }
 1115   
 1116      /**
 1117       * {@inheritdoc}
 1118       */
 1119      public function getParameterBag()
 1120      {
 1121          if (null === $this->parameterBag) {
 1122              $this->parameterBag = new FrozenParameterBag($this->parameters);
 1123          }
 1124   
 1125          return $this->parameterBag;
 1126      }
 1127   
 1128  EOF;
 1129   
 1130              if ('' === $this->docStar) {
 1131                  $code = str_replace('/**', '/*', $code);
 1132              }
 1133          }
 1134   
 1135          $code .= <<<EOF
 1136   
 1137      /*{$this->docStar}
 1138       * Gets the default parameters.
 1139       *
 1140       * @return array An array of the default parameters
 1141       */
 1142      protected function getDefaultParameters()
 1143      {
 1144          return $parameters;
 1145      }
 1146   
 1147  EOF;
 1148   
 1149   
 1150          return $code;
 1151      }
 1152   
 1153      /**
 1154       * Exports parameters.
 1155       *
 1156       * @param array  $parameters
 1157       * @param string $path
 1158       * @param int    $indent
 1159       *
 1160       * @return string
 1161       *
 1162       * @throws InvalidArgumentException
 1163       */
 1164      private function exportParameters(array $parameters, $path = '', $indent = 12)
 1165      {
 1166          $php = array();
 1167          foreach ($parameters as $key => $value) {
 1168              if (is_array($value)) {
 1169                  $value = $this->exportParameters($value, $path.'/'.$key, $indent + 4);
 1170              } elseif ($value instanceof Variable) {
 1171                  throw new InvalidArgumentException(sprintf('You cannot dump a container with parameters that contain variable references. Variable "%s" found in "%s".', $value, $path.'/'.$key));
 1172              } elseif ($value instanceof Definition) {
 1173                  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));
 1174              } elseif ($value instanceof Reference) {
 1175                  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));
 1176              } elseif ($value instanceof Expression) {
 1177                  throw new InvalidArgumentException(sprintf('You cannot dump a container with parameters that contain expressions. Expression "%s" found in "%s".', $value, $path.'/'.$key));
 1178              } else {
 1179                  $value = $this->export($value);
 1180              }
 1181   
 1182              $php[] = sprintf('%s%s => %s,', str_repeat(' ', $indent), var_export($key, true), $value);
 1183          }
 1184   
 1185          return sprintf("array(\n%s\n%s)", implode("\n", $php), str_repeat(' ', $indent - 4));
 1186      }
 1187   
 1188      /**
 1189       * Ends the class definition.
 1190       *
 1191       * @return string
 1192       */
 1193      private function endClass()
 1194      {
 1195          return <<<'EOF'
 1196  }
 1197   
 1198  EOF;
 1199   
 1200      }
 1201   
 1202      /**
 1203       * Wraps the service conditionals.
 1204       *
 1205       * @param string $value
 1206       * @param string $code
 1207       *
 1208       * @return string
 1209       */
 1210      private function wrapServiceConditionals($value, $code)
 1211      {
 1212          if (!$services = ContainerBuilder::getServiceConditionals($value)) {
 1213              return $code;
 1214          }
 1215   
 1216          $conditions = array();
 1217          foreach ($services as $service) {
 1218              $conditions[] = sprintf("\$this->has('%s')", $service);
 1219          }
 1220   
 1221          // re-indent the wrapped code
 1222          $code = implode("\n", array_map(function ($line) { return $line ? '    '.$line : $line; }, explode("\n", $code)));
 1223   
 1224          return sprintf("        if (%s) {\n%s        }\n", implode(' && ', $conditions), $code);
 1225      }
 1226   
 1227      /**
 1228       * Builds service calls from arguments.
 1229       *
 1230       * @param array $arguments
 1231       * @param array &$calls    By reference
 1232       * @param array &$behavior By reference
 1233       */
 1234      private function getServiceCallsFromArguments(array $arguments, array &$calls, array &$behavior)
 1235      {
 1236          foreach ($arguments as $argument) {
 1237              if (is_array($argument)) {
 1238                  $this->getServiceCallsFromArguments($argument, $calls, $behavior);
 1239              } elseif ($argument instanceof Reference) {
 1240                  $id = (string) $argument;
 1241   
 1242                  if (!isset($calls[$id])) {
 1243                      $calls[$id] = 0;
 1244                  }
 1245                  if (!isset($behavior[$id])) {
 1246                      $behavior[$id] = $argument->getInvalidBehavior();
 1247                  } elseif (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $behavior[$id]) {
 1248                      $behavior[$id] = $argument->getInvalidBehavior();
 1249                  }
 1250   
 1251                  ++$calls[$id];
 1252              }
 1253          }
 1254      }
 1255   
 1256      /**
 1257       * Returns the inline definition.
 1258       *
 1259       * @param Definition $definition
 1260       *
 1261       * @return array
 1262       */
 1263      private function getInlinedDefinitions(Definition $definition)
 1264      {
 1265          if (false === $this->inlinedDefinitions->contains($definition)) {
 1266              $definitions = array_merge(
 1267                  $this->getDefinitionsFromArguments($definition->getArguments()),
 1268                  $this->getDefinitionsFromArguments($definition->getMethodCalls()),
 1269                  $this->getDefinitionsFromArguments($definition->getProperties()),
 1270                  $this->getDefinitionsFromArguments(array($definition->getConfigurator())),
 1271                  $this->getDefinitionsFromArguments(array($definition->getFactory()))
 1272              );
 1273   
 1274              $this->inlinedDefinitions->offsetSet($definition, $definitions);
 1275   
 1276              return $definitions;
 1277          }
 1278   
 1279          return $this->inlinedDefinitions->offsetGet($definition);
 1280      }
 1281   
 1282      /**
 1283       * Gets the definition from arguments.
 1284       *
 1285       * @param array $arguments
 1286       *
 1287       * @return array
 1288       */
 1289      private function getDefinitionsFromArguments(array $arguments)
 1290      {
 1291          $definitions = array();
 1292          foreach ($arguments as $argument) {
 1293              if (is_array($argument)) {
 1294                  $definitions = array_merge($definitions, $this->getDefinitionsFromArguments($argument));
 1295              } elseif ($argument instanceof Definition) {
 1296                  $definitions = array_merge(
 1297                      $definitions,
 1298                      $this->getInlinedDefinitions($argument),
 1299                      array($argument)
 1300                  );
 1301              }
 1302          }
 1303   
 1304          return $definitions;
 1305      }
 1306   
 1307      /**
 1308       * Checks if a service id has a reference.
 1309       *
 1310       * @param string $id
 1311       * @param array  $arguments
 1312       * @param bool   $deep
 1313       * @param array  $visited
 1314       *
 1315       * @return bool
 1316       */
 1317      private function hasReference($id, array $arguments, $deep = false, array &$visited = array())
 1318      {
 1319          foreach ($arguments as $argument) {
 1320              if (is_array($argument)) {
 1321                  if ($this->hasReference($id, $argument, $deep, $visited)) {
 1322                      return true;
 1323                  }
 1324              } elseif ($argument instanceof Reference) {
 1325                  $argumentId = (string) $argument;
 1326                  if ($id === $argumentId) {
 1327                      return true;
 1328                  }
 1329   
 1330                  if ($deep && !isset($visited[$argumentId]) && 'service_container' !== $argumentId) {
 1331                      $visited[$argumentId] = true;
 1332   
 1333                      $service = $this->container->getDefinition($argumentId);
 1334                      $arguments = array_merge($service->getMethodCalls(), $service->getArguments(), $service->getProperties());
 1335   
 1336                      if ($this->hasReference($id, $arguments, $deep, $visited)) {
 1337                          return true;
 1338                      }
 1339                  }
 1340              }
 1341          }
 1342   
 1343          return false;
 1344      }
 1345   
 1346      /**
 1347       * Dumps values.
 1348       *
 1349       * @param mixed $value
 1350       * @param bool  $interpolate
 1351       *
 1352       * @return string
 1353       *
 1354       * @throws RuntimeException
 1355       */
 1356      private function dumpValue($value, $interpolate = true)
 1357      {
 1358          if (is_array($value)) {
 1359              $code = array();
 1360              foreach ($value as $k => $v) {
 1361                  $code[] = sprintf('%s => %s', $this->dumpValue($k, $interpolate), $this->dumpValue($v, $interpolate));
 1362              }
 1363   
 1364              return sprintf('array(%s)', implode(', ', $code));
 1365          } elseif ($value instanceof Definition) {
 1366              if (null !== $this->definitionVariables && $this->definitionVariables->contains($value)) {
 1367                  return $this->dumpValue($this->definitionVariables->offsetGet($value), $interpolate);
 1368              }
 1369              if (count($value->getMethodCalls()) > 0) {
 1370                  throw new RuntimeException('Cannot dump definitions which have method calls.');
 1371              }
 1372              if (null !== $value->getConfigurator()) {
 1373                  throw new RuntimeException('Cannot dump definitions which have a configurator.');
 1374              }
 1375   
 1376              $arguments = array();
 1377              foreach ($value->getArguments() as $argument) {
 1378                  $arguments[] = $this->dumpValue($argument);
 1379              }
 1380   
 1381              if (null !== $value->getFactory()) {
 1382                  $factory = $value->getFactory();
 1383   
 1384                  if (is_string($factory)) {
 1385                      return sprintf('\\%s(%s)', $factory, implode(', ', $arguments));
 1386                  }
 1387   
 1388                  if (is_array($factory)) {
 1389                      if (!preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $factory[1])) {
 1390                          throw new RuntimeException(sprintf('Cannot dump definition because of invalid factory method (%s)', $factory[1] ?: 'n/a'));
 1391                      }
 1392   
 1393                      if (is_string($factory[0])) {
 1394                          return sprintf('%s::%s(%s)', $this->dumpLiteralClass($this->dumpValue($factory[0])), $factory[1], implode(', ', $arguments));
 1395                      }
 1396   
 1397                      if ($factory[0] instanceof Definition) {
 1398                          return sprintf("call_user_func(array(%s, '%s')%s)", $this->dumpValue($factory[0]), $factory[1], count($arguments) > 0 ? ', '.implode(', ', $arguments) : '');
 1399                      }
 1400   
 1401                      if ($factory[0] instanceof Reference) {
 1402                          return sprintf('%s->%s(%s)', $this->dumpValue($factory[0]), $factory[1], implode(', ', $arguments));
 1403                      }
 1404                  }
 1405   
 1406                  throw new RuntimeException('Cannot dump definition because of invalid factory');
 1407              }
 1408   
 1409              if (null !== $value->getFactoryMethod(false)) {
 1410                  if (null !== $value->getFactoryClass(false)) {
 1411                      return sprintf("call_user_func(array(%s, '%s')%s)", $this->dumpValue($value->getFactoryClass(false)), $value->getFactoryMethod(false), count($arguments) > 0 ? ', '.implode(', ', $arguments) : '');
 1412                  } elseif (null !== $value->getFactoryService(false)) {
 1413                      $service = $this->dumpValue($value->getFactoryService(false));
 1414   
 1415                      return sprintf('%s->%s(%s)', 0 === strpos($service, '$') ? sprintf('$this->get(%s)', $service) : $this->getServiceCall($value->getFactoryService(false)), $value->getFactoryMethod(false), implode(', ', $arguments));
 1416                  } else {
 1417                      throw new RuntimeException('Cannot dump definitions which have factory method without factory service or factory class.');
 1418                  }
 1419              }
 1420   
 1421              $class = $value->getClass();
 1422              if (null === $class) {
 1423                  throw new RuntimeException('Cannot dump definitions which have no class nor factory.');
 1424              }
 1425   
 1426              return sprintf('new %s(%s)', $this->dumpLiteralClass($this->dumpValue($class)), implode(', ', $arguments));
 1427          } elseif ($value instanceof Variable) {
 1428              return '$'.$value;
 1429          } elseif ($value instanceof Reference) {
 1430              if (null !== $this->referenceVariables && isset($this->referenceVariables[$id = (string) $value])) {
 1431                  return $this->dumpValue($this->referenceVariables[$id], $interpolate);
 1432              }
 1433   
 1434              return $this->getServiceCall((string) $value, $value);
 1435          } elseif ($value instanceof Expression) {
 1436              return $this->getExpressionLanguage()->compile((string) $value, array('this' => 'container'));
 1437          } elseif ($value instanceof Parameter) {
 1438              return $this->dumpParameter($value);
 1439          } elseif (true === $interpolate && is_string($value)) {
 1440              if (preg_match('/^%([^%]+)%$/', $value, $match)) {
 1441                  // we do this to deal with non string values (Boolean, integer, ...)
 1442                  // the preg_replace_callback converts them to strings
 1443                  return $this->dumpParameter(strtolower($match[1]));
 1444              } else {
 1445                  $that = $this;
 1446                  $replaceParameters = function ($match) use ($that) {
 1447                      return "'.".$that->dumpParameter(strtolower($match[2])).".'";
 1448                  };
 1449   
 1450                  $code = str_replace('%%', '%', preg_replace_callback('/(?<!%)(%)([^%]+)\1/', $replaceParameters, $this->export($value)));
 1451   
 1452                  return $code;
 1453              }
 1454          } elseif (is_object($value) || is_resource($value)) {
 1455              throw new RuntimeException('Unable to dump a service container if a parameter is an object or a resource.');
 1456          } else {
 1457              return $this->export($value);
 1458          }
 1459      }
 1460   
 1461      /**
 1462       * Dumps a string to a literal (aka PHP Code) class value.
 1463       *
 1464       * @param string $class
 1465       *
 1466       * @return string
 1467       *
 1468       * @throws RuntimeException
 1469       */
 1470      private function dumpLiteralClass($class)
 1471      {
 1472          if (false !== strpos($class, '$')) {
 1473              throw new RuntimeException('Cannot dump definitions which have a variable class name.');
 1474          }
 1475          if (0 !== strpos($class, "'") || !preg_match('/^\'[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(\\\{2}[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*\'$/', $class)) {
 1476              throw new RuntimeException(sprintf('Cannot dump definition because of invalid class name (%s)', $class ?: 'n/a'));
 1477          }
 1478   
 1479          return '\\'.substr(str_replace('\\\\', '\\', $class), 1, -1);
 1480      }
 1481   
 1482      /**
 1483       * Dumps a parameter.
 1484       *
 1485       * @param string $name
 1486       *
 1487       * @return string
 1488       */
 1489      public function dumpParameter($name)
 1490      {
 1491          if ($this->container->isFrozen() && $this->container->hasParameter($name)) {
 1492              return $this->dumpValue($this->container->getParameter($name), false);
 1493          }
 1494   
 1495          return sprintf("\$this->getParameter('%s')", strtolower($name));
 1496      }
 1497   
 1498      /**
 1499       * @deprecated since version 2.6.2, to be removed in 3.0.
 1500       *             Use \Symfony\Component\DependencyInjection\ContainerBuilder::addExpressionLanguageProvider instead.
 1501       *
 1502       * @param ExpressionFunctionProviderInterface $provider
 1503       */
 1504      public function addExpressionLanguageProvider(ExpressionFunctionProviderInterface $provider)
 1505      {
 1506          @trigger_error('The '.__METHOD__.' method is deprecated since version 2.6.2 and will be removed in 3.0. Use the Symfony\Component\DependencyInjection\ContainerBuilder::addExpressionLanguageProvider method instead.', E_USER_DEPRECATED);
 1507   
 1508          $this->expressionLanguageProviders[] = $provider;
 1509      }
 1510   
 1511      /**
 1512       * Gets a service call.
 1513       *
 1514       * @param string    $id
 1515       * @param Reference $reference
 1516       *
 1517       * @return string
 1518       */
 1519      private function getServiceCall($id, Reference $reference = null)
 1520      {
 1521          if ('service_container' === $id) {
 1522              return '$this';
 1523          }
 1524   
 1525          if (null !== $reference && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $reference->getInvalidBehavior()) {
 1526              return sprintf('$this->get(\'%s\', ContainerInterface::NULL_ON_INVALID_REFERENCE)', $id);
 1527          } else {
 1528              if ($this->container->hasAlias($id)) {
 1529                  $id = (string) $this->container->getAlias($id);
 1530              }
 1531   
 1532              return sprintf('$this->get(\'%s\')', $id);
 1533          }
 1534      }
 1535   
 1536      /**
 1537       * Convert a service id to a valid PHP method name.
 1538       *
 1539       * @param string $id
 1540       *
 1541       * @return string
 1542       *
 1543       * @throws InvalidArgumentException
 1544       */
 1545      private function camelize($id)
 1546      {
 1547          $name = Container::camelize($id);
 1548   
 1549          if (!preg_match('/^[a-zA-Z0-9_\x7f-\xff]+$/', $name)) {
 1550              throw new InvalidArgumentException(sprintf('Service id "%s" cannot be converted to a valid PHP method name.', $id));
 1551          }
 1552   
 1553          return $name;
 1554      }
 1555   
 1556      /**
 1557       * Returns the next name to use.
 1558       *
 1559       * @return string
 1560       */
 1561      private function getNextVariableName()
 1562      {
 1563          $firstChars = self::FIRST_CHARS;
 1564          $firstCharsLength = strlen($firstChars);
 1565          $nonFirstChars = self::NON_FIRST_CHARS;
 1566          $nonFirstCharsLength = strlen($nonFirstChars);
 1567   
 1568          while (true) {
 1569              $name = '';
 1570              $i = $this->variableCount;
 1571   
 1572              if ('' === $name) {
 1573                  $name .= $firstChars[$i % $firstCharsLength];
 1574                  $i = (int) ($i / $firstCharsLength);
 1575              }
 1576   
 1577              while ($i > 0) {
 1578                  --$i;
 1579                  $name .= $nonFirstChars[$i % $nonFirstCharsLength];
 1580                  $i = (int) ($i / $nonFirstCharsLength);
 1581              }
 1582   
 1583              ++$this->variableCount;
 1584   
 1585              // check that the name is not reserved
 1586              if (in_array($name, $this->reservedVariables, true)) {
 1587                  continue;
 1588              }
 1589   
 1590              return $name;
 1591          }
 1592      }
 1593   
 1594      private function getExpressionLanguage()
 1595      {
 1596          if (null === $this->expressionLanguage) {
 1597              if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) {
 1598                  throw new RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.');
 1599              }
 1600              $providers = array_merge($this->container->getExpressionLanguageProviders(), $this->expressionLanguageProviders);
 1601              $this->expressionLanguage = new ExpressionLanguage(null, $providers);
 1602   
 1603              if ($this->container->isTrackingResources()) {
 1604                  foreach ($providers as $provider) {
 1605                      $this->container->addObjectResource($provider);
 1606                  }
 1607              }
 1608          }
 1609   
 1610          return $this->expressionLanguage;
 1611      }
 1612   
 1613      private function exportTargetDirs()
 1614      {
 1615          return null === $this->targetDirRegex ? '' : <<<EOF
 1616   
 1617          \$dir = __DIR__;
 1618          for (\$i = 1; \$i <= {$this->targetDirMaxMatches}; ++\$i) {
 1619              \$this->targetDirs[\$i] = \$dir = dirname(\$dir);
 1620          }
 1621  EOF;
 1622   
 1623      }
 1624   
 1625      private function export($value)
 1626      {
 1627          if (null !== $this->targetDirRegex && is_string($value) && preg_match($this->targetDirRegex, $value, $matches, PREG_OFFSET_CAPTURE)) {
 1628              $prefix = $matches[0][1] ? var_export(substr($value, 0, $matches[0][1]), true).'.' : '';
 1629              $suffix = $matches[0][1] + strlen($matches[0][0]);
 1630              $suffix = isset($value[$suffix]) ? '.'.var_export(substr($value, $suffix), true) : '';
 1631              $dirname = '__DIR__';
 1632   
 1633              if (0 < $offset = 1 + $this->targetDirMaxMatches - count($matches)) {
 1634                  $dirname = sprintf('$this->targetDirs[%d]', $offset);
 1635              }
 1636   
 1637              if ($prefix || $suffix) {
 1638                  return sprintf('(%s%s%s)', $prefix, $dirname, $suffix);
 1639              }
 1640   
 1641              return $dirname;
 1642          }
 1643   
 1644          return var_export($value, true);
 1645      }
 1646  }
 1647