Seditio Source
Root |
./othercms/croogo-4.0.7/vendor/croogo/croogo/Menus/src/View/Helper/MenusHelper.php
<?php

namespace Croogo\Menus\View\Helper;

use
Cake\Event\Event;
use
Cake\Log\LogTrait;
use
Cake\Routing\Exception\MissingRouteException;
use
Cake\Routing\Router;
use
Cake\Utility\Hash;
use
Cake\View\Helper;
use
Cake\View\View;
use
Croogo\Core\Nav;
use
Croogo\Core\Utility\StringConverter;

/**
 * Menus Helper
 *
 * @category Menus.View/Helper
 * @package  Croogo.Menus.View.Helper
 * @version  1.0
 * @author   Fahad Ibnay Heylaal <contact@fahad19.com>
 * @license  http://www.opensource.org/licenses/mit-license.php The MIT License
 * @link     http://www.croogo.org
 */
class MenusHelper extends Helper
{

    use
LogTrait;

    public
$helpers = [
       
'Html',
       
'Layout',
    ];

   
/**
     * constructor
     */
   
public function __construct(View $view, $settings = [])
    {
       
parent::__construct($view, $settings);
       
$this->_setupEvents();
       
$this->_converter = new StringConverter();
    }

   
/**
     * setup events
     */
   
protected function _setupEvents()
    {
       
$events = [
           
'Helper.Layout.beforeFilter' => [
               
'callable' => 'filter', 'passParams' => true,
            ],
        ];
       
$eventManager = $this->_View->getEventManager();
        foreach (
$events as $name => $config) {
           
$eventManager->on($name, $config, [$this, 'filter']);
        }
    }

   
/**
     * beforeRender
     */
   
public function beforeRender($viewFile)
    {
       
$request = $this->getView()->getRequest();
        if ((
$request->getParam('prefix') === 'admin') && (!$request->is('ajax'))) {
           
$this->_adminMenu();
            if (
$request->getParam('plugin') == 'Croogo/Menus') {
               
$this->_View->Js->buffer('Links.init();');
            }
        }
    }

   
/**
     * Inject admin menu items
     */
   
protected function _adminMenu()
    {
        if (empty(
$this->_View->viewVars['menus_for_admin_layout'])) {
            return;
        }
       
$menus = $this->_View->viewVars['menus_for_admin_layout'];
        if (!
Nav::check('sidebar', 'menus')) {
            return;
        }
        foreach (
$menus as $menu) {
           
$weight = 9999 + $menu->weight;
           
$htmlAttributes = $this->__isCurrentMenu($menu->id) ? ['class' => 'current'] : [];
           
Nav::add('sidebar', 'menus.children.' . $menu->alias, [
               
'title' => $menu->title,
               
'url' => [
                   
'prefix' => 'admin',
                   
'plugin' => 'Croogo/Menus',
                   
'controller' => 'Links',
                   
'action' => 'index',
                   
'?' => ['menu_id' => $menu->id]
                ],
               
'weight' => $weight,
               
'htmlAttributes' => $htmlAttributes
           
]);
        };
    }

   
/**
     * Checks wether $id is the current active menu
     *
     * The value is checked against the menuId variable set in
     * LinksController::admin_add() and LinksController::admin_edit()
     *
     * @param string $id Menu id
     * @return bool True if $id is currently the active menu
     */
   
private function __isCurrentMenu($id)
    {
       
$currentMenuId = $this->_View->get('menuId');

        return
$currentMenuId === $id;
    }

   
/**
     * Filter content for Menus
     *
     * Replaces [menu:menu_alias] or [m:menu_alias] with Menu list
     *
     * @param Event $event
     * @return string
     */
   
public function filter(Event $event, $options = [])
    {
       
$data = $event->getData();
       
preg_match_all('/\[(menu|m):([A-Za-z0-9_\-]*)(.*?)\]/i', $data['content'], $tagMatches);
        for (
$i = 0, $ii = count($tagMatches[1]); $i < $ii; $i++) {
           
$regex = '/(\S+)=[\'"]?((?:.(?![\'"]?\s+(?:\S+)=|[>\'"]))+.)[\'"]?/i';
           
preg_match_all($regex, $tagMatches[3][$i], $attributes);
           
$menuAlias = $tagMatches[2][$i];
           
$options = [];
            for (
$j = 0, $jj = count($attributes[0]); $j < $jj; $j++) {
               
$options[$attributes[1][$j]] = $attributes[2][$j];
            }
           
$options = Hash::expand($options);
           
$data['content'] = str_replace($tagMatches[0][$i], $this->verticalNav($menuAlias, $options), $data['content']);
        }

        return
$event->getData();
    }

   
/**
     * Output simple vertical nav
     */
   
protected function verticalNav($menuAlias, $options = [])
    {
       
$menu = Hash::get($this->_View->viewVars, "menusForLayout.$menuAlias");
        if (!
$menu) {
            return
false;
        }
       
$items = [];
       
$roleId = $this->Layout->getRoleId();
        foreach (
$menu['threaded'] as $item) {
            if (!empty(
$item->visibility_roles) && !in_array($roleId, $item->visibility_roles)) {
                continue;
            }

           
$url = $item->link->getUrl();
            try {
               
$items[] = $this->Html->link($item->title, $url, [
                   
'class' => 'nav-link',
                ]);
            } catch (
MissingRouteException $e) {
               
$this->log('Cannot normalize url: ' . print_r($url, true), LOG_WARNING);
            }
        }
        if (!
$items) {
            return
null;
        }

        return
$this->Html->tag('nav', implode('', $items), [
           
'class' => 'nav flex-column',
        ]);
    }

   
/**
     * Show Menu by Alias
     *
     * @param string $menuAlias Menu alias
     * @param array $options (optional)
     * @return string
     */
   
public function menu($menuAlias, $options = [])
    {
       
$_options = [
           
'tag' => 'ul',
           
'tagAttributes' => [
               
'class' => 'dropdown-menu bg-dark',
            ],
           
'subTag' => 'li',
           
'subTagAttributes' => [
               
'class' => 'nav-item',
            ],
           
'linkAttributes' => [
               
'class' => 'nav-link js-scroll-trigger',
            ],
           
'selected' => 'selected',
           
'dropdown' => false,
           
'dropdownClass' => 'navbar-nav ml-auto',
           
'element' => 'Croogo/Menus.menu',
        ];
       
$options = array_merge($_options, $options);

        if (!isset(
$this->_View->viewVars['menusForLayout'][$menuAlias])) {
            return
false;
        }
       
$menu = $this->_View->viewVars['menusForLayout'][$menuAlias];
       
$output = $this->_View->element($options['element'], [
           
'menu' => $menu,
           
'options' => $options,
        ]);

        return
$output;
    }

   
/**
     * Merge Link options retrieved from Params behavior
     *
     * @param array $link Link data
     * @param string $param Parameter name
     * @param array $options Default options
     * @return string
     */
   
protected function _mergeLinkParams($link, $param, $options = [])
    {
        if (isset(
$link['Params'][$param])) {
           
$options = array_merge($options, $link['Params'][$param]);
        }

       
$booleans = ['true', 'false'];
        foreach (
$options as $key => $val) {
            if (
$val == null) {
                unset(
$options[$key]);
            }
            if (
is_string($val) && in_array(strtolower($val), $booleans)) {
               
$options[$key] = ($val === 'true');
            }
        }

        return
$options;
    }

   
/**
     * Nested Links
     *
     * @param array $links model output (threaded)
     * @param array $options (optional)
     * @param int $depth level
     * @return string
     */
   
public function nestedLinks($links, $options = [], $depth = 1)
    {
       
$_options = [
           
'linkAttributes' => []
        ];
       
$options = array_merge($_options, $options);

       
$roleId = $this->Layout->getRoleId();
       
$output = '';
        foreach (
$links as $link) {
           
$linkAttr = $options['linkAttributes'] + [
               
'id' => 'link-' . $link->id,
               
'rel' => $link->rel,
               
'target' => $link->target,
               
'title' => $link->description,
               
'class' => $link->class,
            ];

            if (!empty(
$link->visibility_roles) && !in_array($roleId, $link->visibility_roles)) {
                continue;
            }

           
$linkAttr = $this->_mergeLinkParams($link, 'liAttr', $linkAttr);

            if (!empty(
$link->class) && strpos($linkAttr['class'], $link->class)) {
               
$linkAttr['class'] = $this->addClass($linkAttr['class'], $link->class);
            }

           
// Remove locale part before comparing links
           
if ($this->getView()->getRequest()->getParam('locale')) {
               
$currentUrl = substr($this->getView()->getRequest()->getPath(), strlen($this->getView()->getRequest()->getParam('locale') . '/'));
            } else {
               
$currentUrl = $this->getView()->getRequest()->getPath();
            }

            try {
                if (
Router::url($link->link->getUrl()) == Router::url('/' . $currentUrl)) {
                    if (!isset(
$linkAttr['class'])) {
                       
$linkAttr['class'] = '';
                    }
                   
$linkAttr['class'] .= ' ' . $options['selected'];
                }
            } catch (
MissingRouteException $e) {
               
$this->log(
                   
sprintf(
                       
'MissingRouteException for menu id %d - %s:',
                       
$link->id,
                       
$link->title
                   
),
                   
LOG_WARNING
               
);
               
$this->log($e->getMessage(), LOG_WARNING);
                continue;
            }

            if (isset(
$link['children']) && count($link['children']) > 0) {
               
$linkAttr['class'] .= ' dropdown-toggle';
               
$linkAttr['data-toggle'] = 'dropdown';
               
$linkAttr['aria-haspopup'] = 'true';
               
$linkAttr['aria-expanded'] = 'false';
            }

           
$linkOutput = $this->Html->link($link->title, $link->link->getUrl(), $linkAttr);
            if (isset(
$link['children']) && count($link['children']) > 0) {
               
$childOptions = $options;
               
$childOptions['subTagAttributes']['class'] = 'dropdown-item bg-dark';
               
$linkOutput .= $this->nestedLinks($link['children'], $childOptions, $depth + 1);
            }
           
$liAttr = $this->_mergeLinkParams($link, 'liAttr');
           
$liAttr = !empty($liAttr) ? $liAttr : $options['subTagAttributes'];

            if (isset(
$link['children']) && count($link['children']) > 0) {
               
$liAttr['class'] .= ' dropdown';
            }

           
$linkOutput = $this->Html->tag($options['subTag'], $linkOutput, $liAttr);
           
$output .= $linkOutput;
        }
        if (
$output != null) {
           
$tagAttr = $options['tagAttributes'];
            if (
$options['dropdown'] && $depth == 1) {
               
$tagAttr['class'] = $options['dropdownClass'];
            }
           
$output = $this->Html->tag($options['tag'], $output, $tagAttr);
        }

        return
$output;
    }

   
/**
     * Converts strings like controller:abc/action:xyz/ to arrays
     *
     * @param string|array $link link
     * @return array
     * @see Use StringConverter::linkStringToArray()
     */
   
public function linkStringToArray($link)
    {
        return
$this->_converter->linkStringToArray($link);
    }

   
/**
     * Converts array into string controller:abc/action:xyz/value1/value2
     *
     * @param array $url link
     * @return array
     * @see StringConverter::urlToLinkString()
     */
   
public function urlToLinkString($url)
    {
        return
$this->_converter->urlToLinkString($url);
    }
}