PageRenderTime 29ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/library/Zend/Reflection/File.php

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