PageRenderTime 83ms CodeModel.GetById 25ms RepoModel.GetById 1ms app.codeStats 0ms

/src/application/libraries/Zend/CodeGenerator/Php/File.php

https://bitbucket.org/masnug/grc276-blog-laravel
PHP | 468 lines | 379 code | 26 blank | 63 comment | 20 complexity | 6645e93ce395bf8b758248fc40f89aea MD5 | raw file
  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_CodeGenerator
  17. * @subpackage PHP
  18. * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
  19. * @license http://framework.zend.com/license/new-bsd New BSD License
  20. * @version $Id: File.php 24457 2011-09-11 13:34:44Z padraic $
  21. */
  22. /**
  23. * @see Zend_CodeGenerator_Php_Abstract
  24. */
  25. require_once 'Zend/CodeGenerator/Php/Abstract.php';
  26. /**
  27. * @see Zend_CodeGenerator_Php_Class
  28. */
  29. require_once 'Zend/CodeGenerator/Php/Class.php';
  30. /**
  31. * @category Zend
  32. * @package Zend_CodeGenerator
  33. * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
  34. * @license http://framework.zend.com/license/new-bsd New BSD License
  35. */
  36. class Zend_CodeGenerator_Php_File extends Zend_CodeGenerator_Php_Abstract
  37. {
  38. /**
  39. * @var array Array of Zend_CodeGenerator_Php_File
  40. */
  41. protected static $_fileCodeGenerators = array();
  42. /**#@+
  43. * @var string
  44. */
  45. protected static $_markerDocblock = '/* Zend_CodeGenerator_Php_File-DocblockMarker */';
  46. protected static $_markerRequire = '/* Zend_CodeGenerator_Php_File-RequireMarker: {?} */';
  47. protected static $_markerClass = '/* Zend_CodeGenerator_Php_File-ClassMarker: {?} */';
  48. /**#@-*/
  49. /**
  50. * @var string
  51. */
  52. protected $_filename = null;
  53. /**
  54. * @var Zend_CodeGenerator_Php_Docblock
  55. */
  56. protected $_docblock = null;
  57. /**
  58. * @var array
  59. */
  60. protected $_requiredFiles = array();
  61. /**
  62. * @var array
  63. */
  64. protected $_classes = array();
  65. /**
  66. * @var string
  67. */
  68. protected $_body = null;
  69. public static function registerFileCodeGenerator(Zend_CodeGenerator_Php_File $fileCodeGenerator, $fileName = null)
  70. {
  71. if ($fileName == null) {
  72. $fileName = $fileCodeGenerator->getFilename();
  73. }
  74. if ($fileName == '') {
  75. require_once 'Zend/CodeGenerator/Php/Exception.php';
  76. throw new Zend_CodeGenerator_Php_Exception('FileName does not exist.');
  77. }
  78. // cannot use realpath since the file might not exist, but we do need to have the index
  79. // in the same DIRECTORY_SEPARATOR that realpath would use:
  80. $fileName = str_replace(array('\\', '/'), DIRECTORY_SEPARATOR, $fileName);
  81. self::$_fileCodeGenerators[$fileName] = $fileCodeGenerator;
  82. }
  83. /**
  84. * fromReflectedFileName() - use this if you intend on generating code generation objects based on the same file.
  85. * This will keep previous changes to the file in tact during the same PHP process
  86. *
  87. * @param string $filePath
  88. * @param bool $usePreviousCodeGeneratorIfItExists
  89. * @param bool $includeIfNotAlreadyIncluded
  90. * @return Zend_CodeGenerator_Php_File
  91. */
  92. public static function fromReflectedFileName($filePath, $usePreviousCodeGeneratorIfItExists = true, $includeIfNotAlreadyIncluded = true)
  93. {
  94. $realpath = realpath($filePath);
  95. if ($realpath === false) {
  96. if ( ($realpath = Zend_Reflection_file::findRealpathInIncludePath($filePath)) === false) {
  97. require_once 'Zend/CodeGenerator/Php/Exception.php';
  98. throw new Zend_CodeGenerator_Php_Exception('No file for ' . $realpath . ' was found.');
  99. }
  100. }
  101. if ($usePreviousCodeGeneratorIfItExists && isset(self::$_fileCodeGenerators[$realpath])) {
  102. return self::$_fileCodeGenerators[$realpath];
  103. }
  104. if ($includeIfNotAlreadyIncluded && !in_array($realpath, get_included_files())) {
  105. include $realpath;
  106. }
  107. $codeGenerator = self::fromReflection(($fileReflector = new Zend_Reflection_File($realpath)));
  108. if (!isset(self::$_fileCodeGenerators[$fileReflector->getFileName()])) {
  109. self::$_fileCodeGenerators[$fileReflector->getFileName()] = $codeGenerator;
  110. }
  111. return $codeGenerator;
  112. }
  113. /**
  114. * fromReflection()
  115. *
  116. * @param Zend_Reflection_File $reflectionFile
  117. * @return Zend_CodeGenerator_Php_File
  118. */
  119. public static function fromReflection(Zend_Reflection_File $reflectionFile)
  120. {
  121. $file = new self();
  122. $file->setSourceContent($reflectionFile->getContents());
  123. $file->setSourceDirty(false);
  124. $body = $reflectionFile->getContents();
  125. // @todo this whole area needs to be reworked with respect to how body lines are processed
  126. foreach ($reflectionFile->getClasses() as $class) {
  127. $file->setClass(Zend_CodeGenerator_Php_Class::fromReflection($class));
  128. $classStartLine = $class->getStartLine(true);
  129. $classEndLine = $class->getEndLine();
  130. $bodyLines = explode("\n", $body);
  131. $bodyReturn = array();
  132. for ($lineNum = 1; $lineNum <= count($bodyLines); $lineNum++) {
  133. if ($lineNum == $classStartLine) {
  134. $bodyReturn[] = str_replace('?', $class->getName(), self::$_markerClass); //'/* Zend_CodeGenerator_Php_File-ClassMarker: {' . $class->getName() . '} */';
  135. $lineNum = $classEndLine;
  136. } else {
  137. $bodyReturn[] = $bodyLines[$lineNum - 1]; // adjust for index -> line conversion
  138. }
  139. }
  140. $body = implode("\n", $bodyReturn);
  141. unset($bodyLines, $bodyReturn, $classStartLine, $classEndLine);
  142. }
  143. if (($reflectionFile->getDocComment() != '')) {
  144. $docblock = $reflectionFile->getDocblock();
  145. $file->setDocblock(Zend_CodeGenerator_Php_Docblock::fromReflection($docblock));
  146. $bodyLines = explode("\n", $body);
  147. $bodyReturn = array();
  148. for ($lineNum = 1; $lineNum <= count($bodyLines); $lineNum++) {
  149. if ($lineNum == $docblock->getStartLine()) {
  150. $bodyReturn[] = str_replace('?', $class->getName(), self::$_markerDocblock); //'/* Zend_CodeGenerator_Php_File-ClassMarker: {' . $class->getName() . '} */';
  151. $lineNum = $docblock->getEndLine();
  152. } else {
  153. $bodyReturn[] = $bodyLines[$lineNum - 1]; // adjust for index -> line conversion
  154. }
  155. }
  156. $body = implode("\n", $bodyReturn);
  157. unset($bodyLines, $bodyReturn, $classStartLine, $classEndLine);
  158. }
  159. $file->setBody($body);
  160. return $file;
  161. }
  162. /**
  163. * setDocblock() Set the docblock
  164. *
  165. * @param Zend_CodeGenerator_Php_Docblock|array|string $docblock
  166. * @return Zend_CodeGenerator_Php_File
  167. */
  168. public function setDocblock($docblock)
  169. {
  170. if (is_string($docblock)) {
  171. $docblock = array('shortDescription' => $docblock);
  172. }
  173. if (is_array($docblock)) {
  174. $docblock = new Zend_CodeGenerator_Php_Docblock($docblock);
  175. } elseif (!$docblock instanceof Zend_CodeGenerator_Php_Docblock) {
  176. require_once 'Zend/CodeGenerator/Php/Exception.php';
  177. throw new Zend_CodeGenerator_Php_Exception('setDocblock() is expecting either a string, array or an instance of Zend_CodeGenerator_Php_Docblock');
  178. }
  179. $this->_docblock = $docblock;
  180. return $this;
  181. }
  182. /**
  183. * Get docblock
  184. *
  185. * @return Zend_CodeGenerator_Php_Docblock
  186. */
  187. public function getDocblock()
  188. {
  189. return $this->_docblock;
  190. }
  191. /**
  192. * setRequiredFiles
  193. *
  194. * @param array $requiredFiles
  195. * @return Zend_CodeGenerator_Php_File
  196. */
  197. public function setRequiredFiles($requiredFiles)
  198. {
  199. $this->_requiredFiles = $requiredFiles;
  200. return $this;
  201. }
  202. /**
  203. * getRequiredFiles()
  204. *
  205. * @return array
  206. */
  207. public function getRequiredFiles()
  208. {
  209. return $this->_requiredFiles;
  210. }
  211. /**
  212. * setClasses()
  213. *
  214. * @param array $classes
  215. * @return Zend_CodeGenerator_Php_File
  216. */
  217. public function setClasses(Array $classes)
  218. {
  219. foreach ($classes as $class) {
  220. $this->setClass($class);
  221. }
  222. return $this;
  223. }
  224. /**
  225. * getClass()
  226. *
  227. * @param string $name
  228. * @return Zend_CodeGenerator_Php_Class
  229. */
  230. public function getClass($name = null)
  231. {
  232. if ($name == null) {
  233. reset($this->_classes);
  234. return current($this->_classes);
  235. }
  236. return $this->_classes[$name];
  237. }
  238. /**
  239. * setClass()
  240. *
  241. * @param Zend_CodeGenerator_Php_Class|array $class
  242. * @return Zend_CodeGenerator_Php_File
  243. */
  244. public function setClass($class)
  245. {
  246. if (is_array($class)) {
  247. $class = new Zend_CodeGenerator_Php_Class($class);
  248. $className = $class->getName();
  249. } elseif ($class instanceof Zend_CodeGenerator_Php_Class) {
  250. $className = $class->getName();
  251. } else {
  252. require_once 'Zend/CodeGenerator/Php/Exception.php';
  253. throw new Zend_CodeGenerator_Php_Exception('Expecting either an array or an instance of Zend_CodeGenerator_Php_Class');
  254. }
  255. // @todo check for dup here
  256. $this->_classes[$className] = $class;
  257. return $this;
  258. }
  259. /**
  260. * setFilename()
  261. *
  262. * @param string $filename
  263. * @return Zend_CodeGenerator_Php_File
  264. */
  265. public function setFilename($filename)
  266. {
  267. $this->_filename = $filename;
  268. return $this;
  269. }
  270. /**
  271. * getFilename()
  272. *
  273. * @return string
  274. */
  275. public function getFilename()
  276. {
  277. return $this->_filename;
  278. }
  279. /**
  280. * getClasses()
  281. *
  282. * @return array Array of Zend_CodeGenerator_Php_Class
  283. */
  284. public function getClasses()
  285. {
  286. return $this->_classes;
  287. }
  288. /**
  289. * setBody()
  290. *
  291. * @param string $body
  292. * @return Zend_CodeGenerator_Php_File
  293. */
  294. public function setBody($body)
  295. {
  296. $this->_body = $body;
  297. return $this;
  298. }
  299. /**
  300. * getBody()
  301. *
  302. * @return string
  303. */
  304. public function getBody()
  305. {
  306. return $this->_body;
  307. }
  308. /**
  309. * isSourceDirty()
  310. *
  311. * @return bool
  312. */
  313. public function isSourceDirty()
  314. {
  315. if (($docblock = $this->getDocblock()) && $docblock->isSourceDirty()) {
  316. return true;
  317. }
  318. foreach ($this->_classes as $class) {
  319. if ($class->isSourceDirty()) {
  320. return true;
  321. }
  322. }
  323. return parent::isSourceDirty();
  324. }
  325. /**
  326. * generate()
  327. *
  328. * @return string
  329. */
  330. public function generate()
  331. {
  332. if ($this->isSourceDirty() === false) {
  333. return $this->_sourceContent;
  334. }
  335. $output = '';
  336. // start with the body (if there), or open tag
  337. if (preg_match('#(?:\s*)<\?php#', $this->getBody()) == false) {
  338. $output = '<?php' . self::LINE_FEED;
  339. }
  340. // if there are markers, put the body into the output
  341. $body = $this->getBody();
  342. if (preg_match('#/\* Zend_CodeGenerator_Php_File-(.*?)Marker#', $body)) {
  343. $output .= $body;
  344. $body = '';
  345. }
  346. // Add file docblock, if any
  347. if (null !== ($docblock = $this->getDocblock())) {
  348. $docblock->setIndentation('');
  349. $regex = preg_quote(self::$_markerDocblock, '#');
  350. if (preg_match('#'.$regex.'#', $output)) {
  351. $output = preg_replace('#'.$regex.'#', $docblock->generate(), $output, 1);
  352. } else {
  353. $output .= $docblock->generate() . self::LINE_FEED;
  354. }
  355. }
  356. // newline
  357. $output .= self::LINE_FEED;
  358. // process required files
  359. // @todo marker replacement for required files
  360. $requiredFiles = $this->getRequiredFiles();
  361. if (!empty($requiredFiles)) {
  362. foreach ($requiredFiles as $requiredFile) {
  363. $output .= 'require_once \'' . $requiredFile . '\';' . self::LINE_FEED;
  364. }
  365. $output .= self::LINE_FEED;
  366. }
  367. // process classes
  368. $classes = $this->getClasses();
  369. if (!empty($classes)) {
  370. foreach ($classes as $class) {
  371. if($this->getDocblock() == $class->getDocblock()) {
  372. $class->setDocblock(null);
  373. }
  374. $regex = str_replace('?', $class->getName(), self::$_markerClass);
  375. $regex = preg_quote($regex, '#');
  376. if (preg_match('#'.$regex.'#', $output)) {
  377. $output = preg_replace('#'.$regex.'#', $class->generate(), $output, 1);
  378. } else {
  379. $output .= $class->generate() . self::LINE_FEED;
  380. }
  381. }
  382. }
  383. if (!empty($body)) {
  384. // add an extra space betwee clsses and
  385. if (!empty($classes)) {
  386. $output .= self::LINE_FEED;
  387. }
  388. $output .= $body;
  389. }
  390. return $output;
  391. }
  392. public function write()
  393. {
  394. if ($this->_filename == '' || !is_writable(dirname($this->_filename))) {
  395. require_once 'Zend/CodeGenerator/Php/Exception.php';
  396. throw new Zend_CodeGenerator_Php_Exception('This code generator object is not writable.');
  397. }
  398. file_put_contents($this->_filename, $this->generate());
  399. return $this;
  400. }
  401. }