You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

114 lines
3.3 KiB

  1. <?php
  2. /**
  3. * Generates array of classes for autoload
  4. *
  5. * @copyright NetMonsters <team@netmonsters.ru>
  6. * @link http://netmonsters.ru
  7. * @package Majestic
  8. * @subpackage util
  9. * @since 2010-02-24
  10. * @version SVN: $Id$
  11. * @filesource $URL$
  12. */
  13. /**
  14. * @todo Refactoring writing, locking
  15. */
  16. class AutoloadBuilder
  17. {
  18. protected $autoload;
  19. protected $dirs;
  20. protected $exclude;
  21. protected $handler;
  22. protected $regex = '/(class|interface) ([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)/';
  23. public function __construct($autoload, $dirs = array(), $exclude = array())
  24. {
  25. $this->autoload = $autoload;
  26. $this->dirs = $dirs;
  27. $this->exclude = $exclude;
  28. }
  29. public function build()
  30. {
  31. $array_string = "<?php\n// This file is autogenerated by \n// " . __FILE__ . " script.\nreturn array(\n";
  32. // for dublicates check
  33. $classes = array();
  34. foreach ($this->dirs as $dir) {
  35. $iterator = new RecursiveIteratorIterator(
  36. new RecursiveDirectoryIterator($dir),
  37. RecursiveIteratorIterator::LEAVES_ONLY
  38. );
  39. foreach ($iterator as $file) {
  40. if ($this->isExcluded($file->getRealPath())) {
  41. continue;
  42. }
  43. // skip non php files
  44. $e = explode('.', $file->getFileName());
  45. if ((end($e) !== 'php') || $this->rightSubstr($file->getFileName(), 8) == 'Test.php') {
  46. continue;
  47. }
  48. $content = file_get_contents($file->getRealPath());
  49. $matches = array();
  50. $relative_path = substr($file->getRealPath(), strlen(PATH));
  51. if (preg_match_all($this->regex, $content, $matches, PREG_SET_ORDER)) {
  52. foreach ($matches as $match) {
  53. if (array_key_exists($match[2], $classes)) {
  54. continue;
  55. }
  56. $array_string .= "'{$match[2]}'=>'" . $relative_path . "',\n";
  57. $classes[$match[2]] = $file->getRealPath();
  58. }
  59. }
  60. }
  61. unset($file); // without this line trigger_error throws 'Serialization of 'SplFileInfo' is not allowed' exception under PHPUnit
  62. }
  63. $array_string .= ');';
  64. $this->writeAutoload($array_string);
  65. if (!$this->isFileConsistent()) {
  66. unlink($this->autoload);
  67. trigger_error("Error while generating autoload file.", E_USER_ERROR);
  68. }
  69. }
  70. protected function writeAutoload($string)
  71. {
  72. $pid = getmypid();
  73. $tmp = dirname($this->autoload) . '/' . md5(time() + $pid);
  74. file_put_contents($tmp, $string);
  75. rename($tmp, $this->autoload);
  76. }
  77. protected function isFileConsistent()
  78. {
  79. $autoload_array = include($this->autoload);
  80. if (!is_array($autoload_array)) {
  81. return false;
  82. }
  83. return true;
  84. }
  85. protected function isExcluded($file)
  86. {
  87. foreach ($this->exclude as $dir) {
  88. if (stripos($file, $dir) === 0) {
  89. return true;
  90. }
  91. }
  92. return false;
  93. }
  94. protected function rightSubstr($string, $nchars)
  95. {
  96. $right = substr($string, strlen($string) - $nchars, $nchars);
  97. return $right;
  98. }
  99. }