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
Improved structure for error message generation in configuration pages #29494
base: develop
Are you sure you want to change the base?
Improved structure for error message generation in configuration pages #29494
Conversation
JevgenijVisockij
commented
Aug 31, 2022
•
edited
edited
Questions | Answers |
---|---|
Branch? | develop |
Description? | Refactors error generation for configuration pages. With changes error system is more streamlined allowing for pages with same error reuse the code rather then duplicating it, as well as moving code from controllers to separate factories. Also added label provider which takes label from the form, rather then having to duplicate label somewhere else. |
Type? | refacto |
Category? | BO |
BC breaks? | no |
Deprecations? | no |
Fixed ticket? | |
Related PRs | #20243 same was done in invoice PR, but separating this, so it hopefully get's faster and is part of 8.0 |
How to test? | Test that administration page throws errors correctly, when entering wrong info. |
use PrestaShop\PrestaShop\Core\Form\ErrorMessage\ConfigurationErrorInterface; | ||
|
||
/** Interface for configuration error factories which are responsible for returning error messages for configuration errors */ | ||
interface ConfigurationErrorFactoryInterface |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
seems more like a message provider.
"ConfigurationErrorMessageProvider".
then it will be less confusing considering we also have src/PrestaShopBundle/Form/ErrorMessage/Factory/ConfigurationErrorFactory.php
(because now its named the same, but is different service)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I guess the name make sense, thanks!
foreach ($view->children as $child) { | ||
if (isset($child->vars['name']) && $fieldName === $child->vars['name']) { | ||
if (!isset($child->vars['label'])) { | ||
throw new FieldLabelNotFoundException( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we really need to throw error if label isn't there?
I think It is legit that some fields doesn't have labels, so what happens if such field is violated? then everything will probably break, no?
Maybe we should fallback to field name when label is not set?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, I guess you are right, I will just return fieldName, probably better then breaking everything, since then only display will be a worse in worst case.
The base branch was changed.
7fe26fa
to
24b036c
Compare
Delayed until 9.0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As we discussed we'll try and minimize the breaking changes here so:
- we don't remove the initial error class, nor the collection and its associated exception, but we deprecate them
- create new Error classes (with your interface) along with a new collection and associated exception
In the end, the only BC is that the validation method triggers a new kind of exception
@@ -35,10 +35,6 @@ | |||
*/ | |||
final class FormDataProvider implements FormDataProviderInterface | |||
{ | |||
public const ERROR_NOT_NUMERIC_OR_LOWER_THAN_ZERO = 1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
are these constants already part of a release ? if yes that is a BC Break
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right, it's BC break will add them back and depricate
@@ -31,6 +31,7 @@ | |||
use PrestaShop\PrestaShop\Core\Domain\Exception\DomainException; | |||
use Throwable; | |||
|
|||
/** @deprecated and will be removed in 9.0 */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can call @trigger_error before the class to make sure in will appear in the logs.
src/PrestaShopBundle/Form/Exception/InvalidConfigurationDataErrorCollection.php
Show resolved
Hide resolved
@@ -0,0 +1,27 @@ | |||
services: | |||
_defaults: | |||
public: true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think these services don't need to be public
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As far as I see every single yml file in PS has services as public, I don't remember the exact reason, but I know at least in modules sometimes things don't work if you don't make services public.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are starting to make private services to optimize the container, I think it is better to stop adding public service, il will ease the work in the future.
Also, you can create your new services with the FQCN now :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alright that makes sense. Implemented FQCN.
use PrestaShopBundle\Entity\Repository\LangRepository; | ||
use PrestaShopBundle\Form\Admin\Configure\AdvancedParameters\Administration\GeneralDataProvider; | ||
use PrestaShopBundle\Form\ErrorMessage\Factory\AdministrationConfigurationErrorMessageProvider; | ||
use Symfony\Component\Translation\Translator; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wrong namespace here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You mean the translator? Changed it to interface since that's what class is using
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
he one from Symfony\Contracts should be used instead.
#30496
/** | ||
* @return int|null | ||
*/ | ||
public function getLanguageId(): ?int |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where is this function used ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's needed in the future, but after thinking about it yeah it's probably not needed now. Removed it.
/** | ||
* @return int|null | ||
*/ | ||
public function getLanguageId(): ?int; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think the interface should have this method. An error does not have to be aware of the context locale IMO.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It meant not for the context locale, but for when there is mulitlang field, so we know in which language error happened. But yeah it's not needed in interface errors needing that can use the function without it being in interface.
* AdministrationConfigurationError constructor. | ||
* |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* AdministrationConfigurationError constructor. | |
* |
use PrestaShop\PrestaShop\Core\Form\ErrorMessage\ConfigurationErrorInterface; | ||
use PrestaShop\PrestaShop\Core\Form\ErrorMessage\Factory\ConfigurationErrorMessageProviderInterface; | ||
use PrestaShopBundle\Entity\Repository\LangRepository; | ||
use Symfony\Component\Translation\TranslatorInterface; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The translator should come from Symfony/Contracts (in mutliple places)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed those
@@ -0,0 +1,27 @@ | |||
services: | |||
_defaults: | |||
public: true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are starting to make private services to optimize the container, I think it is better to stop adding public service, il will ease the work in the future.
Also, you can create your new services with the FQCN now :)
@@ -0,0 +1,23 @@ | |||
services: | |||
PrestaShopBundle\Form\ErrorMessage\LabelProvider: | |||
class: PrestaShopBundle\Form\ErrorMessage\LabelProvider |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When using FQCN, the class:
is not needed anymore, as it should follow the namespace and symfony finds it. (on the other hand when the service have multiple implementations, then it is supposed to be defined using snake_case and requires the class:
attribute)
class: PrestaShopBundle\Form\ErrorMessage\LabelProvider |
check other definitions too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changes those, thanks!
} catch (DataProviderException $e) { | ||
$this->flashErrors($this->getErrorMessages($e->getInvalidConfigurationDataErrors())); | ||
} catch (FormDataProviderException $e) { | ||
$errorMessageFactory = $this->get('prestashop.form.error_message.configuration_error_factory'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think for new service call, we should fit with https://github.com/PrestaShop/ADR/blob/master/0019-FQCN-Autowiring.md. You probably should create FQCN version of prestashop.form.error_message.configuration_error_factory and use it here.
ping @PrestaShop/wording-managers to approve the wording before we go to QA |
...estaShopBundle/Form/ErrorMessage/Factory/AdministrationConfigurationErrorMessageProvider.php
Outdated
Show resolved
Hide resolved
private function getDefaultErrorMessage(string $label): string | ||
{ | ||
return $this->translator->trans( | ||
'%s is invalid.', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there more info on the nature of the error? Telling the user "x is invalid" isn't going to help them 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This message is used only for the fallback case, the idea here is to try and match any Exception with the appropriate error message, that is actually what was done in the previous provider classes like CommonConfigurationErrorMessageProvider
on a case by case based on the exception
But in case no specific case was handled for an unexpected error we still need to display some default message, it will lack details until the error use case is properly handled for the specific error case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, ok - I see. Thank you
switch ($error->getErrorCode()) { | ||
case AdministrationConfigurationError::ERROR_COOKIE_LIFETIME_MAX_VALUE_EXCEEDED: | ||
return $this->translator->trans( | ||
'%s is invalid. Please enter an integer lower than %s.', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
'%s is invalid. Please enter an integer lower than %s.', | |
'Exceeds the maximum lifetime value of a cookie. Please enter an integer lower than %s.', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't it be better to add a help text to tell the user what the max lifetime value of a cookie is?
So that we don't have to tell them "No, the value you entered is too high" after they're done typing it in.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually @l-delin the message here uses a placeholder %s is invalid
the %s
part is replaced by the variable $label
which will automatically provide the name of the field from the form (which is also translated independently). So the interest here is to use a single wording with placeholder for any label/field
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alright, makes sense. Then, feel free to dismiss this edit :-)
…onErrorMessageProvider.php fixed tests
…onfigurationErrorMessageProvider.php Wording changes Co-authored-by: l-delin <113511191+l-delin@users.noreply.github.com>
8767a90
to
f32ea6d
Compare
Fixed thie issue |