<commit_before><?php
/**
 * Copyright (c) Qobo Ltd. (https://www.qobo.biz)
 *
 * Licensed under The MIT License
 * For full copyright and license information, please see the LICENSE
 * Redistributions of files must retain the above copyright notice.
 *
 * @copyright     Copyright (c) Qobo Ltd. (https://www.qobo.biz)
 * @license       https://opensource.org/licenses/mit-license.php MIT License
 */
namespace Menu\MenuBuilder;

use Cake\View\View;

/**
 *  BaseMenuRenderClass class
 *
 *  Base class for menu renders
 */
class BaseMenuRenderClass implements MenuRenderInterface
{
    const RENDER_CLASS_NAME_POSTFIX = 'Render';

    /**
     * @var $format array with formats
     */
    protected $format = [];

    /**
     * @var Menu $menu
     */
    protected $menu = null;

    /**
     * @var View $viewEntity
     */
    protected $viewEntity = null;

    /**
     * @var $noLabel
     */
    protected $noLabel = false;

    /**
     * @var array Mapping between MenuItemInterface implementation and render method
     */
    private static $itemRenderer = [
        'Menu\MenuBuilder\MenuItemPostlink' => 'buildPostlink',
        'Menu\MenuBuilder\MenuItemButton' => 'buildButton',
        'Menu\MenuBuilder\MenuItemSeparator' => 'buildSeparator',
        'Menu\MenuBuilder\MenuItemLinkButton' => 'buildLinkButton',
        'Menu\MenuBuilder\MenuItemPostlinkButton' => 'buildPostlinkButton',
        'Menu\MenuBuilder\MenuItemLinkButtonModal' => 'buildLinkButtonModal',
        'Menu\MenuBuilder\MenuItemLinkModal' => 'buildLinkModal',
    ];

    /**
     *  __construct method
     *
     * @param \Menu\MenuBuilder\Menu $menu menu to render
     * @param \Cake\View\View $viewEntity view entity
     * @return void
     */
    public function __construct(Menu $menu, View $viewEntity)
    {
        $this->menu = $menu;
        $this->viewEntity = $viewEntity;
    }

    /**
     * setFormat method
     *
     * @param array $format containing all required keys
     * @return void
     */
    public function setFormat(array $format = [])
    {
        $this->format = $format;
    }

    /**
     * getFormat method
     *
     * @return array $format containing menu settings
     */
    public function getFormat()
    {
        return $this->format;
    }

    /**
     *  render method
     *
     * @param array $options to generate menu
     * @return string rendered menu as per specified format
     */
    public function render(array $options = [])
    {
        $html = $this->format['menuStart'];
        $html .= !empty($options['title']) ? $options['title'] : '';

        /**
         * @var MenuItemInterface $menuItem
         */
        foreach ($this->menu->getMenuItems() as $menuItem) {
            if ($menuItem->isEnabled()) {
                $html .= $this->renderMenuItem($menuItem);
            }
        }
        $html .= $this->format['menuEnd'];

        return $html;
    }

    /**
     *  _renderMenuItem method
     *
     * @param \Menu\MenuBuilder\MenuItemInterface $item menu item definition
     * @return string rendered menu item as HTML
     */
    protected function renderMenuItem(MenuItemInterface $item)
    {
        $children = $item->getMenuItems();

        $html = $this->format['itemStart'];

        $html .= $this->buildItem($item, !empty($children) && !empty($this->format['itemWithChildrenPostfix']) ? $this->format['itemWithChildrenPostfix'] : '');

        if (!empty($children)) {
            $enabledChildren = array_filter($children, function (MenuItemInterface $child) {
                return $child->isEnabled();
            });

            $html .= $this->format['childMenuStart'];
            /** @var MenuItemInterface $childItem */
            foreach ($enabledChildren as $childItem) {
                $html .= !empty($this->format['childItemStart']) ? $this->format['childItemStart'] : '';
                $html .= $this->renderMenuItem($childItem);
                $html .= !empty($this->format['childItemEnd']) ? $this->format['childItemEnd'] : '';
            }
            $html .= $this->format['childMenuEnd'];
        }

        $html .= $this->format['itemEnd'];

        return $html;
    }

    /**
     *  buildItem method
     *
     * @param MenuItemInterface $item menu item entity
     * @param string $extLabel additional label elements
     * @return string generated HTML element
     */
    protected function buildItem(MenuItemInterface $item, $extLabel)
    {
        $result = null;

        $class = get_class($item);
        if (array_key_exists($class, self::$itemRenderer)) {
            $method = self::$itemRenderer[$class];
            $result = call_user_func([$this, $method], $item, $extLabel);
        } else {
            $result = $this->buildLink($item, $extLabel);
        }

        $result .= !empty($item->getRawHtml()) ? $item->getRawHtml() : '';

        return $result;
    }

    /**
     *  buildLink method
     *
     * @param MenuItemInterface $item menu item entity
     * @param string $extLabel additional label elements
     * @param array $params additional params
     * @return string generated HTML element
     */
    protected function buildLink(MenuItemInterface $item, $extLabel = '', $params = [])
    {
        $params['title'] = __($item->getLabel());
        $params['escape'] = false;
        $params['target'] = $item->getTarget();

        $label = '<i class="menu-icon fa fa-' . $item->getIcon() . '"></i> ';
        $label .= !empty($this->format['itemHeaderStart']) ? $this->format['itemHeaderStart'] : '';
        $label .= !empty($this->format['itemWrapperStart']) ? $this->format['itemWrapperStart'] : '';
        $label .= $this->noLabel ? '' : __($item->getLabel());
        $label .= !empty($this->format['itemWrapperEnd']) ? $this->format['itemWrapperEnd'] : '';
        $label .= $extLabel;
        $label .= !empty($item->getDescription()) ? $this->format['itemDescrStart'] . $item->getDescription() . $this->format['itemDescrEnd'] : '';
        $label .= !empty($this->format['itemHeaderEnd']) ? $this->format['itemHeaderEnd'] : '';
        $result = $this->viewEntity->Html->link($label, $item->getUrl(), $params);

        return $result;<commit_msg>Rely on naming conventions to load renderer method. Always fall back to buildLink as default (task #809)<commit_after><?php
/**
 * Copyright (c) Qobo Ltd. (https://www.qobo.biz)
 *
 * Licensed under The MIT License
 * For full copyright and license information, please see the LICENSE
 * Redistributions of files must retain the above copyright notice.
 *
 * @copyright     Copyright (c) Qobo Ltd. (https://www.qobo.biz)
 * @license       https://opensource.org/licenses/mit-license.php MIT License
 */
namespace Menu\MenuBuilder;

use Cake\View\View;

/**
 *  BaseMenuRenderClass class
 *
 *  Base class for menu renders
 */
class BaseMenuRenderClass implements MenuRenderInterface
{
    const RENDER_CLASS_NAME_POSTFIX = 'Render';
    const DEFAULT_RENDER_METHOD = 'buildLink';

    /**
     * @var $format array with formats
     */
    protected $format = [];

    /**
     * @var Menu $menu
     */
    protected $menu = null;

    /**
     * @var View $viewEntity
     */
    protected $viewEntity = null;

    /**
     * @var $noLabel
     */
    protected $noLabel = false;

    /**
     *  __construct method
     *
     * @param \Menu\MenuBuilder\Menu $menu menu to render
     * @param \Cake\View\View $viewEntity view entity
     * @return void
     */
    public function __construct(Menu $menu, View $viewEntity)
    {
        $this->menu = $menu;
        $this->viewEntity = $viewEntity;
    }

    /**
     * setFormat method
     *
     * @param array $format containing all required keys
     * @return void
     */
    public function setFormat(array $format = [])
    {
        $this->format = $format;
    }

    /**
     * getFormat method
     *
     * @return array $format containing menu settings
     */
    public function getFormat()
    {
        return $this->format;
    }

    /**
     *  render method
     *
     * @param array $options to generate menu
     * @return string rendered menu as per specified format
     */
    public function render(array $options = [])
    {
        $html = $this->format['menuStart'];
        $html .= !empty($options['title']) ? $options['title'] : '';

        /**
         * @var MenuItemInterface $menuItem
         */
        foreach ($this->menu->getMenuItems() as $menuItem) {
            if ($menuItem->isEnabled()) {
                $html .= $this->renderMenuItem($menuItem);
            }
        }
        $html .= $this->format['menuEnd'];

        return $html;
    }

    /**
     *  _renderMenuItem method
     *
     * @param \Menu\MenuBuilder\MenuItemInterface $item menu item definition
     * @return string rendered menu item as HTML
     */
    protected function renderMenuItem(MenuItemInterface $item)
    {
        $children = $item->getMenuItems();

        $html = $this->format['itemStart'];

        $html .= $this->buildItem($item, !empty($children) && !empty($this->format['itemWithChildrenPostfix']) ? $this->format['itemWithChildrenPostfix'] : '');

        if (!empty($children)) {
            $enabledChildren = array_filter($children, function (MenuItemInterface $child) {
                return $child->isEnabled();
            });

            $html .= $this->format['childMenuStart'];
            /** @var MenuItemInterface $childItem */
            foreach ($enabledChildren as $childItem) {
                $html .= !empty($this->format['childItemStart']) ? $this->format['childItemStart'] : '';
                $html .= $this->renderMenuItem($childItem);
                $html .= !empty($this->format['childItemEnd']) ? $this->format['childItemEnd'] : '';
            }
            $html .= $this->format['childMenuEnd'];
        }

        $html .= $this->format['itemEnd'];

        return $html;
    }

    /**
     *  buildItem method
     *
     * @param MenuItemInterface $item menu item entity
     * @param string $extLabel additional label elements
     * @return string generated HTML element
     */
    protected function buildItem(MenuItemInterface $item, $extLabel)
    {
        try {
            $shortClass = (new \ReflectionClass($item))->getShortName();
            $method = str_replace(BaseMenuItem::MENU_ITEM_CLASS_PREFIX, 'build', $shortClass);
            if (!method_exists($this, $method)) {
                $method = self::DEFAULT_RENDER_METHOD;
            }
        } catch (\ReflectionException $e) {
            $method = self::DEFAULT_RENDER_METHOD;
        }

        $result = call_user_func([$this, $method], $item, $extLabel);
        $result .= !empty($item->getRawHtml()) ? $item->getRawHtml() : '';

        return $result;
    }

    /**
     *  buildLink method
     *
     * @param MenuItemInterface $item menu item entity
     * @param string $extLabel additional label elements
     * @param array $params additional params
     * @return string generated HTML element
     */
    protected function buildLink(MenuItemInterface $item, $extLabel = '', $params = [])
    {
        $params['title'] = __($item->getLabel());
        $params['escape'] = false;
        $params['target'] = $item->getTarget();

        $label = '<i class="menu-icon fa fa-' . $item->getIcon() . '"></i> ';
        $label .= !empty($this->format['itemHeaderStart']) ? $this->format['itemHeaderStart'] : '';
        $label .= !empty($this->format['itemWrapperStart']) ? $this->format['itemWrapperStart'] : '';
        $label .= $this->noLabel ? '' : __($item->getLabel());
        $label .= !empty($this->format['itemWrapperEnd']) ? $this->format['itemWrapperEnd'] : '';
        $label .= $extLabel;
        $label .= !empty($item->getDescription()) ? $this->format['itemDescrStart'] . $item->getDescription() . $this->format['itemDescrEnd'] : '';
        $label .= !empty($this->format['itemHeaderEnd']) ? $this->format['itemHeaderEnd'] : '';
        $result = $this->viewEntity->Html->link($label, $item->getUrl(), $params);

        return $result;
{'fraction_non_alphanumeric': 0.15384615384615385, 'fraction_numerical': 0.00024787242832355615, 'mean_word_length': 2.4464692482915718, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 110, 'https://': 6, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '918182', 'n_tokens_mistral': 3420, 'n_tokens_neox': 3339, 'n_words': 759}