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

Refactor the page cache plugin #36042

Merged
merged 26 commits into from May 13, 2022
Merged

Refactor the page cache plugin #36042

merged 26 commits into from May 13, 2022

Conversation

nikosdion
Copy link
Contributor

@nikosdion nikosdion commented Nov 14, 2021

Pull Request to replace #35986

Ping @HLeithner @anibalsanchez @laoneo

Summary of Changes

Refactored the system/cache plugin into the new Joomla 4 style.

Discussion

Please test. I did not have the time to do any decent testing before going to bed; I need to wake up early tomorrow to get the kid to school. Sorry.

I am using the SubscriberInterface to register the three plugin events. The two events which add the page to the cache are rigged to always run last, otherwise the plugin wouldn't work right.

Each event checks whether the app is in a state that supports serving cached pages or storing pages into the cache:

  • Must be the Site application
  • Must be a GET request
  • Must be a guest user
  • No application messages are to be displayed

The first two checks are cached on first use for a faster false return since these conditions don't change throughout the request. The latter two checks are performed each time the first two checks pass because a user may be logged in and application messages may be generated throughout the request lifetime.

I refactored the page exclusion checks to use a bit more modern PHP code.

The cache controller is not created until it's needed. This saves some initialization time when visiting pages which shouldn't be cached or served from the cache as this means the cache controller would never get to be initialized.

The external (possible SEF) URL to the page is not retrieved until it's needed instead of in the constructor to save a few microseconds there too.

Copy link
Member

@HLeithner HLeithner left a comment

Choose a reason for hiding this comment

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

Thanks for this PR, I just did a quick look at the code and found some questions^^.

If we merge this we also should find a way that 3rd party plugins can also be installed without the .php but that's another story.

I will test it later this week.

plugins/system/cache/src/Extension/Cache.php Outdated Show resolved Hide resolved
plugins/system/cache/src/Extension/Cache.php Outdated Show resolved Hide resolved
@nikosdion
Copy link
Contributor Author

@HLeithner I forgot to mention this. Over the course of last week @laoneo found a way to make the plugins installable without any change in core code! He moved the plugin attribute from <file> to <folder> and Joomla 4.0 handled it beautifully. We confirmed his change on our own company's extensions. That's what I did in the XML manifest.

@HLeithner
Copy link
Member

@HLeithner I forgot to mention this. Over the course of last week @laoneo found a way to make the plugins installable without any change in core code! He moved the plugin attribute from <file> to <folder> and Joomla 4.0 handled it beautifully. We confirmed his change on our own company's extensions. That's what I did in the XML manifest.

perfect one problem less ;-)

This solves the issue when multiple plugins are being
executed on these 2 events. If a plugin really needs
to be executed after the page cache plugin it can still
use \Joomla\Event\Priority::MIN for its own event handler.
@laoneo
Copy link
Member

laoneo commented Nov 15, 2021

moved the plugin attribute from <file> to <folder> and Joomla 4.0 handled it beautifully. We confirmed his change on our own company's extensions. That's what I did in the XML manifest.

Actually you can do this already since 3.4 f90ff60#diff-f1347eb6172ab8188fa384c60a35be15af08dc341072aad5e842e912679234de

@laoneo
Copy link
Member

laoneo commented Jan 3, 2022

@HLeithner any comments for triggerEvent usage here? Otherwise I give it a test and get it merged. Afterwards we can discus if we want to migrate more plugins as suggested by @nikosdion.

@nikosdion
Copy link
Contributor Author

@laoneo @HLeithner IMHO the triggerEvent helper method shouldn't disappear forever. I have written a number of plugins which do not use it and my takeaway from this is that the alternative is clunky.

What I'd like to do is create a new trait where event creation and parsing the event results are separate methods. Think of calling something like $resultsArray = $this->getEventResults($this->createEvent('onFoobar', $argumentsArray, CustomEventClass::class)); where the arguments array could be associative (for named arguments) and the CustomEventClass::class could be omitted to use the generic \Joomla\Event\Event class.

Otherwise every time we call an event we need to use the same boilerplate code:

$result = $this->getDispatcher()->dispatch($eventName, $new Event($eventName, $argumentsArray));
$actualResult = !isset($result['result']) || \is_null($result['result']) ? [] : $result['result'];

I would argue that the boilerplate code looks clunky and inscrutable to newcomers. We don't want to dissuade new developers so a couple method calls may be better than lab clean code. What do you think?

@laoneo
Copy link
Member

laoneo commented Jan 3, 2022

Otherwise every time we call an event we need to use the same boilerplate code:

$result = $this->getDispatcher()->dispatch($eventName, $new Event($eventName, $argumentsArray));
$actualResult = !isset($result['result']) || \is_null($result['result']) ? [] : $result['result'];

This is true for J3 events for BC reasons. But for new ones you can use the argument from the event as result as we did in #35396.

In this pr here you can just replace $this->app->triggerEvent() with $this->app->getDispatcher()->dispatch() as there are no arguments and results to work with.

@HLeithner
Copy link
Member

Since the events are not new I wouldn't require a proper event object. But we should get rid of all events without it own class as already discussed.

It would be a great time/pr to do this as part of the refactoring.

As allon already said for new event we can guarantee that $result['result'] exists (and of course should).

If you don't like to do it now or in a future pr, I'm fine with it but as it's also an example PR it would be great if can set a milestone how to do it for events so a refer to this single pr is easier then having a couple of PRs to refer to.

@nikosdion
Copy link
Contributor Author

@HLeithner Just to be clear: you'd like me to create Event classes for all the events referenced in this plugin and use them without going through triggerEvent. Say yes and I'll start working on it tonight.

@HLeithner
Copy link
Member

@nikosdion yes when I'm not wrong we discussed this in another Issue that we want to move all legacy events to the "new" event system. And iirc this is possible in a fully b/c way right?

@nikosdion
Copy link
Contributor Author

I thought it was a 5.0 goal 😛 You are right that it can be done b/c as long as the event handlers parse the event arguments positionally instead of by name i.e. [$arg1, $arg2, ...., $argN] = $event->getArguments() AND use the generic \Joomla\Event\Event class for their parameter type hint (or use legacy Joomla 3 event handlers). To make things easier, the docblock should also or–type the specific Event subclass we will be expecting in the future.

Throughout the 4.x release cycle this is how event handlers should be written. Moreover, throughout the 4.x release we need to VERY CLEARLY document these specific event classes, which version they appeared and instruct developers to use them.

When we start working on 5.0 we can type hint with the correct event subclass and use its named arguments.

PS: About the “clearly document” we can also create a trait which generates the correct event class based on the event name. For example, if Joomla has a core event onFoobarScream which should be conveyed through an event object of the class \Joomla\Event\Foobar\Scream our Trait's makeEvent method would return a new \Joomla\Event\Foobar\Scream object with the correct arguments. This would be @deprecated 6.0 and would act as the b/c layer for the events system come Joomla 5.0.

Should I give it a stab? Now that I've worked with events on real world stuff, not just the lab environment I was using back in 2015, I have a much better ‘feel’ for how to do things in a way that doesn't screw the core over in the long term and doesn't screw third party developers over in the short to medium term.

@HLeithner
Copy link
Member

I would like to remove the old event system in j5.0 already and to have all Events have there correct classes already in 4.x ready and used. Maybe the validation have to be more relaxed with deprecation warnings if wrong values are provided.

About the trait I can't follow you for what it's needed maybe you can outline it a bit.

The plan to start on j5 is with release of 4.1, at this point we will branch out 4.2 and 5.0, we also have a project to migrate to PSR-12 withing 4.1 which is maybe too late... so it's possible that we do this in 4.1.x or 4.2. to reduce the impact on upmerge to 5.0 but I hadn't the time since the j3.10 phpunit and 8.0 comes into my way...

@nikosdion
Copy link
Contributor Author

I was busy doing releases today. Tomorrow I'll write a POC as a console plugin so you can see what the Trait would look like and how we can tackle b/c. It's about 80% there in my head, I need to put it into code and get it to the next 20% (to make sure I don't mess up b/c with J3 plugins running in Joomla 4). Then we can get back on the discussion about this PR and how much we want to do now.

But as a general idea, yeah, I'd agree that if we convert all of the plugin events at least two minor releases before 5.0 we can definitely remove legacy event handling from 5.0.

Why two minor releases? Because this would allow for smooth updates based on my experience with the 3.x to 4.0 migration 😉 In August 2021 I had to simultaneously support 3.9, 3.10 and 4.0. This allowed clients using my software on Joomla 3.9 to follow a dead simple upgrade procedure: update extensions, backup, upgrade to Joomla 3.10, backup, upgrade to 4.0, done. My limiting factor was what the penultimate version of 3.x (i.e. 3.9) supported. In those versions I couldn't use any code that only appears in 3.10 and 4.0. So, if we're touching something as fundamental as events handling we should most definitely do it with this kind conservative upgrade process in mind.

Regarding PSR-12 I am NOT a big fan on two accounts:

  1. Namespace bundling in use statements. Sure it makes sense if you use Vim to write PHP. Any half–decent IDE handles imports automatically... as long as you don't do bundling. Enforcing bundling makes for busywork AND simultaneously makes it harder to find all uses of classes when they are deprecated, moved to a different namespace etc.
  2. Open braces at the end of the line. Yeah, it makes for more compact code and date back to K&R when 80x25 terminals were expensive. We now code in 27" monitors (or larger), typically in vertical orientation. Meanwhile, having braces like that makes the code harder to read and leads to stupid bugs. Why?!
  3. 80 characters soft limit for line length. Again, it's no longer 1975, we are not limited to 80x25 terminals. 120 characters is more than reasonable, even on a 13" laptop with sidebars open in any decent IDE (phpStorm, Netbeans, Eclipse, ...).

I think Joomla should have its own code style, like it does now, because the objective of code is to a. perform a certain function; b. make it easily readable; c. minimise busywork and d. minimise the possibility of stupid bugs. PSR-12 fails miserably in the latter three. At some point CS people need to understand the historical context of K&R before trying to apply it indiscriminately on all modern code.

@HLeithner
Copy link
Member

I was busy doing releases today. Tomorrow I'll write a POC as a console plugin so you can see what the Trait would look like and how we can tackle b/c. It's about 80% there in my head, I need to put it into code and get it to the next 20% (to make sure I don't mess up b/c with J3 plugins running in Joomla 4). Then we can get back on the discussion about this PR and how much we want to do now.

Sounds great thanks

Why two minor releases? Because this would allow for smooth updates based on my experience with the 3.x to 4.0 migration 😉 In August 2021 I had to simultaneously support 3.9, 3.10 and 4.0. This allowed clients using my software on Joomla 3.9 to follow a dead simple upgrade procedure: update extensions, backup, upgrade to Joomla 3.10, backup, upgrade to 4.0, done. My limiting factor was what the penultimate version of 3.x (i.e. 3.9) supported. In those versions I couldn't use any code that only appears in 3.10 and 4.0. So, if we're touching something as fundamental as events handling we should most definitely do it with this kind conservative upgrade process in mind.

I know the pain...

Regarding PSR-12 I am NOT a big fan on two accounts:

  1. Namespace bundling in use statements. Sure it makes sense if you use Vim to write PHP. Any half–decent IDE handles imports automatically... as long as you don't do bundling. Enforcing bundling makes for busywork AND simultaneously makes it harder to find all uses of classes when they are deprecated, moved to a different namespace etc.
  2. Open braces at the end of the line. Yeah, it makes for more compact code and date back to K&R when 80x25 terminals were expensive. We now code in 27" monitors (or larger), typically in vertical orientation. Meanwhile, having braces like that makes the code harder to read and leads to stupid bugs. Why?!
  3. 80 characters soft limit for line length. Again, it's no longer 1975, we are not limited to 80x25 terminals. 120 characters is more than reasonable, even on a 13" laptop with sidebars open in any decent IDE (phpStorm, Netbeans, Eclipse, ...).

I think Joomla should have its own code style, like it does now, because the objective of code is to a. perform a certain function; b. make it easily readable; c. minimise busywork and d. minimise the possibility of stupid bugs. PSR-12 fails miserably in the latter three. At some point CS people need to understand the historical context of K&R before trying to apply it indiscriminately on all modern code.

This topic is heavily opinion driven but to be honest we don't have the resources to maintain our code style and it really doesn't make sense to do every thing different then the rest of the php eco system. We can discuss this to at a later time in another topic. Just to your mentioned things.

  1. It's not a must to compound namespaces and I don't like either (namespaces at all haha)
  2. To be honest earlier in my life I was unable to deal with other code styles as my own (and I hate open braces on it own line ;-) but I learned to life with other codestyles and in the meantime I'm happy if the same codestyle is use by the complete application and not 10 different (or none) codestyle. But yes that's opinionated and thanks good with have braces and don't need to care about the right indention.
  3. The good thing is it's only a softlimit and I'm pretty sure we keep our 150 character limited (also because nobody want's to rewrite the codebase and work on a c64)

Anyway that topic can be discussed later and if we need exceptions or stick to psr-12 completely.

@chmst chmst changed the base branch from 4.0-dev to 4.1-dev January 31, 2022 17:29
@chmst
Copy link
Contributor

chmst commented Jan 31, 2022

@nikosdion could you please fix conflicts here?

Nicholas K. Dionysopoulos added 4 commits January 31, 2022 23:44
This solves the issue when multiple plugins are being
executed on these 2 events. If a plugin really needs
to be executed after the page cache plugin it can still
use \Joomla\Event\Priority::MIN for its own event handler.
Copy link
Contributor

@roland-d roland-d left a comment

Choose a reason for hiding this comment

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

@nikosdion Well done, looks good to me.

@laoneo
Copy link
Member

laoneo commented May 4, 2022

@nikosdion can you fix the conflicts here? Thanks.

Nicholas K. Dionysopoulos added 3 commits May 4, 2022 16:10
@nikosdion
Copy link
Contributor Author

@laoneo There you go.

I also fixed the docblock and inject the frontend router object; these should be the last two pending items.

@laoneo
Copy link
Member

laoneo commented May 9, 2022

The intendation is still not correct as the other docblocks do look like:
image
while on yours:
image

@nikosdion
Copy link
Contributor Author

The funny thing is that the weird indentation comes from me copying that weird docblock from the original file. Whenever I have time (this week is really difficult) I will reformat the docblocks. Unless you want to do a PR to my branch if you have the time?

plugins/system/cache/services/provider.php Outdated Show resolved Hide resolved
plugins/system/cache/services/provider.php Outdated Show resolved Hide resolved
plugins/system/cache/services/provider.php Outdated Show resolved Hide resolved
plugins/system/cache/services/provider.php Outdated Show resolved Hide resolved
@laoneo
Copy link
Member

laoneo commented May 9, 2022

Guess now it is correct.

@nikosdion
Copy link
Contributor Author

Thank you

@laoneo laoneo merged commit 2c16e7f into joomla:4.2-dev May 13, 2022
@laoneo
Copy link
Member

laoneo commented May 13, 2022

Thanks for your patience! Now we can start to convert the rest of the plugins.

@laoneo laoneo added this to the Joomla 4.2.0 milestone May 13, 2022
@nikosdion
Copy link
Contributor Author

Thank you for merging!

roland-d added a commit that referenced this pull request May 21, 2022
* cs

* cs

Co-authored-by: Quy <quy@fluxbb.org>
Co-authored-by: Roland Dalmulder <contact@rolandd.com>
Co-authored-by: Allon Moritz <allon.moritz@digital-peak.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants