PageRenderTime 26ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/Zend/Reflection/File.php

https://github.com/lanmediaservice/lms-tplib
PHP | 411 lines | 191 code | 44 blank | 176 comment | 30 complexity | aed69ebf2caf6682a13dcb49fb9c0c83 MD5 | raw file
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_Reflection
  17. * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
  18. * @license http://framework.zend.com/license/new-bsd New BSD License
  19. * @version $Id: File.php 17516 2009-08-10 13:50:26Z ralph $
  20. */
  21. /**
  22. * @see Zend_Reflection_Class
  23. */
  24. //*** require_once 'Zend/Reflection/Class.php';
  25. /**
  26. * @see Zend_Reflection_Function
  27. */
  28. //*** require_once 'Zend/Reflection/Function.php';
  29. /**
  30. * @category Zend
  31. * @package Zend_Reflection
  32. * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
  33. * @license http://framework.zend.com/license/new-bsd New BSD License
  34. */
  35. class Zend_Reflection_File implements Reflector
  36. {
  37. /**
  38. * @var string
  39. */
  40. protected $_filepath = null;
  41. /**
  42. * @var string
  43. */
  44. protected $_docComment = null;
  45. /**
  46. * @var int
  47. */
  48. protected $_startLine = 1;
  49. /**
  50. * @var int
  51. */
  52. protected $_endLine = null;
  53. /**
  54. * @var string[]
  55. */
  56. protected $_requiredFiles = array();
  57. /**
  58. * @var Zend_Reflection_Class[]
  59. */
  60. protected $_classes = array();
  61. /**
  62. * @var Zend_Reflection_Function[]
  63. */
  64. protected $_functions = array();
  65. /**
  66. * @var string
  67. */
  68. protected $_contents = null;
  69. /**
  70. * Constructor
  71. *
  72. * @param string $file
  73. * @return void
  74. */
  75. public function __construct($file)
  76. {
  77. $fileName = $file;
  78. if (($fileRealpath = realpath($fileName)) === false) {
  79. $fileRealpath = self::findRealpathInIncludePath($file);
  80. }
  81. if (!$fileRealpath || !in_array($fileRealpath, get_included_files())) {
  82. //*** require_once 'Zend/Reflection/Exception.php';
  83. throw new Zend_Reflection_Exception('File ' . $file . ' must be required before it can be reflected');
  84. }
  85. $this->_fileName = $fileRealpath;
  86. $this->_contents = file_get_contents($this->_fileName);
  87. $this->_reflect();
  88. }
  89. /**
  90. * Find realpath of file based on include_path
  91. *
  92. * @param string $fileName
  93. * @return string
  94. */
  95. public static function findRealpathInIncludePath($fileName)
  96. {
  97. $includePaths = explode(PATH_SEPARATOR, get_include_path());
  98. while (count($includePaths) > 0) {
  99. $filePath = array_shift($includePaths) . DIRECTORY_SEPARATOR . $fileName;
  100. if ( ($foundRealpath = realpath($filePath)) !== false) {
  101. break;
  102. }
  103. }
  104. return $foundRealpath;
  105. }
  106. /**
  107. * Export
  108. *
  109. * Required by the Reflector interface.
  110. *
  111. * @todo What should this do?
  112. * @return null
  113. */
  114. public static function export()
  115. {
  116. return null;
  117. }
  118. /**
  119. * Return the file name of the reflected file
  120. *
  121. * @return string
  122. */
  123. public function getFileName()
  124. {
  125. return $this->_fileName;
  126. }
  127. /**
  128. * Get the start line - Always 1, staying consistent with the Reflection API
  129. *
  130. * @return int
  131. */
  132. public function getStartLine()
  133. {
  134. return $this->_startLine;
  135. }
  136. /**
  137. * Get the end line / number of lines
  138. *
  139. * @return int
  140. */
  141. public function getEndLine()
  142. {
  143. return $this->_endLine;
  144. }
  145. /**
  146. * Return the doc comment
  147. *
  148. * @return string
  149. */
  150. public function getDocComment()
  151. {
  152. return $this->_docComment;
  153. }
  154. /**
  155. * Return the docblock
  156. *
  157. * @param string $reflectionClass Reflection class to use
  158. * @return Zend_Reflection_Docblock
  159. */
  160. public function getDocblock($reflectionClass = 'Zend_Reflection_Docblock')
  161. {
  162. $instance = new $reflectionClass($this);
  163. if (!$instance instanceof Zend_Reflection_Docblock) {
  164. //*** require_once 'Zend/Reflection/Exception.php';
  165. throw new Zend_Reflection_Exception('Invalid reflection class specified; must extend Zend_Reflection_Docblock');
  166. }
  167. return $instance;
  168. }
  169. /**
  170. * Return the reflection classes of the classes found inside this file
  171. *
  172. * @param string $reflectionClass Name of reflection class to use for instances
  173. * @return array Array of Zend_Reflection_Class instances
  174. */
  175. public function getClasses($reflectionClass = 'Zend_Reflection_Class')
  176. {
  177. $classes = array();
  178. foreach ($this->_classes as $class) {
  179. $instance = new $reflectionClass($class);
  180. if (!$instance instanceof Zend_Reflection_Class) {
  181. //*** require_once 'Zend/Reflection/Exception.php';
  182. throw new Zend_Reflection_Exception('Invalid reflection class provided; must extend Zend_Reflection_Class');
  183. }
  184. $classes[] = $instance;
  185. }
  186. return $classes;
  187. }
  188. /**
  189. * Return the reflection functions of the functions found inside this file
  190. *
  191. * @param string $reflectionClass Name of reflection class to use for instances
  192. * @return array Array of Zend_Reflection_Functions
  193. */
  194. public function getFunctions($reflectionClass = 'Zend_Reflection_Function')
  195. {
  196. $functions = array();
  197. foreach ($this->_functions as $function) {
  198. $instance = new $reflectionClass($function);
  199. if (!$instance instanceof Zend_Reflection_Function) {
  200. //*** require_once 'Zend/Reflection/Exception.php';
  201. throw new Zend_Reflection_Exception('Invalid reflection class provided; must extend Zend_Reflection_Function');
  202. }
  203. $functions[] = $instance;
  204. }
  205. return $functions;
  206. }
  207. /**
  208. * Retrieve the reflection class of a given class found in this file
  209. *
  210. * @param null|string $name
  211. * @param string $reflectionClass Reflection class to use when creating reflection instance
  212. * @return Zend_Reflection_Class
  213. * @throws Zend_Reflection_Exception for invalid class name or invalid reflection class
  214. */
  215. public function getClass($name = null, $reflectionClass = 'Zend_Reflection_Class')
  216. {
  217. if ($name === null) {
  218. reset($this->_classes);
  219. $selected = current($this->_classes);
  220. $instance = new $reflectionClass($selected);
  221. if (!$instance instanceof Zend_Reflection_Class) {
  222. //*** require_once 'Zend/Reflection/Exception.php';
  223. throw new Zend_Reflection_Exception('Invalid reflection class given; must extend Zend_Reflection_Class');
  224. }
  225. return $instance;
  226. }
  227. if (in_array($name, $this->_classes)) {
  228. $instance = new $reflectionClass($name);
  229. if (!$instance instanceof Zend_Reflection_Class) {
  230. //*** require_once 'Zend/Reflection/Exception.php';
  231. throw new Zend_Reflection_Exception('Invalid reflection class given; must extend Zend_Reflection_Class');
  232. }
  233. return $instance;
  234. }
  235. //*** require_once 'Zend/Reflection/Exception.php';
  236. throw new Zend_Reflection_Exception('Class by name ' . $name . ' not found.');
  237. }
  238. /**
  239. * Return the full contents of file
  240. *
  241. * @return string
  242. */
  243. public function getContents()
  244. {
  245. return $this->_contents;
  246. }
  247. /**
  248. * Serialize to string
  249. *
  250. * Required by the Reflector interface
  251. *
  252. * @todo What should this serialization look like?
  253. * @return string
  254. */
  255. public function __toString()
  256. {
  257. return '';
  258. }
  259. /**
  260. * This method does the work of "reflecting" the file
  261. *
  262. * Uses PHP's tokenizer to perform file reflection.
  263. *
  264. * @return void
  265. */
  266. protected function _reflect()
  267. {
  268. $contents = $this->_contents;
  269. $tokens = token_get_all($contents);
  270. $functionTrapped = false;
  271. $classTrapped = false;
  272. $requireTrapped = false;
  273. $openBraces = 0;
  274. $this->_checkFileDocBlock($tokens);
  275. foreach ($tokens as $token) {
  276. /*
  277. * Tokens are characters representing symbols or arrays
  278. * representing strings. The keys/values in the arrays are
  279. *
  280. * - 0 => token id,
  281. * - 1 => string,
  282. * - 2 => line number
  283. *
  284. * Token ID's are explained here:
  285. * http://www.php.net/manual/en/tokens.php.
  286. */
  287. if (is_array($token)) {
  288. $type = $token[0];
  289. $value = $token[1];
  290. $lineNum = $token[2];
  291. } else {
  292. // It's a symbol
  293. // Maintain the count of open braces
  294. if ($token == '{') {
  295. $openBraces++;
  296. } else if ($token == '}') {
  297. $openBraces--;
  298. }
  299. continue;
  300. }
  301. switch ($type) {
  302. // Name of something
  303. case T_STRING:
  304. if ($functionTrapped) {
  305. $this->_functions[] = $value;
  306. $functionTrapped = false;
  307. } elseif ($classTrapped) {
  308. $this->_classes[] = $value;
  309. $classTrapped = false;
  310. }
  311. continue;
  312. // Required file names are T_CONSTANT_ENCAPSED_STRING
  313. case T_CONSTANT_ENCAPSED_STRING:
  314. if ($requireTrapped) {
  315. $this->_requiredFiles[] = $value ."\n";
  316. $requireTrapped = false;
  317. }
  318. continue;
  319. // Functions
  320. case T_FUNCTION:
  321. if ($openBraces == 0) {
  322. $functionTrapped = true;
  323. }
  324. break;
  325. // Classes
  326. case T_CLASS:
  327. case T_INTERFACE:
  328. $classTrapped = true;
  329. break;
  330. // All types of requires
  331. case T_REQUIRE:
  332. case T_REQUIRE_ONCE:
  333. case T_INCLUDE:
  334. case T_INCLUDE_ONCE:
  335. $requireTrapped = true;
  336. break;
  337. // Default case: do nothing
  338. default:
  339. break;
  340. }
  341. }
  342. $this->_endLine = count(explode("\n", $this->_contents));
  343. }
  344. /**
  345. * Validate / check a file level docblock
  346. *
  347. * @param array $tokens Array of tokenizer tokens
  348. * @return void
  349. */
  350. protected function _checkFileDocBlock($tokens) {
  351. foreach ($tokens as $token) {
  352. $type = $token[0];
  353. $value = $token[1];
  354. $lineNum = $token[2];
  355. if(($type == T_OPEN_TAG) || ($type == T_WHITESPACE)) {
  356. continue;
  357. } elseif ($type == T_DOC_COMMENT) {
  358. $this->_docComment = $value;
  359. $this->_startLine = $lineNum + substr_count($value, "\n") + 1;
  360. return;
  361. } else {
  362. // Only whitespace is allowed before file docblocks
  363. return;
  364. }
  365. }
  366. }
  367. }