Skip to content

Commit e8e73c7

Browse files
authored
IBX-8697: Added validation for Keyword field type values in content and tests (#592)
* IBX-8697: Added validation for Keyword field type values in content and tests * IBX-8697: Updated return type annotations in KeywordTest for better type safety and removed obsolete PHPStan baseline rules * IBX-8697: Revised validation error message for Keyword field type to improve clarity
1 parent 07187f8 commit e8e73c7

File tree

2 files changed

+116
-0
lines changed

2 files changed

+116
-0
lines changed

src/lib/FieldType/Keyword/Type.php

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use Ibexa\Contracts\Core\Repository\Values\ContentType\FieldDefinition;
1212
use Ibexa\Core\Base\Exceptions\InvalidArgumentType;
1313
use Ibexa\Core\FieldType\FieldType;
14+
use Ibexa\Core\FieldType\ValidationError;
1415
use Ibexa\Core\FieldType\Value as BaseValue;
1516
use JMS\TranslationBundle\Model\Message;
1617
use JMS\TranslationBundle\Translation\TranslationContainerInterface;
@@ -22,6 +23,8 @@
2223
*/
2324
class Type extends FieldType implements TranslationContainerInterface
2425
{
26+
public const MAX_KEYWORD_LENGTH = 255;
27+
2528
/**
2629
* Returns the field type identifier for this field type.
2730
*
@@ -87,6 +90,44 @@ protected function checkValueStructure(BaseValue $value)
8790
$value->values
8891
);
8992
}
93+
94+
foreach ($value->values as $keyword) {
95+
if (!is_string($keyword) || mb_strlen($keyword) > self::MAX_KEYWORD_LENGTH) {
96+
throw new InvalidArgumentType(
97+
'$value->values[]',
98+
'string up to ' . self::MAX_KEYWORD_LENGTH . ' characters',
99+
$keyword
100+
);
101+
}
102+
}
103+
}
104+
105+
/**
106+
* @param \Ibexa\Core\FieldType\Keyword\Value $fieldValue
107+
*/
108+
public function validate(FieldDefinition $fieldDefinition, SPIValue $fieldValue): array
109+
{
110+
$validationErrors = [];
111+
112+
foreach ($fieldValue->values as $keyword) {
113+
if (!is_string($keyword)) {
114+
$validationErrors[] = new ValidationError(
115+
'Each keyword must be a string.',
116+
null,
117+
[],
118+
'values'
119+
);
120+
} elseif (mb_strlen($keyword) > self::MAX_KEYWORD_LENGTH) {
121+
$validationErrors[] = new ValidationError(
122+
'Keyword value must be less than or equal to ' . self::MAX_KEYWORD_LENGTH . ' characters.',
123+
null,
124+
[],
125+
'values'
126+
);
127+
}
128+
}
129+
130+
return $validationErrors;
90131
}
91132

92133
/**

tests/lib/FieldType/KeywordTest.php

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use Ibexa\Core\Base\Exceptions\InvalidArgumentException;
1010
use Ibexa\Core\FieldType\Keyword\Type as KeywordType;
1111
use Ibexa\Core\FieldType\Keyword\Value as KeywordValue;
12+
use Ibexa\Core\FieldType\ValidationError;
1213

1314
/**
1415
* @group fieldType
@@ -238,6 +239,80 @@ public function provideDataForGetName(): array
238239
[new KeywordValue(['foo', 'bar']), 'foo, bar', [], 'en_GB'],
239240
];
240241
}
242+
243+
/**
244+
* @return iterable<string, array{0: array<string, mixed>, 1: \Ibexa\Core\FieldType\Keyword\Value}>
245+
*/
246+
public function provideValidDataForValidate(): iterable
247+
{
248+
yield 'multiple keywords' => [
249+
[],
250+
new KeywordValue(['foo', 'bar']),
251+
];
252+
253+
yield 'empty string keyword' => [
254+
[],
255+
new KeywordValue(['']),
256+
];
257+
258+
yield 'empty keyword list' => [
259+
[],
260+
new KeywordValue([]),
261+
];
262+
}
263+
264+
/**
265+
* @return iterable<string, array{
266+
* 0: array<string, mixed>,
267+
* 1: \Ibexa\Core\FieldType\Keyword\Value,
268+
* 2: array<\Ibexa\Contracts\Core\FieldType\ValidationError>
269+
* }>
270+
*/
271+
public function provideInvalidDataForValidate(): iterable
272+
{
273+
$maxLen = KeywordType::MAX_KEYWORD_LENGTH;
274+
275+
yield 'non-string keyword (int)' => [
276+
[],
277+
// @phpstan-ignore-next-line
278+
new KeywordValue(['valid', 123]),
279+
[
280+
new ValidationError(
281+
'Each keyword must be a string.',
282+
null,
283+
[],
284+
'values'
285+
),
286+
],
287+
];
288+
289+
yield 'non-string keyword (null)' => [
290+
[],
291+
// @phpstan-ignore-next-line
292+
new KeywordValue(['valid', null]),
293+
[
294+
new ValidationError(
295+
'Each keyword must be a string.',
296+
null,
297+
[],
298+
'values'
299+
),
300+
],
301+
];
302+
303+
yield 'too long keyword' => [
304+
[],
305+
new KeywordValue(['valid', str_repeat('a', $maxLen + 1)]),
306+
[
307+
new ValidationError(
308+
'Keyword value must be less than or equal to ' . $maxLen . ' characters.',
309+
null,
310+
[],
311+
'values'
312+
),
313+
],
314+
];
315+
}
241316
}
242317

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

0 commit comments

Comments
 (0)