/src/Zf2tb/View/Helper/Navigation/AbstractHelper.php

https://bitbucket.org/andrew_lebedenko/zf2tb · PHP · 425 lines · 270 code · 42 blank · 113 comment · 32 complexity · b455af63949062f1ad35dc7b0e5846b8 MD5 · raw file

  1. <?php
  2. namespace Zf2tb\View\Helper\Navigation;
  3. use Zend\Navigation\Navigation;
  4. use Zend\Navigation\Page\AbstractPage;
  5. use Zend\View\Helper\Navigation\AbstractHelper as AbstractZfNavigationHelper;
  6. /**
  7. * Abstract Helper
  8. *
  9. * @package Zf2tb
  10. * @author Andrew Lebedenko
  11. * @copyright Andrew Lebedenko (c)
  12. * @link https://bitbucket.org/andrew_lebedenko/zf2tb
  13. */
  14. abstract class AbstractHelper extends AbstractZfNavigationHelper
  15. {
  16. const ALIGN_LEFT = 'left';
  17. const ALIGN_RIGHT = 'right';
  18. /**
  19. * CSS class to use for the ul element
  20. *
  21. * @var string
  22. */
  23. protected $ulClass = 'nav';
  24. protected $inverseIcon = false;
  25. /**
  26. * Css class to use for the li element containing dropdown submenu
  27. *
  28. * @var string
  29. */
  30. protected $parentMenuClass = 'dropdown';
  31. /**
  32. * Css class to use for the ul element of dropdown submenu
  33. *
  34. * @var string
  35. */
  36. protected $dropdownUlClass = 'dropdown-menu';
  37. /**
  38. * Whether icons should be rendered
  39. *
  40. * @var boolean
  41. */
  42. protected $renderIcons = true;
  43. /**
  44. * Whether caret should be rendered for dropdown parent item
  45. *
  46. * @var boolean
  47. */
  48. protected $useDropdownParentCaret = true;
  49. protected function renderContainer(Navigation $container, array $options = array()) {
  50. $pages = $container->getPages();
  51. $html = '';
  52. foreach ($pages as $page) {
  53. /* @var $page \Zend\Navigation\Page\AbstractPage */
  54. if($page->hasPages()) {
  55. //Dropdown menu
  56. $html .= PHP_EOL . $this->renderDropdown($page, $options);
  57. } else {
  58. $html .= PHP_EOL . $this->renderItem($page, false, $options);
  59. }
  60. }
  61. $html = $this->decorateContainer($html, $options);
  62. return $html;
  63. }
  64. abstract protected function decorateContainer($content, array $options = array());
  65. protected function renderItem(AbstractPage $page,
  66. $renderInDropdown = false,
  67. array $options = array())
  68. {
  69. if(!$this->accept($page)) {
  70. return '';
  71. }
  72. if($page->navHeader) {
  73. //Nav Header
  74. if($renderInDropdown) {
  75. $itemHtml = $this->renderNavHeaderInDropdown($page, $options);
  76. $html = $this->decorateNavHeaderInDropdown($itemHtml, $page, $options);
  77. } else {
  78. $itemHtml = $this->renderNavHeader($page, $options);
  79. $html = $this->decorateNavHeader($itemHtml, $page, $options);
  80. }
  81. } elseif($page->divider) {
  82. //Divider
  83. if($renderInDropdown) {
  84. $itemHtml = $this->renderDividerInDropdown($page, $options);
  85. $html = $this->decorateDividerInDropdown($itemHtml, $page, $options);
  86. } else {
  87. $itemHtml = $this->renderDivider($page, $options);
  88. $html = $this->decorateDivider($itemHtml, $page, $options);
  89. }
  90. } else {
  91. //Nav link
  92. if($renderInDropdown) {
  93. $itemHtml = $this->renderLinkInDropdown($page, $options);
  94. $html = $this->decorateLinkInDropdown($itemHtml, $page, $options);
  95. } else {
  96. $itemHtml = $this->renderLink($page, $options);
  97. $html = $this->decorateLink($itemHtml, $page, $options);
  98. }
  99. }
  100. return $html;
  101. }
  102. protected function renderNavHeader(AbstractPage $item, array $options = array()) {
  103. $icon = $this->htmlifyIcon($item);
  104. $label = $this->translate($item->getLabel());
  105. $html = $icon . $this->getView()->escapeHtml($label);
  106. return $html;
  107. }
  108. protected function renderNavHeaderInDropdown(AbstractPage $item,
  109. array $options = array()) {
  110. $html = $this->renderNavHeader($item, $options);
  111. return $html;
  112. }
  113. abstract protected function decorateNavHeader($content,
  114. AbstractPage $item,
  115. array $options = array());
  116. protected function decorateNavHeaderInDropdown($content,
  117. AbstractPage $item,
  118. array $options = array()) {
  119. $html = '<li class="nav-header">' . $content . '</li>';
  120. return $html;
  121. }
  122. protected function renderDivider(AbstractPage $item, array $options = array()) {
  123. return '';
  124. }
  125. protected function renderDividerInDropdown(AbstractPage $item, array $options = array()) {
  126. $html = $this->renderDivider($item, $options);
  127. return $html;
  128. }
  129. abstract protected function decorateDivider($content,
  130. AbstractPage $item,
  131. array $options = array());
  132. protected function decorateDividerInDropdown($content,
  133. AbstractPage $item,
  134. array $options = array()) {
  135. $html = '<li class="divider">' . $content . '</li>';
  136. return $html;
  137. }
  138. protected function renderLink(AbstractPage $page, array $options = array()) {
  139. //Assemble html
  140. $html = $this->htmlifyA($page);
  141. return $html;
  142. }
  143. protected function renderLinkInDropdown(AbstractPage $page,
  144. array $options = array()) {
  145. $html = $this->renderLink($page, $options);
  146. return $html;
  147. }
  148. abstract protected function decorateLink($content,
  149. AbstractPage $page,
  150. array $options = array());
  151. protected function decorateLinkInDropdown($content,
  152. AbstractPage $page,
  153. array $options = array()) {
  154. //Active
  155. if($page->isActive(true)) {
  156. $liClass = ' class="active"';
  157. } else {
  158. $liClass = '';
  159. }
  160. $html = '<li' . $liClass . '>' . $content . '</li>';
  161. return $html;
  162. }
  163. protected function renderDropdown(AbstractPage $page, array $options = array()) {
  164. //Get label and title
  165. $label = $this->translate($page->getLabel());
  166. $title = $this->translate($page->getTitle());
  167. $escaper = $this->view->plugin('escapeHtml');
  168. //Get attribs
  169. $class = $page->getClass();
  170. $this->addWord('dropdown-toggle', $class);
  171. $aAttribs = array(
  172. 'title' => $title,
  173. 'class' => $class,
  174. 'data-toggle' => 'dropdown',
  175. 'href' => '#',
  176. );
  177. if($this->renderIcons) {
  178. $iconHtml = $this->htmlifyIcon($page);
  179. } else {
  180. $iconHtml = '';
  181. }
  182. $html = '<a' . $this->htmlAttribs($aAttribs) . '>'
  183. . $iconHtml . $escaper($label);
  184. if ($this->useDropdownParentCaret) {
  185. $html .= ' <b class="caret"></b>';
  186. }
  187. $html .= '</a>' . PHP_EOL . '<ul class="' . $this->dropdownUlClass . '">';
  188. $pages = $page->getPages();
  189. foreach($pages as $dropdownPage) {
  190. /* @var $dropdownPage \Zend\Navigation\Page\AbstractPage */
  191. $html .= PHP_EOL . $this->renderItem($dropdownPage, true, $options);
  192. }
  193. $html .= PHP_EOL . '</ul>';
  194. $html = $this->decorateDropdown($html, $page, $options);
  195. return $html;
  196. }
  197. abstract protected function decorateDropdown($content,
  198. AbstractPage $page,
  199. array $options = array());
  200. /**
  201. * Returns an HTML string containing an 'a' element for the given page
  202. * @param \Zend\Navigation\Page\AbstractPage $page
  203. * @param bool $renderIcons
  204. * @param bool $activeIconInverse
  205. * @return string
  206. */
  207. public function htmlifyA(AbstractPage $page)
  208. {
  209. // get label and title for translating
  210. $label = $this->translate($page->getLabel());
  211. $title = $this->translate($page->getTitle());
  212. $escaper = $this->view->plugin('escapeHtml');
  213. //Get attribs for anchor element
  214. $attribs = array(
  215. 'id' => $page->getId(),
  216. 'title' => $title,
  217. 'class' => $page->getClass(),
  218. 'href' => $page->getHref(),
  219. 'target' => $page->getTarget()
  220. );
  221. if($this->renderIcons) {
  222. $iconHtml = $this->htmlifyIcon($page);
  223. } else {
  224. $iconHtml = '';
  225. }
  226. $html = '<a' . $this->htmlAttribs($attribs) . '>' . $iconHtml . $escaper($label) . '</a>';
  227. return $html;
  228. }
  229. protected function htmlifyIcon(AbstractPage $item)
  230. {
  231. if($item->icon) {
  232. $iClass = $item->icon;
  233. if($this->inverseIcon && $item->isActive(true)) {
  234. $classes = explode(' ', $iClass);
  235. $iconWhiteClassKey = array_search('icon-white', $classes);
  236. if($iconWhiteClassKey === false) {
  237. //icon-white class not found
  238. $iClass .= ' icon-white';
  239. } else {
  240. //icon-white class found
  241. unset($classes[$iconWhiteClassKey]);
  242. $iClass = implode(' ', $classes);
  243. }
  244. }
  245. $icon = '<i class="' . $iClass . '"></i> ';
  246. } else {
  247. $icon = '';
  248. }
  249. return $icon;
  250. }
  251. /**
  252. * View helper entry point:
  253. * Retrieves helper and optionally sets container to operate on
  254. * @param \Zend\Navigation\Navigation $container [optional] container to operate on
  255. * @return TbNavbar fluent interface, returns self
  256. */
  257. public function __invoke(Navigation $container = null)
  258. {
  259. if (null !== $container) {
  260. $this->setContainer($container);
  261. }
  262. return $this;
  263. }
  264. protected function translate($text)
  265. {
  266. $t = $this->getTranslator();
  267. if ($this->isTranslatorEnabled()
  268. && $t
  269. && is_string($text)
  270. && !empty($text)) {
  271. $text = $t->translate($text);
  272. }
  273. return $text;
  274. }
  275. /**
  276. * If missing in the text, adds the space separated word to the text
  277. * @param string $word
  278. * @param string $text
  279. */
  280. protected function addWord($word, &$text)
  281. {
  282. $text = trim($text);
  283. if(!$text) {
  284. $wordsLower = array();
  285. $words = array();
  286. } else {
  287. $wordsLower = explode(' ', strtolower($text));
  288. $words = explode(' ', $text);
  289. }
  290. if(!in_array(strtolower($word), $wordsLower)) {
  291. $words[] = $word;
  292. $text = implode(' ', $words);
  293. }
  294. }
  295. /**
  296. * Sets CSS class to use for the ul element
  297. *
  298. * @param string $class
  299. * @return \Zf2tb\View\Helper\Navigation\AbstractHelper
  300. */
  301. public function setUlClass($class)
  302. {
  303. $this->ulClass = (string) $class;
  304. return $this;
  305. }
  306. /**
  307. * Adds CSS class to the ul element
  308. *
  309. * @param string $class
  310. * @return \Zf2tb\View\Helper\Navigation\AbstractHelper
  311. */
  312. public function addUlClass($class)
  313. {
  314. $this->ulClass .= ' ' . (string) $class;
  315. return $this;
  316. }
  317. /**
  318. * Sets CSS class to use for the li element containing submenu
  319. *
  320. * @param string $class
  321. * @return \Zf2tb\View\Helper\Navigation\AbstractHelper
  322. */
  323. public function setParentMenuClass($class)
  324. {
  325. $this->parentMenuClass = (string) $class;
  326. return $this;
  327. }
  328. /**
  329. * Adds CSS class to the li element containing submenu
  330. *
  331. * @param string $class
  332. * @return \Zf2tb\View\Helper\Navigation\AbstractHelper
  333. */
  334. public function addParentMenuClass($class)
  335. {
  336. $this->parentMenuClass .= ' ' . (string) $class;
  337. return $this;
  338. }
  339. /**
  340. * Sets CSS class to use for the ul element of a submenu
  341. *
  342. * @param string $class
  343. * @return \Zf2tb\View\Helper\Navigation\AbstractHelper
  344. */
  345. public function setDropdownUlClass($class)
  346. {
  347. $this->dropdownUlClass = (string) $class;
  348. return $this;
  349. }
  350. /**
  351. * Adds CSS class to the ul element containing a submenu
  352. *
  353. * @param string $class
  354. * @return \Zf2tb\View\Helper\Navigation\AbstractHelper
  355. */
  356. public function addDropdownUlClass($class)
  357. {
  358. $this->dropdownUlClass .= ' ' . (string) $class;
  359. return $this;
  360. }
  361. /**
  362. * Sets whether to render icons
  363. *
  364. * @param bool $flag
  365. * @return \Zf2tb\View\Helper\Navigation\AbstractHelper
  366. */
  367. public function setRenderIcons($flag = true)
  368. {
  369. $this->renderIcons = (bool) $flag;
  370. return $this;
  371. }
  372. /**
  373. * Sets whether to use caret in dropdown parent menu item
  374. *
  375. * @param bool $flag
  376. * @return \Zf2tb\View\Helper\Navigation\AbstractHelper
  377. */
  378. public function setUseDropdownParentCaret($flag = true)
  379. {
  380. $this->useDropdownParentCaret = (bool) $flag;
  381. return $this;
  382. }
  383. }