|
10 | 10 | use ReflectionClass; |
11 | 11 | use ReflectionMethod; |
12 | 12 | use ReflectionNamedType; |
| 13 | +use ReflectionParameter; |
13 | 14 | use ReflectionUnionType; |
14 | | -use RuntimeException; |
| 15 | +use ComplexHeart\Domain\Model\Exceptions\InstantiationException; |
15 | 16 | use TypeError; |
16 | 17 |
|
17 | 18 | /** |
@@ -51,7 +52,7 @@ final public static function make(mixed ...$params): static |
51 | 52 | $constructor = $reflection->getConstructor(); |
52 | 53 |
|
53 | 54 | if (!$constructor) { |
54 | | - throw new RuntimeException( |
| 55 | + throw new InstantiationException( |
55 | 56 | sprintf('%s must have a constructor to use make()', static::class) |
56 | 57 | ); |
57 | 58 | } |
@@ -121,46 +122,54 @@ private static function validateConstructorParameters( |
121 | 122 |
|
122 | 123 | // Validate types for each parameter |
123 | 124 | foreach ($constructorParams as $index => $param) { |
124 | | - if (!isset($params[$index])) { |
125 | | - continue; // Optional parameter not provided |
| 125 | + if (isset($params[$index])) { |
| 126 | + self::validateParameterType($param, $params[$index]); |
126 | 127 | } |
| 128 | + } |
| 129 | + } |
127 | 130 |
|
128 | | - $value = $params[$index]; |
129 | | - $type = $param->getType(); |
130 | 131 |
|
131 | | - if ($type === null) { |
132 | | - continue; // No type hint |
133 | | - } |
| 132 | + /** |
| 133 | + * Validate a single parameter's type. |
| 134 | + * |
| 135 | + * @param ReflectionParameter $param |
| 136 | + * @param mixed $value |
| 137 | + * @return void |
| 138 | + * @throws TypeError |
| 139 | + */ |
| 140 | + private static function validateParameterType(ReflectionParameter $param, mixed $value): void |
| 141 | + { |
| 142 | + $type = $param->getType(); |
134 | 143 |
|
135 | | - $isValid = false; |
136 | | - $expectedTypes = ''; |
137 | | - |
138 | | - if ($type instanceof ReflectionNamedType) { |
139 | | - // Single type |
140 | | - $isValid = self::validateType($value, $type->getName(), $type->allowsNull()); |
141 | | - $expectedTypes = $type->getName(); |
142 | | - } elseif ($type instanceof ReflectionUnionType) { |
143 | | - // Union type (e.g., int|float|string) |
144 | | - $isValid = self::validateUnionType($value, $type); |
145 | | - $expectedTypes = implode('|', array_map( |
146 | | - fn ($t) => $t instanceof ReflectionNamedType ? $t->getName() : 'mixed', |
147 | | - $type->getTypes() |
148 | | - )); |
149 | | - } else { |
150 | | - continue; // Intersection types or other complex types not supported yet |
151 | | - } |
| 144 | + if ($type === null) { |
| 145 | + return; // No type hint |
| 146 | + } |
152 | 147 |
|
153 | | - if (!$isValid) { |
154 | | - throw new TypeError( |
155 | | - sprintf( |
156 | | - '%s::make() parameter "%s" must be of type %s, %s given', |
157 | | - basename(str_replace('\\', '/', static::class)), |
158 | | - $param->getName(), |
159 | | - $expectedTypes, |
160 | | - get_debug_type($value) |
161 | | - ) |
162 | | - ); |
163 | | - } |
| 148 | + if ($type instanceof ReflectionNamedType) { |
| 149 | + // Single type |
| 150 | + $isValid = self::validateType($value, $type->getName(), $type->allowsNull()); |
| 151 | + $expectedTypes = $type->getName(); |
| 152 | + } elseif ($type instanceof ReflectionUnionType) { |
| 153 | + // Union type (e.g., int|float|string) |
| 154 | + $isValid = self::validateUnionType($value, $type); |
| 155 | + $expectedTypes = implode('|', array_map( |
| 156 | + fn ($t) => $t instanceof ReflectionNamedType ? $t->getName() : 'mixed', |
| 157 | + $type->getTypes() |
| 158 | + )); |
| 159 | + } else { |
| 160 | + return; // Intersection types or other complex types not supported yet |
| 161 | + } |
| 162 | + |
| 163 | + if (!$isValid) { |
| 164 | + throw new TypeError( |
| 165 | + sprintf( |
| 166 | + '%s::make() parameter "%s" must be of type %s, %s given', |
| 167 | + basename(str_replace('\\', '/', static::class)), |
| 168 | + $param->getName(), |
| 169 | + $expectedTypes, |
| 170 | + get_debug_type($value) |
| 171 | + ) |
| 172 | + ); |
164 | 173 | } |
165 | 174 | } |
166 | 175 |
|
|
0 commit comments