[5.3] Error handling: Adding new ExceptionTrait #44098
Draft
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Summary of Changes
Since forever we have the legacy error handling with
getError()
andsetError()
, implemented with theLegacyErrorHandlingTrait
and since forever this has actually been wrong, since the right solution would be exceptions. In an easy world we would simply switch all code over from the legacy method to using exceptions in the next major version, but since that breaks basically every website out there, we need a transition period here. That is the reason for this horribly complex solution.ExceptionTrait
To make an easy transition, this PR introduces a new trait, which allows to set a flag if exceptions should be used or not. This trait can be used in all classes which also use the
LegacyErrorHandlingTrait
. The plan is to add this to 5.3 and then to remove all of this from 7.0 again.Changed error handling
This transition method requires a lot more code right now. Old error handling often enough looked like this:
The new code would look similar to this:
We could of course add some code to the
ExceptionTrait
to simply replace thesetError()
, which automatically either sets the error or throws an exception. However that means that we are still in the same situation as before, that we have to refactor all error handling to use exceptions the moment we want to remove the trait again, with the difference that now we have one more trait to remove than before. d'oh.So instead we use this more complex code and when we are finally at the point where we want to remove all the legacy error handling, we only have to look for all occurences of calls to the
ExceptionTrait
and delete the code around the exception. The above code would then look like this:Another example would be this example of the refactored code from
AdminModel::save()
:This would shrink to
Using the new exception handling
The new error handling would have to be enabled by the code calling the model/table. In most cases this would be the view. The code right now looks for example like this:
and would have to be refactored like this in the future:
Inheritance of the exception setting
Since we have the legacy error handling not only in the models, but also in the tables, the question is how to migrate both and how to set that correctly. The solution is to have the object created inside another object to inherit the setting from the parent. In reality in most cases this would be the table object in the model. For that, the
getTable()
method checks if the table has thesetUseException()
method available and then hands in the setting from its own class. The way the code in this PR is written, this even makes it possible to only convert the model and defer the conversion of the table to later. If you look at the models in this PR, you can see that the model keeps the legacy error handling of the table and converts it to exceptions. At the same time, when the table also supports the exception method, the exceptions from the table are simply passed through the model to the calling code. This is in line with how it is now, except that right now we are manually handing the error from the table to the model to...Third party code
Third party extensions can include the trait and then call the
$this->setUseException(true);
in their constructor in order to force the exception behavior for the base core classes. In the rest of their code, they can directly use exception handling and thus be done with this basically with one refactoring.Future plans on how to remove the trait
As explained, we want to remove the whole legacy error handling at some point, which would also include this ExceptionTrait. The proposal would be to allow third party developers to migrate to exception error handling between 5.3 and 7.0 with the help of the ExceptionTrait. At 7.0 we would be removing the legacy error handling, but keep the ExceptionTrait. The ExceptionTrait would be changed to only be a placeholder which doesn't do anything. That means that in terms of error handling an extension coded properly for 6.0 will also work in 7.0 and only in 8.0 you would have to have the call to
$model->setUseException()
removed.This is only a proposal to make it easier, but we could also just remove this right away with 7.0...
Testing Instructions
Actual result BEFORE applying this Pull Request
Expected result AFTER applying this Pull Request
Link to documentations
Please select:
Documentation link for docs.joomla.org:
No documentation changes for docs.joomla.org needed
Pull Request link for manual.joomla.org:
No documentation changes for manual.joomla.org needed