Skip to content

Commit 1f867c4

Browse files
committed
ISSUE-345: attribute type validator
1 parent 10fb048 commit 1f867c4

File tree

7 files changed

+125
-10
lines changed

7 files changed

+125
-10
lines changed

config/services/validators.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,7 @@ services:
66
PhpList\Core\Domain\Messaging\Validator\TemplateImageValidator:
77
autowire: true
88
autoconfigure: true
9+
10+
PhpList\Core\Domain\Subscription\Validator\AttributeTypeValidator:
11+
autowire: true
12+
autoconfigure: true

src/Domain/Identity/Service/AdminAttributeDefinitionManager.php

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,19 @@
88
use PhpList\Core\Domain\Identity\Model\Dto\AdminAttributeDefinitionDto;
99
use PhpList\Core\Domain\Identity\Repository\AdminAttributeDefinitionRepository;
1010
use PhpList\Core\Domain\Identity\Exception\AttributeDefinitionCreationException;
11+
use PhpList\Core\Domain\Subscription\Validator\AttributeTypeValidator;
1112

1213
class AdminAttributeDefinitionManager
1314
{
1415
private AdminAttributeDefinitionRepository $definitionRepository;
16+
private AttributeTypeValidator $attributeTypeValidator;
1517

16-
public function __construct(AdminAttributeDefinitionRepository $definitionRepository)
17-
{
18+
public function __construct(
19+
AdminAttributeDefinitionRepository $definitionRepository,
20+
AttributeTypeValidator $attributeTypeValidator
21+
) {
1822
$this->definitionRepository = $definitionRepository;
23+
$this->attributeTypeValidator = $attributeTypeValidator;
1924
}
2025

2126
public function create(AdminAttributeDefinitionDto $attributeDefinitionDto): AdminAttributeDefinition
@@ -24,6 +29,7 @@ public function create(AdminAttributeDefinitionDto $attributeDefinitionDto): Adm
2429
if ($existingAttribute) {
2530
throw new AttributeDefinitionCreationException('Attribute definition already exists', 409);
2631
}
32+
$this->attributeTypeValidator->validate($attributeDefinitionDto->type);
2733

2834
$attributeDefinition = (new AdminAttributeDefinition($attributeDefinitionDto->name))
2935
->setType($attributeDefinitionDto->type)
@@ -45,6 +51,7 @@ public function update(
4551
if ($existingAttribute && $existingAttribute->getId() !== $attributeDefinition->getId()) {
4652
throw new AttributeDefinitionCreationException('Another attribute with this name already exists.', 409);
4753
}
54+
$this->attributeTypeValidator->validate($attributeDefinitionDto->type);
4855

4956
$attributeDefinition
5057
->setName($attributeDefinitionDto->name)

src/Domain/Subscription/Service/Manager/AttributeDefinitionManager.php

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,19 @@
88
use PhpList\Core\Domain\Subscription\Model\Dto\AttributeDefinitionDto;
99
use PhpList\Core\Domain\Subscription\Model\SubscriberAttributeDefinition;
1010
use PhpList\Core\Domain\Subscription\Repository\SubscriberAttributeDefinitionRepository;
11+
use PhpList\Core\Domain\Subscription\Validator\AttributeTypeValidator;
1112

1213
class AttributeDefinitionManager
1314
{
1415
private SubscriberAttributeDefinitionRepository $definitionRepository;
16+
private AttributeTypeValidator $attributeTypeValidator;
1517

16-
public function __construct(SubscriberAttributeDefinitionRepository $definitionRepository)
17-
{
18+
public function __construct(
19+
SubscriberAttributeDefinitionRepository $definitionRepository,
20+
AttributeTypeValidator $attributeTypeValidator
21+
) {
1822
$this->definitionRepository = $definitionRepository;
23+
$this->attributeTypeValidator = $attributeTypeValidator;
1924
}
2025

2126
public function create(AttributeDefinitionDto $attributeDefinitionDto): SubscriberAttributeDefinition
@@ -24,6 +29,7 @@ public function create(AttributeDefinitionDto $attributeDefinitionDto): Subscrib
2429
if ($existingAttribute) {
2530
throw new AttributeDefinitionCreationException('Attribute definition already exists', 409);
2631
}
32+
$this->attributeTypeValidator->validate($attributeDefinitionDto->type);
2733

2834
$attributeDefinition = (new SubscriberAttributeDefinition())
2935
->setName($attributeDefinitionDto->name)
@@ -46,6 +52,7 @@ public function update(
4652
if ($existingAttribute && $existingAttribute->getId() !== $attributeDefinition->getId()) {
4753
throw new AttributeDefinitionCreationException('Another attribute with this name already exists.', 409);
4854
}
55+
$this->attributeTypeValidator->validate($attributeDefinitionDto->type);
4956

5057
$attributeDefinition
5158
->setName($attributeDefinitionDto->name)
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpList\Core\Domain\Subscription\Validator;
6+
7+
use InvalidArgumentException;
8+
use PhpList\Core\Domain\Common\Model\ValidationContext;
9+
use PhpList\Core\Domain\Common\Validator\ValidatorInterface;
10+
use Symfony\Component\Validator\Exception\ValidatorException;
11+
12+
class AttributeTypeValidator implements ValidatorInterface
13+
{
14+
private const VALID_TYPES = [
15+
'textline',
16+
'checkbox',
17+
'checkboxgroup',
18+
'radio',
19+
'select',
20+
'hidden',
21+
'textarea',
22+
'date',
23+
];
24+
25+
public function validate(mixed $value, ValidationContext $context = null): void
26+
{
27+
if (!is_string($value)) {
28+
throw new InvalidArgumentException('Value must be a string.');
29+
}
30+
31+
$errors = [];
32+
if (!in_array($value, self::VALID_TYPES, true)) {
33+
$errors[] = sprintf(
34+
'Invalid attribute type: "%s". Valid types are: %s',
35+
$value,
36+
implode(', ', self::VALID_TYPES)
37+
);
38+
}
39+
40+
if (!empty($errors)) {
41+
throw new ValidatorException(implode("\n", $errors));
42+
}
43+
}
44+
}

tests/Unit/Domain/Identity/Service/AdminAttributeDefinitionManagerTest.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use PhpList\Core\Domain\Identity\Repository\AdminAttributeDefinitionRepository;
1010
use PhpList\Core\Domain\Identity\Service\AdminAttributeDefinitionManager;
1111
use PhpList\Core\Domain\Identity\Exception\AttributeDefinitionCreationException;
12+
use PhpList\Core\Domain\Subscription\Validator\AttributeTypeValidator;
1213
use PHPUnit\Framework\MockObject\MockObject;
1314
use PHPUnit\Framework\TestCase;
1415

@@ -20,7 +21,8 @@ class AdminAttributeDefinitionManagerTest extends TestCase
2021
protected function setUp(): void
2122
{
2223
$this->repository = $this->createMock(AdminAttributeDefinitionRepository::class);
23-
$this->subject = new AdminAttributeDefinitionManager($this->repository);
24+
$attributeTypeValidator = $this->createMock(AttributeTypeValidator::class);
25+
$this->subject = new AdminAttributeDefinitionManager($this->repository, $attributeTypeValidator);
2426
}
2527

2628
public function testCreateCreatesNewAttributeDefinition(): void

tests/Unit/Domain/Subscription/Service/AttributeDefinitionManagerTest.php

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,16 @@
99
use PhpList\Core\Domain\Subscription\Model\SubscriberAttributeDefinition;
1010
use PhpList\Core\Domain\Subscription\Repository\SubscriberAttributeDefinitionRepository;
1111
use PhpList\Core\Domain\Subscription\Service\Manager\AttributeDefinitionManager;
12+
use PhpList\Core\Domain\Subscription\Validator\AttributeTypeValidator;
1213
use PHPUnit\Framework\TestCase;
1314

1415
class AttributeDefinitionManagerTest extends TestCase
1516
{
1617
public function testCreateAttributeDefinition(): void
1718
{
1819
$repository = $this->createMock(SubscriberAttributeDefinitionRepository::class);
19-
$manager = new AttributeDefinitionManager($repository);
20+
$validator = $this->createMock(AttributeTypeValidator::class);
21+
$manager = new AttributeDefinitionManager($repository, $validator);
2022

2123
$dto = new AttributeDefinitionDto(
2224
name: 'Country',
@@ -48,7 +50,8 @@ public function testCreateAttributeDefinition(): void
4850
public function testCreateThrowsWhenAttributeAlreadyExists(): void
4951
{
5052
$repository = $this->createMock(SubscriberAttributeDefinitionRepository::class);
51-
$manager = new AttributeDefinitionManager($repository);
53+
$validator = $this->createMock(AttributeTypeValidator::class);
54+
$manager = new AttributeDefinitionManager($repository, $validator);
5255

5356
$dto = new AttributeDefinitionDto(
5457
name: 'Country',
@@ -74,7 +77,8 @@ public function testCreateThrowsWhenAttributeAlreadyExists(): void
7477
public function testUpdateAttributeDefinition(): void
7578
{
7679
$repository = $this->createMock(SubscriberAttributeDefinitionRepository::class);
77-
$manager = new AttributeDefinitionManager($repository);
80+
$validator = $this->createMock(AttributeTypeValidator::class);
81+
$manager = new AttributeDefinitionManager($repository, $validator);
7882

7983
$attribute = new SubscriberAttributeDefinition();
8084
$attribute->setName('Old');
@@ -108,7 +112,8 @@ public function testUpdateAttributeDefinition(): void
108112
public function testUpdateThrowsWhenAnotherAttributeWithSameNameExists(): void
109113
{
110114
$repository = $this->createMock(SubscriberAttributeDefinitionRepository::class);
111-
$manager = new AttributeDefinitionManager($repository);
115+
$validator = $this->createMock(AttributeTypeValidator::class);
116+
$manager = new AttributeDefinitionManager($repository, $validator);
112117

113118
$dto = new AttributeDefinitionDto(
114119
name: 'Existing',
@@ -138,7 +143,8 @@ public function testUpdateThrowsWhenAnotherAttributeWithSameNameExists(): void
138143
public function testDeleteAttributeDefinition(): void
139144
{
140145
$repository = $this->createMock(SubscriberAttributeDefinitionRepository::class);
141-
$manager = new AttributeDefinitionManager($repository);
146+
$validator = $this->createMock(AttributeTypeValidator::class);
147+
$manager = new AttributeDefinitionManager($repository, $validator);
142148

143149
$attribute = new SubscriberAttributeDefinition();
144150

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpList\Core\Tests\Unit\Domain\Subscription\Validator;
6+
7+
use InvalidArgumentException;
8+
use PhpList\Core\Domain\Subscription\Validator\AttributeTypeValidator;
9+
use PHPUnit\Framework\TestCase;
10+
use Symfony\Component\Validator\Exception\ValidatorException;
11+
12+
class AttributeTypeValidatorTest extends TestCase
13+
{
14+
private AttributeTypeValidator $validator;
15+
16+
protected function setUp(): void
17+
{
18+
$this->validator = new AttributeTypeValidator();
19+
}
20+
21+
public function testValidatesValidType(): void
22+
{
23+
$this->validator->validate('textline');
24+
$this->validator->validate('checkbox');
25+
$this->validator->validate('date');
26+
27+
$this->assertTrue(true);
28+
}
29+
30+
public function testThrowsExceptionForInvalidType(): void
31+
{
32+
$this->expectException(ValidatorException::class);
33+
$this->expectExceptionMessage('Invalid attribute type: "invalid_type"');
34+
35+
$this->validator->validate('invalid_type');
36+
}
37+
38+
public function testThrowsExceptionForNonStringValue(): void
39+
{
40+
$this->expectException(InvalidArgumentException::class);
41+
$this->expectExceptionMessage('Value must be a string.');
42+
43+
$this->validator->validate(123);
44+
}
45+
}

0 commit comments

Comments
 (0)