Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[4.0] Making CategoryNode and MenuItem ImmutableNodes #23452

Merged
merged 22 commits into from
Feb 17, 2019

Conversation

Hackwar
Copy link
Member

@Hackwar Hackwar commented Jan 4, 2019

In #23364 we added a node interface for object nodes and in this PR I'm making CategoryNode and MenuItem implement those interfaces. That should then make it possible to drop \Joomla\CMS\Menu\Node and we can maybe replace some nasty stuff where we build menus or similar stuff with convoluted code with proper tree traversal instead.

I added a trait for such node systems and changed CategoryNode and MenuItem to use those and a few fixes and improvements. I then also changed the menu item discovery of routing. This should improve the parseing quite a bit, since we don't have to run through all menu items.

I also fixed a few docblocks...

Looking forward to your feedback. Next thing would be to change mod_menu to use such a tree iterator to render the menu instead of what we have right now.

Testinstructions

The idea is, that this does not change anything visibly for the user. Take your testsite, preferably with some deeply nested menu items and lots of menu items. Check that the links all work and maybe how long it takes for Joomla to render a page. Apply this patch and see that the URLs stay the same and still all work and hopefully also see a slight performance improvement for page rendering by Joomla. The performance improvement should only be noticeable for really large sites with several thousand menu items.

Optimising CategoryNode, MenuItem
Improving menu item discovery in routing
@Hackwar
Copy link
Member Author

Hackwar commented Jan 5, 2019

FYI: If we had running unittests, they would fail because of backwards incompatible changes here. They aren't major changes, but still the behavior is slightly different.

@Hackwar
Copy link
Member Author

Hackwar commented Feb 3, 2019

I changed the backend menu to use the MenuItem class and re-ordered a lot of code as well. This makes about a 1000 lines of code obsolete...

These changes had 3 goals:

  1. Make the Joomla\CMS\Menu\Node class obsolete, since it is a copy of MenuItem of this PR.
  2. Reduce the code necessary for the backend menu.
  3. Make the code easier to understand.

I succeeded with 1. and as you can see reduced the code quite a bit, but it still isn't easy to understand. sigh

The current implementation works in a way that is very strange to me... I don't even really know how to explain how it works. I felt uncomfortable working with first flat lists, then converting those into a pseudo-tree, then converting that again into a "real" tree, but being unable to access that without going through the Tree class first... The new implementation now works with nodes of type MenuItem right from the start and then modifies and iterates the whole tree afterwards. The code still is pretty complex, but I hope that I reduced the complexity by a degree. Maybe from a 10 to a 9?

I also moved code from the Joomla\CMS\Menu\MenuHelper to the MenusHelper of com_menus, because we are already using code from that class in that whole system and I couldn't see a reason for having some code in the component and other code in the framework. Since this is highly application specific code, I decided to move this entirely to the components MenusHelper and to drop the framework class. This reduces the rendering of the backend menu from 10 files down to 3.

One detail that I feel a bit uncomfortable with is removing the Joomla\CMS\Menu\Node* classes. The backend menu has special classes for each node type which contain some special handling and which I would consider a rather better implementation than what is in this PR. But I decided against those node-type-classes since it brings the backend menu closer to a copy of the frontend menu. At the same time, there is so much special logic in the code to render the menu, that a little bit more to acommodate for this wont change the overall impression of this noticeably.

The part of creating your own backend menu has to be tested again, but shouldn't be far off from what we expect.

@wilsonge I hope that raises the chance to merge this. If you want to know a different reason to make MenuItem implement the NodeInterface: With this change, you could dynamically extend the menu system during runtime. You could generate menu items from categories and insert them wherever you want by doing addChild(), etc. and it would automatically propagate through routing and menu displays without storing this in the DB. It would make the menu more flexible. ;-)


// Call preprocess for the menu items on plugins.
// Plugins should normally process the current level only unless their logic needs deep levels too.
$this->application->triggerEvent('onPreprocessMenuItems', array('com_menus.administrator.module', &$items, $this->params, $this->enabled));
$this->application->triggerEvent('onPreprocessMenuItems', array('com_menus.administrator.module', $children, $this->params, $this->enabled));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this going to cause a b/c break on existing plugins triggering on this? Just for the purposes of documenting it if it is

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes and no. It principally is the same event with the same data, but the actual menu item objects are now different to the current ones. It depends on the plugin if it needs updates, since there is no submenu attribute anymore, but the methods to traverse the tree.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK. But it will need a few lines of docs to be safe. Honestly I have no clue if this is used but always better safe than sorry

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I hope that comment explains this enough?

@Hackwar
Copy link
Member Author

Hackwar commented Feb 9, 2019

Deprecation notices are added in #23842

@chmst
Copy link
Contributor

chmst commented Feb 10, 2019

I have tested this item ✅ successfully on cf51ece

I have tested this successfully - from the user's point of view - without code inspection.
I used 5 levels of categories. Some with articles and some without.
In Backend and Frontend, the tested structure looks equal after patch and before patch and links work as expected.

The amount of categories was not sufficient to say anything about performance.


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

@wilsonge wilsonge merged commit 0ae1a54 into joomla:4.0-dev Feb 17, 2019
@wilsonge
Copy link
Contributor

Thanks for being patient with this!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants