PageRenderTime 55ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/views/helpers/layout.php

https://github.com/caist/croogo
PHP | 768 lines | 475 code | 36 blank | 257 comment | 73 complexity | e29e94e9fb1d004ae2d1dbd20ff47a10 MD5 | raw file
  1. <?php
  2. /**
  3. * Layout Helper
  4. *
  5. * PHP version 5
  6. *
  7. * @category Helper
  8. * @package Croogo
  9. * @version 1.0
  10. * @author Fahad Ibnay Heylaal <contact@fahad19.com>
  11. * @license http://www.opensource.org/licenses/mit-license.php The MIT License
  12. * @link http://www.croogo.org
  13. */
  14. class LayoutHelper extends AppHelper {
  15. /**
  16. * Other helpers used by this helper
  17. *
  18. * @var array
  19. * @access public
  20. */
  21. public $helpers = array(
  22. 'Html',
  23. 'Form',
  24. 'Session',
  25. 'Js',
  26. );
  27. /**
  28. * Current Node
  29. *
  30. * @var array
  31. * @access public
  32. */
  33. public $node = null;
  34. /**
  35. * Hook helpers
  36. *
  37. * @var array
  38. * @access public
  39. */
  40. public $hooks = array();
  41. /**
  42. * Constructor
  43. *
  44. * @param array $options options
  45. * @access public
  46. */
  47. public function __construct($options = array()) {
  48. $this->View =& ClassRegistry::getObject('view');
  49. $this->loadHooks();
  50. return parent::__construct($options);
  51. }
  52. /**
  53. * Load hooks as helpers
  54. *
  55. * @return void
  56. */
  57. public function loadHooks() {
  58. if (is_array(Configure::read('Hook.helpers'))) {
  59. foreach (Configure::read('Hook.helpers') AS $hook) {
  60. if (App::import('Helper', $hook)) {
  61. $this->hooks[] = $hook;
  62. $this->helpers[] = $hook;
  63. }
  64. }
  65. }
  66. }
  67. /**
  68. * Javascript variables
  69. *
  70. * @return string
  71. */
  72. public function js() {
  73. $output = $this->Html->script('croogo');
  74. $croogo = array();
  75. $croogo['basePath'] = Router::url('/');
  76. $croogo['params'] = array(
  77. 'controller' => $this->params['controller'],
  78. 'action' => $this->params['action'],
  79. 'named' => $this->params['named'],
  80. );
  81. $output .= $this->Html->scriptBlock('$.extend(Croogo, ' . $this->Js->object($croogo) . ');');
  82. echo $output;
  83. }
  84. /**
  85. * Status
  86. *
  87. * instead of 0/1, show tick/cross
  88. *
  89. * @param integer $value 0 or 1
  90. * @return string formatted img tag
  91. */
  92. public function status($value) {
  93. if ($value == 1) {
  94. $output = $this->Html->image('/img/icons/tick.png');
  95. } else {
  96. $output = $this->Html->image('/img/icons/cross.png');
  97. }
  98. return $output;
  99. }
  100. /**
  101. * Show flash message
  102. *
  103. * @return void
  104. */
  105. public function sessionFlash() {
  106. $messages = $this->Session->read('Message');
  107. if( is_array($messages) ) {
  108. foreach(array_keys($messages) AS $key) {
  109. echo $this->Session->flash($key);
  110. }
  111. }
  112. }
  113. /**
  114. * Meta tags
  115. *
  116. * @return string
  117. */
  118. public function meta($metaForLayout = array()) {
  119. $_metaForLayout = array();
  120. if (is_array(Configure::read('Meta'))) {
  121. $_metaForLayout = Configure::read('Meta');
  122. }
  123. if (count($metaForLayout) == 0 &&
  124. isset($this->View->viewVars['node']['CustomFields']) &&
  125. count($this->View->viewVars['node']['CustomFields']) > 0) {
  126. $metaForLayout = array();
  127. foreach ($this->View->viewVars['node']['CustomFields'] AS $key => $value) {
  128. if (strstr($key, 'meta_')) {
  129. $key = str_replace('meta_', '', $key);
  130. $metaForLayout[$key] = $value;
  131. }
  132. }
  133. }
  134. $metaForLayout = array_merge($_metaForLayout, $metaForLayout);
  135. $output = '';
  136. foreach ($metaForLayout AS $name => $content) {
  137. $output .= '<meta name="' . $name . '" content="' . $content . '" />';
  138. }
  139. return $output;
  140. }
  141. /**
  142. * isLoggedIn
  143. *
  144. * if User is logged in
  145. *
  146. * @return boolean
  147. */
  148. public function isLoggedIn() {
  149. if ($this->Session->check('Auth.User.id')) {
  150. return true;
  151. } else {
  152. return false;
  153. }
  154. }
  155. /**
  156. * Feed
  157. *
  158. * RSS feeds
  159. *
  160. * @param boolean $returnUrl if true, only the URL will be returned
  161. * @return string
  162. */
  163. public function feed($returnUrl = false) {
  164. if (Configure::read('Site.feed_url')) {
  165. $url = Configure::read('Site.feed_url');
  166. } else {
  167. /*$url = Router::url(array(
  168. 'controller' => 'nodes',
  169. 'action' => 'index',
  170. 'type' => 'blog',
  171. 'ext' => 'rss',
  172. ));*/
  173. $url = '/nodes/promoted.rss';
  174. }
  175. if ($returnUrl) {
  176. $output = $url;
  177. } else {
  178. $url = Router::url($url);
  179. $output = '<link href="' . $url . '" type="application/rss+xml" rel="alternate" title="RSS 2.0" />';
  180. return $output;
  181. }
  182. return $output;
  183. }
  184. /**
  185. * Get Role ID
  186. *
  187. * @return integer
  188. */
  189. public function getRoleId() {
  190. if ($this->isLoggedIn()) {
  191. $roleId = $this->Session->read('Auth.User.role_id');
  192. } else {
  193. // Public
  194. $roleId = 3;
  195. }
  196. return $roleId;
  197. }
  198. /**
  199. * Region is empty
  200. *
  201. * returns true if Region has no Blocks.
  202. *
  203. * @param string $regionAlias Region alias
  204. * @return boolean
  205. */
  206. public function regionIsEmpty($regionAlias) {
  207. if (isset($this->View->viewVars['blocks_for_layout'][$regionAlias]) &&
  208. count($this->View->viewVars['blocks_for_layout'][$regionAlias]) > 0) {
  209. return false;
  210. } else {
  211. return true;
  212. }
  213. }
  214. /**
  215. * Show Blocks for a particular Region
  216. *
  217. * @param string $regionAlias Region alias
  218. * @param array $options
  219. * @return string
  220. */
  221. public function blocks($regionAlias, $options = array()) {
  222. $_options = array();
  223. $options = array_merge($_options, $options);
  224. $output = '';
  225. if (!$this->regionIsEmpty($regionAlias)) {
  226. $blocks = $this->View->viewVars['blocks_for_layout'][$regionAlias];
  227. foreach ($blocks AS $block) {
  228. $plugin = false;
  229. if ($block['Block']['element'] != null) {
  230. if (strstr($block['Block']['element'], '.')) {
  231. $plugin_element = explode('.', $block['Block']['element']);
  232. $plugin = $plugin_element[0];
  233. $element = $plugin_element[1];
  234. } else {
  235. $element = $block['Block']['element'];
  236. }
  237. } else {
  238. $element = 'block';
  239. }
  240. if ($plugin) {
  241. $output .= $this->View->element($element, array('block' => $block, 'plugin' => $plugin));
  242. } else {
  243. $output .= $this->View->element($element, array('block' => $block));
  244. }
  245. }
  246. }
  247. return $output;
  248. }
  249. /**
  250. * Show Menu by Alias
  251. *
  252. * @param string $menuAlias Menu alias
  253. * @param array $options (optional)
  254. * @return string
  255. */
  256. public function menu($menuAlias, $options = array()) {
  257. $_options = array(
  258. 'tag' => 'ul',
  259. 'tagAttributes' => array(),
  260. 'selected' => 'selected',
  261. 'dropdown' => false,
  262. 'dropdownClass' => 'sf-menu',
  263. 'element' => 'menu',
  264. );
  265. $options = array_merge($_options, $options);
  266. if (!isset($this->View->viewVars['menus_for_layout'][$menuAlias])) {
  267. return false;
  268. }
  269. $menu = $this->View->viewVars['menus_for_layout'][$menuAlias];
  270. $output = $this->View->element($options['element'], array(
  271. 'menu' => $menu,
  272. 'options' => $options,
  273. ));
  274. return $output;
  275. }
  276. /**
  277. * Nested Links
  278. *
  279. * @param array $links model output (threaded)
  280. * @param array $options (optional)
  281. * @param integer $depth depth level
  282. * @return string
  283. */
  284. public function nestedLinks($links, $options = array(), $depth = 1) {
  285. $_options = array();
  286. $options = array_merge($_options, $options);
  287. $output = '';
  288. foreach ($links AS $link) {
  289. $linkAttr = array(
  290. 'id' => 'link-' . $link['Link']['id'],
  291. 'rel' => $link['Link']['rel'],
  292. 'target' => $link['Link']['target'],
  293. 'title' => $link['Link']['description'],
  294. );
  295. foreach ($linkAttr AS $attrKey => $attrValue) {
  296. if ($attrValue == null) {
  297. unset($linkAttr[$attrKey]);
  298. }
  299. }
  300. // if link is in the format: controller:contacts/action:view
  301. if (strstr($link['Link']['link'], 'controller:')) {
  302. $link['Link']['link'] = $this->linkStringToArray($link['Link']['link']);
  303. }
  304. if (Router::url($link['Link']['link']) == Router::url('/' . $this->params['url']['url'])) {
  305. $linkAttr['class'] = $options['selected'];
  306. }
  307. $linkOutput = $this->Html->link($link['Link']['title'], $link['Link']['link'], $linkAttr);
  308. if (isset($link['children']) && count($link['children']) > 0) {
  309. $linkOutput .= $this->nestedLinks($link['children'], $options, $depth + 1);
  310. }
  311. $linkOutput = $this->Html->tag('li', $linkOutput);
  312. $output .= $linkOutput;
  313. }
  314. if ($output != null) {
  315. $tagAttr = $options['tagAttributes'];
  316. if ($options['dropdown'] && $depth == 1) {
  317. $tagAttr['class'] = $options['dropdownClass'];
  318. }
  319. $output = $this->Html->tag($options['tag'], $output, $tagAttr);
  320. }
  321. return $output;
  322. }
  323. /**
  324. * Converts strings like controller:abc/action:xyz/ to arrays
  325. *
  326. * @param string $link link
  327. * @return array
  328. */
  329. public function linkStringToArray($link) {
  330. $link = explode('/', $link);
  331. $linkArr = array();
  332. foreach ($link AS $linkElement) {
  333. if ($linkElement != null) {
  334. $linkElementE = explode(':', $linkElement);
  335. if (isset($linkElementE['1'])) {
  336. $linkArr[$linkElementE['0']] = $linkElementE['1'];
  337. } else {
  338. $linkArr[] = $linkElement;
  339. }
  340. }
  341. }
  342. if (!isset($linkArr['plugin'])) {
  343. $linkArr['plugin'] = false;
  344. }
  345. return $linkArr;
  346. }
  347. /**
  348. * Show Vocabulary by Alias
  349. *
  350. * @param string $vocabularyAlias Vocabulary alias
  351. * @param array $options (optional)
  352. * @return string
  353. */
  354. public function vocabulary($vocabularyAlias, $options = array()) {
  355. $_options = array(
  356. 'tag' => 'ul',
  357. 'tagAttributes' => array(),
  358. 'type' => null,
  359. 'link' => true,
  360. 'plugin' => false,
  361. 'controller' => 'nodes',
  362. 'action' => 'term',
  363. 'element' => 'vocabulary',
  364. );
  365. $options = array_merge($_options, $options);
  366. $output = '';
  367. if (isset($this->View->viewVars['vocabularies_for_layout'][$vocabularyAlias]['threaded'])) {
  368. $vocabulary = $this->View->viewVars['vocabularies_for_layout'][$vocabularyAlias];
  369. $output .= $this->View->element($options['element'], array(
  370. 'vocabulary' => $vocabulary,
  371. 'options' => $options,
  372. ));
  373. }
  374. return $output;
  375. }
  376. /**
  377. * Nested Terms
  378. *
  379. * @param array $terms
  380. * @param array $options
  381. * @param integer $depth
  382. */
  383. public function nestedTerms($terms, $options, $depth = 1) {
  384. $_options = array();
  385. $options = array_merge($_options, $options);
  386. $output = '';
  387. foreach ($terms AS $term) {
  388. if ($options['link']) {
  389. $termAttr = array(
  390. 'id' => 'term-' . $term['Term']['id'],
  391. );
  392. $termOutput = $this->Html->link($term['Term']['title'], array(
  393. 'plugin' => $options['plugin'],
  394. 'controller' => $options['controller'],
  395. 'action' => $options['action'],
  396. 'type' => $options['type'],
  397. 'slug' => $term['Term']['slug'],
  398. ), $termAttr);
  399. } else {
  400. $termOutput = $term['Term']['title'];
  401. }
  402. if (isset($term['children']) && count($term['children']) > 0) {
  403. $termOutput .= $this->nestedTerms($term['children'], $options, $depth + 1);
  404. }
  405. $termOutput = $this->Html->tag('li', $termOutput);
  406. $output .= $termOutput;
  407. }
  408. if ($output != null) {
  409. $output = $this->Html->tag($options['tag'], $output, $options['tagAttributes']);
  410. }
  411. return $output;
  412. }
  413. /**
  414. * Show nodes list
  415. *
  416. * @param string $alias Node query alias
  417. * @param array $options (optional)
  418. * @return string
  419. */
  420. public function nodeList($alias, $options = array()) {
  421. $_options = array(
  422. 'link' => true,
  423. 'plugin' => false,
  424. 'controller' => 'nodes',
  425. 'action' => 'view',
  426. 'element' => 'node_list',
  427. );
  428. $options = array_merge($_options, $options);
  429. $output = '';
  430. if (isset($this->View->viewVars['nodes_for_layout'][$alias])) {
  431. $nodes = $this->View->viewVars['nodes_for_layout'][$alias];
  432. $output = $this->View->element($options['element'], array(
  433. 'alias' => $alias,
  434. 'nodesList' => $this->View->viewVars['nodes_for_layout'][$alias],
  435. 'options' => $options,
  436. ));
  437. }
  438. return $output;
  439. }
  440. /**
  441. * Filter content
  442. *
  443. * Replaces bbcode-like element tags
  444. *
  445. * @param string $content content
  446. * @return string
  447. */
  448. public function filter($content) {
  449. $content = $this->filterElements($content);
  450. $content = $this->filterMenus($content);
  451. $content = $this->filterVocabularies($content);
  452. $content = $this->filterNodes($content);
  453. return $content;
  454. }
  455. /**
  456. * Filter content for elements
  457. *
  458. * Original post by Stefan Zollinger: http://bakery.cakephp.org/articles/view/element-helper
  459. * [element:element_name] or [e:element_name]
  460. *
  461. * @param string $content
  462. * @return string
  463. */
  464. public function filterElements($content) {
  465. preg_match_all('/\[(element|e):([A-Za-z0-9_\-]*)(.*?)\]/i', $content, $tagMatches);
  466. for ($i=0; $i < count($tagMatches[1]); $i++) {
  467. $regex = '/(\S+)=[\'"]?((?:.(?![\'"]?\s+(?:\S+)=|[>\'"]))+.)[\'"]?/i';
  468. preg_match_all($regex, $tagMatches[3][$i], $attributes);
  469. $element = $tagMatches[2][$i];
  470. $options = array();
  471. for ($j=0; $j < count($attributes[0]); $j++) {
  472. $options[$attributes[1][$j]] = $attributes[2][$j];
  473. }
  474. $content = str_replace($tagMatches[0][$i], $this->View->element($element,$options), $content);
  475. }
  476. return $content;
  477. }
  478. /**
  479. * Filter content for Menus
  480. *
  481. * Replaces [menu:menu_alias] or [m:menu_alias] with Menu list
  482. *
  483. * @param string $content
  484. * @return string
  485. */
  486. public function filterMenus($content) {
  487. preg_match_all('/\[(menu|m):([A-Za-z0-9_\-]*)(.*?)\]/i', $content, $tagMatches);
  488. for ($i=0; $i < count($tagMatches[1]); $i++) {
  489. $regex = '/(\S+)=[\'"]?((?:.(?![\'"]?\s+(?:\S+)=|[>\'"]))+.)[\'"]?/i';
  490. preg_match_all($regex, $tagMatches[3][$i], $attributes);
  491. $menuAlias = $tagMatches[2][$i];
  492. $options = array();
  493. for ($j=0; $j < count($attributes[0]); $j++) {
  494. $options[$attributes[1][$j]] = $attributes[2][$j];
  495. }
  496. $content = str_replace($tagMatches[0][$i], $this->menu($menuAlias,$options), $content);
  497. }
  498. return $content;
  499. }
  500. /**
  501. * Filter content for Vocabularies
  502. *
  503. * Replaces [vocabulary:vocabulary_alias] or [v:vocabulary_alias] with Terms list
  504. *
  505. * @param string $content
  506. * @return string
  507. */
  508. public function filterVocabularies($content) {
  509. preg_match_all('/\[(vocabulary|v):([A-Za-z0-9_\-]*)(.*?)\]/i', $content, $tagMatches);
  510. for ($i=0; $i < count($tagMatches[1]); $i++) {
  511. $regex = '/(\S+)=[\'"]?((?:.(?![\'"]?\s+(?:\S+)=|[>\'"]))+.)[\'"]?/i';
  512. preg_match_all($regex, $tagMatches[3][$i], $attributes);
  513. $vocabularyAlias = $tagMatches[2][$i];
  514. $options = array();
  515. for ($j=0; $j < count($attributes[0]); $j++) {
  516. $options[$attributes[1][$j]] = $attributes[2][$j];
  517. }
  518. $content = str_replace($tagMatches[0][$i], $this->vocabulary($vocabularyAlias,$options), $content);
  519. }
  520. return $content;
  521. }
  522. /**
  523. * Filter content for Nodes
  524. *
  525. * Replaces [node:unique_name_for_query] or [n:unique_name_for_query] with Nodes list
  526. *
  527. * @param string $content
  528. * @return string
  529. */
  530. public function filterNodes($content) {
  531. preg_match_all('/\[(node|n):([A-Za-z0-9_\-]*)(.*?)\]/i', $content, $tagMatches);
  532. for ($i=0; $i < count($tagMatches[1]); $i++) {
  533. $regex = '/(\S+)=[\'"]?((?:.(?![\'"]?\s+(?:\S+)=|[>\'"]))+.)[\'"]?/i';
  534. preg_match_all($regex, $tagMatches[3][$i], $attributes);
  535. $alias = $tagMatches[2][$i];
  536. $options = array();
  537. for ($j=0; $j < count($attributes[0]); $j++) {
  538. $options[$attributes[1][$j]] = $attributes[2][$j];
  539. }
  540. $content = str_replace($tagMatches[0][$i], $this->nodeList($alias,$options), $content);
  541. }
  542. return $content;
  543. }
  544. /**
  545. * Meta field: with key/value fields
  546. *
  547. * @param string $key (optional) key
  548. * @param string $value (optional) value
  549. * @param integer $id (optional) ID of Meta
  550. * @param array $options (optional) options
  551. * @return string
  552. */
  553. public function metaField($key = '', $value = null, $id = null, $options = array()) {
  554. $_options = array(
  555. 'key' => array(
  556. 'label' => __('Key', true),
  557. 'value' => $key,
  558. ),
  559. 'value' => array(
  560. 'label' => __('Value', true),
  561. 'value' => $value,
  562. ),
  563. );
  564. $options = array_merge($_options, $options);
  565. $uuid = String::uuid();
  566. $fields = '';
  567. if ($id != null) {
  568. $fields .= $this->Form->input('Meta.'.$uuid.'.id', array('type' => 'hidden', 'value' => $id));
  569. }
  570. $fields .= $this->Form->input('Meta.'.$uuid.'.key', $options['key']);
  571. $fields .= $this->Form->input('Meta.'.$uuid.'.value', $options['value']);
  572. $fields = $this->Html->tag('div', $fields, array('class' => 'fields'));
  573. $actions = $this->Html->link(__('Remove', true), '#', array('class' => 'remove-meta', 'rel' => $id), null, null, false);
  574. $actions = $this->Html->tag('div', $actions, array('class' => 'actions'));
  575. $output = $this->Html->tag('div', $actions . $fields, array('class' => 'meta'));
  576. return $output;
  577. }
  578. /**
  579. * Show links under Actions column
  580. *
  581. * @param integer $id
  582. * @param array $options
  583. * @return string
  584. */
  585. public function adminRowActions($id, $options = array()) {
  586. $_options = array();
  587. $options = array_merge($_options, $options);
  588. $output = '';
  589. $rowActions = Configure::read('Admin.rowActions.' . Inflector::camelize($this->params['controller']) . '/' . $this->params['action']);
  590. if (is_array($rowActions)) {
  591. foreach ($rowActions AS $title => $link) {
  592. if ($output != '') {
  593. $output .= ' ';
  594. }
  595. $link = $this->linkStringToArray(str_replace(':id', $id, $link));
  596. $output .= $this->Html->link($title, $link);
  597. }
  598. }
  599. return $output;
  600. }
  601. /**
  602. * Set current Node
  603. *
  604. * @param array $node
  605. * @return void
  606. */
  607. public function setNode($node) {
  608. $this->node = $node;
  609. $this->hook('afterSetNode');
  610. }
  611. /**
  612. * Set value of a field
  613. *
  614. * @param string $field
  615. * @param string $value
  616. * @return void
  617. */
  618. public function setNodeField($field, $value) {
  619. $model = 'Node';
  620. if (strstr($field, '.')) {
  621. $fieldE = explode('.', $field);
  622. $model = $fieldE['0'];
  623. $field = $fieldE['1'];
  624. }
  625. $this->node[$model][$field] = $value;
  626. }
  627. /**
  628. * Get value of a Node field
  629. *
  630. * @param string $field
  631. * @return string
  632. */
  633. public function node($field = 'id') {
  634. $model = 'Node';
  635. if (strstr($field, '.')) {
  636. $fieldE = explode('.', $field);
  637. $model = $fieldE['0'];
  638. $field = $fieldE['1'];
  639. }
  640. if (isset($this->node[$model][$field])) {
  641. return $this->node[$model][$field];
  642. } else {
  643. return false;
  644. }
  645. }
  646. /**
  647. * Node info
  648. *
  649. * @param array $options
  650. * @return string
  651. */
  652. public function nodeInfo($options = array()) {
  653. $_options = array(
  654. 'element' => 'node_info',
  655. );
  656. $options = array_merge($_options, $options);
  657. $output = $this->hook('beforeNodeInfo');
  658. $output .= $this->View->element($options['element']);
  659. $output .= $this->hook('afterNodeInfo');
  660. return $output;
  661. }
  662. /**
  663. * Node excerpt (summary)
  664. *
  665. * @param array $options
  666. * @return string
  667. */
  668. public function nodeExcerpt($options = array()) {
  669. $_options = array(
  670. 'element' => 'node_excerpt',
  671. );
  672. $options = array_merge($_options, $options);
  673. $output = $this->hook('beforeNodeExcerpt');
  674. $output .= $this->View->element($options['element']);
  675. $output .= $this->hook('afterNodeExcerpt');
  676. return $output;
  677. }
  678. /**
  679. * Node body
  680. *
  681. * @param array $options
  682. * @return string
  683. */
  684. public function nodeBody($options = array()) {
  685. $_options = array(
  686. 'element' => 'node_body',
  687. );
  688. $options = array_merge($_options, $options);
  689. $output = $this->hook('beforeNodeBody');
  690. $output .= $this->View->element($options['element']);
  691. $output .= $this->hook('afterNodeBody');
  692. return $output;
  693. }
  694. /**
  695. * Node more info
  696. *
  697. * @param array $options
  698. * @return string
  699. */
  700. public function nodeMoreInfo($options = array()) {
  701. $_options = array(
  702. 'element' => 'node_more_info',
  703. );
  704. $options = array_merge($_options, $options);
  705. $output = $this->hook('beforeNodeMoreInfo');
  706. $output .= $this->View->element($options['element']);
  707. $output .= $this->hook('afterNodeMoreInfo');
  708. return $output;
  709. }
  710. /**
  711. * Hook
  712. *
  713. * Used for calling hook methods from other HookHelpers
  714. *
  715. * @param string $methodName
  716. * @return string
  717. */
  718. public function hook($methodName) {
  719. $output = '';
  720. foreach ($this->hooks AS $hook) {
  721. if (strstr($hook, '.')) {
  722. $hookE = explode('.', $hook);
  723. $hook = $hookE['1'];
  724. }
  725. if (method_exists($this->{$hook}, $methodName)) {
  726. $output .= $this->{$hook}->$methodName();
  727. }
  728. }
  729. return $output;
  730. }
  731. }
  732. ?>