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

/src/autoloadbuilder.php

http://github.com/theseer/Autoload
PHP | 313 lines | 103 code | 33 blank | 177 comment | 6 complexity | 020de7ad5f5ac536291a18948bc4a1b1 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. <?php
  2. /**
  3. * Copyright (c) 2009-2012 Arne Blankerts <arne@blankerts.de>
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without modification,
  7. * are permitted provided that the following conditions are met:
  8. *
  9. * * Redistributions of source code must retain the above copyright notice,
  10. * this list of conditions and the following disclaimer.
  11. *
  12. * * Redistributions in binary form must reproduce the above copyright notice,
  13. * this list of conditions and the following disclaimer in the documentation
  14. * and/or other materials provided with the distribution.
  15. *
  16. * * Neither the name of Arne Blankerts nor the names of contributors
  17. * may be used to endorse or promote products derived from this software
  18. * without specific prior written permission.
  19. *
  20. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  21. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO,
  22. * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  23. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER ORCONTRIBUTORS
  24. * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
  25. * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  26. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  27. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  28. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  29. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  30. * POSSIBILITY OF SUCH DAMAGE.
  31. *
  32. * @package Autoload
  33. * @author Arne Blankerts <arne@blankerts.de>
  34. * @copyright Arne Blankerts <arne@blankerts.de>, All rights reserved.
  35. * @license BSD License
  36. */
  37. namespace TheSeer\Autoload {
  38. /**
  39. * Builds spl based autoload code for inclusion into projects
  40. *
  41. * @author Arne Blankerts <arne@blankerts.de>
  42. * @copyright Arne Blankerts <arne@blankerts.de>, All rights reserved.
  43. */
  44. class AutoloadBuilder {
  45. /**
  46. * Associative array of classes (key) and the files (value) they are in
  47. *
  48. * @var array
  49. */
  50. protected $classes;
  51. /**
  52. * An optional base dir to strip for the realpath of the filename
  53. *
  54. * @var string
  55. */
  56. protected $baseDir;
  57. /**
  58. * Indenting char(s)
  59. *
  60. * @var string
  61. */
  62. protected $indent;
  63. /**
  64. * Char(s) used as linebreak
  65. *
  66. * @var string
  67. */
  68. protected $linebreak = "\n";
  69. /**
  70. * PHP Template code to render autoload list
  71. *
  72. * @var string
  73. */
  74. protected $template;
  75. /**
  76. * Timestamp of production start
  77. *
  78. * @var integer
  79. */
  80. protected $timestamp;
  81. /**
  82. * Format string supplied to date() for use with ___CREATED___
  83. *
  84. * @var string
  85. */
  86. protected $dateformat = 'r';
  87. /**
  88. * Variables for templates
  89. *
  90. * @var array
  91. */
  92. protected $variables = array();
  93. /**
  94. * Flag to toggle PHP 5.2 compat mode
  95. *
  96. * @var boolean
  97. */
  98. protected $compat = false;
  99. /**
  100. * Constructor of AutoloadBuilder class
  101. *
  102. * @param array $classlist Array of classes
  103. * @param string $baseDir Base folder for class files
  104. * @param string $tpl Template file to use for generated code
  105. * @param string $indent Chars to set default indenting to
  106. *
  107. * @return void
  108. */
  109. public function __construct(array $classlist, $baseDir = '', $caseSensitive = false, $indent = ' ') {
  110. $this->classes = $classlist;
  111. ksort($this->classes);
  112. $this->baseDir = $baseDir;
  113. $this->indent = $indent;
  114. $this->setTemplateFile( __DIR__ . '/templates/' . ($caseSensitive ? 'cs' : 'ci') . '/default.php.tpl' );
  115. }
  116. /**
  117. * Toggle PHP 5.2 compat mode
  118. *
  119. * @param boolean $mode Mode to set compat to
  120. */
  121. public function setCompat($mode) {
  122. $this->compat = $mode;
  123. }
  124. /**
  125. * Setter to load a new template from a file
  126. *
  127. * @param string $fname File to load as template
  128. *
  129. * @return void
  130. */
  131. public function setTemplateFile($fname) {
  132. if (!file_exists($fname)) {
  133. throw new AutoloadBuilderException("Template '$fname' not found.", AutoloadBuilderException::TemplateNotFound);
  134. }
  135. $this->template = file_get_contents($fname);
  136. }
  137. /**
  138. * Setter for Template from string
  139. *
  140. * @param string $tpl Template code string
  141. *
  142. * @return void
  143. */
  144. public function setTemplateCode($tpl) {
  145. $this->template = $tpl;
  146. }
  147. /**
  148. * Setter for the Basedir
  149. *
  150. * @param string $dir Path to strip from beginning of filenames
  151. *
  152. * @return void
  153. */
  154. public function setBaseDir($dir) {
  155. $this->baseDir = $dir;
  156. }
  157. /**
  158. * Overwrite default or previously set indenting option
  159. *
  160. * @param string $indent Char(s) to use for indenting
  161. *
  162. * @return void
  163. */
  164. public function setIndent($indent) {
  165. $this->indent = $indent;
  166. }
  167. /**
  168. * Overwrite default or previously set linebreak chars
  169. *
  170. * @param string $lbs Code to set linebreak
  171. *
  172. * @return void
  173. */
  174. public function setLineBreak($lbs) {
  175. $this->linebreak = $lbs;
  176. }
  177. /**
  178. * Accessor for current linebreak setting
  179. *
  180. * @return string
  181. */
  182. public function getLineBreak() {
  183. return $this->linebreak;
  184. }
  185. /**
  186. * Setter to use allow usage of fixed date/time for ___CREATED___
  187. *
  188. * @param integer $time unix timestamp
  189. */
  190. public function setTimestamp($time) {
  191. if (!is_int($time) && !is_null($time)) {
  192. throw new AutoloadBuilderException("'$time' is not a unix timestamp", AutoloadBuilderException::InvalidTimestamp);
  193. }
  194. $this->timestamp = $time;
  195. }
  196. /**
  197. * Setter to adjust the date/time format output of ___CREATED___
  198. *
  199. * @param string $frmt Date/Time format string
  200. */
  201. public function setDateTimeFormat($frmt) {
  202. $this->dateformat = $frmt;
  203. }
  204. /**
  205. * Set a variable for use with template code
  206. *
  207. * @param string $name Key name (use as ___key___ in template)
  208. * @param string $value Value to use
  209. */
  210. public function setVariable($name, $value) {
  211. $this->variables['___'.$name.'___'] = $value;
  212. }
  213. /**
  214. * Resolve relative location of file path to basedir if one is set and fix potential
  215. * broken windows pathnames when run on windows.
  216. *
  217. * @param string $fname
  218. *
  219. * @return string
  220. */
  221. protected function resolvePath($fname) {
  222. if (empty($this->baseDir)) {
  223. return str_replace('\\', '/', $fname);
  224. }
  225. $basedir = explode(DIRECTORY_SEPARATOR, $this->baseDir);
  226. $filedir = explode(DIRECTORY_SEPARATOR, dirname(realpath($fname)));
  227. $pos = 0;
  228. $max = count($basedir);
  229. while ($filedir[$pos] == $basedir[$pos]) {
  230. $pos++;
  231. if ($pos == $max) break;
  232. }
  233. if ($pos == 0) {
  234. return str_replace('\\', '/', $fname);
  235. }
  236. $rel = join('/', array_slice($filedir, $pos));
  237. if ($pos<count($basedir)) {
  238. $rel = str_repeat('../', count($basedir)-$pos) . $rel;
  239. }
  240. return '/' . (!empty($rel) ? $rel . '/' : '') . basename($fname);
  241. }
  242. /**
  243. * Render autoload code into a string
  244. *
  245. * @return string
  246. */
  247. public function render() {
  248. $entries = array();
  249. foreach($this->classes as $class => $file) {
  250. $fname = $this->resolvePath($file);
  251. $entries[] = "'$class' => '$fname'";
  252. }
  253. $baseDir = '';
  254. if ($this->baseDir) {
  255. $baseDir = $this->compat ? 'dirname(__FILE__) . ' : '__DIR__ . ';
  256. }
  257. $replace = array_merge($this->variables, array(
  258. '___CREATED___' => date( $this->dateformat, $this->timestamp ? $this->timestamp : time()),
  259. '___CLASSLIST___' => join( ',' . $this->linebreak . $this->indent, $entries),
  260. '___BASEDIR___' => $baseDir,
  261. '___AUTOLOAD___' => 'autoload' . md5(serialize($entries))
  262. ));
  263. return str_replace(array_keys($replace), array_values($replace), $this->template);
  264. }
  265. /**
  266. * Save autoload code to given filename
  267. *
  268. * @param string $filename Filename to store code in
  269. *
  270. * @return integer|boolean
  271. */
  272. public function save($filename) {
  273. return file_put_contents($filename, $this->render());
  274. }
  275. }
  276. class AutoloadBuilderException extends \Exception {
  277. const TemplateNotFound = 1;
  278. const InvalidTimestamp = 2;
  279. }
  280. }