No Code Attached Yet
avatar mavrosxristoforos
mavrosxristoforos
6 Feb 2024

Steps to reproduce the issue

Edit any system plugin and add this:

public function afterRoute() { // or afterRender, anything after routing the main component.
    $router = \Joomla\CMS\Factory::getContainer()->get(SiteRouter::class);
    $u = \Joomla\CMS\Uri\Uri::getInstance(Uri::base().'component/content/article/2-demo-article');
    // replace the above with the ID and alias of one of your articles
    $variables = $router->parse($u, false);
    var_dump($variables);
}

Expected result

$variables populated with option, view, id.

Actual result

Throws a 404 error.

System information (as much as possible)

Tested in both J4 and 5.

Additional comments

So, the Joomla\CMS\Router\Router is supposedly able to parse any Uri with the option to $setVars = false.
As far as I understand, this is supposed to mean that you can parse any Uri and get its variables, regardless of the active menu item.
Correct me if I'm wrong.

What actually happens is that while most of the process -I read through a lot of the code- is menu-independent, the default StandardRules, at line 72 and the default NoMenuRules, at line 71 use the active menu item as a guide on how to parse the passed Uri object.

If you replace these lines with $active = null, the expected variables return correctly.
I'm relatively unfamiliar with the rest of the routing system, so I'm probably missing a lot.
Is this the expected behavior or is this a bug?

avatar mavrosxristoforos mavrosxristoforos - open - 6 Feb 2024
avatar joomla-cms-bot joomla-cms-bot - change - 6 Feb 2024
Labels Added: No Code Attached Yet
avatar joomla-cms-bot joomla-cms-bot - labeled - 6 Feb 2024
avatar mavrosxristoforos mavrosxristoforos - change - 6 Feb 2024
Title
Is the SiteRouter supposed to work like that?
SiteRouter throwing 404 when parsing instead of returning variables
avatar mavrosxristoforos mavrosxristoforos - edited - 6 Feb 2024
avatar mavrosxristoforos mavrosxristoforos - change - 6 Feb 2024
Title
SiteRouter throwing 404 when parsing instead of returning variables
SiteRouter throws 404 when parsing instead of returning variables
avatar mavrosxristoforos mavrosxristoforos - edited - 6 Feb 2024
avatar mavrosxristoforos mavrosxristoforos - change - 6 Feb 2024
Title
SiteRouter throws 404 when parsing instead of returning variables
SiteRouter throws 404 when parsing other Uris instead of returning variables
avatar mavrosxristoforos mavrosxristoforos - edited - 6 Feb 2024
avatar Hackwar Hackwar - change - 22 Mar 2024
Status New Closed
Closed_Date 0000-00-00 00:00:00 2024-03-22 11:57:08
Closed_By Hackwar
avatar Hackwar Hackwar - close - 22 Mar 2024
avatar Hackwar
Hackwar - comment - 22 Mar 2024

I created a PR to fix this with #43118. Thus I'm closing this issue.

avatar mavrosxristoforos
mavrosxristoforos - comment - 22 Mar 2024

@Hackwar Thank you for your effort. However, I think that returning an empty array doesn't fix the expected functionality. Since the StandardRules and NoMenuRules rely on the active menu item, there's always something left in the $uri->getPath() if you are trying to parse another URL that is not the active menu item. Did you find something different in your tests?

avatar Hackwar
Hackwar - comment - 22 Mar 2024

The thing is that the router currently sets the active menu item to the one it parsed in the current run. So when parsing the URL, the active menu item actually is changed, which of course is wrong. But the code now would parse this "correctly". I'm still working on getting the rest cleaned up.

avatar mavrosxristoforos
mavrosxristoforos - comment - 22 Mar 2024

I'd be happy to help if you want me to.

avatar Hackwar
Hackwar - comment - 22 Mar 2024

Be my guest. I can use all the help for routing I can get. Ideally could you contact me on the Joomla Mattermost on https://joom.la/chat ? Then we could coordinate that. Just send me a DM

avatar Hackwar Hackwar - change - 3 Apr 2024
Status Closed New
Closed_Date 2024-03-22 11:57:08
Closed_By Hackwar
avatar Hackwar Hackwar - reopen - 3 Apr 2024
avatar Hackwar
Hackwar - comment - 3 Apr 2024

We discussed the PR in the maintainer meeting and decided that my approach wasn't correct. The PR also didn't really solve your issue, I think. Seems like I misunderstood you. The main problem is, that the parse method has side effects from setting the active menu item. My idea would be to introduce a new interface for component routers and when those component routers implement that new interface, the parse() method would have an additional parameter with the current parsed query parameters as well and not just the segments. That way we wouldn't have to read the active menu item.

avatar mavrosxristoforos
mavrosxristoforos - comment - 8 Apr 2024

As much as I would like to follow your thinking, I'm not that familiar with the routing process. In my initial comment, I mentioned the points of the default rules that the active menu item is being used. Removing them seems to work for me, but of course I cannot imagine how this would affect the millions of installations of Joomla.

avatar Hackwar
Hackwar - comment - 8 Apr 2024

The problem is, that the component router when parsing does not get the currently discovered menu item ID as input, but just can read that from the active menu item in the global application object. That means we have to change that global state, which affects other things and is VERY bad. So we somehow have to get that information directly into the component router. I'm still looking into how we could do that.

avatar mavrosxristoforos
mavrosxristoforos - comment - 8 Apr 2024

I understand. This may be a dumb suggestion, but you can judge it: What if you just use the $setVars parameter of the Router to determine if you should use the menu item? Or even add a different parameter? Then, anyone that tries to use the Router::parse would come across this parameter and know what to do with his own code.

avatar Hackwar
Hackwar - comment - 8 Apr 2024

We don't have the $setVars available at the point where we would have to decide this. However we will probably change the component router to something like this:

public function parse(&$segments, &$vars)

where $vars contains the parsed queries so far, among others the Itemid. I was unsure if this works with our interface, etc. right now, but it does and we hopefully can do this in 5.2 or 5.3.

Add a Comment

Login with GitHub to post a comment