PageRenderTime 41ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/application/libraries/Engine/Content/Element/Abstract.php

https://github.com/grandison/budo16
PHP | 614 lines | 465 code | 121 blank | 28 comment | 56 complexity | 50eb6eb11d88e44330e317077446db91 MD5 | raw file
  1. <?php
  2. /**
  3. * SocialEngine
  4. *
  5. * @category Engine
  6. * @package Engine_Content
  7. * @copyright Copyright 2006-2010 Webligo Developments
  8. * @license http://www.socialengine.net/license/
  9. * @version $Id: Abstract.php 7244 2010-09-01 01:49:53Z john $
  10. */
  11. /**
  12. * @category Engine
  13. * @package Engine_Content
  14. * @copyright Copyright 2006-2010 Webligo Developments
  15. * @license http://www.socialengine.net/license/
  16. */
  17. abstract class Engine_Content_Element_Abstract
  18. {
  19. // Constants
  20. const DECORATOR = 'DECORATOR';
  21. const ELEMENT = 'ELEMENT';
  22. // Properties
  23. protected $_attribs = array();
  24. protected $_belongsTo;
  25. protected $_decorators = array();
  26. protected $_elements = array();
  27. protected $_elementsNeedSort = false;
  28. protected $_elementsOrder = array();
  29. protected $_identity;
  30. protected $_loaders = array();
  31. protected $_name;
  32. protected $_noRender = false;
  33. protected $_order;
  34. protected $_params = array();
  35. protected $_parent;
  36. protected $_title;
  37. protected $_view;
  38. // General
  39. public function __construct($options = null)
  40. {
  41. if( is_array($options) ) {
  42. $this->setOptions($options);
  43. }
  44. $this->loadDefaultDecorators();
  45. }
  46. public function setOptions(array $options)
  47. {
  48. foreach( $options as $key => $value ) {
  49. $method = 'set' . ucfirst($key);
  50. if( method_exists($this, $method) ) {
  51. $this->$method($value);
  52. } else {
  53. $this->setAttrib($key, $value);
  54. }
  55. }
  56. return $this;
  57. }
  58. public function loadDefaultDecorators()
  59. {
  60. if( !empty($this->_decorators) ) {
  61. return;
  62. }
  63. $this
  64. ->addDecorator('Title')
  65. ->addDecorator('Container');
  66. }
  67. // Info
  68. public function setIdentity($identity)
  69. {
  70. $this->_identity = $identity;
  71. return $this;
  72. }
  73. public function getIdentity()
  74. {
  75. return $this->_identity;
  76. }
  77. public function setName($name)
  78. {
  79. $this->_name = (string) $name;
  80. return $this;
  81. }
  82. public function getName()
  83. {
  84. return $this->_name;
  85. }
  86. public function setTitle($title)
  87. {
  88. $this->_title = (string) $title;
  89. return $this;
  90. }
  91. public function getTitle()
  92. {
  93. return $this->_title;
  94. }
  95. public function setNoRender($flag = true)
  96. {
  97. $this->_noRender = (bool) $flag;
  98. return $this;
  99. }
  100. public function getNoRender()
  101. {
  102. return (bool) $this->_noRender;
  103. }
  104. public function getOrder()
  105. {
  106. return $this->_order;
  107. }
  108. public function setOrder($order)
  109. {
  110. $this->_order = (int) $order;
  111. return $this;
  112. }
  113. public function setParent(Engine_Content_Element_Abstract $element)
  114. {
  115. $this->_parent = $element;
  116. return $this;
  117. }
  118. public function getParent()
  119. {
  120. return $this->_parent;
  121. }
  122. // Attributes
  123. public function setAttrib($key, $value)
  124. {
  125. $this->_attribs[$key] = $value;
  126. return $this;
  127. }
  128. public function setAttribs(array $attribs)
  129. {
  130. foreach( $attribs as $key => $value ) {
  131. $this->_attribs[$key] = $value;
  132. }
  133. return $this;
  134. }
  135. public function getAttrib($key, $default = null)
  136. {
  137. if( isset($this->_attribs[$key]) ) {
  138. return $this->_attribs[$key];
  139. } else {
  140. return $default;
  141. }
  142. }
  143. public function getAttribs()
  144. {
  145. return $this->_attribs;
  146. }
  147. // Params
  148. public function setParam($key, $value)
  149. {
  150. $this->_params[$key] = $value;
  151. return $this;
  152. }
  153. public function setParams(array $attribs)
  154. {
  155. foreach( $attribs as $key => $value ) {
  156. $this->_params[$key] = $value;
  157. }
  158. return $this;
  159. }
  160. public function getParam($key, $default = null)
  161. {
  162. if( isset($this->_params[$key]) ) {
  163. return $this->_params[$key];
  164. } else {
  165. return $default;
  166. }
  167. }
  168. public function getParams()
  169. {
  170. return $this->_params;
  171. }
  172. // Decorators
  173. public function addDecorator($decorator, $options = null)
  174. {
  175. if ($decorator instanceof Zend_Form_Decorator_Interface) {
  176. $name = get_class($decorator);
  177. } elseif( is_string($decorator) ) {
  178. $name = $decorator;
  179. $decorator = array(
  180. 'decorator' => $name,
  181. 'options' => $options,
  182. );
  183. } elseif( is_array($decorator) ) {
  184. foreach ($decorator as $name => $spec) {
  185. break;
  186. }
  187. if (is_numeric($name)) {
  188. throw new Engine_Content_Element_Exception('Invalid alias provided to addDecorator; must be alphanumeric string');
  189. }
  190. if (is_string($spec)) {
  191. $decorator = array(
  192. 'decorator' => $spec,
  193. 'options' => $options,
  194. );
  195. } elseif ($spec instanceof Zend_Form_Decorator_Interface) {
  196. $decorator = $spec;
  197. }
  198. } else {
  199. throw new Engine_Content_Element_Exception('Invalid decorator provided to addDecorator; must be string or Engine_Content_Decorator_Abstract');
  200. }
  201. $this->_decorators[$name] = $decorator;
  202. return $this;
  203. }
  204. public function addDecorators(array $decorators)
  205. {
  206. foreach( $decorators as $decoratorInfo ) {
  207. if( $decoratorInfo instanceof Engine_Content_Decorator_Abstract ) {
  208. $this->addDecorator($decoratorInfo);
  209. } else if( is_string($decoratorInfo) ) {
  210. $this->addDecorator($decoratorInfo);
  211. } else if( is_array($decoratorInfo) ) {
  212. if( isset($decoratorInfo['decorator']) ) {
  213. $decorator = $decoratorInfo['decorator'];
  214. $options = ( isset($decoratorInfo['options']) && is_array($decoratorInfo['options']) ? $decoratorInfo['options'] : null );
  215. $this->addDecorator($decorator, $options);
  216. } else {
  217. $argc = count($decoratorInfo);
  218. $options = array();
  219. switch (true) {
  220. case (0 == $argc):
  221. break;
  222. case (1 <= $argc):
  223. $decorator = array_shift($decoratorInfo);
  224. case (2 <= $argc):
  225. $options = array_shift($decoratorInfo);
  226. default:
  227. $this->addDecorator($decorator, $options);
  228. break;
  229. }
  230. }
  231. } else {
  232. throw new Engine_Content_Element_Exception('Invalid decorator passed to addDecorators()');
  233. }
  234. }
  235. return $this;
  236. }
  237. public function clearDecorators()
  238. {
  239. $this->_decorators = array();
  240. return $this;
  241. }
  242. public function setDecorators(array $decorators)
  243. {
  244. $this->clearDecorators();
  245. $this->addDecorators($decorators);
  246. return $this;
  247. }
  248. public function getDecorator($name)
  249. {
  250. if (!isset($this->_decorators[$name])) {
  251. $len = strlen($name);
  252. foreach ($this->_decorators as $localName => $decorator) {
  253. if ($len > strlen($localName)) {
  254. continue;
  255. }
  256. if (0 === substr_compare($localName, $name, -$len, $len, true)) {
  257. if (is_array($decorator)) {
  258. return $this->_loadDecorator($decorator, $localName);
  259. }
  260. return $decorator;
  261. }
  262. }
  263. return false;
  264. }
  265. if (is_array($this->_decorators[$name])) {
  266. return $this->_loadDecorator($this->_decorators[$name], $name);
  267. }
  268. return $this->_decorators[$name];
  269. }
  270. public function getDecorators()
  271. {
  272. foreach ($this->_decorators as $key => $value) {
  273. if( is_array($value) ) {
  274. $this->_loadDecorator($value, $key);
  275. }
  276. }
  277. return $this->_decorators;
  278. }
  279. public function removeDecorator($name)
  280. {
  281. if (isset($this->_decorators[$name])) {
  282. unset($this->_decorators[$name]);
  283. } else {
  284. $len = strlen($name);
  285. foreach (array_keys($this->_decorators) as $decorator) {
  286. if ($len > strlen($decorator)) {
  287. continue;
  288. }
  289. if (0 === substr_compare($decorator, $name, -$len, $len, true)) {
  290. unset($this->_decorators[$decorator]);
  291. break;
  292. }
  293. }
  294. }
  295. return $this;
  296. }
  297. protected function _loadDecorator(array $decorator, $name)
  298. {
  299. $sameName = false;
  300. if ($name == $decorator['decorator']) {
  301. $sameName = true;
  302. }
  303. $class = $this->getPluginLoader(self::DECORATOR)->load($name);
  304. if( null === $decorator['options'] ) {
  305. $instance = new $class;
  306. } else {
  307. $instance = new $class($decorator['options']);
  308. }
  309. $instance->setElement($this);
  310. if ($sameName) {
  311. $newName = get_class($instance);
  312. $decoratorNames = array_keys($this->_decorators);
  313. $order = array_flip($decoratorNames);
  314. $order[$newName] = $order[$name];
  315. $decoratorsExchange = array();
  316. unset($order[$name]);
  317. asort($order);
  318. foreach ($order as $key => $index) {
  319. if ($key == $newName) {
  320. $decoratorsExchange[$key] = $instance;
  321. continue;
  322. }
  323. $decoratorsExchange[$key] = $this->_decorators[$key];
  324. }
  325. $this->_decorators = $decoratorsExchange;
  326. } else {
  327. $this->_decorators[$name] = $instance;
  328. }
  329. return $instance;
  330. }
  331. // Elements
  332. public function addElement($spec, $options = null)
  333. {
  334. if( $spec instanceof Engine_Content_Element_Abstract ) {
  335. $element = $spec;
  336. } else if( is_string($spec) ) {
  337. $element = $this->createElement($spec, $options);
  338. } else if( is_array($spec) ) {
  339. if( !isset($spec['type']) ) {
  340. throw new Engine_Content_Element_Exception('Element must have a type');
  341. }
  342. $type = $spec['type'];
  343. unset($spec['type']);
  344. if( is_array($options) ) $spec = array_merge($spec, $options);
  345. $element = $this->createElement($type, $spec);
  346. } else {
  347. throw new Engine_Content_Element_Exception('Unknown element spec');
  348. }
  349. $this->_elements[] = $element;
  350. $this->_elementsNeedSort = true;
  351. return $this;
  352. }
  353. public function addElements(array $elements)
  354. {
  355. foreach( $elements as $key => $value ) {
  356. $this->addElement($value);
  357. }
  358. return $this;
  359. }
  360. public function clearElements()
  361. {
  362. $this->_elements = array();
  363. $this->_elementsOrder = array();
  364. $this->_elementsNeedSort = false;
  365. return $this;
  366. }
  367. public function createElement($type, $options = null)
  368. {
  369. if( !is_string($type) ) {
  370. throw new Engine_Content_Element_Exception('Element type must be a string indicating type');
  371. }
  372. $class = $this->getPluginLoader(self::ELEMENT)->load($type);
  373. $element = new $class($options);
  374. return $element;
  375. }
  376. public function getElement($index)
  377. {
  378. if( isset($this->_elements[$index]) ) {
  379. return $this->_elements[$index];
  380. }
  381. return null;
  382. }
  383. public function getElements()
  384. {
  385. if( $this->_elementsNeedSort ) {
  386. $this->_sortElements();
  387. }
  388. return $this->_elements;
  389. }
  390. public function setElements(array $elements)
  391. {
  392. $this->addElements($elements);
  393. return $this;
  394. }
  395. public function removeElement($index)
  396. {
  397. if( isset($this->_elements[$index]) ) {
  398. unset($this->_elements[$index]);
  399. unset($this->_elementsOrder[$index]);
  400. }
  401. return $this;
  402. }
  403. protected function _sortElements()
  404. {
  405. foreach( $this->_elements as $index => $element ) {
  406. $this->_elementsOrder[$index] = $element->getOrder();
  407. }
  408. asort($this->_elementsOrder);
  409. $elements = array();
  410. foreach( $this->_elementsOrder as $index => $order ) {
  411. $elements[$index] = $this->_elements[$index];
  412. }
  413. $this->_elements = $elements;
  414. $this->_elementsNeedSort = false;
  415. }
  416. // Plugin Loader
  417. public function getPluginLoader($type)
  418. {
  419. $type = strtoupper($type);
  420. if( !isset($this->_loaders[$type]) ) {
  421. switch( $type ) {
  422. case self::DECORATOR:
  423. $prefixSegment = 'Content_Decorator';
  424. $pathSegment = 'Content/Decorator';
  425. break;
  426. case self::ELEMENT:
  427. $prefixSegment = 'Content_Element';
  428. $pathSegment = 'Content/Element';
  429. break;
  430. default:
  431. throw new Engine_Content_Element_Exception(sprintf('Invalid type "%s" provided to getPluginLoader()', $type));
  432. break;
  433. }
  434. $this->_loaders[$type] = new Zend_Loader_PluginLoader(
  435. array('Engine_' . $prefixSegment . '_' => 'Engine/' . $pathSegment . '/')
  436. );
  437. }
  438. return $this->_loaders[$type];
  439. }
  440. public function setPluginLoader($type, $pluginLoader)
  441. {
  442. switch( $type ) {
  443. case self::DECORATOR:
  444. case self::ELEMENT:
  445. $this->_loaders[$type] = $pluginLoader;
  446. break;
  447. default:
  448. throw new Engine_Content_Element_Exception(sprintf('Invalid type "%s" provided to getPluginLoader()', $type));
  449. break;
  450. }
  451. }
  452. // Rendering
  453. public function getView()
  454. {
  455. if( null === $this->_view ) {
  456. return Engine_Content::getInstance()->getView();
  457. }
  458. return $this->_view;
  459. }
  460. public function setView(Zend_View_Interface $view)
  461. {
  462. $this->_view = $view;
  463. return $this;
  464. }
  465. public function render()
  466. {
  467. $content = $this->_render();
  468. // Do not render decorators if no content
  469. //if( '' === $content ) {
  470. if( $this->getNoRender() ) {
  471. return '';
  472. }
  473. // Do decorators
  474. foreach( $this->getDecorators() as $decorator ) {
  475. $decorator->setElement($this);
  476. $content = $decorator->render($content);
  477. }
  478. return $content;
  479. }
  480. public function __toString()
  481. {
  482. try {
  483. $return = $this->render();
  484. return $return;
  485. } catch (Exception $e) {
  486. $message = "Exception caught by form: " . $e->getMessage()
  487. . "\nStack Trace:\n" . $e->getTraceAsString();
  488. trigger_error($message, E_USER_WARNING);
  489. return '';
  490. }
  491. }
  492. abstract protected function _render();
  493. }