PageRenderTime 46ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/common/libraries/plugin/simpletest/reflection_php5.php

https://bitbucket.org/chamilo/chamilo-dev/
PHP | 431 lines | 239 code | 25 blank | 167 comment | 37 complexity | c3a039f8853585436dc13197f5e4c782 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause, LGPL-2.1, LGPL-3.0, GPL-3.0, MIT
  1. <?php
  2. /**
  3. * base include file for SimpleTest
  4. * @package SimpleTest
  5. * @subpackage UnitTester
  6. * @version $Id: reflection_php5.php 1683 2008-03-05 21:57:08Z lastcraft $
  7. */
  8. /**
  9. * Version specific reflection API.
  10. * @package SimpleTest
  11. * @subpackage UnitTester
  12. */
  13. class SimpleReflection
  14. {
  15. var $_interface;
  16. /**
  17. * Stashes the class/interface.
  18. * @param string $interface Class or interface
  19. * to inspect.
  20. */
  21. function __construct($interface)
  22. {
  23. $this->_interface = $interface;
  24. }
  25. /**
  26. * Checks that a class has been declared. Versions
  27. * before PHP5.0.2 need a check that it's not really
  28. * an interface.
  29. * @return boolean True if defined.
  30. * @access public
  31. */
  32. function classExists()
  33. {
  34. if (! class_exists($this->_interface))
  35. {
  36. return false;
  37. }
  38. $reflection = new ReflectionClass($this->_interface);
  39. return ! $reflection->isInterface();
  40. }
  41. /**
  42. * Needed to kill the autoload feature in PHP5
  43. * for classes created dynamically.
  44. * @return boolean True if defined.
  45. * @access public
  46. */
  47. function classExistsSansAutoload()
  48. {
  49. return class_exists($this->_interface, false);
  50. }
  51. /**
  52. * Checks that a class or interface has been
  53. * declared.
  54. * @return boolean True if defined.
  55. * @access public
  56. */
  57. function classOrInterfaceExists()
  58. {
  59. return $this->_classOrInterfaceExistsWithAutoload($this->_interface, true);
  60. }
  61. /**
  62. * Needed to kill the autoload feature in PHP5
  63. * for classes created dynamically.
  64. * @return boolean True if defined.
  65. * @access public
  66. */
  67. function classOrInterfaceExistsSansAutoload()
  68. {
  69. return $this->_classOrInterfaceExistsWithAutoload($this->_interface, false);
  70. }
  71. /**
  72. * Needed to select the autoload feature in PHP5
  73. * for classes created dynamically.
  74. * @param string $interface Class or interface name.
  75. * @param boolean $autoload True totriggerautoload.
  76. * @return boolean True if interface defined.
  77. * @access private
  78. */
  79. function _classOrInterfaceExistsWithAutoload($interface, $autoload)
  80. {
  81. if (function_exists('interface_exists'))
  82. {
  83. if (interface_exists($this->_interface, $autoload))
  84. {
  85. return true;
  86. }
  87. }
  88. return class_exists($this->_interface, $autoload);
  89. }
  90. /**
  91. * Gets the list of methods on a class or
  92. * interface.
  93. * @returns array List of method names.
  94. * @access public
  95. */
  96. function getMethods()
  97. {
  98. return array_unique(get_class_methods($this->_interface));
  99. }
  100. /**
  101. * Gets the list of interfaces from a class. If the
  102. * class name is actually an interface then just that
  103. * interface is returned.
  104. * @returns array List of interfaces.
  105. * @access public
  106. */
  107. function getInterfaces()
  108. {
  109. $reflection = new ReflectionClass($this->_interface);
  110. if ($reflection->isInterface())
  111. {
  112. return array($this->_interface);
  113. }
  114. return $this->_onlyParents($reflection->getInterfaces());
  115. }
  116. /**
  117. * Gets the list of methods for the implemented
  118. * interfaces only.
  119. * @returns array List of enforced method signatures.
  120. * @access public
  121. */
  122. function getInterfaceMethods()
  123. {
  124. $methods = array();
  125. foreach ($this->getInterfaces() as $interface)
  126. {
  127. $methods = array_merge($methods, get_class_methods($interface));
  128. }
  129. return array_unique($methods);
  130. }
  131. /**
  132. * Checks to see if the method signature has to be tightly
  133. * specified.
  134. * @param string $method Method name.
  135. * @returns boolean True if enforced.
  136. * @access private
  137. */
  138. function _isInterfaceMethod($method)
  139. {
  140. return in_array($method, $this->getInterfaceMethods());
  141. }
  142. /**
  143. * Finds the parent class name.
  144. * @returns string Parent class name.
  145. * @access public
  146. */
  147. function getParent()
  148. {
  149. $reflection = new ReflectionClass($this->_interface);
  150. $parent = $reflection->getParentClass();
  151. if ($parent)
  152. {
  153. return $parent->getName();
  154. }
  155. return false;
  156. }
  157. /**
  158. * Trivially determines if the class is abstract.
  159. * @returns boolean True if abstract.
  160. * @access public
  161. */
  162. function isAbstract()
  163. {
  164. $reflection = new ReflectionClass($this->_interface);
  165. return $reflection->isAbstract();
  166. }
  167. /**
  168. * Trivially determines if the class is an interface.
  169. * @returns boolean True if interface.
  170. * @access public
  171. */
  172. function isInterface()
  173. {
  174. $reflection = new ReflectionClass($this->_interface);
  175. return $reflection->isInterface();
  176. }
  177. /**
  178. * Scans for final methods, as they screw up inherited
  179. * mocks by not allowing you to override them.
  180. * @returns boolean True if the class has a final method.
  181. * @access public
  182. */
  183. function hasFinal()
  184. {
  185. $reflection = new ReflectionClass($this->_interface);
  186. foreach ($reflection->getMethods() as $method)
  187. {
  188. if ($method->isFinal())
  189. {
  190. return true;
  191. }
  192. }
  193. return false;
  194. }
  195. /**
  196. * Whittles a list of interfaces down to only the
  197. * necessary top level parents.
  198. * @param array $interfaces Reflection API interfaces
  199. * to reduce.
  200. * @returns array List of parent interface names.
  201. * @access private
  202. */
  203. function _onlyParents($interfaces)
  204. {
  205. $parents = array();
  206. $blacklist = array();
  207. foreach ($interfaces as $interface)
  208. {
  209. foreach ($interfaces as $possible_parent)
  210. {
  211. if ($interface->getName() == $possible_parent->getName())
  212. {
  213. continue;
  214. }
  215. if ($interface->isSubClassOf($possible_parent))
  216. {
  217. $blacklist[$possible_parent->getName()] = true;
  218. }
  219. }
  220. if (! isset($blacklist[$interface->getName()]))
  221. {
  222. $parents[] = $interface->getName();
  223. }
  224. }
  225. return $parents;
  226. }
  227. /**
  228. * Checks whether a method is abstract or not.
  229. * @param string $name Method name.
  230. * @return bool true if method is abstract, else false
  231. * @access private
  232. */
  233. function _isAbstractMethod($name)
  234. {
  235. $interface = new ReflectionClass($this->_interface);
  236. if (! $interface->hasMethod($name))
  237. {
  238. return false;
  239. }
  240. return $interface->getMethod($name)->isAbstract();
  241. }
  242. /**
  243. * Checks whether a method is the constructor.
  244. * @param string $name Method name.
  245. * @return bool true if method is the constructor
  246. * @access private
  247. */
  248. function _isConstructor($name)
  249. {
  250. return ($name == '__construct') || ($name == $this->_interface);
  251. }
  252. /**
  253. * Checks whether a method is abstract in all parents or not.
  254. * @param string $name Method name.
  255. * @return bool true if method is abstract in parent, else false
  256. * @access private
  257. */
  258. function _isAbstractMethodInParents($name)
  259. {
  260. $interface = new ReflectionClass($this->_interface);
  261. $parent = $interface->getParentClass();
  262. while ($parent)
  263. {
  264. if (! $parent->hasMethod($name))
  265. {
  266. return false;
  267. }
  268. if ($parent->getMethod($name)->isAbstract())
  269. {
  270. return true;
  271. }
  272. $parent = $parent->getParentClass();
  273. }
  274. return false;
  275. }
  276. /**
  277. * Checks whether a method is static or not.
  278. * @param string $name Method name
  279. * @return bool true if method is static, else false
  280. * @access private
  281. */
  282. function _isStaticMethod($name)
  283. {
  284. $interface = new ReflectionClass($this->_interface);
  285. if (! $interface->hasMethod($name))
  286. {
  287. return false;
  288. }
  289. return $interface->getMethod($name)->isStatic();
  290. }
  291. /**
  292. * Writes the source code matching the declaration
  293. * of a method.
  294. * @param string $name Method name.
  295. * @return string Method signature up to last
  296. * bracket.
  297. * @access public
  298. */
  299. function getSignature($name)
  300. {
  301. if ($name == '__set')
  302. {
  303. return 'function __set($key, $value)';
  304. }
  305. if ($name == '__call')
  306. {
  307. return 'function __call($method, $arguments)';
  308. }
  309. if (version_compare(phpversion(), '5.1.0', '>='))
  310. {
  311. if (in_array($name, array('__get', '__isset', $name == '__unset')))
  312. {
  313. return "function {$name}(\$key)";
  314. }
  315. }
  316. if ($name == '__toString')
  317. {
  318. return "function $name()";
  319. }
  320. if ($this->_isInterfaceMethod($name) || $this->_isAbstractMethod($name) || $this->_isAbstractMethodInParents($name) || $this->_isStaticMethod($name))
  321. {
  322. return $this->_getFullSignature($name);
  323. }
  324. return "function $name()";
  325. }
  326. /**
  327. * For a signature specified in an interface, full
  328. * details must be replicated to be a valid implementation.
  329. * @param string $name Method name.
  330. * @return string Method signature up to last
  331. * bracket.
  332. * @access private
  333. */
  334. function _getFullSignature($name)
  335. {
  336. $interface = new ReflectionClass($this->_interface);
  337. $method = $interface->getMethod($name);
  338. $reference = $method->returnsReference() ? '&' : '';
  339. $static = $method->isStatic() ? 'static ' : '';
  340. return "{$static}function $reference$name(" . implode(', ', $this->_getParameterSignatures($method)) . ")";
  341. }
  342. /**
  343. * Gets the source code for each parameter.
  344. * @param ReflectionMethod $method Method object from
  345. * reflection API
  346. * @return array List of strings, each
  347. * a snippet of code.
  348. * @access private
  349. */
  350. function _getParameterSignatures($method)
  351. {
  352. $signatures = array();
  353. foreach ($method->getParameters() as $parameter)
  354. {
  355. $signature = '';
  356. $type = $parameter->getClass();
  357. if (is_null($type) && version_compare(phpversion(), '5.1.0', '>=') && $parameter->isArray())
  358. {
  359. $signature .= 'array ';
  360. }
  361. elseif (! is_null($type))
  362. {
  363. $signature .= $type->getName() . ' ';
  364. }
  365. if ($parameter->isPassedByReference())
  366. {
  367. $signature .= '&';
  368. }
  369. $signature .= '$' . $this->_suppressSpurious($parameter->getName());
  370. if ($this->_isOptional($parameter))
  371. {
  372. $signature .= ' = null';
  373. }
  374. $signatures[] = $signature;
  375. }
  376. return $signatures;
  377. }
  378. /**
  379. * The SPL library has problems with the
  380. * Reflection library. In particular, you can
  381. * get extra characters in parameter names :(.
  382. * @param string $name Parameter name.
  383. * @return string Cleaner name.
  384. * @access private
  385. */
  386. function _suppressSpurious($name)
  387. {
  388. return str_replace(array('[', ']', ' '), '', $name);
  389. }
  390. /**
  391. * Test of a reflection parameter being optional
  392. * that works with early versions of PHP5.
  393. * @param reflectionParameter $parameter Is this optional.
  394. * @return boolean True if optional.
  395. * @access private
  396. */
  397. function _isOptional($parameter)
  398. {
  399. if (method_exists($parameter, 'isOptional'))
  400. {
  401. return $parameter->isOptional();
  402. }
  403. return false;
  404. }
  405. }
  406. ?>