Skip to content

Commit e0f8101

Browse files
rasstislavf3l1x
authored andcommitted
feat: added support for enum values in request parameter
1 parent e3c4087 commit e0f8101

File tree

14 files changed

+70
-4
lines changed

14 files changed

+70
-4
lines changed

.docs/mapping.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ class UsersController extends BaseV1Controller
6666
- `required=true|false` - required by default, but you could make parameter optional
6767
- `deprecated=true|false` - used in [openapi](schema.md#openapi) schema
6868
- `allowEmpty=true|false` - make parameter nullable
69+
- `enum={"only", "these", "values"}` - allowable values
6970

7071
### Data types
7172

@@ -105,6 +106,7 @@ api:
105106
float: Apitte\Core\Mapping\Parameter\FloatTypeMapper
106107
bool: Apitte\Core\Mapping\Parameter\BooleanTypeMapper
107108
datetime: Apitte\Core\Mapping\Parameter\DateTimeTypeMapper
109+
enum: Apitte\Core\Mapping\Parameter\EnumTypeMapper
108110
```
109111
110112
### Custom datatypes

src/Core/Annotation/Controller/RequestParameter.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,17 @@ class RequestParameter
3131

3232
private bool $allowEmpty;
3333

34+
private ?array $enum;
35+
3436
public function __construct(
3537
string $name,
3638
string $type,
3739
string $in = EndpointParameter::IN_PATH,
3840
bool $required = true,
3941
bool $allowEmpty = false,
4042
bool $deprecated = false,
41-
?string $description = null
43+
?string $description = null,
44+
?array $enum = null
4245
)
4346
{
4447
if ($name === '') {
@@ -60,6 +63,7 @@ public function __construct(
6063
$this->deprecated = $deprecated;
6164
$this->description = $description;
6265
$this->in = $in;
66+
$this->enum = $enum;
6367
}
6468

6569
public function getName(): string
@@ -97,4 +101,9 @@ public function isAllowEmpty(): bool
97101
return $this->allowEmpty;
98102
}
99103

104+
public function getEnum(): ?array
105+
{
106+
return $this->enum;
107+
}
108+
100109
}

src/Core/DI/Loader/DoctrineAnnotationLoader.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,7 @@ private function addEndpointParameterToSchemaMethod(SchemaMethod $schemaMethod,
317317
$endpointParameter->setRequired($requestParameter->isRequired());
318318
$endpointParameter->setDeprecated($requestParameter->isDeprecated());
319319
$endpointParameter->setAllowEmpty($requestParameter->isAllowEmpty());
320+
$endpointParameter->setEnum($requestParameter->getEnum());
320321
}
321322

322323
private function addNegotiationToSchemaMethod(SchemaMethod $schemaMethod, Negotiation $negotiation): void

src/Core/DI/Loader/NeonLoader.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ private function setEndpointParameters(Method $method, array $parametersSettings
6969
$parameter->setRequired($settings['required'] ?? true);
7070
$parameter->setAllowEmpty($settings['allowEmpty'] ?? false);
7171
$parameter->setDeprecated($settings['deprecated'] ?? false);
72+
$parameter->setEnum($settings['enum'] ?? null);
7273
}
7374
}
7475

src/Core/DI/Plugin/CoreMappingPlugin.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Apitte\Core\DI\ApiExtension;
88
use Apitte\Core\Mapping\Parameter\BooleanTypeMapper;
99
use Apitte\Core\Mapping\Parameter\DateTimeTypeMapper;
10+
use Apitte\Core\Mapping\Parameter\EnumTypeMapper;
1011
use Apitte\Core\Mapping\Parameter\FloatTypeMapper;
1112
use Apitte\Core\Mapping\Parameter\IntegerTypeMapper;
1213
use Apitte\Core\Mapping\Parameter\StringTypeMapper;
@@ -33,6 +34,7 @@ class CoreMappingPlugin extends Plugin
3334
'float' => FloatTypeMapper::class,
3435
'bool' => BooleanTypeMapper::class,
3536
'datetime' => DateTimeTypeMapper::class,
37+
'enum' => EnumTypeMapper::class,
3638
];
3739

3840
public static function getName(): string

src/Core/Exception/Runtime/InvalidArgumentTypeException.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ class InvalidArgumentTypeException extends RuntimeException
1111
public const TYPE_FLOAT = 'float';
1212
public const TYPE_BOOLEAN = 'bool';
1313
public const TYPE_DATETIME = 'datetime';
14+
public const TYPE_ENUM = 'enum';
1415

1516
private string $type;
1617

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace Apitte\Core\Mapping\Parameter;
4+
5+
use Apitte\Core\Exception\Runtime\InvalidArgumentTypeException;
6+
7+
class EnumTypeMapper implements ITypeMapper
8+
{
9+
10+
public function normalize(mixed $value, ?array $enumValues = null): string
11+
{
12+
if (!in_array($value, $enumValues)) {
13+
throw new InvalidArgumentTypeException(InvalidArgumentTypeException::TYPE_ENUM);
14+
}
15+
16+
return $value;
17+
}
18+
19+
}

src/Core/Mapping/Parameter/ITypeMapper.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@ interface ITypeMapper
1010
/**
1111
* @throws InvalidArgumentTypeException
1212
*/
13-
public function normalize(mixed $value): mixed;
13+
public function normalize(mixed $value/*, ?array $enumValues = null*/): mixed;
1414

1515
}

src/Core/Mapping/RequestParameterMapping.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ class RequestParameterMapping
2222
InvalidArgumentTypeException::TYPE_FLOAT => '%s request parameter "%s" should be of type float or integer.',
2323
InvalidArgumentTypeException::TYPE_BOOLEAN => '%s request parameter "%s" should be of type boolean. Pass "true" for true or "false" for false.',
2424
InvalidArgumentTypeException::TYPE_DATETIME => '%s request parameter "%s" should be of type datetime in format ISO 8601 (Y-m-d\TH:i:sP).',
25+
InvalidArgumentTypeException::TYPE_ENUM => '%s request parameter "%s" is not in the allowed values `[%s]`.',
2526
];
2627

2728
protected static string $customException = '%s request parameter "%s" should be of type %s.%s';
@@ -210,13 +211,14 @@ protected function normalize(mixed $value, EndpointParameter $parameter, ITypeMa
210211
}
211212

212213
try {
213-
return $mapper->normalize($value);
214+
return $mapper->normalize($value, $parameter->getEnum());
214215
} catch (InvalidArgumentTypeException $e) {
215216
if (array_key_exists($e->getType(), self::$exceptions)) {
216217
throw new ClientErrorException(sprintf(
217218
self::$exceptions[$e->getType()],
218219
ucfirst($parameter->getIn()),
219-
$parameter->getName()
220+
$parameter->getName(),
221+
$parameter->getEnum() ? implode(', ', $parameter->getEnum()) : ''
220222
));
221223
} else {
222224
throw new ClientErrorException(sprintf(

src/Core/Schema/EndpointParameter.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,15 @@ class EndpointParameter
1010
public const TYPE_FLOAT = 'float';
1111
public const TYPE_BOOLEAN = 'bool';
1212
public const TYPE_DATETIME = 'datetime';
13+
public const TYPE_ENUM = 'enum';
1314

1415
public const TYPES = [
1516
self::TYPE_STRING,
1617
self::TYPE_INTEGER,
1718
self::TYPE_FLOAT,
1819
self::TYPE_BOOLEAN,
1920
self::TYPE_DATETIME,
21+
self::TYPE_ENUM,
2022
];
2123

2224
public const IN_QUERY = 'query';
@@ -45,6 +47,8 @@ class EndpointParameter
4547

4648
private bool $allowEmpty = false;
4749

50+
private ?array $enum = null;
51+
4852
public function __construct(string $name, string $type = self::TYPE_STRING)
4953
{
5054
$this->name = $name;
@@ -72,6 +76,8 @@ public function getSchemaType(): string
7276
return 'boolean';
7377
case self::TYPE_INTEGER:
7478
return 'integer';
79+
case self::TYPE_ENUM:
80+
return 'string';
7581
default:
7682
// custom type
7783
return 'string';
@@ -128,4 +134,14 @@ public function setAllowEmpty(bool $allowEmpty): void
128134
$this->allowEmpty = $allowEmpty;
129135
}
130136

137+
public function getEnum(): ?array
138+
{
139+
return $this->enum;
140+
}
141+
142+
public function setEnum(?array $enum): void
143+
{
144+
$this->enum = $enum;
145+
}
146+
131147
}

0 commit comments

Comments
 (0)