/library/Zend/File/ClassFileLocator.php

https://github.com/obias/zf2 · PHP · 155 lines · 103 code · 18 blank · 34 comment · 22 complexity · 9ed344d96ee8495fb09b842abc2ccb44 MD5 · raw file

  1. <?php
  2. /** @namespace */
  3. namespace Zend\File;
  4. // import SPL classes/interfaces into local scope
  5. use DirectoryIterator,
  6. FilterIterator,
  7. RecursiveIterator,
  8. RecursiveDirectoryIterator,
  9. RecursiveIteratorIterator;
  10. /**
  11. * Locate files containing PHP classes, interfaces, or abstracts
  12. *
  13. * @package Zend_File
  14. * @license New BSD {@link http://framework.zend.com/license/new-bsd}
  15. */
  16. class ClassFileLocator extends FilterIterator
  17. {
  18. /**
  19. * Create an instance of the locator iterator
  20. *
  21. * Expects either a directory, or a DirectoryIterator (or its recursive variant)
  22. * instance.
  23. *
  24. * @param string|DirectoryIterator $dirOrIterator
  25. * @return void
  26. */
  27. public function __construct($dirOrIterator = '.')
  28. {
  29. if (is_string($dirOrIterator)) {
  30. if (!is_dir($dirOrIterator)) {
  31. throw new Exception\InvalidArgumentException('Expected a valid directory name');
  32. }
  33. $dirOrIterator = new RecursiveDirectoryIterator($dirOrIterator, RecursiveDirectoryIterator::FOLLOW_SYMLINKS);
  34. }
  35. if (!$dirOrIterator instanceof DirectoryIterator) {
  36. throw new Exception\InvalidArgumentException('Expected a DirectoryIterator');
  37. }
  38. if ($dirOrIterator instanceof RecursiveIterator) {
  39. $iterator = new RecursiveIteratorIterator($dirOrIterator);
  40. } else {
  41. $iterator = $dirOrIterator;
  42. }
  43. parent::__construct($iterator);
  44. $this->rewind();
  45. }
  46. /**
  47. * Filter for files containing PHP classes, interfaces, or abstracts
  48. *
  49. * @return bool
  50. */
  51. public function accept()
  52. {
  53. $file = $this->getInnerIterator()->current();
  54. // If we somehow have something other than an SplFileInfo object, just
  55. // return false
  56. if (!$file instanceof \SplFileInfo) {
  57. return false;
  58. }
  59. // If we have a directory, it's not a file, so return false
  60. if (!$file->isFile()) {
  61. return false;
  62. }
  63. // If not a PHP file, skip
  64. if ($file->getBasename('.php') == $file->getBasename()) {
  65. return false;
  66. }
  67. $contents = file_get_contents($file->getRealPath());
  68. $tokens = token_get_all($contents);
  69. $count = count($tokens);
  70. $i = 0;
  71. while ($i < $count) {
  72. $token = $tokens[$i];
  73. if (!is_array($token)) {
  74. // single character token found; skip
  75. $i++;
  76. continue;
  77. }
  78. list($id, $content, $line) = $token;
  79. switch ($id) {
  80. case T_NAMESPACE:
  81. // Namespace found; grab it for later
  82. $namespace = '';
  83. $done = false;
  84. do {
  85. ++$i;
  86. $token = $tokens[$i];
  87. if (is_string($token)) {
  88. if (';' === $token) {
  89. $done = true;
  90. }
  91. continue;
  92. }
  93. list($type, $content, $line) = $token;
  94. switch ($type) {
  95. case T_STRING:
  96. case T_NS_SEPARATOR:
  97. $namespace .= $content;
  98. break;
  99. }
  100. } while (!$done && $i < $count);
  101. // Set the namespace of this file in the object
  102. $file->namespace = $namespace;
  103. break;
  104. case T_CLASS:
  105. case T_INTERFACE:
  106. // Abstract class, class, or interface found
  107. // Get the classname
  108. $class = '';
  109. do {
  110. ++$i;
  111. $token = $tokens[$i];
  112. if (is_string($token)) {
  113. continue;
  114. }
  115. list($type, $content, $line) = $token;
  116. switch ($type) {
  117. case T_STRING:
  118. $class = $content;
  119. break;
  120. }
  121. } while (empty($class) && $i < $count);
  122. // If a classname was found, set it in the object, and
  123. // return boolean true (found)
  124. if (!empty($class)) {
  125. $file->classname = $class;
  126. return true;
  127. }
  128. break;
  129. default:
  130. break;
  131. }
  132. ++$i;
  133. }
  134. // No class-type tokens found; return false
  135. return false;
  136. }
  137. }