InterfaceInjector.php 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. <?php
  2. namespace Symfony\Component\DependencyInjection;
  3. use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
  4. /*
  5. * This file is part of the Symfony framework.
  6. *
  7. * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
  8. *
  9. * This source file is subject to the MIT license that is bundled
  10. * with this source code in the file LICENSE.
  11. */
  12. /**
  13. * InterfaceInjector is used for Interface Injection.
  14. *
  15. * @author Bulat Shakirzyanov <mallluhuct@gmail.com>
  16. */
  17. class InterfaceInjector
  18. {
  19. protected $class;
  20. protected $calls = array();
  21. protected $processedDefinitions = array();
  22. /**
  23. * Contructs interface injector by specifying the target class name
  24. *
  25. * @param string $class
  26. */
  27. public function __construct($class)
  28. {
  29. $this->class = $class;
  30. }
  31. /**
  32. * Returns the interface name
  33. *
  34. * @return string
  35. */
  36. public function getClass()
  37. {
  38. return $this->class;
  39. }
  40. /**
  41. * Adds method calls if Definition is of required interface
  42. *
  43. * @param Definition $definition
  44. * @return void
  45. */
  46. public function processDefinition(Definition $definition, $class = null)
  47. {
  48. if (in_array($definition, $this->processedDefinitions, true)) {
  49. return;
  50. }
  51. $class = $class ?: $definition->getClass();
  52. if (!$this->supports($class)) {
  53. return;
  54. }
  55. foreach ($this->calls as $callback) {
  56. list($method, $arguments) = $callback;
  57. $definition->addMethodCall($method, $arguments);
  58. }
  59. $this->processedDefinitions[] = $definition;
  60. }
  61. /**
  62. * Inspects if current interface injector is to be used with a given class
  63. *
  64. * @param string $object
  65. * @return boolean
  66. */
  67. public function supports($object)
  68. {
  69. if (is_string($object)) {
  70. $reflection = new \ReflectionClass($object);
  71. return $reflection->isSubClassOf($this->class)
  72. || $object === $this->class;
  73. }
  74. if ( ! is_object($object)) {
  75. throw new InvalidArgumentException(sprintf("%s expects class or object, %s given", __METHOD__, substr(str_replace("\n", '', var_export($object, true)), 0, 10)));
  76. }
  77. return is_a($object, $this->class);
  78. }
  79. /**
  80. * Adds a method to call to be injected on any service implementing the interface.
  81. *
  82. * @param string $method The method name to call
  83. * @param array $arguments An array of arguments to pass to the method call
  84. *
  85. * @return InterfaceInjector The current instance
  86. */
  87. public function addMethodCall($method, array $arguments = array())
  88. {
  89. $this->calls[] = array($method, $arguments);
  90. return $this;
  91. }
  92. /**
  93. * Removes a method to call after service initialization.
  94. *
  95. * @param string $method The method name to remove
  96. *
  97. * @return Definition The current instance
  98. */
  99. public function removeMethodCall($method)
  100. {
  101. foreach ($this->calls as $i => $call) {
  102. if ($call[0] === $method) {
  103. unset($this->calls[$i]);
  104. break;
  105. }
  106. }
  107. return $this;
  108. }
  109. /**
  110. * Check if the current definition has a given method to call after service initialization.
  111. *
  112. * @param string $method The method name to search for
  113. *
  114. * @return boolean
  115. */
  116. public function hasMethodCall($method)
  117. {
  118. foreach ($this->calls as $i => $call) {
  119. if ($call[0] === $method) {
  120. return true;
  121. }
  122. }
  123. return false;
  124. }
  125. /**
  126. * Gets the methods to call after service initialization.
  127. *
  128. * @return array An array of method calls
  129. */
  130. public function getMethodCalls()
  131. {
  132. return $this->calls;
  133. }
  134. /**
  135. * Merges another InterfaceInjector
  136. *
  137. * @param InterfaceInjector $injector
  138. */
  139. public function merge(InterfaceInjector $injector)
  140. {
  141. if ($this->class === $injector->getClass()) {
  142. foreach ($injector->getMethodCalls() as $call) {
  143. list ($method, $arguments) = $call;
  144. $this->addMethodCall($method, $arguments);
  145. }
  146. }
  147. }
  148. }