Verzeichnisstruktur phpBB-3.1.0


Veröffentlicht
27.10.2014

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