[ 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; 13 14 use Symfony\Component\Config\Resource\FileResource; 15 use Symfony\Component\Config\Resource\ResourceInterface; 16 use Symfony\Component\DependencyInjection\Compiler\Compiler; 17 use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; 18 use Symfony\Component\DependencyInjection\Compiler\PassConfig; 19 use Symfony\Component\DependencyInjection\Exception\BadMethodCallException; 20 use Symfony\Component\DependencyInjection\Exception\InactiveScopeException; 21 use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; 22 use Symfony\Component\DependencyInjection\Exception\LogicException; 23 use Symfony\Component\DependencyInjection\Exception\RuntimeException; 24 use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException; 25 use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; 26 use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; 27 use Symfony\Component\DependencyInjection\LazyProxy\Instantiator\InstantiatorInterface; 28 use Symfony\Component\DependencyInjection\LazyProxy\Instantiator\RealServiceInstantiator; 29 use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; 30 use Symfony\Component\ExpressionLanguage\Expression; 31 use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface; 32 33 /** 34 * ContainerBuilder is a DI container that provides an API to easily describe services. 35 * 36 * @author Fabien Potencier <fabien@symfony.com> 37 */ 38 class ContainerBuilder extends Container implements TaggedContainerInterface 39 { 40 /** 41 * @var ExtensionInterface[] 42 */ 43 private $extensions = array(); 44 45 /** 46 * @var ExtensionInterface[] 47 */ 48 private $extensionsByNs = array(); 49 50 /** 51 * @var Definition[] 52 */ 53 private $definitions = array(); 54 55 /** 56 * @var Definition[] 57 */ 58 private $obsoleteDefinitions = array(); 59 60 /** 61 * @var Alias[] 62 */ 63 private $aliasDefinitions = array(); 64 65 /** 66 * @var ResourceInterface[] 67 */ 68 private $resources = array(); 69 70 private $extensionConfigs = array(); 71 72 /** 73 * @var Compiler 74 */ 75 private $compiler; 76 77 private $trackResources; 78 79 /** 80 * @var InstantiatorInterface|null 81 */ 82 private $proxyInstantiator; 83 84 /** 85 * @var ExpressionLanguage|null 86 */ 87 private $expressionLanguage; 88 89 /** 90 * @var ExpressionFunctionProviderInterface[] 91 */ 92 private $expressionLanguageProviders = array(); 93 94 public function __construct(ParameterBagInterface $parameterBag = null) 95 { 96 parent::__construct($parameterBag); 97 98 $this->trackResources = interface_exists('Symfony\Component\Config\Resource\ResourceInterface'); 99 } 100 101 /** 102 * @var string[] with tag names used by findTaggedServiceIds 103 */ 104 private $usedTags = array(); 105 106 /** 107 * Sets the track resources flag. 108 * 109 * If you are not using the loaders and therefore don't want 110 * to depend on the Config component, set this flag to false. 111 * 112 * @param bool $track True if you want to track resources, false otherwise 113 */ 114 public function setResourceTracking($track) 115 { 116 $this->trackResources = (bool) $track; 117 } 118 119 /** 120 * Checks if resources are tracked. 121 * 122 * @return bool true If resources are tracked, false otherwise 123 */ 124 public function isTrackingResources() 125 { 126 return $this->trackResources; 127 } 128 129 /** 130 * Sets the instantiator to be used when fetching proxies. 131 */ 132 public function setProxyInstantiator(InstantiatorInterface $proxyInstantiator) 133 { 134 $this->proxyInstantiator = $proxyInstantiator; 135 } 136 137 public function registerExtension(ExtensionInterface $extension) 138 { 139 $this->extensions[$extension->getAlias()] = $extension; 140 141 if (false !== $extension->getNamespace()) { 142 $this->extensionsByNs[$extension->getNamespace()] = $extension; 143 } 144 } 145 146 /** 147 * Returns an extension by alias or namespace. 148 * 149 * @param string $name An alias or a namespace 150 * 151 * @return ExtensionInterface An extension instance 152 * 153 * @throws LogicException if the extension is not registered 154 */ 155 public function getExtension($name) 156 { 157 if (isset($this->extensions[$name])) { 158 return $this->extensions[$name]; 159 } 160 161 if (isset($this->extensionsByNs[$name])) { 162 return $this->extensionsByNs[$name]; 163 } 164 165 throw new LogicException(sprintf('Container extension "%s" is not registered', $name)); 166 } 167 168 /** 169 * Returns all registered extensions. 170 * 171 * @return ExtensionInterface[] An array of ExtensionInterface 172 */ 173 public function getExtensions() 174 { 175 return $this->extensions; 176 } 177 178 /** 179 * Checks if we have an extension. 180 * 181 * @param string $name The name of the extension 182 * 183 * @return bool If the extension exists 184 */ 185 public function hasExtension($name) 186 { 187 return isset($this->extensions[$name]) || isset($this->extensionsByNs[$name]); 188 } 189 190 /** 191 * Returns an array of resources loaded to build this configuration. 192 * 193 * @return ResourceInterface[] An array of resources 194 */ 195 public function getResources() 196 { 197 return array_unique($this->resources); 198 } 199 200 /** 201 * @return $this 202 */ 203 public function addResource(ResourceInterface $resource) 204 { 205 if (!$this->trackResources) { 206 return $this; 207 } 208 209 $this->resources[] = $resource; 210 211 return $this; 212 } 213 214 /** 215 * Sets the resources for this configuration. 216 * 217 * @param ResourceInterface[] $resources An array of resources 218 * 219 * @return $this 220 */ 221 public function setResources(array $resources) 222 { 223 if (!$this->trackResources) { 224 return $this; 225 } 226 227 $this->resources = $resources; 228 229 return $this; 230 } 231 232 /** 233 * Adds the object class hierarchy as resources. 234 * 235 * @param object $object An object instance 236 * 237 * @return $this 238 */ 239 public function addObjectResource($object) 240 { 241 if ($this->trackResources) { 242 $this->addClassResource(new \ReflectionClass($object)); 243 } 244 245 return $this; 246 } 247 248 /** 249 * Adds the given class hierarchy as resources. 250 * 251 * @return $this 252 */ 253 public function addClassResource(\ReflectionClass $class) 254 { 255 if (!$this->trackResources) { 256 return $this; 257 } 258 259 do { 260 if (is_file($class->getFileName())) { 261 $this->addResource(new FileResource($class->getFileName())); 262 } 263 } while ($class = $class->getParentClass()); 264 265 return $this; 266 } 267 268 /** 269 * Loads the configuration for an extension. 270 * 271 * @param string $extension The extension alias or namespace 272 * @param array $values An array of values that customizes the extension 273 * 274 * @return $this 275 * 276 * @throws BadMethodCallException When this ContainerBuilder is frozen 277 * @throws \LogicException if the container is frozen 278 */ 279 public function loadFromExtension($extension, array $values = null) 280 { 281 if ($this->isFrozen()) { 282 throw new BadMethodCallException('Cannot load from an extension on a frozen container.'); 283 } 284 285 if (\func_num_args() < 2) { 286 $values = array(); 287 } 288 289 $namespace = $this->getExtension($extension)->getAlias(); 290 291 $this->extensionConfigs[$namespace][] = $values; 292 293 return $this; 294 } 295 296 /** 297 * Adds a compiler pass. 298 * 299 * @param CompilerPassInterface $pass A compiler pass 300 * @param string $type The type of compiler pass 301 * 302 * @return $this 303 */ 304 public function addCompilerPass(CompilerPassInterface $pass, $type = PassConfig::TYPE_BEFORE_OPTIMIZATION) 305 { 306 $this->getCompiler()->addPass($pass, $type); 307 308 $this->addObjectResource($pass); 309 310 return $this; 311 } 312 313 /** 314 * Returns the compiler pass config which can then be modified. 315 * 316 * @return PassConfig The compiler pass config 317 */ 318 public function getCompilerPassConfig() 319 { 320 return $this->getCompiler()->getPassConfig(); 321 } 322 323 /** 324 * Returns the compiler. 325 * 326 * @return Compiler The compiler 327 */ 328 public function getCompiler() 329 { 330 if (null === $this->compiler) { 331 $this->compiler = new Compiler(); 332 } 333 334 return $this->compiler; 335 } 336 337 /** 338 * Returns all Scopes. 339 * 340 * @return array An array of scopes 341 * 342 * @deprecated since version 2.8, to be removed in 3.0. 343 */ 344 public function getScopes($triggerDeprecationError = true) 345 { 346 if ($triggerDeprecationError) { 347 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED); 348 } 349 350 return $this->scopes; 351 } 352 353 /** 354 * Returns all Scope children. 355 * 356 * @return array An array of scope children 357 * 358 * @deprecated since version 2.8, to be removed in 3.0. 359 */ 360 public function getScopeChildren($triggerDeprecationError = true) 361 { 362 if ($triggerDeprecationError) { 363 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED); 364 } 365 366 return $this->scopeChildren; 367 } 368 369 /** 370 * Sets a service. 371 * 372 * Note: The $scope parameter is deprecated since version 2.8 and will be removed in 3.0. 373 * 374 * @param string $id The service identifier 375 * @param object $service The service instance 376 * @param string $scope The scope 377 * 378 * @throws BadMethodCallException When this ContainerBuilder is frozen 379 */ 380 public function set($id, $service, $scope = self::SCOPE_CONTAINER) 381 { 382 $id = strtolower($id); 383 $set = isset($this->definitions[$id]); 384 385 if ($this->isFrozen() && ($set || isset($this->obsoleteDefinitions[$id])) && !$this->{$set ? 'definitions' : 'obsoleteDefinitions'}[$id]->isSynthetic()) { 386 // setting a synthetic service on a frozen container is alright 387 throw new BadMethodCallException(sprintf('Setting service "%s" on a frozen container is not allowed.', $id)); 388 } 389 390 if ($set) { 391 $this->obsoleteDefinitions[$id] = $this->definitions[$id]; 392 } 393 394 unset($this->definitions[$id], $this->aliasDefinitions[$id]); 395 396 parent::set($id, $service, $scope); 397 398 if (isset($this->obsoleteDefinitions[$id]) && $this->obsoleteDefinitions[$id]->isSynchronized(false)) { 399 $this->synchronize($id); 400 } 401 } 402 403 /** 404 * Removes a service definition. 405 * 406 * @param string $id The service identifier 407 */ 408 public function removeDefinition($id) 409 { 410 unset($this->definitions[strtolower($id)]); 411 } 412 413 /** 414 * Returns true if the given service is defined. 415 * 416 * @param string $id The service identifier 417 * 418 * @return bool true if the service is defined, false otherwise 419 */ 420 public function has($id) 421 { 422 $id = strtolower($id); 423 424 return isset($this->definitions[$id]) || isset($this->aliasDefinitions[$id]) || parent::has($id); 425 } 426 427 /** 428 * Gets a service. 429 * 430 * @param string $id The service identifier 431 * @param int $invalidBehavior The behavior when the service does not exist 432 * 433 * @return object The associated service 434 * 435 * @throws InvalidArgumentException when no definitions are available 436 * @throws ServiceCircularReferenceException When a circular reference is detected 437 * @throws ServiceNotFoundException When the service is not defined 438 * @throws \Exception 439 * 440 * @see Reference 441 */ 442 public function get($id, $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE) 443 { 444 $id = strtolower($id); 445 446 if ($service = parent::get($id, ContainerInterface::NULL_ON_INVALID_REFERENCE)) { 447 return $service; 448 } 449 450 if (!array_key_exists($id, $this->definitions) && isset($this->aliasDefinitions[$id])) { 451 return $this->get((string) $this->aliasDefinitions[$id], $invalidBehavior); 452 } 453 454 try { 455 $definition = $this->getDefinition($id); 456 } catch (ServiceNotFoundException $e) { 457 if (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $invalidBehavior) { 458 return; 459 } 460 461 throw $e; 462 } 463 464 $this->loading[$id] = true; 465 466 try { 467 $service = $this->createService($definition, new \SplObjectStorage(), $id); 468 } catch (\Exception $e) { 469 unset($this->loading[$id]); 470 471 if ($e instanceof InactiveScopeException && self::EXCEPTION_ON_INVALID_REFERENCE !== $invalidBehavior) { 472 return; 473 } 474 475 throw $e; 476 } catch (\Throwable $e) { 477 unset($this->loading[$id]); 478 479 throw $e; 480 } 481 482 unset($this->loading[$id]); 483 484 return $service; 485 } 486 487 /** 488 * Merges a ContainerBuilder with the current ContainerBuilder configuration. 489 * 490 * Service definitions overrides the current defined ones. 491 * 492 * But for parameters, they are overridden by the current ones. It allows 493 * the parameters passed to the container constructor to have precedence 494 * over the loaded ones. 495 * 496 * $container = new ContainerBuilder(new ParameterBag(array('foo' => 'bar'))); 497 * $loader = new LoaderXXX($container); 498 * $loader->load('resource_name'); 499 * $container->register('foo', 'stdClass'); 500 * 501 * In the above example, even if the loaded resource defines a foo 502 * parameter, the value will still be 'bar' as defined in the ContainerBuilder 503 * constructor. 504 * 505 * @throws BadMethodCallException When this ContainerBuilder is frozen 506 */ 507 public function merge(ContainerBuilder $container) 508 { 509 if ($this->isFrozen()) { 510 throw new BadMethodCallException('Cannot merge on a frozen container.'); 511 } 512 513 $this->addDefinitions($container->getDefinitions()); 514 $this->addAliases($container->getAliases()); 515 $this->getParameterBag()->add($container->getParameterBag()->all()); 516 517 if ($this->trackResources) { 518 foreach ($container->getResources() as $resource) { 519 $this->addResource($resource); 520 } 521 } 522 523 foreach ($this->extensions as $name => $extension) { 524 if (!isset($this->extensionConfigs[$name])) { 525 $this->extensionConfigs[$name] = array(); 526 } 527 528 $this->extensionConfigs[$name] = array_merge($this->extensionConfigs[$name], $container->getExtensionConfig($name)); 529 } 530 } 531 532 /** 533 * Returns the configuration array for the given extension. 534 * 535 * @param string $name The name of the extension 536 * 537 * @return array An array of configuration 538 */ 539 public function getExtensionConfig($name) 540 { 541 if (!isset($this->extensionConfigs[$name])) { 542 $this->extensionConfigs[$name] = array(); 543 } 544 545 return $this->extensionConfigs[$name]; 546 } 547 548 /** 549 * Prepends a config array to the configs of the given extension. 550 * 551 * @param string $name The name of the extension 552 * @param array $config The config to set 553 */ 554 public function prependExtensionConfig($name, array $config) 555 { 556 if (!isset($this->extensionConfigs[$name])) { 557 $this->extensionConfigs[$name] = array(); 558 } 559 560 array_unshift($this->extensionConfigs[$name], $config); 561 } 562 563 /** 564 * Compiles the container. 565 * 566 * This method passes the container to compiler 567 * passes whose job is to manipulate and optimize 568 * the container. 569 * 570 * The main compiler passes roughly do four things: 571 * 572 * * The extension configurations are merged; 573 * * Parameter values are resolved; 574 * * The parameter bag is frozen; 575 * * Extension loading is disabled. 576 */ 577 public function compile() 578 { 579 $compiler = $this->getCompiler(); 580 581 if ($this->trackResources) { 582 foreach ($compiler->getPassConfig()->getPasses() as $pass) { 583 $this->addObjectResource($pass); 584 } 585 } 586 587 $compiler->compile($this); 588 589 if ($this->trackResources) { 590 foreach ($this->definitions as $definition) { 591 if ($definition->isLazy() && ($class = $definition->getClass()) && class_exists($class)) { 592 $this->addClassResource(new \ReflectionClass($class)); 593 } 594 } 595 } 596 597 $this->extensionConfigs = array(); 598 599 parent::compile(); 600 } 601 602 /** 603 * Gets all service ids. 604 * 605 * @return array An array of all defined service ids 606 */ 607 public function getServiceIds() 608 { 609 return array_unique(array_merge(array_keys($this->getDefinitions()), array_keys($this->aliasDefinitions), parent::getServiceIds())); 610 } 611 612 /** 613 * Adds the service aliases. 614 */ 615 public function addAliases(array $aliases) 616 { 617 foreach ($aliases as $alias => $id) { 618 $this->setAlias($alias, $id); 619 } 620 } 621 622 /** 623 * Sets the service aliases. 624 */ 625 public function setAliases(array $aliases) 626 { 627 $this->aliasDefinitions = array(); 628 $this->addAliases($aliases); 629 } 630 631 /** 632 * Sets an alias for an existing service. 633 * 634 * @param string $alias The alias to create 635 * @param string|Alias $id The service to alias 636 * 637 * @throws InvalidArgumentException if the id is not a string or an Alias 638 * @throws InvalidArgumentException if the alias is for itself 639 */ 640 public function setAlias($alias, $id) 641 { 642 $alias = strtolower($alias); 643 644 if ('' === $alias || '\\' === substr($alias, -1) || \strlen($alias) !== strcspn($alias, "\0\r\n'")) { 645 throw new InvalidArgumentException(sprintf('Invalid alias id: "%s"', $alias)); 646 } 647 648 if (\is_string($id)) { 649 $id = new Alias($id); 650 } elseif (!$id instanceof Alias) { 651 throw new InvalidArgumentException('$id must be a string, or an Alias object.'); 652 } 653 654 if ($alias === (string) $id) { 655 throw new InvalidArgumentException(sprintf('An alias can not reference itself, got a circular reference on "%s".', $alias)); 656 } 657 658 unset($this->definitions[$alias]); 659 660 $this->aliasDefinitions[$alias] = $id; 661 } 662 663 /** 664 * Removes an alias. 665 * 666 * @param string $alias The alias to remove 667 */ 668 public function removeAlias($alias) 669 { 670 unset($this->aliasDefinitions[strtolower($alias)]); 671 } 672 673 /** 674 * Returns true if an alias exists under the given identifier. 675 * 676 * @param string $id The service identifier 677 * 678 * @return bool true if the alias exists, false otherwise 679 */ 680 public function hasAlias($id) 681 { 682 return isset($this->aliasDefinitions[strtolower($id)]); 683 } 684 685 /** 686 * Gets all defined aliases. 687 * 688 * @return Alias[] An array of aliases 689 */ 690 public function getAliases() 691 { 692 return $this->aliasDefinitions; 693 } 694 695 /** 696 * Gets an alias. 697 * 698 * @param string $id The service identifier 699 * 700 * @return Alias An Alias instance 701 * 702 * @throws InvalidArgumentException if the alias does not exist 703 */ 704 public function getAlias($id) 705 { 706 $id = strtolower($id); 707 708 if (!isset($this->aliasDefinitions[$id])) { 709 throw new InvalidArgumentException(sprintf('The service alias "%s" does not exist.', $id)); 710 } 711 712 return $this->aliasDefinitions[$id]; 713 } 714 715 /** 716 * Registers a service definition. 717 * 718 * This methods allows for simple registration of service definition 719 * with a fluid interface. 720 * 721 * @param string $id The service identifier 722 * @param string $class|null The service class 723 * 724 * @return Definition A Definition instance 725 */ 726 public function register($id, $class = null) 727 { 728 return $this->setDefinition($id, new Definition($class)); 729 } 730 731 /** 732 * Adds the service definitions. 733 * 734 * @param Definition[] $definitions An array of service definitions 735 */ 736 public function addDefinitions(array $definitions) 737 { 738 foreach ($definitions as $id => $definition) { 739 $this->setDefinition($id, $definition); 740 } 741 } 742 743 /** 744 * Sets the service definitions. 745 * 746 * @param Definition[] $definitions An array of service definitions 747 */ 748 public function setDefinitions(array $definitions) 749 { 750 $this->definitions = array(); 751 $this->addDefinitions($definitions); 752 } 753 754 /** 755 * Gets all service definitions. 756 * 757 * @return Definition[] An array of Definition instances 758 */ 759 public function getDefinitions() 760 { 761 return $this->definitions; 762 } 763 764 /** 765 * Sets a service definition. 766 * 767 * @param string $id The service identifier 768 * @param Definition $definition A Definition instance 769 * 770 * @return Definition the service definition 771 * 772 * @throws BadMethodCallException When this ContainerBuilder is frozen 773 */ 774 public function setDefinition($id, Definition $definition) 775 { 776 if ($this->isFrozen()) { 777 throw new BadMethodCallException('Adding definition to a frozen container is not allowed'); 778 } 779 780 $id = strtolower($id); 781 782 if ('' === $id || '\\' === substr($id, -1) || \strlen($id) !== strcspn($id, "\0\r\n'")) { 783 throw new InvalidArgumentException(sprintf('Invalid service id: "%s"', $id)); 784 } 785 786 unset($this->aliasDefinitions[$id]); 787 788 return $this->definitions[$id] = $definition; 789 } 790 791 /** 792 * Returns true if a service definition exists under the given identifier. 793 * 794 * @param string $id The service identifier 795 * 796 * @return bool true if the service definition exists, false otherwise 797 */ 798 public function hasDefinition($id) 799 { 800 return array_key_exists(strtolower($id), $this->definitions); 801 } 802 803 /** 804 * Gets a service definition. 805 * 806 * @param string $id The service identifier 807 * 808 * @return Definition A Definition instance 809 * 810 * @throws ServiceNotFoundException if the service definition does not exist 811 */ 812 public function getDefinition($id) 813 { 814 $id = strtolower($id); 815 816 if (!array_key_exists($id, $this->definitions)) { 817 throw new ServiceNotFoundException($id); 818 } 819 820 return $this->definitions[$id]; 821 } 822 823 /** 824 * Gets a service definition by id or alias. 825 * 826 * The method "unaliases" recursively to return a Definition instance. 827 * 828 * @param string $id The service identifier or alias 829 * 830 * @return Definition A Definition instance 831 * 832 * @throws ServiceNotFoundException if the service definition does not exist 833 */ 834 public function findDefinition($id) 835 { 836 $id = strtolower($id); 837 838 while (isset($this->aliasDefinitions[$id])) { 839 $id = (string) $this->aliasDefinitions[$id]; 840 } 841 842 return $this->getDefinition($id); 843 } 844 845 /** 846 * Creates a service for a service definition. 847 * 848 * @param Definition $definition A service definition instance 849 * @param string $id The service identifier 850 * @param bool $tryProxy Whether to try proxying the service with a lazy proxy 851 * 852 * @return object The service described by the service definition 853 * 854 * @throws RuntimeException When the scope is inactive 855 * @throws RuntimeException When the factory definition is incomplete 856 * @throws RuntimeException When the service is a synthetic service 857 * @throws InvalidArgumentException When configure callable is not callable 858 * 859 * @internal this method is public because of PHP 5.3 limitations, do not use it explicitly in your code 860 */ 861 public function createService(Definition $definition, \SplObjectStorage $inlinedDefinitions, $id = null, $tryProxy = true) 862 { 863 if (null === $id && isset($inlinedDefinitions[$definition])) { 864 return $inlinedDefinitions[$definition]; 865 } 866 867 if ($definition instanceof DefinitionDecorator) { 868 throw new RuntimeException(sprintf('Constructing service "%s" from a parent definition is not supported at build time.', $id)); 869 } 870 871 if ($definition->isSynthetic()) { 872 throw new RuntimeException(sprintf('You have requested a synthetic service ("%s"). The DIC does not know how to construct this service.', $id)); 873 } 874 875 if ($definition->isDeprecated()) { 876 @trigger_error($definition->getDeprecationMessage($id), E_USER_DEPRECATED); 877 } 878 879 if ($tryProxy && $definition->isLazy()) { 880 $container = $this; 881 882 $proxy = $this 883 ->getProxyInstantiator() 884 ->instantiateProxy( 885 $container, 886 $definition, 887 $id, function () use ($definition, $inlinedDefinitions, $id, $container) { 888 return $container->createService($definition, $inlinedDefinitions, $id, false); 889 } 890 ); 891 $this->shareService($definition, $proxy, $id, $inlinedDefinitions); 892 893 return $proxy; 894 } 895 896 $parameterBag = $this->getParameterBag(); 897 898 if (null !== $definition->getFile()) { 899 require_once $parameterBag->resolveValue($definition->getFile()); 900 } 901 902 $arguments = $this->doResolveServices($parameterBag->unescapeValue($parameterBag->resolveValue($definition->getArguments())), $inlinedDefinitions); 903 904 if (null !== $factory = $definition->getFactory()) { 905 if (\is_array($factory)) { 906 $factory = array($this->doResolveServices($parameterBag->resolveValue($factory[0]), $inlinedDefinitions), $factory[1]); 907 } elseif (!\is_string($factory)) { 908 throw new RuntimeException(sprintf('Cannot create service "%s" because of invalid factory', $id)); 909 } 910 911 $service = \call_user_func_array($factory, $arguments); 912 913 if (!$definition->isDeprecated() && \is_array($factory) && \is_string($factory[0])) { 914 $r = new \ReflectionClass($factory[0]); 915 916 if (0 < strpos($r->getDocComment(), "\n * @deprecated ")) { 917 @trigger_error(sprintf('The "%s" service relies on the deprecated "%s" factory class. It should either be deprecated or its factory upgraded.', $id, $r->name), E_USER_DEPRECATED); 918 } 919 } 920 } elseif (null !== $definition->getFactoryMethod(false)) { 921 if (null !== $definition->getFactoryClass(false)) { 922 $factory = $parameterBag->resolveValue($definition->getFactoryClass(false)); 923 } elseif (null !== $definition->getFactoryService(false)) { 924 $factory = $this->get($parameterBag->resolveValue($definition->getFactoryService(false))); 925 } else { 926 throw new RuntimeException(sprintf('Cannot create service "%s" from factory method without a factory service or factory class.', $id)); 927 } 928 929 $service = \call_user_func_array(array($factory, $definition->getFactoryMethod(false)), $arguments); 930 } else { 931 $r = new \ReflectionClass($parameterBag->resolveValue($definition->getClass())); 932 933 $service = null === $r->getConstructor() ? $r->newInstance() : $r->newInstanceArgs($arguments); 934 935 if (!$definition->isDeprecated() && 0 < strpos($r->getDocComment(), "\n * @deprecated ")) { 936 @trigger_error(sprintf('The "%s" service relies on the deprecated "%s" class. It should either be deprecated or its implementation upgraded.', $id, $r->name), E_USER_DEPRECATED); 937 } 938 } 939 940 if ($tryProxy || !$definition->isLazy()) { 941 // share only if proxying failed, or if not a proxy 942 $this->shareService($definition, $service, $id, $inlinedDefinitions); 943 } 944 945 $properties = $this->doResolveServices($parameterBag->unescapeValue($parameterBag->resolveValue($definition->getProperties())), $inlinedDefinitions); 946 foreach ($properties as $name => $value) { 947 $service->$name = $value; 948 } 949 950 foreach ($definition->getMethodCalls() as $call) { 951 $this->callMethod($service, $call, $inlinedDefinitions); 952 } 953 954 if ($callable = $definition->getConfigurator()) { 955 if (\is_array($callable)) { 956 $callable[0] = $parameterBag->resolveValue($callable[0]); 957 958 if ($callable[0] instanceof Reference) { 959 $callable[0] = $this->get((string) $callable[0], $callable[0]->getInvalidBehavior()); 960 } elseif ($callable[0] instanceof Definition) { 961 $callable[0] = $this->createService($callable[0], $inlinedDefinitions); 962 } 963 } 964 965 if (!\is_callable($callable)) { 966 throw new InvalidArgumentException(sprintf('The configure callable for class "%s" is not a callable.', \get_class($service))); 967 } 968 969 \call_user_func($callable, $service); 970 } 971 972 return $service; 973 } 974 975 /** 976 * Replaces service references by the real service instance and evaluates expressions. 977 * 978 * @param mixed $value A value 979 * 980 * @return mixed The same value with all service references replaced by 981 * the real service instances and all expressions evaluated 982 */ 983 public function resolveServices($value) 984 { 985 return $this->doResolveServices($value, new \SplObjectStorage()); 986 } 987 988 private function doResolveServices($value, \SplObjectStorage $inlinedDefinitions) 989 { 990 if (\is_array($value)) { 991 foreach ($value as $k => $v) { 992 $value[$k] = $this->doResolveServices($v, $inlinedDefinitions); 993 } 994 } elseif ($value instanceof Reference) { 995 $value = $this->get((string) $value, $value->getInvalidBehavior()); 996 } elseif ($value instanceof Definition) { 997 $value = $this->createService($value, $inlinedDefinitions); 998 } elseif ($value instanceof Expression) { 999 $value = $this->getExpressionLanguage()->evaluate($value, array('container' => $this)); 1000 } 1001 1002 return $value; 1003 } 1004 1005 /** 1006 * Returns service ids for a given tag. 1007 * 1008 * Example: 1009 * 1010 * $container->register('foo')->addTag('my.tag', array('hello' => 'world')); 1011 * 1012 * $serviceIds = $container->findTaggedServiceIds('my.tag'); 1013 * foreach ($serviceIds as $serviceId => $tags) { 1014 * foreach ($tags as $tag) { 1015 * echo $tag['hello']; 1016 * } 1017 * } 1018 * 1019 * @param string $name The tag name 1020 * 1021 * @return array An array of tags with the tagged service as key, holding a list of attribute arrays 1022 */ 1023 public function findTaggedServiceIds($name) 1024 { 1025 $this->usedTags[] = $name; 1026 $tags = array(); 1027 foreach ($this->getDefinitions() as $id => $definition) { 1028 if ($definition->hasTag($name)) { 1029 $tags[$id] = $definition->getTag($name); 1030 } 1031 } 1032 1033 return $tags; 1034 } 1035 1036 /** 1037 * Returns all tags the defined services use. 1038 * 1039 * @return array An array of tags 1040 */ 1041 public function findTags() 1042 { 1043 $tags = array(); 1044 foreach ($this->getDefinitions() as $id => $definition) { 1045 $tags = array_merge(array_keys($definition->getTags()), $tags); 1046 } 1047 1048 return array_unique($tags); 1049 } 1050 1051 /** 1052 * Returns all tags not queried by findTaggedServiceIds. 1053 * 1054 * @return string[] An array of tags 1055 */ 1056 public function findUnusedTags() 1057 { 1058 return array_values(array_diff($this->findTags(), $this->usedTags)); 1059 } 1060 1061 public function addExpressionLanguageProvider(ExpressionFunctionProviderInterface $provider) 1062 { 1063 $this->expressionLanguageProviders[] = $provider; 1064 } 1065 1066 /** 1067 * @return ExpressionFunctionProviderInterface[] 1068 */ 1069 public function getExpressionLanguageProviders() 1070 { 1071 return $this->expressionLanguageProviders; 1072 } 1073 1074 /** 1075 * Returns the Service Conditionals. 1076 * 1077 * @param mixed $value An array of conditionals to return 1078 * 1079 * @return array An array of Service conditionals 1080 */ 1081 public static function getServiceConditionals($value) 1082 { 1083 $services = array(); 1084 1085 if (\is_array($value)) { 1086 foreach ($value as $v) { 1087 $services = array_unique(array_merge($services, self::getServiceConditionals($v))); 1088 } 1089 } elseif ($value instanceof Reference && ContainerInterface::IGNORE_ON_INVALID_REFERENCE === $value->getInvalidBehavior()) { 1090 $services[] = (string) $value; 1091 } 1092 1093 return $services; 1094 } 1095 1096 /** 1097 * Retrieves the currently set proxy instantiator or instantiates one. 1098 * 1099 * @return InstantiatorInterface 1100 */ 1101 private function getProxyInstantiator() 1102 { 1103 if (!$this->proxyInstantiator) { 1104 $this->proxyInstantiator = new RealServiceInstantiator(); 1105 } 1106 1107 return $this->proxyInstantiator; 1108 } 1109 1110 /** 1111 * Synchronizes a service change. 1112 * 1113 * This method updates all services that depend on the given 1114 * service by calling all methods referencing it. 1115 * 1116 * @param string $id A service id 1117 * 1118 * @deprecated since version 2.7, will be removed in 3.0. 1119 */ 1120 private function synchronize($id) 1121 { 1122 if ('request' !== $id) { 1123 @trigger_error('The '.__METHOD__.' method is deprecated in version 2.7 and will be removed in version 3.0.', E_USER_DEPRECATED); 1124 } 1125 1126 foreach ($this->definitions as $definitionId => $definition) { 1127 // only check initialized services 1128 if (!$this->initialized($definitionId)) { 1129 continue; 1130 } 1131 1132 foreach ($definition->getMethodCalls() as $call) { 1133 foreach ($call[1] as $argument) { 1134 if ($argument instanceof Reference && $id == (string) $argument) { 1135 $this->callMethod($this->get($definitionId), $call, new \SplObjectStorage()); 1136 } 1137 } 1138 } 1139 } 1140 } 1141 1142 private function callMethod($service, $call, \SplObjectStorage $inlinedDefinitions) 1143 { 1144 $services = self::getServiceConditionals($call[1]); 1145 1146 foreach ($services as $s) { 1147 if (!$this->has($s)) { 1148 return; 1149 } 1150 } 1151 1152 \call_user_func_array(array($service, $call[0]), $this->doResolveServices($this->getParameterBag()->unescapeValue($this->getParameterBag()->resolveValue($call[1])), $inlinedDefinitions)); 1153 } 1154 1155 /** 1156 * Shares a given service in the container. 1157 * 1158 * @param Definition $definition 1159 * @param mixed $service 1160 * @param string|null $id 1161 * 1162 * @throws InactiveScopeException 1163 */ 1164 private function shareService(Definition $definition, $service, $id, \SplObjectStorage $inlinedDefinitions) 1165 { 1166 if (!$definition->isShared() || self::SCOPE_PROTOTYPE === $scope = $definition->getScope(false)) { 1167 return; 1168 } 1169 if (null === $id) { 1170 $inlinedDefinitions[$definition] = $service; 1171 } else { 1172 if (self::SCOPE_CONTAINER !== $scope && !isset($this->scopedServices[$scope])) { 1173 throw new InactiveScopeException($id, $scope); 1174 } 1175 1176 $this->services[$lowerId = strtolower($id)] = $service; 1177 1178 if (self::SCOPE_CONTAINER !== $scope) { 1179 $this->scopedServices[$scope][$lowerId] = $service; 1180 } 1181 } 1182 } 1183 1184 private function getExpressionLanguage() 1185 { 1186 if (null === $this->expressionLanguage) { 1187 if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) { 1188 throw new RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.'); 1189 } 1190 $this->expressionLanguage = new ExpressionLanguage(null, $this->expressionLanguageProviders); 1191 } 1192 1193 return $this->expressionLanguage; 1194 } 1195 }
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 |