ReverseContainer.php 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\DependencyInjection;
  11. use Psr\Container\ContainerInterface;
  12. use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
  13. /**
  14. * Turns public and "container.reversible" services back to their ids.
  15. *
  16. * @author Nicolas Grekas <p@tchwork.com>
  17. */
  18. final class ReverseContainer
  19. {
  20. private $serviceContainer;
  21. private $reversibleLocator;
  22. private $tagName;
  23. private $getServiceId;
  24. public function __construct(Container $serviceContainer, ContainerInterface $reversibleLocator, string $tagName = 'container.reversible')
  25. {
  26. $this->serviceContainer = $serviceContainer;
  27. $this->reversibleLocator = $reversibleLocator;
  28. $this->tagName = $tagName;
  29. $this->getServiceId = \Closure::bind(function ($service): ?string {
  30. return array_search($service, $this->services, true) ?: array_search($service, $this->privates, true) ?: null;
  31. }, $serviceContainer, Container::class);
  32. }
  33. /**
  34. * Returns the id of the passed object when it exists as a service.
  35. *
  36. * To be reversible, services need to be either public or be tagged with "container.reversible".
  37. *
  38. * @param object $service
  39. */
  40. public function getId($service): ?string
  41. {
  42. if ($this->serviceContainer === $service) {
  43. return 'service_container';
  44. }
  45. if (null === $id = ($this->getServiceId)($service)) {
  46. return null;
  47. }
  48. if ($this->serviceContainer->has($id) || $this->reversibleLocator->has($id)) {
  49. return $id;
  50. }
  51. return null;
  52. }
  53. /**
  54. * @return object
  55. *
  56. * @throws ServiceNotFoundException When the service is not reversible
  57. */
  58. public function getService(string $id)
  59. {
  60. if ($this->serviceContainer->has($id)) {
  61. return $this->serviceContainer->get($id);
  62. }
  63. if ($this->reversibleLocator->has($id)) {
  64. return $this->reversibleLocator->get($id);
  65. }
  66. if (isset($this->serviceContainer->getRemovedIds()[$id])) {
  67. throw new ServiceNotFoundException($id, null, null, [], sprintf('The "%s" service is private and cannot be accessed by reference. You should either make it public, or tag it as "%s".', $id, $this->tagName));
  68. }
  69. // will throw a ServiceNotFoundException
  70. $this->serviceContainer->get($id);
  71. }
  72. }