1

This current router.php creates in Joomla 4 this URL: localhost/component/ohanah/?id=688&Itemid=101

But it should create this: localhost/kurse/688-event-name where "event-name" is the event name. The event name is grabbed by public function getEventAlias($id) and automatically updates the URL to the slug table inside the database called ohanah_event. This router.php worked completely fine in Joomla 3.10.0 but broke in Joomla 4.

If I disable the router I get a different URL.

localhost/component/ohanah/?view=event&id=688&format=html&Itemid=101

I also read https://docs.joomla.org/J3.x:Supporting_SEF_URLs_in_your_component but I cannot see what could cause the issue in my current router.

my router.php:

<?php
/**
 * @package     Ohanah
 * @copyright   Copyright (C) 2012 - 2015 Beyounic SA. All rights reserved.
 * @license     GNU GPLv3 <http://www.gnu.org/licenses/gpl.html>
 * @link        http://www.beyounic.com
 */

use Joomla\CMS\Component\Router\RouterBase;
use Joomla\CMS\Application\CMSApplication;
use Joomla\CMS\Factory;

defined('_JEXEC') or die;

/**
 * Ohanah Router
 */
class ComOhanahRouter
{
    /**
     * Private constructor to avoid direct instantiation
     */
    private function __construct()
    {
    }

    /**
     * Returns an instance of the class
     *
     * @return ComOhanahRouter
     */
    public static function getInstance()
    {
        static $instance;

        if (!$instance) {
            $instance = new ComOhanahRouter();
        }

        return $instance;
    }

    /**
     * Builds a URL from a query object
     *
     * @param array $query query object
     *
     * @return array
     */
    public function build(&$query)
    {
        $segments = [];
        $itemid = null;

        if (empty($query['Itemid'])) {
            return $segments;
        }

        $menu = CMSApplication::getInstance('site')->getMenu()->getItem($query['Itemid']);
        if (!$menu) {
            return $segments;
        }

        $menu_query = $menu->query;

        $menu_view = $menu_query['view'] ?? null;

        if ($menu_view === 'events' || $menu_view === 'calendar') {
            if (array_key_exists('id', $query)) {
                $segments[] = $this->getEventAlias($query['id']);
                unset($query['id'], $query['view'], $query['layout'], $query['tmpl']);
            }
        }

        if (isset($query['view'])) {
            if ($query['view'] === 'checkout' || $query['view'] === 'ticket' || $query['view'] === 'receipt') {
                unset($query['Itemid']);
            } else {
                unset($query['view']);
            }
        }

        unset($query['format']);

        return $segments;
    }

    /**
     * Returns the alias (id-slug) for a document
     *
     * @param string $slug document slug
     *
     * @return mixed
     */
    public function getEventAlias($id)
    {
        $db = Factory::getDbo();
        $db->setQuery(sprintf("
            SELECT CONCAT_WS('-', tbl.ohanah_event_id, tbl.slug) AS alias
            FROM `#__ohanah_events` as tbl
            WHERE tbl.ohanah_event_id = %s", $db->quote($id)));

        return $db->loadResult();
    }

    /**
     * Parse the segments into query string
     *
     * @param array $segments
     *
     * @return array
     */
    public function parse($segments)
    {
        // Circumvent Joomla's auto encoding
        foreach ($segments as &$segment) {
            $segment = urldecode($segment);
            $pos = strpos($segment, ':');
            if ($pos !== false) {
                $segment[$pos] = '-';
            }

        }

        $vars = [];
        $app = Factory::getApplication();

        $menu = $app->getMenu()->getActive();
        $view = $app->input->getCmd('view', null);
        $event = $this->_findEvent(array_slice(array_reverse($segments), 0, 2));

        if ($event) {
            $position = array_search($event, $segments);
            $view = 'event';

            unset($segments[$position]);
        }

        if ($menu !== null) {
            if ($view === 'event') {
                $vars['view'] = $view;

                if (isset($menu->query['view']) && $menu->query['view'] === 'event') {
                    $vars['slug'] = $menu->query['slug'];
                } elseif ($event) {
                    $pieces = explode('-', $event, 2);
                    $vars['slug'] = array_pop($pieces);

                } else {
                    $vars['slug'] = '';
                }

                $vars['path'] = '';
                if (isset($menu->query['path'])) {
                    $vars['path'] .= $menu->query['path'] . '/';
                }

                $vars['path'] .= implode('/', $segments);
            } else // list view
            {
                $vars['view'] = $menu->query['view'];
                $vars['slug'] = array_pop($segments);
                if (strpos('/', $vars['slug']) !== false) {
                    $pieces = explode('/', $vars['slug']);
                    $vars['slug'] = array_pop($pieces);
                }

                if (isset($menu->query['layout'])) {
                    $vars['layout'] = $menu->query['layout'];
                }
            }
        }


        return $vars;
    }

    /**
     * Checks the last two segments and tries to find an event
     *
     * @param array $segments
     * @return null|string
     */
    protected function _findEvent($segments)
    {
        $result = null;

        foreach ($segments as $segment) {
            if (preg_match('#[0-9]+-(.*?)#', $segment) && $this->_isEventAlias($segment)) {
                $result = $segment;
            }
        }
        return $result;
    }

    /**
     * Returns true if the given string is an event alias
     *
     * @param string $alias event alias
     *
     * @return bool
     */
    protected function _isEventAlias($alias)
    {
        [$id, $slug] = explode('-', $alias, 2);
        $query = 'SELECT COUNT(*) FROM #__ohanah_events'
            . ' WHERE ohanah_event_id = %d AND slug = %s';

        $db = Factory::getDbo();
        $db->setQuery(sprintf($query, $id, $db->quote($slug)));

        return (bool)$db->loadResult();
    }
}

/**
 * Hooks up Ohanah router to Joomla URL build event
 *
 * @param array $query
 *
 * @return array
 */
function OhanahBuildRoute(&$query)
{
    return ComOhanahRouter::getInstance()->build($query);
}

/**
 * Hooks up Ohanah router to Joomla URL parse event
 *
 * @param array $segments
 *
 * @return array
 */
function OhanahParseRoute($segments)
{
    return ComOhanahRouter::getInstance()->parse($segments);
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.