build_bootstrap.php 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. #!/usr/bin/env php
  2. <?php
  3. /*
  4. * This file is part of Mustache.php.
  5. *
  6. * (c) 2010-2014 Justin Hileman
  7. *
  8. * For the full copyright and license information, please view the LICENSE
  9. * file that was distributed with this source code.
  10. */
  11. /**
  12. * A shell script to create a single-file class cache of the entire Mustache
  13. * library:
  14. *
  15. * $ bin/build_bootstrap.php
  16. *
  17. * ... will create a `mustache.php` bootstrap file in the project directory,
  18. * containing all Mustache library classes. This file can then be included in
  19. * your project, rather than requiring the Mustache Autoloader.
  20. */
  21. $baseDir = realpath(dirname(__FILE__) . '/..');
  22. require $baseDir . '/src/Mustache/Autoloader.php';
  23. Mustache_Autoloader::register();
  24. // delete the old file
  25. $file = $baseDir . '/mustache.php';
  26. if (file_exists($file)) {
  27. unlink($file);
  28. }
  29. // and load the new one
  30. SymfonyClassCollectionLoader::load(array(
  31. 'Mustache_Engine',
  32. 'Mustache_Cache',
  33. 'Mustache_Cache_AbstractCache',
  34. 'Mustache_Cache_FilesystemCache',
  35. 'Mustache_Cache_NoopCache',
  36. 'Mustache_Compiler',
  37. 'Mustache_Context',
  38. 'Mustache_Exception',
  39. 'Mustache_Exception_InvalidArgumentException',
  40. 'Mustache_Exception_LogicException',
  41. 'Mustache_Exception_RuntimeException',
  42. 'Mustache_Exception_SyntaxException',
  43. 'Mustache_Exception_UnknownFilterException',
  44. 'Mustache_Exception_UnknownHelperException',
  45. 'Mustache_Exception_UnknownTemplateException',
  46. 'Mustache_HelperCollection',
  47. 'Mustache_LambdaHelper',
  48. 'Mustache_Loader',
  49. 'Mustache_Loader_ArrayLoader',
  50. 'Mustache_Loader_CascadingLoader',
  51. 'Mustache_Loader_FilesystemLoader',
  52. 'Mustache_Loader_InlineLoader',
  53. 'Mustache_Loader_MutableLoader',
  54. 'Mustache_Loader_StringLoader',
  55. 'Mustache_Logger',
  56. 'Mustache_Logger_AbstractLogger',
  57. 'Mustache_Logger_StreamLogger',
  58. 'Mustache_Parser',
  59. 'Mustache_Template',
  60. 'Mustache_Tokenizer',
  61. ), dirname($file), basename($file, '.php'));
  62. /**
  63. * SymfonyClassCollectionLoader.
  64. *
  65. * Based heavily on the Symfony ClassCollectionLoader component, with all
  66. * the unnecessary bits removed.
  67. *
  68. * @license http://www.opensource.org/licenses/MIT
  69. *
  70. * @author Fabien Potencier <fabien@symfony.com>
  71. */
  72. class SymfonyClassCollectionLoader
  73. {
  74. static private $loaded;
  75. const HEADER = <<<EOS
  76. <?php
  77. /*
  78. * This file is part of Mustache.php.
  79. *
  80. * (c) 2010-%d Justin Hileman
  81. *
  82. * For the full copyright and license information, please view the LICENSE
  83. * file that was distributed with this source code.
  84. */
  85. EOS;
  86. /**
  87. * Loads a list of classes and caches them in one big file.
  88. *
  89. * @param array $classes An array of classes to load
  90. * @param string $cacheDir A cache directory
  91. * @param string $name The cache name prefix
  92. * @param string $extension File extension of the resulting file
  93. *
  94. * @throws InvalidArgumentException When class can't be loaded
  95. */
  96. static public function load(array $classes, $cacheDir, $name, $extension = '.php')
  97. {
  98. // each $name can only be loaded once per PHP process
  99. if (isset(self::$loaded[$name])) {
  100. return;
  101. }
  102. self::$loaded[$name] = true;
  103. $content = '';
  104. foreach ($classes as $class) {
  105. if (!class_exists($class) && !interface_exists($class) && (!function_exists('trait_exists') || !trait_exists($class))) {
  106. throw new InvalidArgumentException(sprintf('Unable to load class "%s"', $class));
  107. }
  108. $r = new ReflectionClass($class);
  109. $content .= preg_replace(array('/^\s*<\?php/', '/\?>\s*$/'), '', file_get_contents($r->getFileName()));
  110. }
  111. $cache = $cacheDir . '/' . $name . $extension;
  112. $header = sprintf(self::HEADER, strftime('%Y'));
  113. self::writeCacheFile($cache, $header . substr(self::stripComments('<?php ' . $content), 5));
  114. }
  115. /**
  116. * Writes a cache file.
  117. *
  118. * @param string $file Filename
  119. * @param string $content Temporary file content
  120. *
  121. * @throws RuntimeException when a cache file cannot be written
  122. */
  123. static private function writeCacheFile($file, $content)
  124. {
  125. $tmpFile = tempnam(dirname($file), basename($file));
  126. if (false !== @file_put_contents($tmpFile, $content) && @rename($tmpFile, $file)) {
  127. chmod($file, 0666 & ~umask());
  128. return;
  129. }
  130. throw new RuntimeException(sprintf('Failed to write cache file "%s".', $file));
  131. }
  132. /**
  133. * Removes comments from a PHP source string.
  134. *
  135. * We don't use the PHP php_strip_whitespace() function
  136. * as we want the content to be readable and well-formatted.
  137. *
  138. * @param string $source A PHP string
  139. *
  140. * @return string The PHP string with the comments removed
  141. */
  142. static private function stripComments($source)
  143. {
  144. if (!function_exists('token_get_all')) {
  145. return $source;
  146. }
  147. $output = '';
  148. foreach (token_get_all($source) as $token) {
  149. if (is_string($token)) {
  150. $output .= $token;
  151. } elseif (!in_array($token[0], array(T_COMMENT, T_DOC_COMMENT))) {
  152. $output .= $token[1];
  153. }
  154. }
  155. // replace multiple new lines with a single newline
  156. $output = preg_replace(array('/\s+$/Sm', '/\n+/S'), "\n", $output);
  157. return $output;
  158. }
  159. }