Parse and validate AT Protocol Lexicons with DTO generation for Laravel
1<?php
2
3namespace SocialDept\AtpSchema\Data\Types;
4
5use SocialDept\AtpSchema\Data\TypeDefinition;
6use SocialDept\AtpSchema\Exceptions\RecordValidationException;
7
8class IntegerType extends TypeDefinition
9{
10 /**
11 * Minimum value.
12 */
13 public readonly ?int $minimum;
14
15 /**
16 * Maximum value.
17 */
18 public readonly ?int $maximum;
19
20 /**
21 * Allowed enum values.
22 *
23 * @var array<int>|null
24 */
25 public readonly ?array $enum;
26
27 /**
28 * Constant value.
29 */
30 public readonly ?int $const;
31
32 /**
33 * Create a new IntegerType.
34 *
35 * @param array<int>|null $enum
36 */
37 public function __construct(
38 ?string $description = null,
39 ?int $minimum = null,
40 ?int $maximum = null,
41 ?array $enum = null,
42 ?int $const = null
43 ) {
44 parent::__construct('integer', $description);
45
46 $this->minimum = $minimum;
47 $this->maximum = $maximum;
48 $this->enum = $enum;
49 $this->const = $const;
50 }
51
52 /**
53 * Create from array data.
54 */
55 public static function fromArray(array $data): self
56 {
57 return new self(
58 description: $data['description'] ?? null,
59 minimum: $data['minimum'] ?? null,
60 maximum: $data['maximum'] ?? null,
61 enum: $data['enum'] ?? null,
62 const: $data['const'] ?? null
63 );
64 }
65
66 /**
67 * Convert to array.
68 */
69 public function toArray(): array
70 {
71 $array = ['type' => $this->type];
72
73 if ($this->description !== null) {
74 $array['description'] = $this->description;
75 }
76
77 if ($this->minimum !== null) {
78 $array['minimum'] = $this->minimum;
79 }
80
81 if ($this->maximum !== null) {
82 $array['maximum'] = $this->maximum;
83 }
84
85 if ($this->enum !== null) {
86 $array['enum'] = $this->enum;
87 }
88
89 if ($this->const !== null) {
90 $array['const'] = $this->const;
91 }
92
93 return $array;
94 }
95
96 /**
97 * Validate a value against this type definition.
98 */
99 public function validate(mixed $value, string $path = ''): void
100 {
101 if (! is_int($value)) {
102 throw RecordValidationException::invalidType($path, 'integer', gettype($value));
103 }
104
105 // Const validation
106 if ($this->const !== null && $value !== $this->const) {
107 throw RecordValidationException::invalidValue($path, "must equal {$this->const}");
108 }
109
110 // Enum validation
111 if ($this->enum !== null && ! in_array($value, $this->enum, true)) {
112 throw RecordValidationException::invalidValue($path, 'must be one of: '.implode(', ', $this->enum));
113 }
114
115 // Range validation
116 if ($this->minimum !== null && $value < $this->minimum) {
117 throw RecordValidationException::invalidValue($path, "must be at least {$this->minimum}");
118 }
119
120 if ($this->maximum !== null && $value > $this->maximum) {
121 throw RecordValidationException::invalidValue($path, "must be at most {$this->maximum}");
122 }
123 }
124}