diff --git a/application/Espo/Core/FieldValidators/CurrencyType.php b/application/Espo/Core/FieldValidators/CurrencyType.php index e2734f5692..e86ace1590 100644 --- a/application/Espo/Core/FieldValidators/CurrencyType.php +++ b/application/Espo/Core/FieldValidators/CurrencyType.php @@ -29,9 +29,6 @@ namespace Espo\Core\FieldValidators; -use \Espo\ORM\Entity; - class CurrencyType extends FloatType { - } diff --git a/application/Espo/Core/FieldValidators/DateType.php b/application/Espo/Core/FieldValidators/DateType.php new file mode 100644 index 0000000000..211c421e87 --- /dev/null +++ b/application/Espo/Core/FieldValidators/DateType.php @@ -0,0 +1,38 @@ +has($field) && $entity->get($field) !== null; + } +} diff --git a/application/Espo/Core/FieldValidators/DatetimeOptionalType.php b/application/Espo/Core/FieldValidators/DatetimeOptionalType.php new file mode 100644 index 0000000000..7841bea02e --- /dev/null +++ b/application/Espo/Core/FieldValidators/DatetimeOptionalType.php @@ -0,0 +1,40 @@ +has($field) && $entity->get($field) !== null) return true; + if ($entity->has($field . 'Date') && $entity->get($field . 'Date') !== null) return true; + return false; + } +} diff --git a/application/Espo/Core/FieldValidators/DatetimeType.php b/application/Espo/Core/FieldValidators/DatetimeType.php new file mode 100644 index 0000000000..6f66ce956f --- /dev/null +++ b/application/Espo/Core/FieldValidators/DatetimeType.php @@ -0,0 +1,34 @@ +has($field) && $entity->get($field) !== '' && $entity->get($field) !== null) return true; + + $dataList = $entity->get($field . 'Data'); + if (!is_array($dataList)) return false; + + foreach ($dataList as $item) { + if (!empty($item->emailAddress)) return true; + } + + return false; + } + + public function checkEmailAddress(\Espo\ORM\Entity $entity, string $field, $validationValue, $data) : bool + { + if ($entity->has($field) && $entity->get($field) !== '' && $entity->get($field) !== null) { + $address = $entity->get($field); + if (!filter_var($address, FILTER_VALIDATE_EMAIL)) { + return false; + } + } + + $dataList = $entity->get($field . 'Data'); + if (is_array($dataList)) { + foreach ($dataList as $item) { + if (empty($item->emailAddress)) continue; + $address = $item->emailAddress; + if (!filter_var($address, FILTER_VALIDATE_EMAIL)) { + return false; + } + } + } + + return true; + } +} diff --git a/application/Espo/Core/FieldValidators/FileType.php b/application/Espo/Core/FieldValidators/FileType.php new file mode 100644 index 0000000000..c0bbb0ccb3 --- /dev/null +++ b/application/Espo/Core/FieldValidators/FileType.php @@ -0,0 +1,34 @@ +has($field) && $entity->get($field) !== null; } + + public function checkMax(\Espo\ORM\Entity $entity, string $field, $validationValue, $data) : bool + { + if (!$entity->has($field) || $entity->get($field) === null) return true; + if ($entity->get($field) > $validationValue) return false; + return true; + } + + public function checkMin(\Espo\ORM\Entity $entity, string $field, $validationValue, $data) : bool + { + if (!$entity->has($field) || $entity->get($field) === null) return true; + if ($entity->get($field) < $validationValue) return false; + return true; + } } diff --git a/application/Espo/Core/FieldValidators/LinkMultipleType.php b/application/Espo/Core/FieldValidators/LinkMultipleType.php new file mode 100644 index 0000000000..e95cc6398f --- /dev/null +++ b/application/Espo/Core/FieldValidators/LinkMultipleType.php @@ -0,0 +1,38 @@ +getLinkMultipleIdList($field)) > 0; + } +} diff --git a/application/Espo/Core/FieldValidators/LinkParentType.php b/application/Espo/Core/FieldValidators/LinkParentType.php new file mode 100644 index 0000000000..d7fd873aa6 --- /dev/null +++ b/application/Espo/Core/FieldValidators/LinkParentType.php @@ -0,0 +1,49 @@ +has($idAttribute) || $entity->get($idAttribute) === '' || $entity->get($idAttribute) === null) { + return false; + } + + if (!$entity->get($typeAttribute)) { + return false; + } + + return true; + } +} diff --git a/application/Espo/Core/FieldValidators/LinkType.php b/application/Espo/Core/FieldValidators/LinkType.php new file mode 100644 index 0000000000..c803ea6178 --- /dev/null +++ b/application/Espo/Core/FieldValidators/LinkType.php @@ -0,0 +1,44 @@ +has($idAttribute)) { + return false; + } + + return $entity->get($idAttribute) !== null && $entity->get($idAttribute) !== ''; + } +} diff --git a/application/Espo/Core/FieldValidators/PersonNameType.php b/application/Espo/Core/FieldValidators/PersonNameType.php index e5c5b7eeb3..1162820eff 100644 --- a/application/Espo/Core/FieldValidators/PersonNameType.php +++ b/application/Espo/Core/FieldValidators/PersonNameType.php @@ -29,8 +29,6 @@ namespace Espo\Core\FieldValidators; -use \Espo\ORM\Entity; - class PersonNameType extends BaseType { public function checkRequired(\Espo\ORM\Entity $entity, string $field, $validationValue, $data) : bool diff --git a/application/Espo/Core/FieldValidators/PhoneType.php b/application/Espo/Core/FieldValidators/PhoneType.php new file mode 100644 index 0000000000..ed895bd885 --- /dev/null +++ b/application/Espo/Core/FieldValidators/PhoneType.php @@ -0,0 +1,47 @@ +has($field) && $entity->get($field) !== '' && $entity->get($field) !== null) return true; + + $dataList = $entity->get($field . 'Data'); + if (!is_array($dataList)) return false; + + foreach ($dataList as $item) { + if (!empty($item->phoneNumber)) return true; + } + + return false; + } +} diff --git a/application/Espo/Core/FieldValidators/VarcharType.php b/application/Espo/Core/FieldValidators/VarcharType.php index a7b2715112..80281a3c15 100644 --- a/application/Espo/Core/FieldValidators/VarcharType.php +++ b/application/Espo/Core/FieldValidators/VarcharType.php @@ -29,12 +29,21 @@ namespace Espo\Core\FieldValidators; -use \Espo\ORM\Entity; - class VarcharType extends BaseType { public function checkRequired(\Espo\ORM\Entity $entity, string $field, $validationValue, $data) : bool { - return $entity->has($field) && $entity->get($field) !== ''; + return $entity->has($field) && $entity->get($field) !== '' && $entity->get($field) !== null; + } + + public function checkMaxLength(\Espo\ORM\Entity $entity, string $field, $validationValue, $data) : bool + { + if ($entity->has($field) && $entity->get($field) !== '' && $entity->get($field) !== null) { + $value = $entity->get($field); + if (mb_strlen($value) > $validationValue) { + return false; + } + } + return true; } } diff --git a/application/Espo/Core/Utils/FieldValidatorManager.php b/application/Espo/Core/Utils/FieldValidatorManager.php index 0d9c2f3983..7603fb81aa 100644 --- a/application/Espo/Core/Utils/FieldValidatorManager.php +++ b/application/Espo/Core/Utils/FieldValidatorManager.php @@ -47,10 +47,16 @@ class FieldValidatorManager { if (!$data) $data = (object) []; - $validationValue = $this->fieldManagerUtil->getEntityTypeFieldParam($entity->getEntityType(), $field, $type); - if (is_null($validationValue) || $validationValue === false) return true; - $fieldType = $this->fieldManagerUtil->getEntityTypeFieldParam($entity->getEntityType(), $field, 'type'); + + $validationValue = $this->fieldManagerUtil->getEntityTypeFieldParam($entity->getEntityType(), $field, $type); + + $mandatoryValidationList = $this->metadata->get(['fields', $fieldType, 'mandatoryValidationList'], []); + + if (!in_array($type, $mandatoryValidationList)) { + if (is_null($validationValue) || $validationValue === false) return true; + } + if (!array_key_exists($fieldType, $this->implHash)) { $this->loadImpl($fieldType); } diff --git a/application/Espo/Resources/metadata/fields/currency.json b/application/Espo/Resources/metadata/fields/currency.json index 984b686b3d..564857653a 100644 --- a/application/Espo/Resources/metadata/fields/currency.json +++ b/application/Espo/Resources/metadata/fields/currency.json @@ -52,7 +52,11 @@ "importDisabled": true } }, - "validationList": ["required"], + "validationList": [ + "required", + "min", + "max" + ], "filter": true, "personalData": true } diff --git a/application/Espo/Resources/metadata/fields/date.json b/application/Espo/Resources/metadata/fields/date.json index 6dd8d5088b..39e9feb7b4 100644 --- a/application/Espo/Resources/metadata/fields/date.json +++ b/application/Espo/Resources/metadata/fields/date.json @@ -61,6 +61,9 @@ "type":"bool" } ], + "validationList": [ + "required" + ], "filter": true, "fieldDefs":{ "notNull":false diff --git a/application/Espo/Resources/metadata/fields/datetime.json b/application/Espo/Resources/metadata/fields/datetime.json index 2623d2c7d5..dd405fb5a5 100644 --- a/application/Espo/Resources/metadata/fields/datetime.json +++ b/application/Espo/Resources/metadata/fields/datetime.json @@ -68,6 +68,9 @@ "type":"bool" } ], + "validationList": [ + "required" + ], "filter": true, "fieldDefs":{ "notNull":false diff --git a/application/Espo/Resources/metadata/fields/datetimeOptional.json b/application/Espo/Resources/metadata/fields/datetimeOptional.json index ac2f33d98f..fbc0b57026 100644 --- a/application/Espo/Resources/metadata/fields/datetimeOptional.json +++ b/application/Espo/Resources/metadata/fields/datetimeOptional.json @@ -73,6 +73,9 @@ "disabled": true } }, + "validationList": [ + "required" + ], "filter": true, "notCreatable": true, "fieldDefs":{ diff --git a/application/Espo/Resources/metadata/fields/email.json b/application/Espo/Resources/metadata/fields/email.json index 22753c3a90..64b037bb4e 100644 --- a/application/Espo/Resources/metadata/fields/email.json +++ b/application/Espo/Resources/metadata/fields/email.json @@ -28,6 +28,13 @@ "customizationReadOnlyDisabled": true } }, + "validationList": [ + "required", + "emailAddress" + ], + "mandatoryValidationList": [ + "emailAddress" + ], "notCreatable": true, "filter": true, "fieldDefs":{ diff --git a/application/Espo/Resources/metadata/fields/file.json b/application/Espo/Resources/metadata/fields/file.json index 64fa97c7a4..1da2aa7d20 100644 --- a/application/Espo/Resources/metadata/fields/file.json +++ b/application/Espo/Resources/metadata/fields/file.json @@ -27,6 +27,9 @@ "notActualFields":[ "name" ], + "validationList": [ + "required" + ], "filter": true, "linkDefs": { "type": "belongsTo", diff --git a/application/Espo/Resources/metadata/fields/float.json b/application/Espo/Resources/metadata/fields/float.json index d431d82737..82e2a8243c 100644 --- a/application/Espo/Resources/metadata/fields/float.json +++ b/application/Espo/Resources/metadata/fields/float.json @@ -26,7 +26,11 @@ "type":"bool" } ], - "validationList": ["required"], + "validationList": [ + "required", + "min", + "max" + ], "filter": true, "fieldDefs":{ "notNull":false diff --git a/application/Espo/Resources/metadata/fields/image.json b/application/Espo/Resources/metadata/fields/image.json index 6b639524b5..75e5f6d9b3 100644 --- a/application/Espo/Resources/metadata/fields/image.json +++ b/application/Espo/Resources/metadata/fields/image.json @@ -28,6 +28,9 @@ "notActualFields":[ "name" ], + "validationList": [ + "required" + ], "filter": true, "linkDefs": { "type": "belongsTo", diff --git a/application/Espo/Resources/metadata/fields/int.json b/application/Espo/Resources/metadata/fields/int.json index 12d60ce3b4..4b857ef298 100644 --- a/application/Espo/Resources/metadata/fields/int.json +++ b/application/Espo/Resources/metadata/fields/int.json @@ -30,7 +30,11 @@ "type":"bool" } ], - "validationList": ["required"], + "validationList": [ + "required", + "min", + "max" + ], "filter": true, "textFilter": true, "textFilterForeign": true, diff --git a/application/Espo/Resources/metadata/fields/link.json b/application/Espo/Resources/metadata/fields/link.json index 3fe894985f..88bca22ec6 100644 --- a/application/Espo/Resources/metadata/fields/link.json +++ b/application/Espo/Resources/metadata/fields/link.json @@ -25,6 +25,9 @@ "notActualFields":[ "name" ], + "validationList": [ + "required" + ], "filter": true, "notCreatable": true } diff --git a/application/Espo/Resources/metadata/fields/linkMultiple.json b/application/Espo/Resources/metadata/fields/linkMultiple.json index e94ed672f8..a15c6a406a 100644 --- a/application/Espo/Resources/metadata/fields/linkMultiple.json +++ b/application/Espo/Resources/metadata/fields/linkMultiple.json @@ -22,6 +22,9 @@ "notActualFields":[ "names" ], + "validationList": [ + "required" + ], "notCreatable": true, "notSortable": true, "filter": true diff --git a/application/Espo/Resources/metadata/fields/linkParent.json b/application/Espo/Resources/metadata/fields/linkParent.json index 2175db10d0..c787927f07 100644 --- a/application/Espo/Resources/metadata/fields/linkParent.json +++ b/application/Espo/Resources/metadata/fields/linkParent.json @@ -26,6 +26,9 @@ "notActualFields":[ "name" ], + "validationList": [ + "required" + ], "filter": true, "notCreatable": true, "fieldDefs":{ diff --git a/application/Espo/Resources/metadata/fields/phone.json b/application/Espo/Resources/metadata/fields/phone.json index d38aeaa85f..715b043586 100644 --- a/application/Espo/Resources/metadata/fields/phone.json +++ b/application/Espo/Resources/metadata/fields/phone.json @@ -39,6 +39,9 @@ "customizationReadOnlyDisabled": true } }, + "validationList": [ + "required" + ], "notCreatable": true, "filter": true, "fieldDefs":{ diff --git a/application/Espo/Resources/metadata/fields/varchar.json b/application/Espo/Resources/metadata/fields/varchar.json index 6ab066363e..276c64eef7 100644 --- a/application/Espo/Resources/metadata/fields/varchar.json +++ b/application/Espo/Resources/metadata/fields/varchar.json @@ -31,7 +31,10 @@ "type":"bool" } ], - "validationList": ["required"], + "validationList": [ + "required", + "maxLength" + ], "filter": true, "personalData": true, "textFilter": true, diff --git a/application/Espo/Services/Record.php b/application/Espo/Services/Record.php index 2d003eb2f1..9b0646c47a 100644 --- a/application/Espo/Services/Record.php +++ b/application/Espo/Services/Record.php @@ -507,25 +507,27 @@ class Record extends \Espo\Core\Services\Base if (!$entity->isNew()) { if (!$this->isFieldSetInData($data, $field)) continue; } - $this->processDataValidationField($entity, $field, $data); + $this->processValidationField($entity, $field, $data); } } - protected function processDataValidationField(Entity $entity, $field, $data) + protected function processValidationField(Entity $entity, $field, $data) { $fieldType = $this->getFieldManagerUtil()->getEntityTypeFieldParam($this->entityType, $field, 'type'); - if (!$fieldType) return; - + $validationList = $this->getMetadata()->get(['fields', $fieldType, 'validationList'], []); + $mandatoryValidationList = $this->getMetadata()->get(['fields', $fieldType, 'mandatoryValidationList'], []); $fieldValidatorManager = $this->getInjection('container')->get('fieldValidatorManager'); - $validationTypeList = $this->getMetadata()->get(['fields', $fieldType, 'validationList'], []); - foreach ($validationTypeList as $validationType) { - $validationValue = $this->getFieldManagerUtil()->getEntityTypeFieldParam($this->entityType, $field, $validationType); - if (is_null($validationValue)) continue; - - if (!$fieldValidatorManager->check($entity, $field, $validationType, $validationValue, $data)) { - throw new BadRequest("Validation {$validationType}: {$field}."); + foreach ($validationList as $type) { + $value = $this->getFieldManagerUtil()->getEntityTypeFieldParam($this->entityType, $field, $type); + if (is_null($value)) { + if (!in_array($type, $mandatoryValidationList)) { + continue; + } + } + if (!$fieldValidatorManager->check($entity, $field, $type, $data)) { + throw new BadRequest("Not valid data. Field: '{$field}', type: {$type}."); } } }