1

For a particular reason, I need to keep in the SEF URL only the alias of the item to have a URL like this www.mywebsite.com/**myItemAlias** but of course without creating a direct menu to the item because I need it to be automatic.

My router code :

// No direct access to this file
defined('_JEXEC') or die('Restricted access');

/**
 * Routing class from com_wm
 *
 * @since  3.3
 */
class WmRouter extends JComponentRouterBase
{   
    /**
     * Build the route for the com_wm component
     *
     * @param   array  &$query  An array of URL arguments
     *
     * @return  array  The URL arguments to use to assemble the subsequent URL.
     *
     * @since   3.3
     */
    public function build(&$query)
    {
        $segments = array();

        // Get a menu item based on Itemid or currently active
        $params = JComponentHelper::getParams('com_wm');
        
        if (empty($query['Itemid']))
        {
            $menuItem = $this->menu->getActive();
        }
        else
        {
            $menuItem = $this->menu->getItem($query['Itemid']);
        }

        $mView = (empty($menuItem->query['view'])) ? null : $menuItem->query['view'];
        $mId = (empty($menuItem->query['id'])) ? null : $menuItem->query['id'];

        if (isset($query['view']))
        {
            $view = $query['view'];

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

            unset($query['view']);
        }
        
        // Are we dealing with a item that is attached to a menu item?
        if (isset($view) && ($mView == $view) and (isset($query['id'])) and ($mId == (int) $query['id']))
        {
            unset($query['view']);
            unset($query['catid']);
            unset($query['id']);
            return $segments;
        }

        if (isset($view) && isset($query['id']) && ($view === 'webcasts' || $view === 'webcast'))
        {
            if ($mId != (int) $query['id'] || $mView != $view)
            {
                if (($view === 'webcasts' || $view === 'webcast'))
                {
                    $segments[] = $view;
                    $id = explode(':', $query['id']);
                    if (count($id) == 2)
                    {
                        $segments[] = $id[1];
                    }
                    else
                    {
                        $segments[] = $id[0];
                    }
                }
            }
            unset($query['id']);
        }
        
        $total = count($segments);

        for ($i = 0; $i < $total; $i++)
        {
            $segments[$i] = str_replace(':', '-', $segments[$i]);
        }

        return $segments; 
        
    }

    /**
     * Parse the segments of a URL.
     *
     * @param   array  &$segments  The segments of the URL to parse.
     *
     * @return  array  The URL attributes to be used by the application.
     *
     * @since   3.3
     */
    public function parse(&$segments)
    {       
        $count = count($segments);
        $vars = array();
        
        //Handle View and Identifier
        switch($segments[0])
        {
            case 'webcasts':
                $vars['view'] = 'webcasts';
                if (is_numeric($segments[$count-1]))
                {
                    $vars['id'] = (int) $segments[$count-1];
                }
                elseif ($segments[$count-1])
                {
                    $id = $this->getVar('webcast', $segments[$count-1], 'alias', 'id');
                    if($id)
                    {
                        $vars['id'] = $id;
                    }
                }
                break;
            case 'webcast':
                $vars['view'] = 'webcast';
                if (is_numeric($segments[$count-1]))
                {
                    $vars['id'] = (int) $segments[$count-1];
                }
                elseif ($segments[$count-1])
                {
                    $id = $this->getVar('webcast', $segments[$count-1], 'alias', 'id');
                    if($id)
                    {
                        $vars['id'] = $id;
                    }
                }
                break;
        }

        return $vars;
    } 

    protected function getVar($table, $where = null, $whereString = null, $what = null, $category = false, $operator = '=', $main = 'wm')
    {
        if(!$where || !$what || !$whereString)
        {
            return false;
        }
        // Get a db connection.
        $db = JFactory::getDbo();
        // Create a new query object.
        $query = $db->getQuery(true);

        $query->select($db->quoteName(array($what)));
        if ('categories' == $table || 'category' == $table || $category)
        {
            $getTable = '#__categories';
            $query->from($db->quoteName($getTable));
            // we need this to target the components categories (TODO will keep an eye on this)
            $query->where($db->quoteName('extension') . ' LIKE '. $db->quote((string)'com_' . $main . '%'));
        }
        else
        {
            // we must check if the table exist (TODO not ideal)
            $tables = $db->getTableList();
            $app = JFactory::getApplication();
            $prefix = $app->get('dbprefix');
            $check = $prefix.$main.'_'.$table;
            if (in_array($check, $tables))
            {
                $getTable = '#__'.$main.'_'.$table;
                $query->from($db->quoteName($getTable));
            }
            else
            {
                return false;
            }
        }
        if (is_numeric($where))
        {
            return false;
        }
        elseif ($this->checkString($where))
        {
            // we must first check if this table has the column
            $columns = $db->getTableColumns($getTable);
            if (isset($columns[$whereString]))
            {
                $query->where($db->quoteName($whereString) . ' '.$operator.' '. $db->quote((string)$where));
            }
            else
            {
                return false;
            }
        }
        else
        {
            return false;
        }
        $db->setQuery($query);
        $db->execute();
        if ($db->getNumRows())
        {
            return $db->loadResult();
        }
        return false;
    }
    
    protected function checkString($string)
    {
        if (isset($string) && is_string($string) && strlen($string) > 0)
        {
            return true;
        }
        return false;
    }
}

function WmBuildRoute(&$query)
{
    $router = new WmRouter;
    
    return $router->build($query);
}

function WmParseRoute($segments)
{
    $router = new WmRouter;

    return $router->parse($segments);
}

I don't really know how to go about it, I think we need to change here :

//Handle View and Identifier
        switch($segments[0])
        {
            case 'webcasts':
                $vars['view'] = 'webcasts';
                if (is_numeric($segments[$count-1]))
                {
                    $vars['id'] = (int) $segments[$count-1];
                }
                elseif ($segments[$count-1])
                {
                    $id = $this->getVar('webcast', $segments[$count-1], 'alias', 'id');
                    if($id)
                    {
                        $vars['id'] = $id;
                    }
                }
                break;
            case 'webcast':
                $vars['view'] = 'webcast';
                if (is_numeric($segments[$count-1]))
                {
                    $vars['id'] = (int) $segments[$count-1];
                }
                elseif ($segments[$count-1])
                {
                    $id = $this->getVar('webcast', $segments[$count-1], 'alias', 'id');
                    if($id)
                    {
                        $vars['id'] = $id;
                    }
                }
                break;
        }

        return $vars;
    }
4
  • You can only do this if the component is the home; for doing it on a website, regardless of the active menu item, you need a system plugin Nov 29, 2020 at 0:10
  • Thanks, by any chance, you wouldn't have an example of a plugin that would help and guide me ?
    – Laurent
    Nov 29, 2020 at 12:54
  • You want to use this for articles (as items) or any other type of items, products...? Do you want to use this system wise or specifically on a component?
    – Zollie
    Nov 29, 2020 at 14:47
  • Hi, yes this is for a specific component and only for view items www.website/aComponentItem
    – Laurent
    Nov 30, 2020 at 16:13

1 Answer 1

1

As I suggested in my comment, building a plugin for this may be an alternative solution worth pursuing.

In a system plugin, simply add code similar to the example below to intercept any calls. Rest assured the code below was not tested on animals.

  1. intercept onAfterRoute()
  2. ensure your code should really run there, as an example:
    • exclude administrator
    • exclude post
    • exclude task= urls
  3. parse the input, determine if you code is now appropriate, if so
    • output and die() or
    • redirect

This is just an example:

public function onAfterRoute() {
    // make sure you only run this plugin where it makes sense:
    if (JPATH_BASE == JPATH_ADMINISTRATOR) return;
    $app = JFactory::getApplication();
    $input = $app->input;
    // you may want to exclude certain pages, components, views ... 
    // then simply query the input object or access some $_SERVER variable

    if (empty($input->get('task'))) {
        // when you are satisfied this is not going to adversely affect any functionality, 
        // either output something and die(), 
        echo 'You are <a href="https://localhost">here</a>';
        die();
        // or redirect:
        $app->redirect('https://example.com');
    }
}

If you want to see it in action, this code was abridged from my own plugin: https://www.fasterjoomla.com/download/stripe/stripe-button-downloads

1
  • OK thanks for your feedback, i will study all this, i will keep you posted.
    – Laurent
    Nov 30, 2020 at 16:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.