PageRenderTime 38ms CodeModel.GetById 14ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/Zend/Reflection/File.php

https://bitbucket.org/acidel/buykoala
PHP | 412 lines | 191 code | 44 blank | 177 comment | 30 complexity | 8e852bfdfe4710ade30e84b1261a32b7 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-2010 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 20904 2010-02-04 16:18:18Z matthew $
  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-2010 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. #require_once 'Zend/Loader.php';
  98. $includePaths = Zend_Loader::explodeIncludePath();
  99. while (count($includePaths) > 0) {
  100. $filePath = array_shift($includePaths) . DIRECTORY_SEPARATOR . $fileName;
  101. if ( ($foundRealpath = realpath($filePath)) !== false) {
  102. break;
  103. }
  104. }
  105. return $foundRealpath;
  106. }
  107. /**
  108. * Export
  109. *
  110. * Required by the Reflector interface.
  111. *
  112. * @todo What should this do?
  113. * @return null
  114. */
  115. public static function export()
  116. {
  117. return null;
  118. }
  119. /**
  120. * Return the file name of the reflected file
  121. *
  122. * @return string
  123. */
  124. public function getFileName()
  125. {
  126. return $this->_fileName;
  127. }
  128. /**
  129. * Get the start line - Always 1, staying consistent with the Reflection API
  130. *
  131. * @return int
  132. */
  133. public function getStartLine()
  134. {
  135. return $this->_startLine;
  136. }
  137. /**
  138. * Get the end line / number of lines
  139. *
  140. * @return int
  141. */
  142. public function getEndLine()
  143. {
  144. return $this->_endLine;
  145. }
  146. /**
  147. * Return the doc comment
  148. *
  149. * @return string
  150. */
  151. public function getDocComment()
  152. {
  153. return $this->_docComment;
  154. }
  155. /**
  156. * Return the docblock
  157. *
  158. * @param string $reflectionClass Reflection class to use
  159. * @return Zend_Reflection_Docblock
  160. */
  161. public function getDocblock($reflectionClass = 'Zend_Reflection_Docblock')
  162. {
  163. $instance = new $reflectionClass($this);
  164. if (!$instance instanceof Zend_Reflection_Docblock) {
  165. #require_once 'Zend/Reflection/Exception.php';
  166. throw new Zend_Reflection_Exception('Invalid reflection class specified; must extend Zend_Reflection_Docblock');
  167. }
  168. return $instance;
  169. }
  170. /**
  171. * Return the reflection classes of the classes found inside this file
  172. *
  173. * @param string $reflectionClass Name of reflection class to use for instances
  174. * @return array Array of Zend_Reflection_Class instances
  175. */
  176. public function getClasses($reflectionClass = 'Zend_Reflection_Class')
  177. {
  178. $classes = array();
  179. foreach ($this->_classes as $class) {
  180. $instance = new $reflectionClass($class);
  181. if (!$instance instanceof Zend_Reflection_Class) {
  182. #require_once 'Zend/Reflection/Exception.php';
  183. throw new Zend_Reflection_Exception('Invalid reflection class provided; must extend Zend_Reflection_Class');
  184. }
  185. $classes[] = $instance;
  186. }
  187. return $classes;
  188. }
  189. /**
  190. * Return the reflection functions of the functions found inside this file
  191. *
  192. * @param string $reflectionClass Name of reflection class to use for instances
  193. * @return array Array of Zend_Reflection_Functions
  194. */
  195. public function getFunctions($reflectionClass = 'Zend_Reflection_Function')
  196. {
  197. $functions = array();
  198. foreach ($this->_functions as $function) {
  199. $instance = new $reflectionClass($function);
  200. if (!$instance instanceof Zend_Reflection_Function) {
  201. #require_once 'Zend/Reflection/Exception.php';
  202. throw new Zend_Reflection_Exception('Invalid reflection class provided; must extend Zend_Reflection_Function');
  203. }
  204. $functions[] = $instance;
  205. }
  206. return $functions;
  207. }
  208. /**
  209. * Retrieve the reflection class of a given class found in this file
  210. *
  211. * @param null|string $name
  212. * @param string $reflectionClass Reflection class to use when creating reflection instance
  213. * @return Zend_Reflection_Class
  214. * @throws Zend_Reflection_Exception for invalid class name or invalid reflection class
  215. */
  216. public function getClass($name = null, $reflectionClass = 'Zend_Reflection_Class')
  217. {
  218. if ($name === null) {
  219. reset($this->_classes);
  220. $selected = current($this->_classes);
  221. $instance = new $reflectionClass($selected);
  222. if (!$instance instanceof Zend_Reflection_Class) {
  223. #require_once 'Zend/Reflection/Exception.php';
  224. throw new Zend_Reflection_Exception('Invalid reflection class given; must extend Zend_Reflection_Class');
  225. }
  226. return $instance;
  227. }
  228. if (in_array($name, $this->_classes)) {
  229. $instance = new $reflectionClass($name);
  230. if (!$instance instanceof Zend_Reflection_Class) {
  231. #require_once 'Zend/Reflection/Exception.php';
  232. throw new Zend_Reflection_Exception('Invalid reflection class given; must extend Zend_Reflection_Class');
  233. }
  234. return $instance;
  235. }
  236. #require_once 'Zend/Reflection/Exception.php';
  237. throw new Zend_Reflection_Exception('Class by name ' . $name . ' not found.');
  238. }
  239. /**
  240. * Return the full contents of file
  241. *
  242. * @return string
  243. */
  244. public function getContents()
  245. {
  246. return $this->_contents;
  247. }
  248. /**
  249. * Serialize to string
  250. *
  251. * Required by the Reflector interface
  252. *
  253. * @todo What should this serialization look like?
  254. * @return string
  255. */
  256. public function __toString()
  257. {
  258. return '';
  259. }
  260. /**
  261. * This method does the work of "reflecting" the file
  262. *
  263. * Uses PHP's tokenizer to perform file reflection.
  264. *
  265. * @return void
  266. */
  267. protected function _reflect()
  268. {
  269. $contents = $this->_contents;
  270. $tokens = token_get_all($contents);
  271. $functionTrapped = false;
  272. $classTrapped = false;
  273. $requireTrapped = false;
  274. $openBraces = 0;
  275. $this->_checkFileDocBlock($tokens);
  276. foreach ($tokens as $token) {
  277. /*
  278. * Tokens are characters representing symbols or arrays
  279. * representing strings. The keys/values in the arrays are
  280. *
  281. * - 0 => token id,
  282. * - 1 => string,
  283. * - 2 => line number
  284. *
  285. * Token ID's are explained here:
  286. * http://www.php.net/manual/en/tokens.php.
  287. */
  288. if (is_array($token)) {
  289. $type = $token[0];
  290. $value = $token[1];
  291. $lineNum = $token[2];
  292. } else {
  293. // It's a symbol
  294. // Maintain the count of open braces
  295. if ($token == '{') {
  296. $openBraces++;
  297. } else if ($token == '}') {
  298. $openBraces--;
  299. }
  300. continue;
  301. }
  302. switch ($type) {
  303. // Name of something
  304. case T_STRING:
  305. if ($functionTrapped) {
  306. $this->_functions[] = $value;
  307. $functionTrapped = false;
  308. } elseif ($classTrapped) {
  309. $this->_classes[] = $value;
  310. $classTrapped = false;
  311. }
  312. continue;
  313. // Required file names are T_CONSTANT_ENCAPSED_STRING
  314. case T_CONSTANT_ENCAPSED_STRING:
  315. if ($requireTrapped) {
  316. $this->_requiredFiles[] = $value ."\n";
  317. $requireTrapped = false;
  318. }
  319. continue;
  320. // Functions
  321. case T_FUNCTION:
  322. if ($openBraces == 0) {
  323. $functionTrapped = true;
  324. }
  325. break;
  326. // Classes
  327. case T_CLASS:
  328. case T_INTERFACE:
  329. $classTrapped = true;
  330. break;
  331. // All types of requires
  332. case T_REQUIRE:
  333. case T_REQUIRE_ONCE:
  334. case T_INCLUDE:
  335. case T_INCLUDE_ONCE:
  336. $requireTrapped = true;
  337. break;
  338. // Default case: do nothing
  339. default:
  340. break;
  341. }
  342. }
  343. $this->_endLine = count(explode("\n", $this->_contents));
  344. }
  345. /**
  346. * Validate / check a file level docblock
  347. *
  348. * @param array $tokens Array of tokenizer tokens
  349. * @return void
  350. */
  351. protected function _checkFileDocBlock($tokens) {
  352. foreach ($tokens as $token) {
  353. $type = $token[0];
  354. $value = $token[1];
  355. $lineNum = $token[2];
  356. if(($type == T_OPEN_TAG) || ($type == T_WHITESPACE)) {
  357. continue;
  358. } elseif ($type == T_DOC_COMMENT) {
  359. $this->_docComment = $value;
  360. $this->_startLine = $lineNum + substr_count($value, "\n") + 1;
  361. return;
  362. } else {
  363. // Only whitespace is allowed before file docblocks
  364. return;
  365. }
  366. }
  367. }
  368. }