[ Index ] |
PHP Cross Reference of phpBB-3.2.11-deutsch |
[Summary view] [Print] [Text view]
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 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Nov 11 20:33:01 2020 | Cross-referenced by PHPXref 0.7.1 |