PageRenderTime 45ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/app/classes/Zend/Di/Definition/RuntimeDefinition.php

https://gitlab.com/jalon/doadoronline
PHP | 353 lines | 197 code | 61 blank | 95 comment | 32 complexity | 479a9bbed503dbbae9e35d4c532307ea MD5 | raw file
  1. <?php
  2. /**
  3. * Zend Framework (http://framework.zend.com/)
  4. *
  5. * @link http://github.com/zendframework/zf2 for the canonical source repository
  6. * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
  7. * @license http://framework.zend.com/license/new-bsd New BSD License
  8. */
  9. namespace Zend\Di\Definition;
  10. use Zend\Code\Annotation\AnnotationCollection;
  11. use Zend\Code\Reflection;
  12. use Zend\Di\Definition\Annotation;
  13. use Zend\Di\Di;
  14. /**
  15. * Class definitions based on runtime reflection
  16. */
  17. class RuntimeDefinition implements DefinitionInterface
  18. {
  19. /**
  20. * @var array
  21. */
  22. protected $classes = array();
  23. /**
  24. * @var bool
  25. */
  26. protected $explicitLookups = false;
  27. /**
  28. * @var IntrospectionStrategy
  29. */
  30. protected $introspectionStrategy = null;
  31. /**
  32. * @var array
  33. */
  34. protected $injectionMethods = array();
  35. /**
  36. * Constructor
  37. *
  38. * @param null|IntrospectionStrategy $introspectionStrategy
  39. * @param array|null $explicitClasses
  40. */
  41. public function __construct(IntrospectionStrategy $introspectionStrategy = null, array $explicitClasses = null)
  42. {
  43. $this->introspectionStrategy = ($introspectionStrategy) ?: new IntrospectionStrategy();
  44. if ($explicitClasses) {
  45. $this->setExplicitClasses($explicitClasses);
  46. }
  47. }
  48. /**
  49. * @param IntrospectionStrategy $introspectionStrategy
  50. * @return void
  51. */
  52. public function setIntrospectionStrategy(IntrospectionStrategy $introspectionStrategy)
  53. {
  54. $this->introspectionStrategy = $introspectionStrategy;
  55. }
  56. /**
  57. * @return IntrospectionStrategy
  58. */
  59. public function getIntrospectionStrategy()
  60. {
  61. return $this->introspectionStrategy;
  62. }
  63. /**
  64. * Set explicit classes
  65. *
  66. * @param array $explicitClasses
  67. */
  68. public function setExplicitClasses(array $explicitClasses)
  69. {
  70. $this->explicitLookups = true;
  71. foreach ($explicitClasses as $eClass) {
  72. $this->classes[$eClass] = true;
  73. }
  74. $this->classes = $explicitClasses;
  75. }
  76. /**
  77. * @param string $class
  78. */
  79. public function forceLoadClass($class)
  80. {
  81. $this->processClass($class);
  82. }
  83. /**
  84. * {@inheritDoc}
  85. */
  86. public function getClasses()
  87. {
  88. return array_keys($this->classes);
  89. }
  90. /**
  91. * {@inheritDoc}
  92. */
  93. public function hasClass($class)
  94. {
  95. if ($this->explicitLookups === true) {
  96. return (array_key_exists($class, $this->classes));
  97. }
  98. return class_exists($class) || interface_exists($class);
  99. }
  100. /**
  101. * {@inheritDoc}
  102. */
  103. public function getClassSupertypes($class)
  104. {
  105. if (!array_key_exists($class, $this->classes)) {
  106. $this->processClass($class);
  107. }
  108. return $this->classes[$class]['supertypes'];
  109. }
  110. /**
  111. * {@inheritDoc}
  112. */
  113. public function getInstantiator($class)
  114. {
  115. if (!array_key_exists($class, $this->classes)) {
  116. $this->processClass($class);
  117. }
  118. return $this->classes[$class]['instantiator'];
  119. }
  120. /**
  121. * {@inheritDoc}
  122. */
  123. public function hasMethods($class)
  124. {
  125. if (!array_key_exists($class, $this->classes)) {
  126. $this->processClass($class);
  127. }
  128. return (count($this->classes[$class]['methods']) > 0);
  129. }
  130. /**
  131. * {@inheritDoc}
  132. */
  133. public function hasMethod($class, $method)
  134. {
  135. if (!array_key_exists($class, $this->classes)) {
  136. $this->processClass($class);
  137. }
  138. return isset($this->classes[$class]['methods'][$method]);
  139. }
  140. /**
  141. * {@inheritDoc}
  142. */
  143. public function getMethods($class)
  144. {
  145. if (!array_key_exists($class, $this->classes)) {
  146. $this->processClass($class);
  147. }
  148. return $this->classes[$class]['methods'];
  149. }
  150. /**
  151. * {@inheritDoc}
  152. */
  153. public function hasMethodParameters($class, $method)
  154. {
  155. if (!isset($this->classes[$class])) {
  156. return false;
  157. }
  158. return (array_key_exists($method, $this->classes[$class]['parameters']));
  159. }
  160. /**
  161. * {@inheritDoc}
  162. */
  163. public function getMethodParameters($class, $method)
  164. {
  165. if (!is_array($this->classes[$class])) {
  166. $this->processClass($class);
  167. }
  168. return $this->classes[$class]['parameters'][$method];
  169. }
  170. /**
  171. * @param string $class
  172. */
  173. protected function processClass($class)
  174. {
  175. $strategy = $this->introspectionStrategy; // localize for readability
  176. /** @var $rClass \Zend\Code\Reflection\ClassReflection */
  177. $rClass = new Reflection\ClassReflection($class);
  178. $className = $rClass->getName();
  179. $matches = null; // used for regex below
  180. // setup the key in classes
  181. $this->classes[$className] = array(
  182. 'supertypes' => array(),
  183. 'instantiator' => null,
  184. 'methods' => array(),
  185. 'parameters' => array()
  186. );
  187. $def = &$this->classes[$className]; // localize for brevity
  188. // class annotations?
  189. if ($strategy->getUseAnnotations() == true) {
  190. $annotations = $rClass->getAnnotations($strategy->getAnnotationManager());
  191. if (($annotations instanceof AnnotationCollection)
  192. && $annotations->hasAnnotation('Zend\Di\Definition\Annotation\Instantiator')) {
  193. // @todo Instantiator support in annotations
  194. }
  195. }
  196. $rTarget = $rClass;
  197. $supertypes = array();
  198. do {
  199. $supertypes = array_merge($supertypes, $rTarget->getInterfaceNames());
  200. if (!($rTargetParent = $rTarget->getParentClass())) {
  201. break;
  202. }
  203. $supertypes[] = $rTargetParent->getName();
  204. $rTarget = $rTargetParent;
  205. } while (true);
  206. $def['supertypes'] = $supertypes;
  207. if ($def['instantiator'] == null) {
  208. if ($rClass->isInstantiable()) {
  209. $def['instantiator'] = '__construct';
  210. }
  211. }
  212. if ($rClass->hasMethod('__construct')) {
  213. $def['methods']['__construct'] = Di::METHOD_IS_CONSTRUCTOR; // required
  214. $this->processParams($def, $rClass, $rClass->getMethod('__construct'));
  215. }
  216. foreach ($rClass->getMethods(Reflection\MethodReflection::IS_PUBLIC) as $rMethod) {
  217. $methodName = $rMethod->getName();
  218. if ($rMethod->getName() === '__construct' || $rMethod->isStatic()) {
  219. continue;
  220. }
  221. if ($strategy->getUseAnnotations() == true) {
  222. $annotations = $rMethod->getAnnotations($strategy->getAnnotationManager());
  223. if (($annotations instanceof AnnotationCollection)
  224. && $annotations->hasAnnotation('Zend\Di\Definition\Annotation\Inject')) {
  225. // use '@inject' and search for parameters
  226. $def['methods'][$methodName] = Di::METHOD_IS_EAGER;
  227. $this->processParams($def, $rClass, $rMethod);
  228. continue;
  229. }
  230. }
  231. $methodPatterns = $this->introspectionStrategy->getMethodNameInclusionPatterns();
  232. // matches a method injection pattern?
  233. foreach ($methodPatterns as $methodInjectorPattern) {
  234. preg_match($methodInjectorPattern, $methodName, $matches);
  235. if ($matches) {
  236. $def['methods'][$methodName] = Di::METHOD_IS_OPTIONAL; // check ot see if this is required?
  237. $this->processParams($def, $rClass, $rMethod);
  238. continue 2;
  239. }
  240. }
  241. // method
  242. // by annotation
  243. // by setter pattern,
  244. // by interface
  245. }
  246. $interfaceInjectorPatterns = $this->introspectionStrategy->getInterfaceInjectionInclusionPatterns();
  247. // matches the interface injection pattern
  248. /** @var $rIface \ReflectionClass */
  249. foreach ($rClass->getInterfaces() as $rIface) {
  250. foreach ($interfaceInjectorPatterns as $interfaceInjectorPattern) {
  251. preg_match($interfaceInjectorPattern, $rIface->getName(), $matches);
  252. if ($matches) {
  253. foreach ($rIface->getMethods() as $rMethod) {
  254. if (($rMethod->getName() === '__construct') || !count($rMethod->getParameters())) {
  255. // constructor not allowed in interfaces
  256. // Don't call interface methods without a parameter (Some aware interfaces define setters in ZF2)
  257. continue;
  258. }
  259. $def['methods'][$rMethod->getName()] = Di::METHOD_IS_AWARE;
  260. $this->processParams($def, $rClass, $rMethod);
  261. }
  262. continue 2;
  263. }
  264. }
  265. }
  266. }
  267. /**
  268. * @param array $def
  269. * @param \Zend\Code\Reflection\ClassReflection $rClass
  270. * @param \Zend\Code\Reflection\MethodReflection $rMethod
  271. */
  272. protected function processParams(&$def, Reflection\ClassReflection $rClass, Reflection\MethodReflection $rMethod)
  273. {
  274. if (count($rMethod->getParameters()) === 0) {
  275. return;
  276. }
  277. $methodName = $rMethod->getName();
  278. // @todo annotations here for alternate names?
  279. $def['parameters'][$methodName] = array();
  280. foreach ($rMethod->getParameters() as $p) {
  281. /** @var $p \ReflectionParameter */
  282. $actualParamName = $p->getName();
  283. $fqName = $rClass->getName() . '::' . $rMethod->getName() . ':' . $p->getPosition();
  284. $def['parameters'][$methodName][$fqName] = array();
  285. // set the class name, if it exists
  286. $def['parameters'][$methodName][$fqName][] = $actualParamName;
  287. $def['parameters'][$methodName][$fqName][] = ($p->getClass() !== null) ? $p->getClass()->getName() : null;
  288. $def['parameters'][$methodName][$fqName][] = !($optional = $p->isOptional() && $p->isDefaultValueAvailable());
  289. $def['parameters'][$methodName][$fqName][] = $optional ? $p->getDefaultValue() : null;
  290. }
  291. }
  292. }