Skip to content

Commit

Permalink
Refactored Float and Integer field types to use external validators (#…
Browse files Browse the repository at this point in the history
…425)

For more details see #425

Key changes:

* Refactored Float and Integer field types to use external validators

* [Tests] Refactored Float, Integer, and String validator tests

---------

Co-authored-by: Adam Wójs <[email protected]>
Co-authored-by: Paweł Niedzielski <[email protected]>
  • Loading branch information
3 people authored Aug 28, 2024
1 parent 4bed131 commit 7c398f2
Show file tree
Hide file tree
Showing 14 changed files with 887 additions and 1,720 deletions.
435 changes: 0 additions & 435 deletions phpstan-baseline.neon

Large diffs are not rendered by default.

83 changes: 83 additions & 0 deletions src/lib/FieldType/BaseNumericType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<?php

/**
* @copyright Copyright (C) Ibexa AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);

namespace Ibexa\Core\FieldType;

use Ibexa\Contracts\Core\FieldType\Value as SPIValue;
use Ibexa\Contracts\Core\Repository\Values\ContentType\FieldDefinition;
use JMS\TranslationBundle\Translation\TranslationContainerInterface;

abstract class BaseNumericType extends FieldType implements TranslationContainerInterface
{
/**
* @return array<string, \Ibexa\Core\FieldType\Validator>
*/
abstract protected function getValidators(): array;

public function getValidator(string $validatorIdentifier): ?Validator
{
return $this->getValidators()[$validatorIdentifier] ?? null;
}

/**
* Validates the validatorConfiguration of a FieldDefinitionCreateStruct or FieldDefinitionUpdateStruct.
*
* @param array<string, mixed> $validatorConfiguration
*
* @return \Ibexa\Contracts\Core\FieldType\ValidationError[]
*/
public function validateValidatorConfiguration($validatorConfiguration): array
{
$validationErrors = [];
$validatorValidationErrors = [];
foreach ($validatorConfiguration as $validatorIdentifier => $constraints) {
$validator = $this->getValidator($validatorIdentifier);
if (null === $validator) {
$validationErrors[] = new ValidationError(
"Validator '%validator%' is unknown",
null,
[
'%validator%' => $validatorIdentifier,
],
"[$validatorIdentifier]"
);

continue;
}

$validatorValidationErrors[] = $validator->validateConstraints($constraints);
}

return array_merge($validationErrors, ...$validatorValidationErrors);
}

/**
* Validates a field based on the validators in the field definition.
*
* @return \Ibexa\Contracts\Core\FieldType\ValidationError[]
*
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\PropertyNotFoundException
*/
public function validate(FieldDefinition $fieldDefinition, SPIValue $value): array
{
if ($this->isEmptyValue($value)) {
return [];
}

$errors = [];
$validatorConfiguration = $fieldDefinition->getValidatorConfiguration();
foreach ($this->getValidators() as $validatorIdentifier => $validator) {
$validator->initializeWithConstraints($validatorConfiguration[$validatorIdentifier] ?? []);
if (!$validator->validate($value, $fieldDefinition)) {
$errors[] = $validator->getMessage();
}
}

return array_merge(...$errors);
}
}
130 changes: 10 additions & 120 deletions src/lib/FieldType/Float/Type.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,17 @@
use Ibexa\Contracts\Core\FieldType\Value as SPIValue;
use Ibexa\Contracts\Core\Repository\Values\ContentType\FieldDefinition;
use Ibexa\Core\Base\Exceptions\InvalidArgumentType;
use Ibexa\Core\FieldType\FieldType;
use Ibexa\Core\FieldType\ValidationError;
use Ibexa\Core\FieldType\BaseNumericType;
use Ibexa\Core\FieldType\Validator;
use Ibexa\Core\FieldType\Value as BaseValue;
use JMS\TranslationBundle\Model\Message;
use JMS\TranslationBundle\Translation\TranslationContainerInterface;

/**
* Float field types.
*
* Represents floats.
*/
class Type extends FieldType implements TranslationContainerInterface
class Type extends BaseNumericType
{
protected $validatorConfigurationSchema = [
'FloatValueValidator' => [
Expand All @@ -36,112 +35,9 @@ class Type extends FieldType implements TranslationContainerInterface
],
];

/**
* Validates the validatorConfiguration of a FieldDefinitionCreateStruct or FieldDefinitionUpdateStruct.
*
* @param mixed $validatorConfiguration
*
* @return \Ibexa\Contracts\Core\FieldType\ValidationError[]
*/
public function validateValidatorConfiguration($validatorConfiguration)
{
$validationErrors = [];

foreach ($validatorConfiguration as $validatorIdentifier => $constraints) {
if ($validatorIdentifier !== 'FloatValueValidator') {
$validationErrors[] = new ValidationError(
"Validator '%validator%' is unknown",
null,
[
'%validator%' => $validatorIdentifier,
],
"[$validatorIdentifier]"
);

continue;
}

foreach ($constraints as $name => $value) {
switch ($name) {
case 'minFloatValue':
case 'maxFloatValue':
if ($value !== null && !is_numeric($value)) {
$validationErrors[] = new ValidationError(
"Validator parameter '%parameter%' value must be of numeric type",
null,
[
'%parameter%' => $name,
],
"[$validatorIdentifier][$name]"
);
}
break;
default:
$validationErrors[] = new ValidationError(
"Validator parameter '%parameter%' is unknown",
null,
[
'%parameter%' => $name,
],
"[$validatorIdentifier][$name]"
);
}
}
}

return $validationErrors;
}

/**
* Validates a field based on the validators in the field definition.
*
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\InvalidArgumentException
*
* @param \Ibexa\Contracts\Core\Repository\Values\ContentType\FieldDefinition $fieldDefinition The field definition of the field
* @param \Ibexa\Core\FieldType\Float\Value $fieldValue The field value for which an action is performed
*
* @return \Ibexa\Contracts\Core\FieldType\ValidationError[]
*/
public function validate(FieldDefinition $fieldDefinition, SPIValue $fieldValue)
protected function getValidators(): array
{
$validationErrors = [];

if ($this->isEmptyValue($fieldValue)) {
return $validationErrors;
}

$validatorConfiguration = $fieldDefinition->getValidatorConfiguration();
$constraints = isset($validatorConfiguration['FloatValueValidator']) ?
$validatorConfiguration['FloatValueValidator'] :
[];

$validationErrors = [];

if (isset($constraints['maxFloatValue']) &&
$constraints['maxFloatValue'] !== null && $fieldValue->value > $constraints['maxFloatValue']) {
$validationErrors[] = new ValidationError(
'The value can not be higher than %size%.',
null,
[
'%size%' => $constraints['maxFloatValue'],
],
'value'
);
}

if (isset($constraints['minFloatValue']) &&
$constraints['minFloatValue'] !== null && $fieldValue->value < $constraints['minFloatValue']) {
$validationErrors[] = new ValidationError(
'The value can not be lower than %size%.',
null,
[
'%size%' => $constraints['minFloatValue'],
],
'value'
);
}

return $validationErrors;
return ['FloatValueValidator' => new Validator\FloatValueValidator()];
}

/**
Expand All @@ -165,20 +61,14 @@ public function getName(SPIValue $value, FieldDefinition $fieldDefinition, strin
/**
* Returns the fallback default value of field type when no such default
* value is provided in the field definition in content types.
*
* @return \Ibexa\Core\FieldType\Float\Value
*/
public function getEmptyValue()
public function getEmptyValue(): Value
{
return new Value();
}

/**
* Implements the core of {@see isEmptyValue()}.
*
* @param mixed $value
*
* @return bool
* @param \Ibexa\Core\FieldType\Float\Value $value
*/
public function isEmptyValue(SPIValue $value)
{
Expand Down Expand Up @@ -209,7 +99,7 @@ protected function createValueFromInput($inputValue)
*
* @param \Ibexa\Core\FieldType\Float\Value $value
*/
protected function checkValueStructure(BaseValue $value)
protected function checkValueStructure(BaseValue $value): void
{
if (!is_float($value->value)) {
throw new InvalidArgumentType(
Expand Down Expand Up @@ -237,7 +127,7 @@ protected function getSortInfo(BaseValue $value)
*
* @return \Ibexa\Core\FieldType\Float\Value $value
*/
public function fromHash($hash)
public function fromHash($hash): Value
{
if ($hash === null) {
return $this->getEmptyValue();
Expand All @@ -253,7 +143,7 @@ public function fromHash($hash)
*
* @return mixed
*/
public function toHash(SPIValue $value)
public function toHash(SPIValue $value): mixed
{
if ($this->isEmptyValue($value)) {
return null;
Expand Down
Loading

0 comments on commit 7c398f2

Please sign in to comment.