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