<?php

/**
 * @file classes/services/PKPNavigationMenuService.php
 *
 * Copyright (c) 2014-2021 Simon Fraser University
 * Copyright (c) 2000-2021 John Willinsky
 * Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
 *
 * @class PKPNavigationMenuService
 *
 * @ingroup services
 *
 * @brief Helper class that encapsulates NavigationMenu business logic
 */

namespace PKP\services;

use APP\core\Application;
use APP\template\TemplateManager;
use PKP\cache\FileCache;
use PKP\core\PKPApplication;
use PKP\db\DAORegistry;
use PKP\facades\Locale;
use PKP\navigationMenu\NavigationMenu;
use PKP\navigationMenu\NavigationMenuDAO;
use PKP\navigationMenu\NavigationMenuItem;
use PKP\navigationMenu\NavigationMenuItemAssignment;
use PKP\navigationMenu\NavigationMenuItemAssignmentDAO;
use PKP\navigationMenu\NavigationMenuItemDAO;
use PKP\pages\navigationMenu\NavigationMenuItemHandler;
use PKP\plugins\Hook;
use PKP\security\Role;
use PKP\security\Validation;

class PKPNavigationMenuService
{
    /**
     * Return all default navigationMenuItemTypes.
     *
     * @return array
     */
    public function getMenuItemTypes()
    {
        $types = [
            NavigationMenuItem::NMI_TYPE_CUSTOM => [
                'title' => __('manager.navigationMenus.customPage'),
                'description' => __('manager.navigationMenus.customPage.description'),
            ],
            NavigationMenuItem::NMI_TYPE_REMOTE_URL => [
                'title' => __('manager.navigationMenus.remoteUrl'),
                'description' => __('manager.navigationMenus.remoteUrl.description'),
            ],
            NavigationMenuItem::NMI_TYPE_ABOUT => [
                'title' => __('navigation.about'),
                'description' => __('manager.navigationMenus.about.description'),
                'conditionalWarning' => __('manager.navigationMenus.about.conditionalWarning'),
            ],
            NavigationMenuItem::NMI_TYPE_EDITORIAL_TEAM => [
                'title' => __('about.editorialTeam'),
                'description' => __('manager.navigationMenus.editorialTeam.description'),
                'conditionalWarning' => __('manager.navigationMenus.editorialTeam.conditionalWarning'),
            ],
            NavigationMenuItem::NMI_TYPE_SUBMISSIONS => [
                'title' => __('about.submissions'),
                'description' => __('manager.navigationMenus.submissions.description'),
            ],
            NavigationMenuItem::NMI_TYPE_ANNOUNCEMENTS => [
                'title' => __('announcement.announcements'),
                'description' => __('manager.navigationMenus.announcements.description'),
                'conditionalWarning' => __('manager.navigationMenus.announcements.conditionalWarning'),
            ],
            NavigationMenuItem::NMI_TYPE_USER_LOGIN => [
                'title' => __('navigation.login'),
                'description' => __('manager.navigationMenus.login.description'),
                'conditionalWarning' => __('manager.navigationMenus.loggedIn.conditionalWarning'),
            ],
            NavigationMenuItem::NMI_TYPE_USER_REGISTER => [
                'title' => __('navigation.register'),
                'description' => __('manager.navigationMenus.register.description'),
                'conditionalWarning' => __('manager.navigationMenus.loggedIn.conditionalWarning'),
            ],
            NavigationMenuItem::NMI_TYPE_USER_DASHBOARD => [
                'title' => __('navigation.dashboard'),
                'description' => __('manager.navigationMenus.dashboard.description'),
                'conditionalWarning' => __('manager.navigationMenus.loggedOut.conditionalWarning'),
            ],
            NavigationMenuItem::NMI_TYPE_USER_PROFILE => [
                'title' => __('common.viewProfile'),
                'description' => __('manager.navigationMenus.profile.description'),
                'conditionalWarning' => __('manager.navigationMenus.loggedOut.conditionalWarning'),
            ],
            NavigationMenuItem::NMI_TYPE_ADMINISTRATION => [
                'title' => __('navigation.admin'),
                'description' => __('manager.navigationMenus.administration.description'),
                'conditionalWarning' => __('manager.navigationMenus.loggedOut.conditionalWarning'),
            ],
            NavigationMenuItem::NMI_TYPE_USER_LOGOUT => [
                'title' => __('user.logOut'),
                'description' => __('manager.navigationMenus.logOut.description'),
                'conditionalWarning' => __('manager.navigationMenus.loggedOut.conditionalWarning'),
            ],
            NavigationMenuItem::NMI_TYPE_CONTACT => [
                'title' => __('about.contact'),
                'description' => __('manager.navigationMenus.contact.description'),
                'conditionalWarning' => __('manager.navigationMenus.contact.conditionalWarning'),
            ],
            NavigationMenuItem::NMI_TYPE_SEARCH => [
                'title' => __('common.search'),
                'description' => __('manager.navigationMenus.search.description'),
            ],
            NavigationMenuItem::NMI_TYPE_PRIVACY => [
                'title' => __('manager.setup.privacyStatement'),
                'description' => __('manager.navigationMenus.privacyStatement.description'),
                'conditionalWarning' => __('manager.navigationMenus.privacyStatement.conditionalWarning'),
            ],
        ];

        Hook::call('NavigationMenus::itemTypes', [&$types]);

        return $types;
    }

    /**
     * Return all custom edit navigationMenuItemTypes Templates.
     *
     * @return array
     */
    public function getMenuItemCustomEditTemplates()
    {
        $templates = [
            NavigationMenuItem::NMI_TYPE_CUSTOM => [
                'template' => 'core:controllers/grid/navigationMenus/customNMIType.tpl',
            ],
            NavigationMenuItem::NMI_TYPE_REMOTE_URL => [
                'template' => 'core:controllers/grid/navigationMenus/remoteUrlNMIType.tpl',
            ],
        ];

        Hook::call('NavigationMenus::itemCustomTemplates', [&$templates]);

        return $templates;
    }

    /**
     * Callback for display menu item functionality
     */
    public function getDisplayStatus(&$navigationMenuItem, &$navigationMenu)
    {
        $request = Application::get()->getRequest();
        $dispatcher = $request->getDispatcher();
        $templateMgr = TemplateManager::getManager($request);

        $isUserLoggedIn = Validation::isLoggedIn();
        $isUserLoggedInAs = Validation::loggedInAs();
        $context = $request->getContext();
        $currentUser = $request->getUser();

        $contextId = $context ? $context->getId() : \PKP\core\PKPApplication::CONTEXT_ID_NONE;

        // Transform an item title if the title includes a {$variable}
        $this->transformNavMenuItemTitle($templateMgr, $navigationMenuItem);

        $menuItemType = $navigationMenuItem->getType();

        // Conditionally hide some items
        switch ($menuItemType) {
            case NavigationMenuItem::NMI_TYPE_ANNOUNCEMENTS:
                $navigationMenuItem->setIsDisplayed(
                    ($context && $context->getData('enableAnnouncements'))
                    || (!$context && $request->getSite()->getData('enableAnnouncements'))
                );
                break;
            case NavigationMenuItem::NMI_TYPE_EDITORIAL_TEAM:
                $navigationMenuItem->setIsDisplayed($context && $context->getLocalizedData('editorialTeam'));
                break;
            case NavigationMenuItem::NMI_TYPE_CONTACT:
                $navigationMenuItem->setIsDisplayed($context && ($context->getData('mailingAddress') || $context->getData('contactName')));
                break;
            case NavigationMenuItem::NMI_TYPE_USER_REGISTER:
                $navigationMenuItem->setIsDisplayed(!$isUserLoggedIn && !($context && $context->getData('disableUserReg')));
                break;
            case NavigationMenuItem::NMI_TYPE_USER_LOGIN:
                $navigationMenuItem->setIsDisplayed(!$isUserLoggedIn);
                break;
            case NavigationMenuItem::NMI_TYPE_USER_LOGOUT:
            case NavigationMenuItem::NMI_TYPE_USER_PROFILE:
            case NavigationMenuItem::NMI_TYPE_USER_DASHBOARD:
                $navigationMenuItem->setIsDisplayed($isUserLoggedIn);
                break;
            case NavigationMenuItem::NMI_TYPE_ADMINISTRATION:
                $navigationMenuItem->setIsDisplayed($isUserLoggedIn && $currentUser->hasRole([Role::ROLE_ID_SITE_ADMIN], PKPApplication::CONTEXT_SITE));
                break;
            case NavigationMenuItem::NMI_TYPE_PRIVACY:
                $navigationMenuItem->setIsDisplayed($context && $context->getLocalizedData('privacyStatement'));
                break;
        }

        if ($navigationMenuItem->getIsDisplayed()) {
            // Adjust some titles
            switch ($menuItemType) {
                case NavigationMenuItem::NMI_TYPE_USER_LOGOUT:
                    if ($isUserLoggedInAs) {
                        $userName = $request->getUser() ? ' ' . $request->getUser()->getUserName() : '';
                        $navigationMenuItem->setTitle(__('user.logOutAs', ['username' => $userName]), Locale::getLocale());
                    }
                    break;
                case NavigationMenuItem::NMI_TYPE_USER_DASHBOARD:
                    $templateMgr->assign('navigationMenuItem', $navigationMenuItem);
                    if ($currentUser->hasRole([Role::ROLE_ID_MANAGER, Role::ROLE_ID_ASSISTANT, Role::ROLE_ID_REVIEWER, Role::ROLE_ID_AUTHOR], $contextId) || $currentUser->hasRole([Role::ROLE_ID_SITE_ADMIN], PKPApplication::CONTEXT_SITE)) {
                        $displayTitle = $templateMgr->fetch('frontend/components/navigationMenus/dashboardMenuItem.tpl');
                        $navigationMenuItem->setTitle($displayTitle, Locale::getLocale());
                    }
                    break;
            }

            // Set the URL
            switch ($menuItemType) {
                case NavigationMenuItem::NMI_TYPE_ANNOUNCEMENTS:
                    $navigationMenuItem->setUrl($dispatcher->url(
                        $request,
                        PKPApplication::ROUTE_PAGE,
                        null,
                        'announcement',
                        null,
                        null
                    ));
                    break;
                case NavigationMenuItem::NMI_TYPE_ABOUT:
                    $navigationMenuItem->setUrl($dispatcher->url(
                        $request,
                        PKPApplication::ROUTE_PAGE,
                        null,
                        'about',
                        null,
                        null
                    ));
                    break;
                case NavigationMenuItem::NMI_TYPE_SUBMISSIONS:
                    $navigationMenuItem->setUrl($dispatcher->url(
                        $request,
                        PKPApplication::ROUTE_PAGE,
                        null,
                        'about',
                        'submissions',
                        null
                    ));
                    break;
                case NavigationMenuItem::NMI_TYPE_EDITORIAL_TEAM:
                    $navigationMenuItem->setUrl($dispatcher->url(
                        $request,
                        PKPApplication::ROUTE_PAGE,
                        null,
                        'about',
                        'editorialTeam',
                        null
                    ));
                    break;
                case NavigationMenuItem::NMI_TYPE_CONTACT:
                    $navigationMenuItem->setUrl($dispatcher->url(
                        $request,
                        PKPApplication::ROUTE_PAGE,
                        null,
                        'about',
                        'contact',
                        null
                    ));
                    break;
                case NavigationMenuItem::NMI_TYPE_USER_LOGOUT:
                    $navigationMenuItem->setUrl($dispatcher->url(
                        $request,
                        PKPApplication::ROUTE_PAGE,
                        null,
                        'login',
                        $isUserLoggedInAs ? 'signOutAsUser' : 'signOut',
                        null
                    ));
                    break;
                case NavigationMenuItem::NMI_TYPE_USER_PROFILE:
                    $navigationMenuItem->setUrl($dispatcher->url(
                        $request,
                        PKPApplication::ROUTE_PAGE,
                        null,
                        'user',
                        'profile',
                        null
                    ));
                    break;
                case NavigationMenuItem::NMI_TYPE_ADMINISTRATION:
                    $navigationMenuItem->setUrl($dispatcher->url(
                        $request,
                        PKPApplication::ROUTE_PAGE,
                        'index',
                        'admin',
                        'index',
                        null
                    ));
                    break;
                case NavigationMenuItem::NMI_TYPE_USER_DASHBOARD:
                    if ($currentUser->hasRole([Role::ROLE_ID_MANAGER, Role::ROLE_ID_ASSISTANT, Role::ROLE_ID_REVIEWER, Role::ROLE_ID_AUTHOR], $contextId) || $currentUser->hasRole([Role::ROLE_ID_SITE_ADMIN], PKPApplication::CONTEXT_SITE)) {
                        $navigationMenuItem->setUrl($dispatcher->url(
                            $request,
                            PKPApplication::ROUTE_PAGE,
                            null,
                            'submissions',
                            null,
                            null
                        ));
                    } else {
                        $navigationMenuItem->setUrl($dispatcher->url(
                            $request,
                            PKPApplication::ROUTE_PAGE,
                            null,
                            'user',
                            'profile',
                            null
                        ));
                    }

                    break;
                case NavigationMenuItem::NMI_TYPE_USER_REGISTER:
                    $navigationMenuItem->setUrl($dispatcher->url(
                        $request,
                        PKPApplication::ROUTE_PAGE,
                        null,
                        'user',
                        'register',
                        null
                    ));
                    break;
                case NavigationMenuItem::NMI_TYPE_USER_LOGIN:
                    $navigationMenuItem->setUrl($dispatcher->url(
                        $request,
                        PKPApplication::ROUTE_PAGE,
                        null,
                        'login',
                        null,
                        null
                    ));
                    break;
                case NavigationMenuItem::NMI_TYPE_CUSTOM:
                    if ($navigationMenuItem->getPath()) {
                        $path = explode('/', $navigationMenuItem->getPath());
                        $page = array_shift($path);
                        $op = array_shift($path);
                        $navigationMenuItem->setUrl($dispatcher->url(
                            $request,
                            PKPApplication::ROUTE_PAGE,
                            null,
                            $page,
                            $op,
                            $path
                        ));
                    }
                    break;
                case NavigationMenuItem::NMI_TYPE_SEARCH:
                    $navigationMenuItem->setUrl($dispatcher->url(
                        $request,
                        PKPApplication::ROUTE_PAGE,
                        null,
                        'search',
                        null,
                        null
                    ));
                    break;
                case NavigationMenuItem::NMI_TYPE_PRIVACY:
                    $navigationMenuItem->setUrl($dispatcher->url(
                        $request,
                        PKPApplication::ROUTE_PAGE,
                        null,
                        'about',
                        'privacy',
                        null
                    ));
                    break;
                case NavigationMenuItem::NMI_TYPE_REMOTE_URL:
                    $navigationMenuItem->setUrl($navigationMenuItem->getLocalizedRemoteUrl());
                    break;
            }
        }

        Hook::call('NavigationMenus::displaySettings', [$navigationMenuItem, $navigationMenu]);

        $templateMgr->assign('navigationMenuItem', $navigationMenuItem);
    }

    public function loadMenuTree(&$navigationMenu)
    {
        /** @var NavigationMenuItemDAO */
        $navigationMenuItemDao = DAORegistry::getDAO('NavigationMenuItemDAO');
        $items = $navigationMenuItemDao->getByMenuId($navigationMenu->getId())->toArray();

        /** @var NavigationMenuItemAssignmentDAO */
        $navigationMenuItemAssignmentDao = DAORegistry::getDAO('NavigationMenuItemAssignmentDAO');
        $assignments = $navigationMenuItemAssignmentDao->getByMenuId($navigationMenu->getId())
            ->toArray();

        foreach ($assignments as $assignment) {
            foreach ($items as $item) {
                if ($item->getId() === $assignment->getMenuItemId()) {
                    $assignment->setMenuItem($item);
                    break;
                }
            }
        }

        // Create an array of parent items and array of child items sorted by
        // their parent id as the array key
        $navigationMenu->menuTree = [];
        $children = [];
        foreach ($assignments as $assignment) {
            if (!$assignment->getParentId()) {
                $navigationMenu->menuTree[] = $assignment;
            } else {
                if (!isset($children[$assignment->getParentId()])) {
                    $children[$assignment->getParentId()] = [];
                }

                $children[$assignment->getParentId()][] = $assignment;
            }
        }

        // Assign child items to parent in array
        for ($i = 0; $i < count($navigationMenu->menuTree); $i++) {
            $assignmentId = $navigationMenu->menuTree[$i]->getMenuItemId();
            if (isset($children[$assignmentId])) {
                $navigationMenu->menuTree[$i]->children = $children[$assignmentId];
            }
        }
        /** @var NavigationMenuDAO */
        $navigationMenuDao = DAORegistry::getDAO('NavigationMenuDAO');
        $cache = $navigationMenuDao->getCache($navigationMenu->getId());
        $json = json_encode($navigationMenu);
        $cache->setEntireCache($json);
    }

    /**
     * Get a tree of NavigationMenuItems assigned to this menu
     *
     * @param NavigationMenu $navigationMenu
     *
     */
    public function getMenuTree(&$navigationMenu)
    {
        /** @var NavigationMenuDAO */
        $navigationMenuDao = DAORegistry::getDAO('NavigationMenuDAO');
        /** @var FileCache */
        $cache = $navigationMenuDao->getCache($navigationMenu->getId());
        if ($cache->cache) {
            $navigationMenu = json_decode($cache->cache, true);
            $navigationMenu = $this->arrayToObject('NavigationMenu', $navigationMenu);
            $this->loadMenuTreeDisplayState($navigationMenu);
            return;
        }
        $this->loadMenuTree($navigationMenu);
        $this->loadMenuTreeDisplayState($navigationMenu);
    }

    private function loadMenuTreeDisplayState(&$navigationMenu)
    {
        foreach ($navigationMenu->menuTree as $assignment) {
            $nmi = $assignment->getMenuItem();
            if ($assignment->children) {
                foreach ($assignment->children as $childAssignment) {
                    $childNmi = $childAssignment->getMenuItem();
                    $this->getDisplayStatus($childNmi, $navigationMenu);

                    if ($childNmi->getIsDisplayed()) {
                        $nmi->setIsChildVisible(true);
                    }
                }
            }
            $this->getDisplayStatus($nmi, $navigationMenu);
        }
    }

    /**
     * Helper function to transform the json_decoded cached NavigationMenu object (stdClass) to the actual NavigationMenu object
     * Some changes on the NavigationMenu objects must be reflected here
     */
    public function arrayToObject($class, $array)
    {
        if ($class == 'NavigationMenu') {
            $obj = new NavigationMenu();
        } elseif ($class == 'NavigationMenuItem') {
            $obj = new NavigationMenuItem();
        } elseif ($class == 'NavigationMenuItemAssignment') {
            $obj = new NavigationMenuItemAssignment();
        }
        foreach ($array as $k => $v) {
            if (strlen($k)) {
                if (is_array($v) && $k == 'menuTree') {
                    $treeChildren = [];
                    foreach ($v as $treeChild) {
                        array_push($treeChildren, $this->arrayToObject('NavigationMenuItemAssignment', $treeChild));
                    }
                    $obj->{$k} = $treeChildren;
                } elseif (is_array($v) && $k == 'navigationMenuItem') {
                    $obj->{$k} = $this->arrayToObject('NavigationMenuItem', $v); //RECURSION
                } elseif (is_array($v) && $k == 'children') {
                    $treeChildren = [];
                    foreach ($v as $treeChild) {
                        array_push($treeChildren, $this->arrayToObject('NavigationMenuItemAssignment', $treeChild));
                    }
                    $obj->{$k} = $treeChildren;
                } else {
                    $obj->{$k} = $v;
                }
            }
        }

        // should call transformNavMenuItemTitle because some
        // request don't have all template variables in place
        if ($class == 'NavigationMenuItem') {
            $templateMgr = TemplateManager::getManager(Application::get()->getRequest());
            $this->transformNavMenuItemTitle($templateMgr, $obj);
        }

        return $obj;
    }

    /**
     * Transform an item title if the title includes a {$variable}
     *
     * @param TemplateManager $templateMgr
     */
    public function transformNavMenuItemTitle($templateMgr, &$navigationMenuItem)
    {
        $this->setAllNMILocalizedTitles($navigationMenuItem);

        $title = $navigationMenuItem->getLocalizedTitle();
        $prefix = '{$';
        $postfix = '}';

        $prefixPos = strpos($title, $prefix);
        $postfixPos = strpos($title, $postfix);

        if ($prefixPos !== false && $postfixPos !== false && ($postfixPos - $prefixPos) > 0) {
            $titleRepl = substr($title, $prefixPos + strlen($prefix), $postfixPos - $prefixPos - strlen($prefix));

            $templateReplaceTitle = $templateMgr->getTemplateVars($titleRepl);
            if ($templateReplaceTitle) {
                $navigationMenuItem->setTitle($templateReplaceTitle, Locale::getLocale());
            }
        }
    }

    /**
     * Populate the navigationMenuItem and the children properties of the NMIAssignment object
     *
     * @param NavigationMenuItemAssignment $nmiAssignment The NMIAssignment object passed by reference
     */
    public function populateNMIAssignmentContainedObjects(&$nmiAssignment)
    {
        // Set NMI
        /** @var NavigationMenuItemDAO */
        $navigationMenuItemDao = DAORegistry::getDAO('NavigationMenuItemDAO');
        $nmiAssignment->setMenuItem($navigationMenuItemDao->getById($nmiAssignment->getMenuItemId()));

        // Set Children
        /** @var NavigationMenuItemAssignmentDAO */
        $navigationMenuItemAssignmentDao = DAORegistry::getDAO('NavigationMenuItemAssignmentDAO');
        $nmiAssignment->children = $navigationMenuItemAssignmentDao->getByMenuIdAndParentId($nmiAssignment->getMenuId(), $nmiAssignment->getId())
            ->toArray();

        // Recursive call to populate NMI and children properties of NMIAssignment's children
        foreach ($nmiAssignment->children as $assignmentChild) {
            $this->populateNMIAssignmentContainedObjects($assignmentChild);
        }
    }

    /**
     * Returns whether a NM's NMI has a child of a certain NMIType
     *
     * @param NavigationMenu $navigationMenu The NM to be searched
     * @param NavigationMenuItem $navigationMenuItem The NMI to check its children for NMIType
     * @param string $nmiType The NMIType
     * @param bool $isDisplayed optional. If true the function checks if the found NMI of type $nmiType is displayed.
     *
     * @return bool Returns true if a NMI of type $nmiType has been found as child of the given $navigationMenuItem.
     */
    private function _hasNMTreeNMIAssignmentWithChildOfNMIType($navigationMenu, $navigationMenuItem, $nmiType, $isDisplayed = true)
    {
        foreach ($navigationMenu->menuTree as $nmiAssignment) {
            $nmi = $nmiAssignment->getMenuItem();
            if (isset($nmi) && $nmi->getId() == $navigationMenuItem->getId()) {
                foreach ($nmiAssignment->children as $childNmiAssignment) {
                    $childNmi = $childNmiAssignment->getMenuItem();
                    if (isset($nmi) && $childNmi->getType() == $nmiType) {
                        if ($isDisplayed) {
                            return $childNmi->getIsDisplayed();
                        } else {
                            return true;
                        }
                    }
                }
            }
        }

        return false;
    }

    /**
     * Sets the title of a navigation menu item, depending on its title or locale-key
     *
     * @param NavigationMenuItem $nmi The NMI to set its title
     */
    public function setNMITitleLocalized($nmi)
    {
        if ($nmi) {
            if ($localizedTitle = $nmi->getLocalizedTitle()) {
                $nmi->setTitle($localizedTitle, Locale::getLocale());
            } elseif ($nmi->getTitleLocaleKey() === '{$loggedInUsername}') {
                $nmi->setTitle($nmi->getTitleLocaleKey(), Locale::getLocale());
            } else {
                $nmi->setTitle(__($nmi->getTitleLocaleKey()), Locale::getLocale());
            }
        }
    }

    /**
     * Sets the title of a navigation menu item, depending on its title or locale-key
     *
     * @param NavigationMenuItem $nmi The NMI to set its title
     */
    public function setAllNMILocalizedTitles($nmi)
    {
        if ($nmi) {
            $supportedFormLocales = Locale::getSupportedFormLocales();

            foreach ($supportedFormLocales as $supportedFormLocale => $supportedFormLocaleValue) {
                if ($localizedTitle = $nmi->getTitle($supportedFormLocale)) {
                    $nmi->setTitle($localizedTitle, $supportedFormLocale);
                } else {
                    $nmi->setTitle(__($nmi->getTitleLocaleKey(), [], $supportedFormLocale), $supportedFormLocale);
                }
            }
        }
    }

    /**
     * Callback to be registered from PKPTemplateManager for the LoadHandler hook.
     * Used by the Custom NMI to point their URL target to [context]/[path]
     *
     * @return bool true if the callback has handled the request.
     */
    public function _callbackHandleCustomNavigationMenuItems($hookName, $args)
    {
        $request = Application::get()->getRequest();

        $page = & $args[0];
        $op = & $args[1];
        $handler = & $args[3];

        // Construct a path to look for
        $path = $page;
        if ($op !== 'index') {
            $path .= "/{$op}";
        }
        if ($arguments = $request->getRequestedArgs()) {
            $path .= '/' . implode('/', $arguments);
        }

        // Look for a static page with the given path
        /** @var NavigationMenuItemDAO */
        $navigationMenuItemDao = DAORegistry::getDAO('NavigationMenuItemDAO');

        $context = $request->getContext();
        $contextId = $context ? $context->getId() : \PKP\core\PKPApplication::CONTEXT_ID_NONE;
        $customNMI = $navigationMenuItemDao->getByPath($contextId, $path);

        // Check if a custom NMI with the requested path exists
        if ($customNMI) {
            // Trick the handler into dealing with it normally
            $page = 'pages';
            $op = 'view';

            // It is -- attach the custom NMI handler.
            $handler = new NavigationMenuItemHandler($customNMI);

            return true;
        }

        return false;
    }
}
