Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions src/lib/FieldType/Keyword/Type.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
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\Value as BaseValue;
use JMS\TranslationBundle\Model\Message;
use JMS\TranslationBundle\Translation\TranslationContainerInterface;
Expand All @@ -22,6 +23,8 @@
*/
class Type extends FieldType implements TranslationContainerInterface
{
public const MAX_KEYWORD_LENGTH = 255;

/**
* Returns the field type identifier for this field type.
*
Expand Down Expand Up @@ -87,6 +90,44 @@ protected function checkValueStructure(BaseValue $value)
$value->values
);
}

foreach ($value->values as $keyword) {
if (!is_string($keyword) || mb_strlen($keyword) > self::MAX_KEYWORD_LENGTH) {
throw new InvalidArgumentType(
'$value->values[]',
'string up to ' . self::MAX_KEYWORD_LENGTH . ' characters',
$keyword
);
}
}
}

/**
* @param \Ibexa\Core\FieldType\Keyword\Value $fieldValue
*/
public function validate(FieldDefinition $fieldDefinition, SPIValue $fieldValue): array
{
$validationErrors = [];

foreach ($fieldValue->values as $keyword) {
if (!is_string($keyword)) {
$validationErrors[] = new ValidationError(
'Each keyword must be a string.',
null,
[],
'values'
);
} elseif (mb_strlen($keyword) > self::MAX_KEYWORD_LENGTH) {
$validationErrors[] = new ValidationError(
'Keyword value must be less than or equal to ' . self::MAX_KEYWORD_LENGTH . ' characters.',
null,
[],
'values'
);
}
}

return $validationErrors;
}

/**
Expand Down
75 changes: 75 additions & 0 deletions tests/lib/FieldType/KeywordTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Ibexa\Core\Base\Exceptions\InvalidArgumentException;
use Ibexa\Core\FieldType\Keyword\Type as KeywordType;
use Ibexa\Core\FieldType\Keyword\Value as KeywordValue;
use Ibexa\Core\FieldType\ValidationError;

/**
* @group fieldType
Expand Down Expand Up @@ -238,6 +239,80 @@ public function provideDataForGetName(): array
[new KeywordValue(['foo', 'bar']), 'foo, bar', [], 'en_GB'],
];
}

/**
* @return iterable<string, array{0: array<string, mixed>, 1: \Ibexa\Core\FieldType\Keyword\Value}>
*/
public function provideValidDataForValidate(): iterable
{
yield 'multiple keywords' => [
[],
new KeywordValue(['foo', 'bar']),
];

yield 'empty string keyword' => [
[],
new KeywordValue(['']),
];

yield 'empty keyword list' => [
[],
new KeywordValue([]),
];
}

/**
* @return iterable<string, array{
* 0: array<string, mixed>,
* 1: \Ibexa\Core\FieldType\Keyword\Value,
* 2: array<\Ibexa\Contracts\Core\FieldType\ValidationError>
* }>
*/
public function provideInvalidDataForValidate(): iterable
{
$maxLen = KeywordType::MAX_KEYWORD_LENGTH;

yield 'non-string keyword (int)' => [
[],
// @phpstan-ignore-next-line
new KeywordValue(['valid', 123]),
[
new ValidationError(
'Each keyword must be a string.',
null,
[],
'values'
),
],
];

yield 'non-string keyword (null)' => [
[],
// @phpstan-ignore-next-line
new KeywordValue(['valid', null]),
[
new ValidationError(
'Each keyword must be a string.',
null,
[],
'values'
),
],
];

yield 'too long keyword' => [
[],
new KeywordValue(['valid', str_repeat('a', $maxLen + 1)]),
[
new ValidationError(
'Keyword value must be less than or equal to ' . $maxLen . ' characters.',
null,
[],
'values'
),
],
];
}
}

class_alias(KeywordTest::class, 'eZ\Publish\Core\FieldType\Tests\KeywordTest');
Loading