[ Index ]

PHP Cross Reference of phpBB-3.2.8-deutsch

title

Body

[close]

/vendor/symfony/dependency-injection/Dumper/ -> PhpDumper.php (source)

   1  <?php
   2  
   3  /*
   4   * This file is part of the Symfony package.
   5   *
   6   * (c) Fabien Potencier <fabien@symfony.com>
   7   *
   8   * For the full copyright and license information, please view the LICENSE
   9   * file that was distributed with this source code.
  10   */
  11  
  12  namespace Symfony\Component\DependencyInjection\Dumper;
  13  
  14  use Symfony\Component\DependencyInjection\Container;
  15  use Symfony\Component\DependencyInjection\ContainerBuilder;
  16  use Symfony\Component\DependencyInjection\ContainerInterface;
  17  use Symfony\Component\DependencyInjection\Definition;
  18  use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
  19  use Symfony\Component\DependencyInjection\Exception\RuntimeException;
  20  use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
  21  use Symfony\Component\DependencyInjection\ExpressionLanguage;
  22  use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\DumperInterface as ProxyDumper;
  23  use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\NullDumper;
  24  use Symfony\Component\DependencyInjection\Parameter;
  25  use Symfony\Component\DependencyInjection\Reference;
  26  use Symfony\Component\DependencyInjection\Variable;
  27  use Symfony\Component\ExpressionLanguage\Expression;
  28  use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface;
  29  use Symfony\Component\HttpKernel\Kernel;
  30  
  31  /**
  32   * PhpDumper dumps a service container as a PHP class.
  33   *
  34   * @author Fabien Potencier <fabien@symfony.com>
  35   * @author Johannes M. Schmitt <schmittjoh@gmail.com>
  36   */
  37  class PhpDumper extends Dumper
  38  {
  39      /**
  40       * Characters that might appear in the generated variable name as first character.
  41       */
  42      const FIRST_CHARS = 'abcdefghijklmnopqrstuvwxyz';
  43  
  44      /**
  45       * Characters that might appear in the generated variable name as any but the first character.
  46       */
  47      const NON_FIRST_CHARS = 'abcdefghijklmnopqrstuvwxyz0123456789_';
  48  
  49      private $inlinedDefinitions;
  50      private $definitionVariables;
  51      private $referenceVariables;
  52      private $variableCount;
  53      private $reservedVariables = array('instance', 'class');
  54      private $expressionLanguage;
  55      private $targetDirRegex;
  56      private $targetDirMaxMatches;
  57      private $docStar;
  58  
  59      /**
  60       * @var ExpressionFunctionProviderInterface[]
  61       */
  62      private $expressionLanguageProviders = array();
  63  
  64      /**
  65       * @var ProxyDumper
  66       */
  67      private $proxyDumper;
  68  
  69      /**
  70       * {@inheritdoc}
  71       */
  72      public function __construct(ContainerBuilder $container)
  73      {
  74          parent::__construct($container);
  75  
  76          $this->inlinedDefinitions = new \SplObjectStorage();
  77      }
  78  
  79      /**
  80       * Sets the dumper to be used when dumping proxies in the generated container.
  81       */
  82      public function setProxyDumper(ProxyDumper $proxyDumper)
  83      {
  84          $this->proxyDumper = $proxyDumper;
  85      }
  86  
  87      /**
  88       * Dumps the service container as a PHP class.
  89       *
  90       * Available options:
  91       *
  92       *  * class:      The class name
  93       *  * base_class: The base class name
  94       *  * namespace:  The class namespace
  95       *
  96       * @return string A PHP class representing of the service container
  97       */
  98      public function dump(array $options = array())
  99      {
 100          $this->targetDirRegex = null;
 101          $options = array_merge(array(
 102              'class' => 'ProjectServiceContainer',
 103              'base_class' => 'Container',
 104              'namespace' => '',
 105              'debug' => true,
 106          ), $options);
 107          $this->docStar = $options['debug'] ? '*' : '';
 108  
 109          if (!empty($options['file']) && is_dir($dir = \dirname($options['file']))) {
 110              // Build a regexp where the first root dirs are mandatory,
 111              // but every other sub-dir is optional up to the full path in $dir
 112              // Mandate at least 2 root dirs and not more that 5 optional dirs.
 113  
 114              $dir = explode(\DIRECTORY_SEPARATOR, realpath($dir));
 115              $i = \count($dir);
 116  
 117              if (3 <= $i) {
 118                  $regex = '';
 119                  $lastOptionalDir = $i > 8 ? $i - 5 : 3;
 120                  $this->targetDirMaxMatches = $i - $lastOptionalDir;
 121  
 122                  while (--$i >= $lastOptionalDir) {
 123                      $regex = sprintf('(%s%s)?', preg_quote(\DIRECTORY_SEPARATOR.$dir[$i], '#'), $regex);
 124                  }
 125  
 126                  do {
 127                      $regex = preg_quote(\DIRECTORY_SEPARATOR.$dir[$i], '#').$regex;
 128                  } while (0 < --$i);
 129  
 130                  $this->targetDirRegex = '#'.preg_quote($dir[0], '#').$regex.'#';
 131              }
 132          }
 133  
 134          $code = $this->startClass($options['class'], $options['base_class'], $options['namespace']);
 135  
 136          if ($this->container->isFrozen()) {
 137              $code .= $this->addFrozenConstructor();
 138              $code .= $this->addFrozenCompile();
 139              $code .= $this->addIsFrozenMethod();
 140          } else {
 141              $code .= $this->addConstructor();
 142          }
 143  
 144          $code .=
 145              $this->addServices().
 146              $this->addDefaultParametersMethod().
 147              $this->endClass().
 148              $this->addProxyClasses()
 149          ;
 150          $this->targetDirRegex = null;
 151  
 152          return $code;
 153      }
 154  
 155      /**
 156       * Retrieves the currently set proxy dumper or instantiates one.
 157       *
 158       * @return ProxyDumper
 159       */
 160      private function getProxyDumper()
 161      {
 162          if (!$this->proxyDumper) {
 163              $this->proxyDumper = new NullDumper();
 164          }
 165  
 166          return $this->proxyDumper;
 167      }
 168  
 169      /**
 170       * Generates Service local temp variables.
 171       *
 172       * @param string $cId
 173       * @param string $definition
 174       *
 175       * @return string
 176       */
 177      private function addServiceLocalTempVariables($cId, $definition)
 178      {
 179          static $template = "        \$%s = %s;\n";
 180  
 181          $localDefinitions = array_merge(
 182              array($definition),
 183              $this->getInlinedDefinitions($definition)
 184          );
 185  
 186          $calls = $behavior = array();
 187          foreach ($localDefinitions as $iDefinition) {
 188              $this->getServiceCallsFromArguments($iDefinition->getArguments(), $calls, $behavior);
 189              $this->getServiceCallsFromArguments($iDefinition->getMethodCalls(), $calls, $behavior);
 190              $this->getServiceCallsFromArguments($iDefinition->getProperties(), $calls, $behavior);
 191              $this->getServiceCallsFromArguments(array($iDefinition->getConfigurator()), $calls, $behavior);
 192              $this->getServiceCallsFromArguments(array($iDefinition->getFactory()), $calls, $behavior);
 193          }
 194  
 195          $code = '';
 196          foreach ($calls as $id => $callCount) {
 197              if ('service_container' === $id || $id === $cId) {
 198                  continue;
 199              }
 200  
 201              if ($callCount > 1) {
 202                  $name = $this->getNextVariableName();
 203                  $this->referenceVariables[$id] = new Variable($name);
 204  
 205                  if (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE === $behavior[$id]) {
 206                      $code .= sprintf($template, $name, $this->getServiceCall($id));
 207                  } else {
 208                      $code .= sprintf($template, $name, $this->getServiceCall($id, new Reference($id, ContainerInterface::NULL_ON_INVALID_REFERENCE)));
 209                  }
 210              }
 211          }
 212  
 213          if ('' !== $code) {
 214              $code .= "\n";
 215          }
 216  
 217          return $code;
 218      }
 219  
 220      /**
 221       * Generates code for the proxies to be attached after the container class.
 222       *
 223       * @return string
 224       */
 225      private function addProxyClasses()
 226      {
 227          /* @var $definitions Definition[] */
 228          $definitions = array_filter(
 229              $this->container->getDefinitions(),
 230              array($this->getProxyDumper(), 'isProxyCandidate')
 231          );
 232          $code = '';
 233          $strip = '' === $this->docStar && method_exists('Symfony\Component\HttpKernel\Kernel', 'stripComments');
 234  
 235          foreach ($definitions as $definition) {
 236              if ("\n" === $proxyCode = "\n".$this->getProxyDumper()->getProxyCode($definition)) {
 237                  continue;
 238              }
 239              if ($strip) {
 240                  $proxyCode = "<?php\n".$proxyCode;
 241                  $proxyCode = substr(Kernel::stripComments($proxyCode), 5);
 242              }
 243              $code .= $proxyCode;
 244          }
 245  
 246          return $code;
 247      }
 248  
 249      /**
 250       * Generates the require_once statement for service includes.
 251       *
 252       * @return string
 253       */
 254      private function addServiceInclude(Definition $definition)
 255      {
 256          $template = "        require_once %s;\n";
 257          $code = '';
 258  
 259          if (null !== $file = $definition->getFile()) {
 260              $code .= sprintf($template, $this->dumpValue($file));
 261          }
 262  
 263          foreach ($this->getInlinedDefinitions($definition) as $definition) {
 264              if (null !== $file = $definition->getFile()) {
 265                  $code .= sprintf($template, $this->dumpValue($file));
 266              }
 267          }
 268  
 269          if ('' !== $code) {
 270              $code .= "\n";
 271          }
 272  
 273          return $code;
 274      }
 275  
 276      /**
 277       * Generates the inline definition of a service.
 278       *
 279       * @param string     $id
 280       * @param Definition $definition
 281       *
 282       * @return string
 283       *
 284       * @throws RuntimeException                  When the factory definition is incomplete
 285       * @throws ServiceCircularReferenceException When a circular reference is detected
 286       */
 287      private function addServiceInlinedDefinitions($id, Definition $definition)
 288      {
 289          $code = '';
 290          $variableMap = $this->definitionVariables;
 291          $nbOccurrences = new \SplObjectStorage();
 292          $processed = new \SplObjectStorage();
 293          $inlinedDefinitions = $this->getInlinedDefinitions($definition);
 294  
 295          foreach ($inlinedDefinitions as $definition) {
 296              if (false === $nbOccurrences->contains($definition)) {
 297                  $nbOccurrences->offsetSet($definition, 1);
 298              } else {
 299                  $i = $nbOccurrences->offsetGet($definition);
 300                  $nbOccurrences->offsetSet($definition, $i + 1);
 301              }
 302          }
 303  
 304          foreach ($inlinedDefinitions as $sDefinition) {
 305              if ($processed->contains($sDefinition)) {
 306                  continue;
 307              }
 308              $processed->offsetSet($sDefinition);
 309  
 310              $class = $this->dumpValue($sDefinition->getClass());
 311              if ($nbOccurrences->offsetGet($sDefinition) > 1 || $sDefinition->getMethodCalls() || $sDefinition->getProperties() || null !== $sDefinition->getConfigurator() || false !== strpos($class, '$')) {
 312                  $name = $this->getNextVariableName();
 313                  $variableMap->offsetSet($sDefinition, new Variable($name));
 314  
 315                  // a construct like:
 316                  // $a = new ServiceA(ServiceB $b); $b = new ServiceB(ServiceA $a);
 317                  // this is an indication for a wrong implementation, you can circumvent this problem
 318                  // by setting up your service structure like this:
 319                  // $b = new ServiceB();
 320                  // $a = new ServiceA(ServiceB $b);
 321                  // $b->setServiceA(ServiceA $a);
 322                  if ($this->hasReference($id, $sDefinition->getArguments())) {
 323                      throw new ServiceCircularReferenceException($id, array($id));
 324                  }
 325  
 326                  $code .= $this->addNewInstance($id, $sDefinition, '$'.$name, ' = ');
 327  
 328                  if (!$this->hasReference($id, $sDefinition->getMethodCalls(), true) && !$this->hasReference($id, $sDefinition->getProperties(), true)) {
 329                      $code .= $this->addServiceProperties($sDefinition, $name);
 330                      $code .= $this->addServiceMethodCalls($sDefinition, $name);
 331                      $code .= $this->addServiceConfigurator($sDefinition, $name);
 332                  }
 333  
 334                  $code .= "\n";
 335              }
 336          }
 337  
 338          return $code;
 339      }
 340  
 341      /**
 342       * Adds the service return statement.
 343       *
 344       * @param string     $id         Service id
 345       * @param Definition $definition
 346       *
 347       * @return string
 348       */
 349      private function addServiceReturn($id, Definition $definition)
 350      {
 351          if ($this->isSimpleInstance($id, $definition)) {
 352              return "    }\n";
 353          }
 354  
 355          return "\n        return \$instance;\n    }\n";
 356      }
 357  
 358      /**
 359       * Generates the service instance.
 360       *
 361       * @param string     $id
 362       * @param Definition $definition
 363       *
 364       * @return string
 365       *
 366       * @throws InvalidArgumentException
 367       * @throws RuntimeException
 368       */
 369      private function addServiceInstance($id, Definition $definition)
 370      {
 371          $class = $this->dumpValue($definition->getClass());
 372  
 373          if (0 === strpos($class, "'") && !preg_match('/^\'(?:\\\{2})?[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(?:\\\{2}[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*\'$/', $class)) {
 374              throw new InvalidArgumentException(sprintf('"%s" is not a valid class name for the "%s" service.', $class, $id));
 375          }
 376  
 377          $simple = $this->isSimpleInstance($id, $definition);
 378          $isProxyCandidate = $this->getProxyDumper()->isProxyCandidate($definition);
 379          $instantiation = '';
 380  
 381          if (!$isProxyCandidate && $definition->isShared() && ContainerInterface::SCOPE_CONTAINER === $definition->getScope(false)) {
 382              $instantiation = sprintf('$this->services[%s] = %s', var_export($id, true), $simple ? '' : '$instance');
 383          } elseif (!$isProxyCandidate && $definition->isShared() && ContainerInterface::SCOPE_PROTOTYPE !== $scope = $definition->getScope(false)) {
 384              $instantiation = sprintf('$this->services[%s] = $this->scopedServices[%s][%1$s] = %s', var_export($id, true), var_export($scope, true), $simple ? '' : '$instance');
 385          } elseif (!$simple) {
 386              $instantiation = '$instance';
 387          }
 388  
 389          $return = '';
 390          if ($simple) {
 391              $return = 'return ';
 392          } else {
 393              $instantiation .= ' = ';
 394          }
 395  
 396          $code = $this->addNewInstance($id, $definition, $return, $instantiation);
 397  
 398          if (!$simple) {
 399              $code .= "\n";
 400          }
 401  
 402          return $code;
 403      }
 404  
 405      /**
 406       * Checks if the definition is a simple instance.
 407       *
 408       * @param string     $id
 409       * @param Definition $definition
 410       *
 411       * @return bool
 412       */
 413      private function isSimpleInstance($id, Definition $definition)
 414      {
 415          foreach (array_merge(array($definition), $this->getInlinedDefinitions($definition)) as $sDefinition) {
 416              if ($definition !== $sDefinition && !$this->hasReference($id, $sDefinition->getMethodCalls())) {
 417                  continue;
 418              }
 419  
 420              if ($sDefinition->getMethodCalls() || $sDefinition->getProperties() || $sDefinition->getConfigurator()) {
 421                  return false;
 422              }
 423          }
 424  
 425          return true;
 426      }
 427  
 428      /**
 429       * Adds method calls to a service definition.
 430       *
 431       * @param Definition $definition
 432       * @param string     $variableName
 433       *
 434       * @return string
 435       */
 436      private function addServiceMethodCalls(Definition $definition, $variableName = 'instance')
 437      {
 438          $calls = '';
 439          foreach ($definition->getMethodCalls() as $call) {
 440              $arguments = array();
 441              foreach ($call[1] as $value) {
 442                  $arguments[] = $this->dumpValue($value);
 443              }
 444  
 445              $calls .= $this->wrapServiceConditionals($call[1], sprintf("        \$%s->%s(%s);\n", $variableName, $call[0], implode(', ', $arguments)));
 446          }
 447  
 448          return $calls;
 449      }
 450  
 451      private function addServiceProperties(Definition $definition, $variableName = 'instance')
 452      {
 453          $code = '';
 454          foreach ($definition->getProperties() as $name => $value) {
 455              $code .= sprintf("        \$%s->%s = %s;\n", $variableName, $name, $this->dumpValue($value));
 456          }
 457  
 458          return $code;
 459      }
 460  
 461      /**
 462       * Generates the inline definition setup.
 463       *
 464       * @param string     $id
 465       * @param Definition $definition
 466       *
 467       * @return string
 468       *
 469       * @throws ServiceCircularReferenceException when the container contains a circular reference
 470       */
 471      private function addServiceInlinedDefinitionsSetup($id, Definition $definition)
 472      {
 473          $this->referenceVariables[$id] = new Variable('instance');
 474  
 475          $code = '';
 476          $processed = new \SplObjectStorage();
 477          foreach ($this->getInlinedDefinitions($definition) as $iDefinition) {
 478              if ($processed->contains($iDefinition)) {
 479                  continue;
 480              }
 481              $processed->offsetSet($iDefinition);
 482  
 483              if (!$this->hasReference($id, $iDefinition->getMethodCalls(), true) && !$this->hasReference($id, $iDefinition->getProperties(), true)) {
 484                  continue;
 485              }
 486  
 487              // if the instance is simple, the return statement has already been generated
 488              // so, the only possible way to get there is because of a circular reference
 489              if ($this->isSimpleInstance($id, $definition)) {
 490                  throw new ServiceCircularReferenceException($id, array($id));
 491              }
 492  
 493              $name = (string) $this->definitionVariables->offsetGet($iDefinition);
 494              $code .= $this->addServiceProperties($iDefinition, $name);
 495              $code .= $this->addServiceMethodCalls($iDefinition, $name);
 496              $code .= $this->addServiceConfigurator($iDefinition, $name);
 497          }
 498  
 499          if ('' !== $code) {
 500              $code .= "\n";
 501          }
 502  
 503          return $code;
 504      }
 505  
 506      /**
 507       * Adds configurator definition.
 508       *
 509       * @param Definition $definition
 510       * @param string     $variableName
 511       *
 512       * @return string
 513       */
 514      private function addServiceConfigurator(Definition $definition, $variableName = 'instance')
 515      {
 516          if (!$callable = $definition->getConfigurator()) {
 517              return '';
 518          }
 519  
 520          if (\is_array($callable)) {
 521              if ($callable[0] instanceof Reference
 522                  || ($callable[0] instanceof Definition && $this->definitionVariables->contains($callable[0]))) {
 523                  return sprintf("        %s->%s(\$%s);\n", $this->dumpValue($callable[0]), $callable[1], $variableName);
 524              }
 525  
 526              $class = $this->dumpValue($callable[0]);
 527              // If the class is a string we can optimize call_user_func away
 528              if (0 === strpos($class, "'")) {
 529                  return sprintf("        %s::%s(\$%s);\n", $this->dumpLiteralClass($class), $callable[1], $variableName);
 530              }
 531  
 532              return sprintf("        call_user_func(array(%s, '%s'), \$%s);\n", $this->dumpValue($callable[0]), $callable[1], $variableName);
 533          }
 534  
 535          return sprintf("        %s(\$%s);\n", $callable, $variableName);
 536      }
 537  
 538      /**
 539       * Adds a service.
 540       *
 541       * @param string     $id
 542       * @param Definition $definition
 543       *
 544       * @return string
 545       */
 546      private function addService($id, Definition $definition)
 547      {
 548          $this->definitionVariables = new \SplObjectStorage();
 549          $this->referenceVariables = array();
 550          $this->variableCount = 0;
 551  
 552          $return = array();
 553  
 554          if ($definition->isSynthetic()) {
 555              $return[] = '@throws RuntimeException always since this service is expected to be injected dynamically';
 556          } elseif ($class = $definition->getClass()) {
 557              $return[] = sprintf(0 === strpos($class, '%') ? '@return object A %1$s instance' : '@return \%s', ltrim($class, '\\'));
 558          } elseif ($definition->getFactory()) {
 559              $factory = $definition->getFactory();
 560              if (\is_string($factory)) {
 561                  $return[] = sprintf('@return object An instance returned by %s()', $factory);
 562              } elseif (\is_array($factory) && (\is_string($factory[0]) || $factory[0] instanceof Definition || $factory[0] instanceof Reference)) {
 563                  if (\is_string($factory[0]) || $factory[0] instanceof Reference) {
 564                      $return[] = sprintf('@return object An instance returned by %s::%s()', (string) $factory[0], $factory[1]);
 565                  } elseif ($factory[0] instanceof Definition) {
 566                      $return[] = sprintf('@return object An instance returned by %s::%s()', $factory[0]->getClass(), $factory[1]);
 567                  }
 568              }
 569          } elseif ($definition->getFactoryClass(false)) {
 570              $return[] = sprintf('@return object An instance returned by %s::%s()', $definition->getFactoryClass(false), $definition->getFactoryMethod(false));
 571          } elseif ($definition->getFactoryService(false)) {
 572              $return[] = sprintf('@return object An instance returned by %s::%s()', $definition->getFactoryService(false), $definition->getFactoryMethod(false));
 573          }
 574  
 575          $scope = $definition->getScope(false);
 576          if (!\in_array($scope, array(ContainerInterface::SCOPE_CONTAINER, ContainerInterface::SCOPE_PROTOTYPE))) {
 577              if ($return && 0 === strpos($return[\count($return) - 1], '@return')) {
 578                  $return[] = '';
 579              }
 580              $return[] = sprintf("@throws InactiveScopeException when the '%s' service is requested while the '%s' scope is not active", $id, $scope);
 581          }
 582  
 583          if ($definition->isDeprecated()) {
 584              if ($return && 0 === strpos($return[\count($return) - 1], '@return')) {
 585                  $return[] = '';
 586              }
 587  
 588              $return[] = sprintf('@deprecated %s', $definition->getDeprecationMessage($id));
 589          }
 590  
 591          $return = str_replace("\n     * \n", "\n     *\n", implode("\n     * ", $return));
 592  
 593          $shared = $definition->isShared() && ContainerInterface::SCOPE_PROTOTYPE !== $scope ? ' shared' : '';
 594          $public = $definition->isPublic() ? 'public' : 'private';
 595          $autowired = $definition->isAutowired() ? ' autowired' : '';
 596  
 597          if ($definition->isLazy()) {
 598              $lazyInitialization = '$lazyLoad = true';
 599          } else {
 600              $lazyInitialization = '';
 601          }
 602  
 603          // with proxies, for 5.3.3 compatibility, the getter must be public to be accessible to the initializer
 604          $isProxyCandidate = $this->getProxyDumper()->isProxyCandidate($definition);
 605          $visibility = $isProxyCandidate ? 'public' : 'protected';
 606          $code = <<<EOF
 607  
 608      /*{$this->docStar}
 609       * Gets the $public '$id'$shared$autowired service.
 610       *
 611       * $return
 612  EOF;
 613              $code = str_replace('*/', ' ', $code).<<<EOF
 614  
 615       */
 616      {$visibility} function get{$this->camelize($id)}Service($lazyInitialization)
 617      {
 618  
 619  EOF;
 620  
 621          $code .= $isProxyCandidate ? $this->getProxyDumper()->getProxyFactoryCode($definition, $id) : '';
 622  
 623          if (!\in_array($scope, array(ContainerInterface::SCOPE_CONTAINER, ContainerInterface::SCOPE_PROTOTYPE))) {
 624              $code .= <<<EOF
 625          if (!isset(\$this->scopedServices['$scope'])) {
 626              throw new InactiveScopeException({$this->export($id)}, '$scope');
 627          }
 628  
 629  
 630  EOF;
 631          }
 632  
 633          if ($definition->isSynthetic()) {
 634              $code .= sprintf("        throw new RuntimeException(%s);\n    }\n", var_export("You have requested a synthetic service (\"$id\"). The DIC does not know how to construct this service.", true));
 635          } else {
 636              if ($definition->isDeprecated()) {
 637                  $code .= sprintf("        @trigger_error(%s, E_USER_DEPRECATED);\n\n", var_export($definition->getDeprecationMessage($id), true));
 638              }
 639  
 640              $code .=
 641                  $this->addServiceInclude($definition).
 642                  $this->addServiceLocalTempVariables($id, $definition).
 643                  $this->addServiceInlinedDefinitions($id, $definition).
 644                  $this->addServiceInstance($id, $definition).
 645                  $this->addServiceInlinedDefinitionsSetup($id, $definition).
 646                  $this->addServiceProperties($definition).
 647                  $this->addServiceMethodCalls($definition).
 648                  $this->addServiceConfigurator($definition).
 649                  $this->addServiceReturn($id, $definition)
 650              ;
 651          }
 652  
 653          $this->definitionVariables = null;
 654          $this->referenceVariables = null;
 655  
 656          return $code;
 657      }
 658  
 659      /**
 660       * Adds multiple services.
 661       *
 662       * @return string
 663       */
 664      private function addServices()
 665      {
 666          $publicServices = $privateServices = $synchronizers = '';
 667          $definitions = $this->container->getDefinitions();
 668          ksort($definitions);
 669          foreach ($definitions as $id => $definition) {
 670              if ($definition->isPublic()) {
 671                  $publicServices .= $this->addService($id, $definition);
 672              } else {
 673                  $privateServices .= $this->addService($id, $definition);
 674              }
 675  
 676              $synchronizers .= $this->addServiceSynchronizer($id, $definition);
 677          }
 678  
 679          return $publicServices.$synchronizers.$privateServices;
 680      }
 681  
 682      /**
 683       * Adds synchronizer methods.
 684       *
 685       * @param string     $id         A service identifier
 686       * @param Definition $definition A Definition instance
 687       *
 688       * @return string|null
 689       *
 690       * @deprecated since version 2.7, will be removed in 3.0.
 691       */
 692      private function addServiceSynchronizer($id, Definition $definition)
 693      {
 694          if (!$definition->isSynchronized(false)) {
 695              return;
 696          }
 697  
 698          if ('request' !== $id) {
 699              @trigger_error('Synchronized services were deprecated in version 2.7 and won\'t work anymore in 3.0.', E_USER_DEPRECATED);
 700          }
 701  
 702          $code = '';
 703          foreach ($this->container->getDefinitions() as $definitionId => $definition) {
 704              foreach ($definition->getMethodCalls() as $call) {
 705                  foreach ($call[1] as $argument) {
 706                      if ($argument instanceof Reference && $id == (string) $argument) {
 707                          $arguments = array();
 708                          foreach ($call[1] as $value) {
 709                              $arguments[] = $this->dumpValue($value);
 710                          }
 711  
 712                          $definitionId = var_export($definitionId, true);
 713                          $call = $this->wrapServiceConditionals($call[1], sprintf('$this->get(%s)->%s(%s);', $definitionId, $call[0], implode(', ', $arguments)));
 714  
 715                          $code .= <<<EOF
 716          if (\$this->initialized($definitionId)) {
 717              $call
 718          }
 719  
 720  EOF;
 721                      }
 722                  }
 723              }
 724          }
 725  
 726          if (!$code) {
 727              return;
 728          }
 729  
 730          return <<<EOF
 731  
 732      /*{$this->docStar}
 733       * Updates the '$id' service.
 734       */
 735      protected function synchronize{$this->camelize($id)}Service()
 736      {
 737  $code    }
 738  
 739  EOF;
 740      }
 741  
 742      private function addNewInstance($id, Definition $definition, $return, $instantiation)
 743      {
 744          $class = $this->dumpValue($definition->getClass());
 745  
 746          $arguments = array();
 747          foreach ($definition->getArguments() as $value) {
 748              $arguments[] = $this->dumpValue($value);
 749          }
 750  
 751          if (null !== $definition->getFactory()) {
 752              $callable = $definition->getFactory();
 753              if (\is_array($callable)) {
 754                  if (!preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $callable[1])) {
 755                      throw new RuntimeException(sprintf('Cannot dump definition because of invalid factory method (%s)', $callable[1] ?: 'n/a'));
 756                  }
 757  
 758                  if ($callable[0] instanceof Reference
 759                      || ($callable[0] instanceof Definition && $this->definitionVariables->contains($callable[0]))) {
 760                      return sprintf("        $return{$instantiation}%s->%s(%s);\n", $this->dumpValue($callable[0]), $callable[1], $arguments ? implode(', ', $arguments) : '');
 761                  }
 762  
 763                  $class = $this->dumpValue($callable[0]);
 764                  // If the class is a string we can optimize call_user_func away
 765                  if (0 === strpos($class, "'")) {
 766                      return sprintf("        $return{$instantiation}%s::%s(%s);\n", $this->dumpLiteralClass($class), $callable[1], $arguments ? implode(', ', $arguments) : '');
 767                  }
 768  
 769                  return sprintf("        $return{$instantiation}call_user_func(array(%s, '%s')%s);\n", $this->dumpValue($callable[0]), $callable[1], $arguments ? ', '.implode(', ', $arguments) : '');
 770              }
 771  
 772              return sprintf("        $return{$instantiation}\\%s(%s);\n", $callable, $arguments ? implode(', ', $arguments) : '');
 773          } elseif (null !== $definition->getFactoryMethod(false)) {
 774              if (null !== $definition->getFactoryClass(false)) {
 775                  $class = $this->dumpValue($definition->getFactoryClass(false));
 776  
 777                  // If the class is a string we can optimize call_user_func away
 778                  if (0 === strpos($class, "'")) {
 779                      return sprintf("        $return{$instantiation}%s::%s(%s);\n", $this->dumpLiteralClass($class), $definition->getFactoryMethod(false), $arguments ? implode(', ', $arguments) : '');
 780                  }
 781  
 782                  return sprintf("        $return{$instantiation}call_user_func(array(%s, '%s')%s);\n", $this->dumpValue($definition->getFactoryClass(false)), $definition->getFactoryMethod(false), $arguments ? ', '.implode(', ', $arguments) : '');
 783              }
 784  
 785              if (null !== $definition->getFactoryService(false)) {
 786                  return sprintf("        $return{$instantiation}%s->%s(%s);\n", $this->getServiceCall($definition->getFactoryService(false)), $definition->getFactoryMethod(false), implode(', ', $arguments));
 787              }
 788  
 789              throw new RuntimeException(sprintf('Factory method requires a factory service or factory class in service definition for %s', $id));
 790          }
 791  
 792          if (false !== strpos($class, '$')) {
 793              return sprintf("        \$class = %s;\n\n        $return{$instantiation}new \$class(%s);\n", $class, implode(', ', $arguments));
 794          }
 795  
 796          return sprintf("        $return{$instantiation}new %s(%s);\n", $this->dumpLiteralClass($class), implode(', ', $arguments));
 797      }
 798  
 799      /**
 800       * Adds the class headers.
 801       *
 802       * @param string $class     Class name
 803       * @param string $baseClass The name of the base class
 804       * @param string $namespace The class namespace
 805       *
 806       * @return string
 807       */
 808      private function startClass($class, $baseClass, $namespace)
 809      {
 810          $bagClass = $this->container->isFrozen() ? 'use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;' : 'use Symfony\Component\DependencyInjection\ParameterBag\\ParameterBag;';
 811          $namespaceLine = $namespace ? "\nnamespace $namespace;\n" : '';
 812  
 813          return <<<EOF
 814  <?php
 815  $namespaceLine
 816  use Symfony\Component\DependencyInjection\ContainerInterface;
 817  use Symfony\Component\DependencyInjection\Container;
 818  use Symfony\Component\DependencyInjection\Exception\InactiveScopeException;
 819  use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
 820  use Symfony\Component\DependencyInjection\Exception\LogicException;
 821  use Symfony\Component\DependencyInjection\Exception\RuntimeException;
 822  $bagClass
 823  
 824  /*{$this->docStar}
 825   * This class has been auto-generated
 826   * by the Symfony Dependency Injection Component.
 827   */
 828  class $class extends $baseClass
 829  {
 830      private \$parameters;
 831      private \$targetDirs = array();
 832  
 833  EOF;
 834      }
 835  
 836      /**
 837       * Adds the constructor.
 838       *
 839       * @return string
 840       */
 841      private function addConstructor()
 842      {
 843          $targetDirs = $this->exportTargetDirs();
 844          $arguments = $this->container->getParameterBag()->all() ? 'new ParameterBag($this->getDefaultParameters())' : null;
 845  
 846          $code = <<<EOF
 847  
 848      public function __construct()
 849      {{$targetDirs}
 850          parent::__construct($arguments);
 851  
 852  EOF;
 853  
 854          if (\count($scopes = $this->container->getScopes(false)) > 0) {
 855              $code .= "\n";
 856              $code .= '        $this->scopes = '.$this->dumpValue($scopes).";\n";
 857              $code .= '        $this->scopeChildren = '.$this->dumpValue($this->container->getScopeChildren(false)).";\n";
 858          }
 859  
 860          $code .= $this->addMethodMap();
 861          $code .= $this->addAliases();
 862  
 863          $code .= <<<'EOF'
 864      }
 865  
 866  EOF;
 867  
 868          return $code;
 869      }
 870  
 871      /**
 872       * Adds the constructor for a frozen container.
 873       *
 874       * @return string
 875       */
 876      private function addFrozenConstructor()
 877      {
 878          $targetDirs = $this->exportTargetDirs();
 879  
 880          $code = <<<EOF
 881  
 882      public function __construct()
 883      {{$targetDirs}
 884  EOF;
 885  
 886          if ($this->container->getParameterBag()->all()) {
 887              $code .= "\n        \$this->parameters = \$this->getDefaultParameters();\n";
 888          }
 889  
 890          $code .= <<<'EOF'
 891  
 892          $this->services =
 893          $this->scopedServices =
 894          $this->scopeStacks = array();
 895  EOF;
 896  
 897          $code .= "\n";
 898          if (\count($scopes = $this->container->getScopes(false)) > 0) {
 899              $code .= '        $this->scopes = '.$this->dumpValue($scopes).";\n";
 900              $code .= '        $this->scopeChildren = '.$this->dumpValue($this->container->getScopeChildren(false)).";\n";
 901          } else {
 902              $code .= "        \$this->scopes = array();\n";
 903              $code .= "        \$this->scopeChildren = array();\n";
 904          }
 905  
 906          $code .= $this->addMethodMap();
 907          $code .= $this->addAliases();
 908  
 909          $code .= <<<'EOF'
 910      }
 911  
 912  EOF;
 913  
 914          return $code;
 915      }
 916  
 917      /**
 918       * Adds the constructor for a frozen container.
 919       *
 920       * @return string
 921       */
 922      private function addFrozenCompile()
 923      {
 924          return <<<EOF
 925  
 926      /*{$this->docStar}
 927       * {@inheritdoc}
 928       */
 929      public function compile()
 930      {
 931          throw new LogicException('You cannot compile a dumped frozen container.');
 932      }
 933  
 934  EOF;
 935      }
 936  
 937      /**
 938       * Adds the isFrozen method for a frozen container.
 939       *
 940       * @return string
 941       */
 942      private function addIsFrozenMethod()
 943      {
 944          return <<<EOF
 945  
 946      /*{$this->docStar}
 947       * {@inheritdoc}
 948       */
 949      public function isFrozen()
 950      {
 951          return true;
 952      }
 953  
 954  EOF;
 955      }
 956  
 957      /**
 958       * Adds the methodMap property definition.
 959       *
 960       * @return string
 961       */
 962      private function addMethodMap()
 963      {
 964          if (!$definitions = $this->container->getDefinitions()) {
 965              return '';
 966          }
 967  
 968          $code = "        \$this->methodMap = array(\n";
 969          ksort($definitions);
 970          foreach ($definitions as $id => $definition) {
 971              $code .= '            '.var_export($id, true).' => '.var_export('get'.$this->camelize($id).'Service', true).",\n";
 972          }
 973  
 974          return $code."        );\n";
 975      }
 976  
 977      /**
 978       * Adds the aliases property definition.
 979       *
 980       * @return string
 981       */
 982      private function addAliases()
 983      {
 984          if (!$aliases = $this->container->getAliases()) {
 985              return $this->container->isFrozen() ? "\n        \$this->aliases = array();\n" : '';
 986          }
 987  
 988          $code = "        \$this->aliases = array(\n";
 989          ksort($aliases);
 990          foreach ($aliases as $alias => $id) {
 991              $id = (string) $id;
 992              while (isset($aliases[$id])) {
 993                  $id = (string) $aliases[$id];
 994              }
 995              $code .= '            '.var_export($alias, true).' => '.var_export($id, true).",\n";
 996          }
 997  
 998          return $code."        );\n";
 999      }
1000  
1001      /**
1002       * Adds default parameters method.
1003       *
1004       * @return string
1005       */
1006      private function addDefaultParametersMethod()
1007      {
1008          if (!$this->container->getParameterBag()->all()) {
1009              return '';
1010          }
1011  
1012          $parameters = $this->exportParameters($this->container->getParameterBag()->all());
1013  
1014          $code = '';
1015          if ($this->container->isFrozen()) {
1016              $code .= <<<'EOF'
1017  
1018      /**
1019       * {@inheritdoc}
1020       */
1021      public function getParameter($name)
1022      {
1023          $name = strtolower($name);
1024  
1025          if (!(isset($this->parameters[$name]) || array_key_exists($name, $this->parameters))) {
1026              throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name));
1027          }
1028  
1029          return $this->parameters[$name];
1030      }
1031  
1032      /**
1033       * {@inheritdoc}
1034       */
1035      public function hasParameter($name)
1036      {
1037          $name = strtolower($name);
1038  
1039          return isset($this->parameters[$name]) || array_key_exists($name, $this->parameters);
1040      }
1041  
1042      /**
1043       * {@inheritdoc}
1044       */
1045      public function setParameter($name, $value)
1046      {
1047          throw new LogicException('Impossible to call set() on a frozen ParameterBag.');
1048      }
1049  
1050      /**
1051       * {@inheritdoc}
1052       */
1053      public function getParameterBag()
1054      {
1055          if (null === $this->parameterBag) {
1056              $this->parameterBag = new FrozenParameterBag($this->parameters);
1057          }
1058  
1059          return $this->parameterBag;
1060      }
1061  
1062  EOF;
1063              if ('' === $this->docStar) {
1064                  $code = str_replace('/**', '/*', $code);
1065              }
1066          }
1067  
1068          $code .= <<<EOF
1069  
1070      /*{$this->docStar}
1071       * Gets the default parameters.
1072       *
1073       * @return array An array of the default parameters
1074       */
1075      protected function getDefaultParameters()
1076      {
1077          return $parameters;
1078      }
1079  
1080  EOF;
1081  
1082          return $code;
1083      }
1084  
1085      /**
1086       * Exports parameters.
1087       *
1088       * @param array  $parameters
1089       * @param string $path
1090       * @param int    $indent
1091       *
1092       * @return string
1093       *
1094       * @throws InvalidArgumentException
1095       */
1096      private function exportParameters(array $parameters, $path = '', $indent = 12)
1097      {
1098          $php = array();
1099          foreach ($parameters as $key => $value) {
1100              if (\is_array($value)) {
1101                  $value = $this->exportParameters($value, $path.'/'.$key, $indent + 4);
1102              } elseif ($value instanceof Variable) {
1103                  throw new InvalidArgumentException(sprintf('You cannot dump a container with parameters that contain variable references. Variable "%s" found in "%s".', $value, $path.'/'.$key));
1104              } elseif ($value instanceof Definition) {
1105                  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));
1106              } elseif ($value instanceof Reference) {
1107                  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));
1108              } elseif ($value instanceof Expression) {
1109                  throw new InvalidArgumentException(sprintf('You cannot dump a container with parameters that contain expressions. Expression "%s" found in "%s".', $value, $path.'/'.$key));
1110              } else {
1111                  $value = $this->export($value);
1112              }
1113  
1114              $php[] = sprintf('%s%s => %s,', str_repeat(' ', $indent), var_export($key, true), $value);
1115          }
1116  
1117          return sprintf("array(\n%s\n%s)", implode("\n", $php), str_repeat(' ', $indent - 4));
1118      }
1119  
1120      /**
1121       * Ends the class definition.
1122       *
1123       * @return string
1124       */
1125      private function endClass()
1126      {
1127          return <<<'EOF'
1128  }
1129  
1130  EOF;
1131      }
1132  
1133      /**
1134       * Wraps the service conditionals.
1135       *
1136       * @param string $value
1137       * @param string $code
1138       *
1139       * @return string
1140       */
1141      private function wrapServiceConditionals($value, $code)
1142      {
1143          if (!$services = ContainerBuilder::getServiceConditionals($value)) {
1144              return $code;
1145          }
1146  
1147          $conditions = array();
1148          foreach ($services as $service) {
1149              $conditions[] = sprintf('$this->has(%s)', var_export($service, true));
1150          }
1151  
1152          // re-indent the wrapped code
1153          $code = implode("\n", array_map(function ($line) { return $line ? '    '.$line : $line; }, explode("\n", $code)));
1154  
1155          return sprintf("        if (%s) {\n%s        }\n", implode(' && ', $conditions), $code);
1156      }
1157  
1158      /**
1159       * Builds service calls from arguments.
1160       */
1161      private function getServiceCallsFromArguments(array $arguments, array &$calls, array &$behavior)
1162      {
1163          foreach ($arguments as $argument) {
1164              if (\is_array($argument)) {
1165                  $this->getServiceCallsFromArguments($argument, $calls, $behavior);
1166              } elseif ($argument instanceof Reference) {
1167                  $id = (string) $argument;
1168  
1169                  if (!isset($calls[$id])) {
1170                      $calls[$id] = 0;
1171                  }
1172                  if (!isset($behavior[$id])) {
1173                      $behavior[$id] = $argument->getInvalidBehavior();
1174                  } elseif (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $behavior[$id]) {
1175                      $behavior[$id] = $argument->getInvalidBehavior();
1176                  }
1177  
1178                  ++$calls[$id];
1179              }
1180          }
1181      }
1182  
1183      /**
1184       * Returns the inline definition.
1185       *
1186       * @return array
1187       */
1188      private function getInlinedDefinitions(Definition $definition)
1189      {
1190          if (false === $this->inlinedDefinitions->contains($definition)) {
1191              $definitions = array_merge(
1192                  $this->getDefinitionsFromArguments($definition->getArguments()),
1193                  $this->getDefinitionsFromArguments($definition->getMethodCalls()),
1194                  $this->getDefinitionsFromArguments($definition->getProperties()),
1195                  $this->getDefinitionsFromArguments(array($definition->getConfigurator())),
1196                  $this->getDefinitionsFromArguments(array($definition->getFactory()))
1197              );
1198  
1199              $this->inlinedDefinitions->offsetSet($definition, $definitions);
1200  
1201              return $definitions;
1202          }
1203  
1204          return $this->inlinedDefinitions->offsetGet($definition);
1205      }
1206  
1207      /**
1208       * Gets the definition from arguments.
1209       *
1210       * @return array
1211       */
1212      private function getDefinitionsFromArguments(array $arguments)
1213      {
1214          $definitions = array();
1215          foreach ($arguments as $argument) {
1216              if (\is_array($argument)) {
1217                  $definitions = array_merge($definitions, $this->getDefinitionsFromArguments($argument));
1218              } elseif ($argument instanceof Definition) {
1219                  $definitions = array_merge(
1220                      $definitions,
1221                      $this->getInlinedDefinitions($argument),
1222                      array($argument)
1223                  );
1224              }
1225          }
1226  
1227          return $definitions;
1228      }
1229  
1230      /**
1231       * Checks if a service id has a reference.
1232       *
1233       * @param string $id
1234       * @param array  $arguments
1235       * @param bool   $deep
1236       * @param array  $visited
1237       *
1238       * @return bool
1239       */
1240      private function hasReference($id, array $arguments, $deep = false, array &$visited = array())
1241      {
1242          foreach ($arguments as $argument) {
1243              if (\is_array($argument)) {
1244                  if ($this->hasReference($id, $argument, $deep, $visited)) {
1245                      return true;
1246                  }
1247              } elseif ($argument instanceof Reference) {
1248                  $argumentId = (string) $argument;
1249                  if ($id === $argumentId) {
1250                      return true;
1251                  }
1252  
1253                  if ($deep && !isset($visited[$argumentId]) && 'service_container' !== $argumentId) {
1254                      $visited[$argumentId] = true;
1255  
1256                      $service = $this->container->getDefinition($argumentId);
1257  
1258                      // if the proxy manager is enabled, disable searching for references in lazy services,
1259                      // as these services will be instantiated lazily and don't have direct related references.
1260                      if ($service->isLazy() && !$this->getProxyDumper() instanceof NullDumper) {
1261                          continue;
1262                      }
1263  
1264                      $arguments = array_merge($service->getMethodCalls(), $service->getArguments(), $service->getProperties());
1265  
1266                      if ($this->hasReference($id, $arguments, $deep, $visited)) {
1267                          return true;
1268                      }
1269                  }
1270              }
1271          }
1272  
1273          return false;
1274      }
1275  
1276      /**
1277       * Dumps values.
1278       *
1279       * @param mixed $value
1280       * @param bool  $interpolate
1281       *
1282       * @return string
1283       *
1284       * @throws RuntimeException
1285       */
1286      private function dumpValue($value, $interpolate = true)
1287      {
1288          if (\is_array($value)) {
1289              $code = array();
1290              foreach ($value as $k => $v) {
1291                  $code[] = sprintf('%s => %s', $this->dumpValue($k, $interpolate), $this->dumpValue($v, $interpolate));
1292              }
1293  
1294              return sprintf('array(%s)', implode(', ', $code));
1295          } elseif ($value instanceof Definition) {
1296              if (null !== $this->definitionVariables && $this->definitionVariables->contains($value)) {
1297                  return $this->dumpValue($this->definitionVariables->offsetGet($value), $interpolate);
1298              }
1299              if ($value->getMethodCalls()) {
1300                  throw new RuntimeException('Cannot dump definitions which have method calls.');
1301              }
1302              if ($value->getProperties()) {
1303                  throw new RuntimeException('Cannot dump definitions which have properties.');
1304              }
1305              if (null !== $value->getConfigurator()) {
1306                  throw new RuntimeException('Cannot dump definitions which have a configurator.');
1307              }
1308  
1309              $arguments = array();
1310              foreach ($value->getArguments() as $argument) {
1311                  $arguments[] = $this->dumpValue($argument);
1312              }
1313  
1314              if (null !== $value->getFactory()) {
1315                  $factory = $value->getFactory();
1316  
1317                  if (\is_string($factory)) {
1318                      return sprintf('\\%s(%s)', $factory, implode(', ', $arguments));
1319                  }
1320  
1321                  if (\is_array($factory)) {
1322                      if (!preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $factory[1])) {
1323                          throw new RuntimeException(sprintf('Cannot dump definition because of invalid factory method (%s)', $factory[1] ?: 'n/a'));
1324                      }
1325  
1326                      if (\is_string($factory[0])) {
1327                          return sprintf('%s::%s(%s)', $this->dumpLiteralClass($this->dumpValue($factory[0])), $factory[1], implode(', ', $arguments));
1328                      }
1329  
1330                      if ($factory[0] instanceof Definition) {
1331                          return sprintf("call_user_func(array(%s, '%s')%s)", $this->dumpValue($factory[0]), $factory[1], \count($arguments) > 0 ? ', '.implode(', ', $arguments) : '');
1332                      }
1333  
1334                      if ($factory[0] instanceof Reference) {
1335                          return sprintf('%s->%s(%s)', $this->dumpValue($factory[0]), $factory[1], implode(', ', $arguments));
1336                      }
1337                  }
1338  
1339                  throw new RuntimeException('Cannot dump definition because of invalid factory');
1340              }
1341  
1342              if (null !== $value->getFactoryMethod(false)) {
1343                  if (null !== $value->getFactoryClass(false)) {
1344                      return sprintf("call_user_func(array(%s, '%s')%s)", $this->dumpValue($value->getFactoryClass(false)), $value->getFactoryMethod(false), \count($arguments) > 0 ? ', '.implode(', ', $arguments) : '');
1345                  } elseif (null !== $value->getFactoryService(false)) {
1346                      $service = $this->dumpValue($value->getFactoryService(false));
1347  
1348                      return sprintf('%s->%s(%s)', 0 === strpos($service, '$') ? sprintf('$this->get(%s)', $service) : $this->getServiceCall($value->getFactoryService(false)), $value->getFactoryMethod(false), implode(', ', $arguments));
1349                  }
1350  
1351                  throw new RuntimeException('Cannot dump definitions which have factory method without factory service or factory class.');
1352              }
1353  
1354              $class = $value->getClass();
1355              if (null === $class) {
1356                  throw new RuntimeException('Cannot dump definitions which have no class nor factory.');
1357              }
1358  
1359              return sprintf('new %s(%s)', $this->dumpLiteralClass($this->dumpValue($class)), implode(', ', $arguments));
1360          } elseif ($value instanceof Variable) {
1361              return '$'.$value;
1362          } elseif ($value instanceof Reference) {
1363              if (null !== $this->referenceVariables && isset($this->referenceVariables[$id = (string) $value])) {
1364                  return $this->dumpValue($this->referenceVariables[$id], $interpolate);
1365              }
1366  
1367              return $this->getServiceCall((string) $value, $value);
1368          } elseif ($value instanceof Expression) {
1369              return $this->getExpressionLanguage()->compile((string) $value, array('this' => 'container'));
1370          } elseif ($value instanceof Parameter) {
1371              return $this->dumpParameter($value);
1372          } elseif (true === $interpolate && \is_string($value)) {
1373              if (preg_match('/^%([^%]+)%$/', $value, $match)) {
1374                  // we do this to deal with non string values (Boolean, integer, ...)
1375                  // the preg_replace_callback converts them to strings
1376                  return $this->dumpParameter(strtolower($match[1]));
1377              } else {
1378                  $that = $this;
1379                  $replaceParameters = function ($match) use ($that) {
1380                      return "'.".$that->dumpParameter(strtolower($match[2])).".'";
1381                  };
1382  
1383                  $code = str_replace('%%', '%', preg_replace_callback('/(?<!%)(%)([^%]+)\1/', $replaceParameters, $this->export($value)));
1384  
1385                  return $code;
1386              }
1387          } elseif (\is_object($value) || \is_resource($value)) {
1388              throw new RuntimeException('Unable to dump a service container if a parameter is an object or a resource.');
1389          }
1390  
1391          return $this->export($value);
1392      }
1393  
1394      /**
1395       * Dumps a string to a literal (aka PHP Code) class value.
1396       *
1397       * @param string $class
1398       *
1399       * @return string
1400       *
1401       * @throws RuntimeException
1402       */
1403      private function dumpLiteralClass($class)
1404      {
1405          if (false !== strpos($class, '$')) {
1406              throw new RuntimeException('Cannot dump definitions which have a variable class name.');
1407          }
1408          if (0 !== strpos($class, "'") || !preg_match('/^\'(?:\\\{2})?[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(?:\\\{2}[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*\'$/', $class)) {
1409              throw new RuntimeException(sprintf('Cannot dump definition because of invalid class name (%s)', $class ?: 'n/a'));
1410          }
1411  
1412          $class = substr(str_replace('\\\\', '\\', $class), 1, -1);
1413  
1414          return 0 === strpos($class, '\\') ? $class : '\\'.$class;
1415      }
1416  
1417      /**
1418       * Dumps a parameter.
1419       *
1420       * @param string $name
1421       *
1422       * @return string
1423       */
1424      public function dumpParameter($name)
1425      {
1426          $name = (string) $name;
1427  
1428          if ($this->container->isFrozen() && $this->container->hasParameter($name)) {
1429              return $this->dumpValue($this->container->getParameter($name), false);
1430          }
1431  
1432          return sprintf('$this->getParameter(%s)', var_export($name, true));
1433      }
1434  
1435      /**
1436       * @deprecated since version 2.6.2, to be removed in 3.0.
1437       *             Use \Symfony\Component\DependencyInjection\ContainerBuilder::addExpressionLanguageProvider instead.
1438       *
1439       * @param ExpressionFunctionProviderInterface $provider
1440       */
1441      public function addExpressionLanguageProvider(ExpressionFunctionProviderInterface $provider)
1442      {
1443          @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.6.2 and will be removed in 3.0. Use the Symfony\Component\DependencyInjection\ContainerBuilder::addExpressionLanguageProvider method instead.', E_USER_DEPRECATED);
1444  
1445          $this->expressionLanguageProviders[] = $provider;
1446      }
1447  
1448      /**
1449       * Gets a service call.
1450       *
1451       * @param string    $id
1452       * @param Reference $reference
1453       *
1454       * @return string
1455       */
1456      private function getServiceCall($id, Reference $reference = null)
1457      {
1458          while ($this->container->hasAlias($id)) {
1459              $id = (string) $this->container->getAlias($id);
1460          }
1461  
1462          if ('service_container' === $id) {
1463              return '$this';
1464          }
1465  
1466          if (null !== $reference && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $reference->getInvalidBehavior()) {
1467              return sprintf('$this->get(%s, ContainerInterface::NULL_ON_INVALID_REFERENCE)', var_export($id, true));
1468          }
1469  
1470          return sprintf('$this->get(%s)', var_export($id, true));
1471      }
1472  
1473      /**
1474       * Convert a service id to a valid PHP method name.
1475       *
1476       * @param string $id
1477       *
1478       * @return string
1479       *
1480       * @throws InvalidArgumentException
1481       */
1482      private function camelize($id)
1483      {
1484          $name = Container::camelize($id);
1485  
1486          if (!preg_match('/^[a-zA-Z0-9_\x7f-\xff]+$/', $name)) {
1487              throw new InvalidArgumentException(sprintf('Service id "%s" cannot be converted to a valid PHP method name.', $id));
1488          }
1489  
1490          return $name;
1491      }
1492  
1493      /**
1494       * Returns the next name to use.
1495       *
1496       * @return string
1497       */
1498      private function getNextVariableName()
1499      {
1500          $firstChars = self::FIRST_CHARS;
1501          $firstCharsLength = \strlen($firstChars);
1502          $nonFirstChars = self::NON_FIRST_CHARS;
1503          $nonFirstCharsLength = \strlen($nonFirstChars);
1504  
1505          while (true) {
1506              $name = '';
1507              $i = $this->variableCount;
1508  
1509              if ('' === $name) {
1510                  $name .= $firstChars[$i % $firstCharsLength];
1511                  $i = (int) ($i / $firstCharsLength);
1512              }
1513  
1514              while ($i > 0) {
1515                  --$i;
1516                  $name .= $nonFirstChars[$i % $nonFirstCharsLength];
1517                  $i = (int) ($i / $nonFirstCharsLength);
1518              }
1519  
1520              ++$this->variableCount;
1521  
1522              // check that the name is not reserved
1523              if (\in_array($name, $this->reservedVariables, true)) {
1524                  continue;
1525              }
1526  
1527              return $name;
1528          }
1529      }
1530  
1531      private function getExpressionLanguage()
1532      {
1533          if (null === $this->expressionLanguage) {
1534              if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) {
1535                  throw new RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.');
1536              }
1537              $providers = array_merge($this->container->getExpressionLanguageProviders(), $this->expressionLanguageProviders);
1538              $this->expressionLanguage = new ExpressionLanguage(null, $providers);
1539  
1540              if ($this->container->isTrackingResources()) {
1541                  foreach ($providers as $provider) {
1542                      $this->container->addObjectResource($provider);
1543                  }
1544              }
1545          }
1546  
1547          return $this->expressionLanguage;
1548      }
1549  
1550      private function exportTargetDirs()
1551      {
1552          return null === $this->targetDirRegex ? '' : <<<EOF
1553  
1554          \$dir = __DIR__;
1555          for (\$i = 1; \$i <= {$this->targetDirMaxMatches}; ++\$i) {
1556              \$this->targetDirs[\$i] = \$dir = dirname(\$dir);
1557          }
1558  EOF;
1559      }
1560  
1561      private function export($value)
1562      {
1563          if (null !== $this->targetDirRegex && \is_string($value) && preg_match($this->targetDirRegex, $value, $matches, PREG_OFFSET_CAPTURE)) {
1564              $prefix = $matches[0][1] ? var_export(substr($value, 0, $matches[0][1]), true).'.' : '';
1565              $suffix = $matches[0][1] + \strlen($matches[0][0]);
1566              $suffix = isset($value[$suffix]) ? '.'.var_export(substr($value, $suffix), true) : '';
1567              $dirname = '__DIR__';
1568  
1569              if (0 < $offset = 1 + $this->targetDirMaxMatches - \count($matches)) {
1570                  $dirname = sprintf('$this->targetDirs[%d]', $offset);
1571              }
1572  
1573              if ($prefix || $suffix) {
1574                  return sprintf('(%s%s%s)', $prefix, $dirname, $suffix);
1575              }
1576  
1577              return $dirname;
1578          }
1579  
1580          if (\is_string($value) && false !== strpos($value, "\n")) {
1581              $cleanParts = explode("\n", $value);
1582              $cleanParts = array_map(function ($part) { return var_export($part, true); }, $cleanParts);
1583  
1584              return implode('."\n".', $cleanParts);
1585          }
1586  
1587          return var_export($value, true);
1588      }
1589  }


Generated: Tue Apr 7 19:42:26 2020 Cross-referenced by PHPXref 0.7.1