From 22d057328ab84ff727c2f3214e0b2500a06ff139 Mon Sep 17 00:00:00 2001 From: Yuri Kuznetsov Date: Fri, 14 Jul 2023 10:45:44 +0300 Subject: [PATCH] suppressValidationList, no Service class need for template, discard skip type validation in service --- .../FieldValidationManager.php | 40 +++++++++++++------ application/Espo/Core/Record/Service.php | 25 +++++++----- .../Templates/Metadata/Event/entityDefs.json | 3 +- .../Espo/Core/Templates/Services/Event.php | 7 +--- .../metadata/entityDefs/Meeting.json | 3 +- .../Espo/Modules/Crm/Services/Meeting.php | 7 ---- .../Resources/metadata/entityDefs/User.json | 6 ++- application/Espo/Services/User.php | 7 ---- .../Tools/EntityManager/EntityManager.php | 14 +------ schema/metadata/entityDefs.json | 7 ++++ upgrades/7.6/scripts/AfterUpgrade.php | 15 +++++++ 11 files changed, 77 insertions(+), 57 deletions(-) diff --git a/application/Espo/Core/FieldValidation/FieldValidationManager.php b/application/Espo/Core/FieldValidation/FieldValidationManager.php index 14eca5a6aa..5725539043 100644 --- a/application/Espo/Core/FieldValidation/FieldValidationManager.php +++ b/application/Espo/Core/FieldValidation/FieldValidationManager.php @@ -248,17 +248,7 @@ class FieldValidationManager bool $throw ): array { - $entityType = $entity->getEntityType(); - - $validationList = array_unique(array_merge( - $this->getValidationList($entityType, $field), - $this->getMandatoryValidationList($entityType, $field) - )); - - $validationList = array_filter( - $validationList, - fn ($type) => !in_array($field, $params->getTypeSkipFieldList($type)) - ); + $validationList = $this->getAllValidationList($entity->getEntityType(), $field, $params); $failureList = []; @@ -269,7 +259,7 @@ class FieldValidationManager continue; } - $failure = new Failure($entityType, $field, $type); + $failure = new Failure($entity->getEntityType(), $field, $type); $failureList[] = $failure; @@ -287,6 +277,32 @@ class FieldValidationManager return array_merge($failureList, $additionalFailureList); } + /** + * @return string[] + */ + private function getAllValidationList(string $entityType, string $field, FieldValidationParams $params): array + { + $validationList = array_unique(array_merge( + $this->getValidationList($entityType, $field), + $this->getMandatoryValidationList($entityType, $field) + )); + + /** @var string[] $suppressList */ + $suppressList = $this->metadata->get("entityDefs.$entityType.fields.$field.suppressValidationList") ?? []; + + $validationList = array_filter( + $validationList, + fn ($type) => !in_array($type, $suppressList) + ); + + $validationList = array_filter( + $validationList, + fn ($type) => !in_array($field, $params->getTypeSkipFieldList($type)) + ); + + return array_values($validationList); + } + /** * @param mixed $validationValue */ diff --git a/application/Espo/Core/Record/Service.php b/application/Espo/Core/Record/Service.php index 3f1a65c911..05fd49d458 100644 --- a/application/Espo/Core/Record/Service.php +++ b/application/Espo/Core/Record/Service.php @@ -71,6 +71,8 @@ use stdClass; use InvalidArgumentException; use LogicException; +use const E_USER_DEPRECATED; + /** * The layer between a controller and ORM repository. For CRUD and other operations with records. * Access control is processed here. @@ -166,14 +168,13 @@ class Service implements Crud, /** @var bool */ protected $forceSelectAllAttributes = false; /** @var string[] */ - protected $validateSkipFieldList = []; - /** - * @todo Move to metadata. - * @var string[] - */ - protected $validateRequiredSkipFieldList = []; - /** @var string[] */ protected $duplicateIgnoreAttributeList = []; + /** + * @var string[] + * @deprecated As of v8.0. Use `suppressValidationList` metadata parameter. + * @todo Remove in v9.0. + */ + protected $validateSkipFieldList = []; /** @var Acl */ protected $acl = null; @@ -354,8 +355,14 @@ class Service implements Crud, { $params = FieldValidationParams ::create() - ->withSkipFieldList($this->validateSkipFieldList) - ->withTypeSkipFieldList('required', $this->validateRequiredSkipFieldList); + ->withSkipFieldList($this->validateSkipFieldList); + + if (!empty($this->validateSkipFieldList)) { + trigger_error( + '$validateSkipFieldList is deprecated and will be removed in v9.0.', + E_USER_DEPRECATED + ); + } $this->fieldValidationManager->process($entity, $data, $params); } diff --git a/application/Espo/Core/Templates/Metadata/Event/entityDefs.json b/application/Espo/Core/Templates/Metadata/Event/entityDefs.json index 5f30864bd7..eb7ca2ff44 100644 --- a/application/Espo/Core/Templates/Metadata/Event/entityDefs.json +++ b/application/Espo/Core/Templates/Metadata/Event/entityDefs.json @@ -25,7 +25,8 @@ "type": "datetimeOptional", "view": "crm:views/meeting/fields/date-end", "required": true, - "after": "dateStart" + "after": "dateStart", + "suppressValidationList": ["required"] }, "isAllDay": { "type": "bool", diff --git a/application/Espo/Core/Templates/Services/Event.php b/application/Espo/Core/Templates/Services/Event.php index 577cbd1d25..4df98ebbe2 100644 --- a/application/Espo/Core/Templates/Services/Event.php +++ b/application/Espo/Core/Templates/Services/Event.php @@ -33,10 +33,7 @@ use Espo\Services\Record; /** * @extends Record<\Espo\Core\Templates\Entities\Event> + * @deprecated Left for backward compatibility. */ class Event extends Record -{ - protected $validateRequiredSkipFieldList = [ - 'dateEnd' - ]; -} +{} diff --git a/application/Espo/Modules/Crm/Resources/metadata/entityDefs/Meeting.json b/application/Espo/Modules/Crm/Resources/metadata/entityDefs/Meeting.json index c575b4d0f0..bd7829e6e0 100644 --- a/application/Espo/Modules/Crm/Resources/metadata/entityDefs/Meeting.json +++ b/application/Espo/Modules/Crm/Resources/metadata/entityDefs/Meeting.json @@ -26,7 +26,8 @@ "type": "datetimeOptional", "view": "crm:views/meeting/fields/date-end", "required": true, - "after": "dateStart" + "after": "dateStart", + "suppressValidationList": ["required"] }, "isAllDay": { "type": "bool", diff --git a/application/Espo/Modules/Crm/Services/Meeting.php b/application/Espo/Modules/Crm/Services/Meeting.php index b337e81a4b..3a9283480a 100644 --- a/application/Espo/Modules/Crm/Services/Meeting.php +++ b/application/Espo/Modules/Crm/Services/Meeting.php @@ -43,13 +43,6 @@ class Meeting extends Record implements { use Di\HookManagerSetter; - /** - * @var string[] - */ - protected $validateRequiredSkipFieldList = [ - 'dateEnd', - ]; - /** * @var string[] */ diff --git a/application/Espo/Resources/metadata/entityDefs/User.json b/application/Espo/Resources/metadata/entityDefs/User.json index 2e7170eb66..e24b64f8a0 100644 --- a/application/Espo/Resources/metadata/entityDefs/User.json +++ b/application/Espo/Resources/metadata/entityDefs/User.json @@ -98,12 +98,14 @@ }, "firstName": { "type": "varchar", - "maxLength": 100 + "maxLength": 100, + "suppressValidationList": ["required"] }, "lastName": { "type": "varchar", "maxLength": 100, - "required": true + "required": true, + "suppressValidationList": ["required"] }, "isActive": { "type": "bool", diff --git a/application/Espo/Services/User.php b/application/Espo/Services/User.php index 9c73e12aa9..dde679b43a 100644 --- a/application/Espo/Services/User.php +++ b/application/Espo/Services/User.php @@ -72,13 +72,6 @@ class User extends Record implements 'type', ]; - /** @var string[] */ - protected $validateSkipFieldList = [ - 'name', - 'firstName', - 'lastName', - ]; - /** @var string[] */ private $allowedUserTypeList = [ UserEntity::TYPE_REGULAR, diff --git a/application/Espo/Tools/EntityManager/EntityManager.php b/application/Espo/Tools/EntityManager/EntityManager.php index fb62502ed7..0b318e4071 100644 --- a/application/Espo/Tools/EntityManager/EntityManager.php +++ b/application/Espo/Tools/EntityManager/EntityManager.php @@ -139,19 +139,7 @@ class EntityManager "{\n". "}\n"; - $filePath = "custom/Espo/Custom/Controllers/$normalizedName.php"; - - $this->fileManager->putContents($filePath, $contents); - - $contents = "<" . "?" . "php\n\n". - "namespace Espo\Custom\Services;\n\n". - "class $normalizedName extends $templateNamespace\Services\\$type\n". - "{\n". - "}\n"; - - $filePath = "custom/Espo/Custom/Services/$normalizedName.php"; - - $this->fileManager->putContents($filePath, $contents); + $this->fileManager->putContents("custom/Espo/Custom/Controllers/$normalizedName.php", $contents); $stream = false; diff --git a/schema/metadata/entityDefs.json b/schema/metadata/entityDefs.json index f5b445635c..700b036583 100644 --- a/schema/metadata/entityDefs.json +++ b/schema/metadata/entityDefs.json @@ -333,6 +333,13 @@ }, "description": "A custom mandatory validation list for the field. Use this parameter to re-define mandatory validations applied for a specific field. By default, mandatory validations for a field type are applied." }, + "suppressValidationList": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Validations to be bypassed for the field." + }, "customizationDisabled": { "type": "boolean", "description": "Disables the ability to customize the field in the Entity Manager tool." diff --git a/upgrades/7.6/scripts/AfterUpgrade.php b/upgrades/7.6/scripts/AfterUpgrade.php index 427a214cec..eed8943a45 100644 --- a/upgrades/7.6/scripts/AfterUpgrade.php +++ b/upgrades/7.6/scripts/AfterUpgrade.php @@ -28,6 +28,7 @@ ************************************************************************/ use Espo\Core\Container; +use Espo\Core\Templates\Entities\Event; use Espo\Entities\Role; use Espo\ORM\EntityManager; use Espo\ORM\Query\Part\Expression; @@ -73,6 +74,20 @@ class AfterUpgrade continue; } + if ($type === Event::TEMPLATE_TYPE) { + $metadata->set('entityDefs', $entityType, [ + 'fields' => [ + 'dateEnd' => [ + 'suppressValidationList' => ['required'], + ], + ] + ]); + + $metadata->save(); + + continue; + } + if ( !in_array($type, [ BasePlus::TEMPLATE_TYPE,