PageRenderTime 52ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/bin/classmap_generator.php

http://github.com/zendframework/zf2
PHP | 258 lines | 203 code | 16 blank | 39 comment | 12 complexity | dbaab8fed6bd3857df664388e5efd1e7 MD5 | raw file
Possible License(s): BSD-3-Clause
  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_Loader
  17. * @subpackage Exception
  18. * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
  19. * @license http://framework.zend.com/license/new-bsd New BSD License
  20. */
  21. /**
  22. * Generate class maps for use with autoloading.
  23. *
  24. * Usage:
  25. * --help|-h Get usage message
  26. * --library|-l [ <string> ] Library to parse; if none provided, assumes
  27. * current directory
  28. * --output|-o [ <string> ] Where to write autoload file; if not provided,
  29. * assumes "autoload_classmap.php" in library directory
  30. * --append|-a Append to autoload file if it exists
  31. * --overwrite|-w Whether or not to overwrite existing autoload
  32. * file
  33. */
  34. $libPath = getenv('LIB_PATH') ? getenv('LIB_PATH') : __DIR__ . '/../library';
  35. if (!is_dir($libPath)) {
  36. // Try to load StandardAutoloader from include_path
  37. if (false === include('Zend/Loader/StandardAutoloader.php')) {
  38. echo "Unable to locate autoloader via include_path; aborting" . PHP_EOL;
  39. exit(2);
  40. }
  41. } else {
  42. // Try to load StandardAutoloader from library
  43. if (false === include($libPath . '/Zend/Loader/StandardAutoloader.php')) {
  44. echo "Unable to locate autoloader via library; aborting" . PHP_EOL;
  45. exit(2);
  46. }
  47. }
  48. // Setup autoloading
  49. $loader = new Zend\Loader\StandardAutoloader();
  50. $loader->register();
  51. $rules = array(
  52. 'help|h' => 'Get usage message',
  53. 'library|l-s' => 'Library to parse; if none provided, assumes current directory',
  54. 'output|o-s' => 'Where to write autoload file; if not provided, assumes "autoload_classmap.php" in library directory',
  55. 'append|a' => 'Append to autoload file if it exists',
  56. 'overwrite|w' => 'Whether or not to overwrite existing autoload file',
  57. );
  58. try {
  59. $opts = new Zend\Console\Getopt($rules);
  60. $opts->parse();
  61. } catch (Zend\Console\Getopt\Exception $e) {
  62. echo $e->getUsageMessage();
  63. exit(2);
  64. }
  65. if ($opts->getOption('h')) {
  66. echo $opts->getUsageMessage();
  67. exit();
  68. }
  69. $path = $libPath;
  70. if (array_key_exists('PWD', $_SERVER)) {
  71. $path = $_SERVER['PWD'];
  72. }
  73. $relativePathForClassmap = '';
  74. if (isset($opts->l)) {
  75. $libraryPath = $opts->l;
  76. $libraryPath = str_replace('\\', '/', rtrim($libraryPath, '/\\')) . '/';
  77. if (!is_dir($libraryPath)) {
  78. echo "Invalid library directory provided" . PHP_EOL . PHP_EOL;
  79. echo $opts->getUsageMessage();
  80. exit(2);
  81. }
  82. $path = str_replace('\\', '/', realpath($libraryPath));
  83. // If -o has been used, then we need to add the $libraryPath into the relative
  84. // path that is created in the classmap file.
  85. if ($opts->o != '') {
  86. // If both library path and classmap path are absolute, we have to make
  87. // it relative to the classmap file.
  88. $libraryPathCompare = rtrim(str_replace('\\', '/', realpath($libraryPath)), '/');
  89. if (file_exists($opts->o) ) {
  90. $classmapPathCompare = rtrim(str_replace('\\', '/', realpath($opts->o)), '/');
  91. } else {
  92. // realpath() won't work for unexisting files
  93. $newFilePath = explode('/', str_replace('\\', '/', $opts->o));
  94. // stip filename
  95. array_pop($newFilePath);
  96. $classmapPathCompare = rtrim(realpath(implode('/', $newFilePath)), '/');
  97. }
  98. if (is_file($libraryPathCompare)) {
  99. $libraryPathCompare = str_replace('\\', '/', dirname($libraryPathCompare));
  100. }
  101. if (is_file($classmapPathCompare)) {
  102. $classmapPathCompare = str_replace('\\', '/', dirname($classmapPathCompare));
  103. }
  104. // Simple case: $libraryPathCompare is in $classmapPathCompare
  105. if (strpos($libraryPathCompare, $classmapPathCompare) === 0) {
  106. $relativePathForClassmap = substr($libraryPathCompare, strlen($classmapPathCompare) + 1) . '/';
  107. } else {
  108. $relative = array();
  109. $libraryPathParts = explode('/', $libraryPathCompare);
  110. $classmapPathParts = explode('/', $classmapPathCompare);
  111. foreach ($classmapPathParts as $index => $part) {
  112. var_dump($libraryPathParts[$index]);
  113. var_dump($part);
  114. var_dump(1);
  115. if (isset($libraryPathParts[$index]) && $libraryPathParts[$index] == $part) {
  116. continue;
  117. }
  118. $relative[] = '..';
  119. }
  120. foreach ($libraryPathParts as $index => $part ) {
  121. if (isset($classmapPathParts[$index]) && $classmapPathParts[$index] == $part) {
  122. continue;
  123. }
  124. $relative[] = $part;
  125. }
  126. $relativePathForClassmap = implode('/', $relative) . '/';
  127. }
  128. }
  129. }
  130. $usingStdout = false;
  131. $appending = $opts->getOption('a');
  132. $output = $path . '/autoload_classmap.php';
  133. if (isset($opts->o)) {
  134. $output = $opts->o;
  135. if ('-' == $output) {
  136. $output = STDOUT;
  137. $usingStdout = true;
  138. } elseif (!is_writeable(dirname($output))) {
  139. echo "Cannot write to '$output'; aborting." . PHP_EOL
  140. . PHP_EOL
  141. . $opts->getUsageMessage();
  142. exit(2);
  143. } elseif (file_exists($output)) {
  144. if (!$opts->getOption('w') && !$appending) {
  145. echo "Autoload file already exists at '$output'," . PHP_EOL
  146. . "but 'overwrite' flag was not specified; aborting." . PHP_EOL
  147. . PHP_EOL
  148. . $opts->getUsageMessage();
  149. exit(2);
  150. }
  151. }
  152. }
  153. $strip = $path;
  154. if (!$usingStdout) {
  155. if ($appending) {
  156. echo "Appending to class file map '$output' for library in '$path'..." . PHP_EOL;
  157. } else {
  158. echo "Creating class file map for library in '$path'..." . PHP_EOL;
  159. }
  160. }
  161. // Get the ClassFileLocator, and pass it the library path
  162. $l = new \Zend\File\ClassFileLocator($path);
  163. // Iterate over each element in the path, and create a map of
  164. // classname => filename, where the filename is relative to the library path
  165. $map = new \stdClass;
  166. $strip .= '/';
  167. foreach ($l as $file) {
  168. $namespace = empty($file->namespace) ? '' : $file->namespace . '\\';
  169. $filename = str_replace($strip, '', str_replace('\\', '/', $file->getPath()) . '/' . $file->getFilename());
  170. // Add in relative path to library
  171. $filename = $relativePathForClassmap . $filename;
  172. // Replace directory separators with forward slash
  173. $filename = str_replace(array('/', '\\'), '/', $filename);
  174. $map->{$namespace . $file->classname} = $filename;
  175. }
  176. if ($appending) {
  177. $content = var_export((array) $map, true) . ';';
  178. // Prefix with __DIR__; modify the generated content
  179. $content = preg_replace("#(=> ')#", "=> __DIR__ . '/", $content);
  180. // Fix \' strings from injected DIRECTORY_SEPARATOR usage in iterator_apply op
  181. $content = str_replace("\\'", "'", $content);
  182. // Convert to an array and remove the first "array("
  183. $content = explode(PHP_EOL, $content);
  184. array_shift($content);
  185. // Load existing class map file and remove the closing "bracket ");" from it
  186. $existing = file($output, FILE_IGNORE_NEW_LINES);
  187. array_pop($existing);
  188. // Merge
  189. $content = implode(PHP_EOL, array_merge($existing, $content));
  190. } else {
  191. // Create a file with the class/file map.
  192. // Stupid syntax highlighters make separating < from PHP declaration necessary
  193. $content = '<' . "?php\n"
  194. . "// Generated by ZF2's ./bin/classmap_generator.php\n"
  195. . 'return ' . var_export((array) $map, true) . ';';
  196. // Prefix with __DIR__; modify the generated content
  197. $content = preg_replace("#(=> ')#", "=> __DIR__ . '/", $content);
  198. // Fix \' strings from injected DIRECTORY_SEPARATOR usage in iterator_apply op
  199. $content = str_replace("\\'", "'", $content);
  200. }
  201. // Remove unnecessary double-backslashes
  202. $content = str_replace('\\\\', '\\', $content);
  203. // Exchange "array (" width "array("
  204. $content = str_replace('array (', 'array(', $content);
  205. // Allign "=>" operators to match coding standard
  206. preg_match_all('(\n\s+([^=]+)=>)', $content, $matches, PREG_SET_ORDER);
  207. $maxWidth = 0;
  208. foreach ($matches as $match) {
  209. $maxWidth = max($maxWidth, strlen($match[1]));
  210. }
  211. $content = preg_replace('(\n\s+([^=]+)=>)e', "'\n \\1' . str_repeat(' ', " . $maxWidth . " - strlen('\\1')) . '=>'", $content);
  212. // Write the contents to disk
  213. file_put_contents($output, $content);
  214. if (!$usingStdout) {
  215. echo "Wrote classmap file to '" . realpath($output) . "'" . PHP_EOL;
  216. }