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