No Code Attached Yet
avatar Irata
Irata
28 Oct 2021

Steps to reproduce the issue

The error shows up for me using a custom front end component that is a simple menu item displaying a list of records with a simple URI to edit each record that has the &Itemid= suffixed to each URI by SiteRouter.php as the page is created.

Without the &Itemid in the link a Save or Cancel when editing the record returns to the default Menu as the default because it doesn't know the Id of the current or active menu.

Expected result

Links on the page to edit the first record under Joomla 3
/index.php?option=com_sales&task=order.editNC&id=1&Itemid=156

Actual result

Links on the page to edit the first record under Joomla 4
/index.php?option=com_sales&task=order.editNC&id=1

System information (as much as possible)

Joomla 4.0.4
PHP 7.4
Local Development Environment
Default installation plus my custom components only.

Additional comments

This may not be an issue but a feature of the Joomla 4 routing but I can't find anything that explains the alternative or why, however the bits of code that do exists suggest that it might just be an over sight.

In Joomla 4 the /library/src/Router/SiteRouter.php has a new method, buildInit, that replaces the createInit method of Joomla 3. In appearance they do the same thing, suffix the URL with the Itemid=(the value of the current/active menu item) to links on the page, however the logic has changed and it no longer handles a missing ItemId= correctly or at least in the same way as Joomla 3.

public function buildInit(&$router, &$uri)
{
	$itemid = $uri->getVar('Itemid');

	// If no Itemid and option given, merge in the current requests data
	if (!$itemid && !$uri->getVar('option'))
	{
		$uri->setQuery(array_merge($this->getVars(), $uri->getQuery(true)));
	}

	// If Itemid is given, but no option, set the option from the menu item
	if ($itemid && !$uri->getVar('option'))
	{
		if ($item = $this->menu->getItem($itemid))
		{
			$uri->setVar('option', $item->component);
		}
	}
}

In the above code if $itemid is Null or not set AND the $uri contains an valid Option param then it will never meet either of the first level IF statements and the method will complete without ever getting the $itemid.

Compared to the Joomla 3 version posted below there seems to be a block of code missing that would at least get to this statement to get the active menu id

$item = $this->menu->getItem($this->getVar('Itemid')); 

and set the $itemid

$uri->setVar('Itemid', $item->id);

In /libraries/src/Router/SiteRouter.php for Joomla 3 the createInit method where I have highlighted, <===, the lines that are missing in Joomla 4.

protected function createUri($url)
{
	// Create the URI
	$uri = parent::createUri($url);

	// Get the itemid form the URI
	$itemid = $uri->getVar('Itemid');

	if ($itemid === null)                                           <==
	{
		if ($option = $uri->getVar('option'))
		{
			$item = $this->menu->getItem($this->getVar('Itemid'));  <==

			if ($item !== null && $item->component === $option)     <==
			{
				$uri->setVar('Itemid', $item->id);                  <==
			}
		}
		else
		{
			if ($option = $this->getVar('option'))
			{
				$uri->setVar('option', $option);
			}

			if ($itemid = $this->getVar('Itemid'))
			{
				$uri->setVar('Itemid', $itemid);
			}
		}
	}
	else
	{
		if (!$uri->getVar('option'))
		{
			if ($item = $this->menu->getItem($itemid))
			{
				$uri->setVar('option', $item->component);
			}
		}
	}

	return $uri;
}

This issue on JSE is impacted by the same code, https://joomla.stackexchange.com/questions/31422/retrieve-active-menu-link-in-controller-frontend-joomla4, and one issue on Joomla Issue Tracker show similar symptoms and maybe related to this code.

avatar Irata Irata - open - 28 Oct 2021
avatar Irata Irata - change - 28 Oct 2021
Labels Removed: ?
avatar joomla-cms-bot joomla-cms-bot - change - 28 Oct 2021
Labels Added: No Code Attached Yet
avatar joomla-cms-bot joomla-cms-bot - labeled - 28 Oct 2021
avatar Irata Irata - change - 28 Oct 2021
The description was changed
avatar Irata Irata - edited - 28 Oct 2021
avatar Irata Irata - change - 28 Oct 2021
The description was changed
avatar Irata Irata - edited - 28 Oct 2021
avatar Irata Irata - change - 28 Oct 2021
The description was changed
avatar Irata Irata - edited - 28 Oct 2021
avatar Irata Irata - change - 28 Oct 2021
The description was changed
avatar Irata Irata - edited - 28 Oct 2021
avatar Fedik
Fedik - comment - 28 Oct 2021

you have to implement preprocess() in your router, where assign correct Itemid,
see discussion #35621

avatar richard67
richard67 - comment - 28 Oct 2021

@Irata Please check the previous comment, and if it solves your issue let us know and close the issue here, or we can close it for you. Thanks in advance.

avatar Irata
Irata - comment - 28 Oct 2021

Is this the closest thing to up to date information about the router in Joomla 4? I see a few other issues in the past year or so pointing people to this documentation, is it still current?

@Fedik, I don't have my own router I am using what I believe to be the default one, Joomla\CMS\Router\Route.


This comment was created with the J!Tracker Application at issues.joomla.org/tracker/joomla-cms/35919.

avatar Hackwar
Hackwar - comment - 28 Oct 2021

The current behavior is the expected behavior. There are serious issues with defaulting to the current Itemid for any given URL. It is one of the big reasons for "duplicate content" in Joomla among other things.

avatar richard67 richard67 - change - 28 Oct 2021
Status New Expected Behaviour
Closed_Date 0000-00-00 00:00:00 2021-10-28 20:24:43
Closed_By richard67
avatar richard67 richard67 - close - 28 Oct 2021
avatar richard67
richard67 - comment - 28 Oct 2021

Closing as expected behaviour. Feel free to re-open if you think this is wrong.


This comment was created with the J!Tracker Application at issues.joomla.org/tracker/joomla-cms/35919.

avatar brianteeman
brianteeman - comment - 28 Oct 2021

Please re-open. The duplicate content issue is bs. At a minimum this expected behaviour must be documented somewhere other than in one persons head.

avatar richard67 richard67 - reopen - 28 Oct 2021
avatar richard67 richard67 - change - 28 Oct 2021
Status Expected Behaviour New
Closed_Date 2021-10-28 20:24:43
Closed_By richard67
avatar richard67
richard67 - comment - 28 Oct 2021

Re-opening due to previous comment.


This comment was created with the J!Tracker Application at issues.joomla.org/tracker/joomla-cms/35919.

avatar Irata Irata - change - 28 Oct 2021
Title
SiteRouter.php is no longer suffixing a missing &Itemid= to links on pages
[4.0]SiteRouter.php is no longer suffixing a missing &Itemid= to links on pages
avatar Irata Irata - edited - 28 Oct 2021
avatar Irata
Irata - comment - 29 Oct 2021

It is not is expected behaviour to me as the backward compatibility page for J4 makes no mention to the extent of changes you have to make to an existing component to overcome the removal of this default behaviour that a lot of existing code relies on. Any documentation on the 'modern' router seems to be updated J3.x articles but still no mention that $Itemid was no longer going to be handled and there is noting other than a few comments I have seen that says MenuRules class will now handle it.

I want to move sites to Joomla 4 so I can start developing new code with Joomla 4 therefore I have a choice of either spending days or weeks reworking a lot code to make it work under both Joomla 4 and Joomla 3 just to get around this issue, sorry expected behaviour, or I put these few lines of code into SiteRouter.php so I can move sites to Joomla 4 and deal with the older code as more useful documentation becomes availabletime and budget allows.

` if (!$itemid)
{
$item = $this->menu->getItem($this->getVar('Itemid'));

        if ($item !== null && $item->component === $uri->getVar('option'))
        {
            $uri->setVar('Itemid', $item->id);
        }
    }

`

I don't mind whether you close this issue or leave it open, however I have unfortunately spent too many days already getting to this point to waste any more time on it, I know enough now to proceed to Joomla 4 and hopefully this issue will assist others that find their way here looking for an answer why $Itemid is missing in Joomla 4.


This comment was created with the J!Tracker Application at issues.joomla.org/tracker/joomla-cms/35919.

avatar Fedik
Fedik - comment - 29 Oct 2021

I don't have my own router

How do you build your URLs then?

It is not is expected behaviour to me as the backward compatibility page for J4 makes no mention to the extent of changes you have to make to an existing component to overcome the removal of this default behaviour that a lot of existing code relies on.

It is expected for J4.
You have to set Itemid in preprocess() in your router. (Or use new router rule Joomla\CMS\Component\Router\Rules\MenuRules), look my previous comment. It not a "big change".

avatar Irata
Irata - comment - 29 Oct 2021

@Fedik My apologies, I do have a router.php that extends Joomla\CMS\Component\Router\RouterBase with a build and parse method that in their comments says they only come into play when SEF is on, which in this case it is not.

I now understand where your suggested preprocess method gets placed. I will report back when I have had a chance to play with it.

Thank you.


This comment was created with the J!Tracker Application at issues.joomla.org/tracker/joomla-cms/35919.

avatar Fedik
Fedik - comment - 30 Oct 2021

their comments says they only come into play when SEF is on

In new router the preprocess() method will be called no mater if SEF On or Off.
If I right remember.

avatar Irata
Irata - comment - 3 Nov 2021

@Fedik, I was unable to get 'preprocess()' to work correctly using your sample in the other issue you mentioned without breaking some other links in the menu so I am just going to have to manage the extra lines of code I have added to buildInit until I can move to the newer router approach while running it under J4. Not ideal, but that is where I am at if I want to use Joomla 4.

I was able to find this reference to the change, #12168, back in 2016 and there it is acknowledged it will cause a B/C issue but that hasn't made it through to the more recent documentation available.

I am okay with this being closed as expected behaviour.


This comment was created with the J!Tracker Application at issues.joomla.org/tracker/joomla-cms/35919.

avatar Fedik
Fedik - comment - 3 Nov 2021

I was unable to get 'preprocess()' to work correctly using your sample in the other issue you mentioned without breaking some other links

I think for your case, to mimic old behavior it need more simple than in my example.
Kind of this:

public function preprocess(&$query)
{
  if (!isset($query['Itemid'])) 
    {
      $query['Itemid'] = Factory::getApplication()->input->getInt('Itemid');
    }
}

It will always add current Itemid if there no one exists.

It not a right way to do routing, but may help for your case.

avatar Fedik
Fedik - comment - 3 Nov 2021

closed as expected

avatar Fedik Fedik - change - 3 Nov 2021
Status New Closed
Closed_Date 0000-00-00 00:00:00 2021-11-03 10:21:38
Closed_By Fedik
avatar Fedik Fedik - close - 3 Nov 2021

Add a Comment

Login with GitHub to post a comment