Class.php 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618
  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-2015 Zend Technologies USA Inc. (http://www.zend.com)
  19. * @license http://framework.zend.com/license/new-bsd New BSD License
  20. * @version $Id$
  21. */
  22. /**
  23. * @see Zend_CodeGenerator_Php_Abstract
  24. */
  25. require_once 'Zend/CodeGenerator/Php/Abstract.php';
  26. /**
  27. * @see Zend_CodeGenerator_Php_Member_Container
  28. */
  29. require_once 'Zend/CodeGenerator/Php/Member/Container.php';
  30. /**
  31. * @see Zend_CodeGenerator_Php_Method
  32. */
  33. require_once 'Zend/CodeGenerator/Php/Method.php';
  34. /**
  35. * @see Zend_CodeGenerator_Php_Property
  36. */
  37. require_once 'Zend/CodeGenerator/Php/Property.php';
  38. /**
  39. * @see Zend_CodeGenerator_Php_Docblock
  40. */
  41. require_once 'Zend/CodeGenerator/Php/Docblock.php';
  42. /**
  43. * @category Zend
  44. * @package Zend_CodeGenerator
  45. * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
  46. * @license http://framework.zend.com/license/new-bsd New BSD License
  47. */
  48. class Zend_CodeGenerator_Php_Class extends Zend_CodeGenerator_Php_Abstract
  49. {
  50. /**
  51. * @var Zend_CodeGenerator_Php_Docblock
  52. */
  53. protected $_docblock = null;
  54. /**
  55. * @var string
  56. */
  57. protected $_name = null;
  58. /**
  59. * @var bool
  60. */
  61. protected $_isAbstract = false;
  62. /**
  63. * @var string
  64. */
  65. protected $_extendedClass = null;
  66. /**
  67. * @var array Array of string names
  68. */
  69. protected $_implementedInterfaces = array();
  70. /**
  71. * @var array Array of properties
  72. */
  73. protected $_properties = null;
  74. /**
  75. * @var array Array of constants
  76. */
  77. protected $_constants = null;
  78. /**
  79. * @var array Array of methods
  80. */
  81. protected $_methods = null;
  82. /**
  83. * fromReflection() - build a Code Generation PHP Object from a Class Reflection
  84. *
  85. * @param Zend_Reflection_Class $reflectionClass
  86. * @return Zend_CodeGenerator_Php_Class
  87. */
  88. public static function fromReflection(Zend_Reflection_Class $reflectionClass)
  89. {
  90. $class = new self();
  91. $class->setSourceContent($class->getSourceContent());
  92. $class->setSourceDirty(false);
  93. if ($reflectionClass->getDocComment() != '') {
  94. $class->setDocblock(Zend_CodeGenerator_Php_Docblock::fromReflection($reflectionClass->getDocblock()));
  95. }
  96. $class->setAbstract($reflectionClass->isAbstract());
  97. $class->setName($reflectionClass->getName());
  98. if ($parentClass = $reflectionClass->getParentClass()) {
  99. $class->setExtendedClass($parentClass->getName());
  100. $interfaces = array_diff($reflectionClass->getInterfaces(), $parentClass->getInterfaces());
  101. } else {
  102. $interfaces = $reflectionClass->getInterfaces();
  103. }
  104. $interfaceNames = array();
  105. foreach($interfaces AS $interface) {
  106. $interfaceNames[] = $interface->getName();
  107. }
  108. $class->setImplementedInterfaces($interfaceNames);
  109. $properties = array();
  110. foreach ($reflectionClass->getProperties() as $reflectionProperty) {
  111. if ($reflectionProperty->getDeclaringClass()->getName() == $class->getName()) {
  112. $properties[] = Zend_CodeGenerator_Php_Property::fromReflection($reflectionProperty);
  113. }
  114. }
  115. $class->setProperties($properties);
  116. $methods = array();
  117. foreach ($reflectionClass->getMethods() as $reflectionMethod) {
  118. if ($reflectionMethod->getDeclaringClass()->getName() == $class->getName()) {
  119. $methods[] = Zend_CodeGenerator_Php_Method::fromReflection($reflectionMethod);
  120. }
  121. }
  122. $class->setMethods($methods);
  123. return $class;
  124. }
  125. /**
  126. * setDocblock() Set the docblock
  127. *
  128. * @param Zend_CodeGenerator_Php_Docblock|array|string $docblock
  129. * @return Zend_CodeGenerator_Php_File
  130. */
  131. public function setDocblock($docblock)
  132. {
  133. if (is_string($docblock)) {
  134. $docblock = array('shortDescription' => $docblock);
  135. }
  136. if (is_array($docblock)) {
  137. $docblock = new Zend_CodeGenerator_Php_Docblock($docblock);
  138. } elseif ((!is_null($docblock)) && (!$docblock instanceof Zend_CodeGenerator_Php_Docblock)) {
  139. require_once 'Zend/CodeGenerator/Php/Exception.php';
  140. throw new Zend_CodeGenerator_Php_Exception('setDocblock() is expecting either a string, array or an instance of Zend_CodeGenerator_Php_Docblock');
  141. }
  142. $this->_docblock = $docblock;
  143. return $this;
  144. }
  145. /**
  146. * getDocblock()
  147. *
  148. * @return Zend_CodeGenerator_Php_Docblock
  149. */
  150. public function getDocblock()
  151. {
  152. return $this->_docblock;
  153. }
  154. /**
  155. * setName()
  156. *
  157. * @param string $name
  158. * @return Zend_CodeGenerator_Php_Class
  159. */
  160. public function setName($name)
  161. {
  162. $this->_name = $name;
  163. return $this;
  164. }
  165. /**
  166. * getName()
  167. *
  168. * @return string
  169. */
  170. public function getName()
  171. {
  172. return $this->_name;
  173. }
  174. /**
  175. * setAbstract()
  176. *
  177. * @param bool $isAbstract
  178. * @return Zend_CodeGenerator_Php_Class
  179. */
  180. public function setAbstract($isAbstract)
  181. {
  182. $this->_isAbstract = ($isAbstract) ? true : false;
  183. return $this;
  184. }
  185. /**
  186. * isAbstract()
  187. *
  188. * @return bool
  189. */
  190. public function isAbstract()
  191. {
  192. return $this->_isAbstract;
  193. }
  194. /**
  195. * setExtendedClass()
  196. *
  197. * @param string $extendedClass
  198. * @return Zend_CodeGenerator_Php_Class
  199. */
  200. public function setExtendedClass($extendedClass)
  201. {
  202. $this->_extendedClass = $extendedClass;
  203. return $this;
  204. }
  205. /**
  206. * getExtendedClass()
  207. *
  208. * @return string
  209. */
  210. public function getExtendedClass()
  211. {
  212. return $this->_extendedClass;
  213. }
  214. /**
  215. * setImplementedInterfaces()
  216. *
  217. * @param array $implementedInterfaces
  218. * @return Zend_CodeGenerator_Php_Class
  219. */
  220. public function setImplementedInterfaces(Array $implementedInterfaces)
  221. {
  222. $this->_implementedInterfaces = $implementedInterfaces;
  223. return $this;
  224. }
  225. /**
  226. * getImplementedInterfaces
  227. *
  228. * @return array
  229. */
  230. public function getImplementedInterfaces()
  231. {
  232. return $this->_implementedInterfaces;
  233. }
  234. /**
  235. * setProperties()
  236. *
  237. * @param array $properties
  238. * @return Zend_CodeGenerator_Php_Class
  239. */
  240. public function setProperties(Array $properties)
  241. {
  242. foreach ($properties as $property) {
  243. $this->setProperty($property);
  244. }
  245. return $this;
  246. }
  247. /**
  248. * setConstants()
  249. *
  250. * @param array $constants
  251. * @return Zend_CodeGenerator_Php_Class
  252. */
  253. public function setConstants(Array $constants)
  254. {
  255. foreach ($constants as $const) {
  256. $this->setConstant($const);
  257. }
  258. return $this;
  259. }
  260. /**
  261. * setProperty()
  262. *
  263. * @param array|Zend_CodeGenerator_Php_Property $property
  264. * @return Zend_CodeGenerator_Php_Class
  265. */
  266. public function setProperty($property)
  267. {
  268. if (is_array($property)) {
  269. $property = new Zend_CodeGenerator_Php_Property($property);
  270. $propertyName = $property->getName();
  271. } elseif ($property instanceof Zend_CodeGenerator_Php_Property) {
  272. $propertyName = $property->getName();
  273. } else {
  274. require_once 'Zend/CodeGenerator/Php/Exception.php';
  275. throw new Zend_CodeGenerator_Php_Exception('setProperty() expects either an array of property options or an instance of Zend_CodeGenerator_Php_Property');
  276. }
  277. if ($property->isConst()) {
  278. return $this->setConstant($property);
  279. }
  280. if (isset($this->_properties[$propertyName])) {
  281. require_once 'Zend/CodeGenerator/Php/Exception.php';
  282. throw new Zend_CodeGenerator_Php_Exception('A property by name ' . $propertyName . ' already exists in this class.');
  283. }
  284. $this->_properties[$propertyName] = $property;
  285. return $this;
  286. }
  287. /**
  288. * setConstant()
  289. *
  290. * @param array|Zend_CodeGenerator_Php_Property $const
  291. * @return Zend_CodeGenerator_Php_Class
  292. */
  293. public function setConstant($const)
  294. {
  295. if (is_array($const)) {
  296. $const = new Zend_CodeGenerator_Php_Property($const);
  297. $constName = $const->getName();
  298. } elseif ($const instanceof Zend_CodeGenerator_Php_Property) {
  299. $constName = $const->getName();
  300. } else {
  301. require_once 'Zend/CodeGenerator/Php/Exception.php';
  302. throw new Zend_CodeGenerator_Php_Exception('setConstant() expects either an array of property options or an instance of Zend_CodeGenerator_Php_Property');
  303. }
  304. if (!$const->isConst()) {
  305. require_once 'Zend/CodeGenerator/Php/Exception.php';
  306. throw new Zend_CodeGenerator_Php_Exception('setProperty() expects argument to define a constant');
  307. }
  308. if (isset($this->_constants[$constName])) {
  309. require_once 'Zend/CodeGenerator/Php/Exception.php';
  310. throw new Zend_CodeGenerator_Php_Exception('A constant by name ' . $constName . ' already exists in this class.');
  311. }
  312. $this->_constants[$constName] = $const;
  313. return $this;
  314. }
  315. /**
  316. * getProperties()
  317. *
  318. * @return array
  319. */
  320. public function getProperties()
  321. {
  322. return $this->_properties;
  323. }
  324. /**
  325. * getConstants()
  326. *
  327. * @return array
  328. */
  329. public function getConstants()
  330. {
  331. return $this->_constants;
  332. }
  333. /**
  334. * getProperty()
  335. *
  336. * @param string $propertyName
  337. * @return Zend_CodeGenerator_Php_Property
  338. */
  339. public function getProperty($propertyName)
  340. {
  341. foreach ($this->_properties as $property) {
  342. if ($property->getName() == $propertyName) {
  343. return $property;
  344. }
  345. }
  346. return false;
  347. }
  348. /**
  349. * getConstant()
  350. *
  351. * @param string $constName
  352. * @return Zend_CodeGenerator_Php_Property
  353. */
  354. public function getConstant($constName)
  355. {
  356. foreach ($this->_constants as $const) {
  357. if ($const->getName() == $constName) {
  358. return $const;
  359. }
  360. }
  361. return false;
  362. }
  363. /**
  364. * hasProperty()
  365. *
  366. * @param string $propertyName
  367. * @return bool
  368. */
  369. public function hasProperty($propertyName)
  370. {
  371. return isset($this->_properties[$propertyName]);
  372. }
  373. /**
  374. * hasConstant()
  375. *
  376. * @param string $constName
  377. * @return bool
  378. */
  379. public function hasConstant($constName)
  380. {
  381. return isset($this->_constants[$constName]);
  382. }
  383. /**
  384. * setMethods()
  385. *
  386. * @param array $methods
  387. * @return Zend_CodeGenerator_Php_Class
  388. */
  389. public function setMethods(Array $methods)
  390. {
  391. foreach ($methods as $method) {
  392. $this->setMethod($method);
  393. }
  394. return $this;
  395. }
  396. /**
  397. * setMethod()
  398. *
  399. * @param array|Zend_CodeGenerator_Php_Method $method
  400. * @return Zend_CodeGenerator_Php_Class
  401. */
  402. public function setMethod($method)
  403. {
  404. if (is_array($method)) {
  405. $method = new Zend_CodeGenerator_Php_Method($method);
  406. $methodName = $method->getName();
  407. } elseif ($method instanceof Zend_CodeGenerator_Php_Method) {
  408. $methodName = $method->getName();
  409. } else {
  410. require_once 'Zend/CodeGenerator/Php/Exception.php';
  411. throw new Zend_CodeGenerator_Php_Exception('setMethod() expects either an array of method options or an instance of Zend_CodeGenerator_Php_Method');
  412. }
  413. if (isset($this->_methods[$methodName])) {
  414. require_once 'Zend/CodeGenerator/Php/Exception.php';
  415. throw new Zend_CodeGenerator_Php_Exception('A method by name ' . $methodName . ' already exists in this class.');
  416. }
  417. $this->_methods[$methodName] = $method;
  418. return $this;
  419. }
  420. /**
  421. * getMethods()
  422. *
  423. * @return array
  424. */
  425. public function getMethods()
  426. {
  427. return $this->_methods;
  428. }
  429. /**
  430. * getMethod()
  431. *
  432. * @param string $methodName
  433. * @return Zend_CodeGenerator_Php_Method
  434. */
  435. public function getMethod($methodName)
  436. {
  437. foreach ($this->_methods as $method) {
  438. if ($method->getName() == $methodName) {
  439. return $method;
  440. }
  441. }
  442. return false;
  443. }
  444. /**
  445. * hasMethod()
  446. *
  447. * @param string $methodName
  448. * @return bool
  449. */
  450. public function hasMethod($methodName)
  451. {
  452. return isset($this->_methods[$methodName]);
  453. }
  454. /**
  455. * isSourceDirty()
  456. *
  457. * @return bool
  458. */
  459. public function isSourceDirty()
  460. {
  461. if (($docblock = $this->getDocblock()) && $docblock->isSourceDirty()) {
  462. return true;
  463. }
  464. foreach ($this->_properties as $property) {
  465. if ($property->isSourceDirty()) {
  466. return true;
  467. }
  468. }
  469. foreach ($this->_constants as $constant) {
  470. if ($constant->isSourceDirty()) {
  471. return true;
  472. }
  473. }
  474. foreach ($this->_methods as $method) {
  475. if ($method->isSourceDirty()) {
  476. return true;
  477. }
  478. }
  479. return parent::isSourceDirty();
  480. }
  481. /**
  482. * generate()
  483. *
  484. * @return string
  485. */
  486. public function generate()
  487. {
  488. if (!$this->isSourceDirty()) {
  489. return $this->getSourceContent();
  490. }
  491. $output = '';
  492. if (null !== ($docblock = $this->getDocblock())) {
  493. $docblock->setIndentation('');
  494. $output .= $docblock->generate();
  495. }
  496. if ($this->isAbstract()) {
  497. $output .= 'abstract ';
  498. }
  499. $output .= 'class ' . $this->getName();
  500. if ( !empty( $this->_extendedClass) ) {
  501. $output .= ' extends ' . $this->_extendedClass;
  502. }
  503. $implemented = $this->getImplementedInterfaces();
  504. if (!empty($implemented)) {
  505. $output .= ' implements ' . implode(', ', $implemented);
  506. }
  507. $output .= self::LINE_FEED . '{' . self::LINE_FEED . self::LINE_FEED;
  508. $constants = $this->getConstants();
  509. if (!empty($constants)) {
  510. foreach ($constants as $const) {
  511. $output .= $const->generate() . self::LINE_FEED . self::LINE_FEED;
  512. }
  513. }
  514. $properties = $this->getProperties();
  515. if (!empty($properties)) {
  516. foreach ($properties as $property) {
  517. $output .= $property->generate() . self::LINE_FEED . self::LINE_FEED;
  518. }
  519. }
  520. $methods = $this->getMethods();
  521. if (!empty($methods)) {
  522. foreach ($methods as $method) {
  523. $output .= $method->generate() . self::LINE_FEED;
  524. }
  525. }
  526. $output .= self::LINE_FEED . '}' . self::LINE_FEED;
  527. return $output;
  528. }
  529. /**
  530. * _init() - is called at construction time
  531. *
  532. */
  533. protected function _init()
  534. {
  535. $this->_properties = new Zend_CodeGenerator_Php_Member_Container(Zend_CodeGenerator_Php_Member_Container::TYPE_PROPERTY);
  536. $this->_constants = new Zend_CodeGenerator_Php_Member_Container(Zend_CodeGenerator_Php_Member_Container::TYPE_PROPERTY);
  537. $this->_methods = new Zend_CodeGenerator_Php_Member_Container(Zend_CodeGenerator_Php_Member_Container::TYPE_METHOD);
  538. }
  539. }