|
5 | 5 | namespace PhpMcp\Server\Elements; |
6 | 6 |
|
7 | 7 | use InvalidArgumentException; |
| 8 | +use JsonSerializable; |
8 | 9 | use PhpMcp\Server\Exception\McpServerException; |
9 | 10 | use Psr\Container\ContainerInterface; |
10 | 11 | use ReflectionException; |
|
14 | 15 | use Throwable; |
15 | 16 | use TypeError; |
16 | 17 |
|
17 | | -class RegisteredElement |
| 18 | +class RegisteredElement implements JsonSerializable |
18 | 19 | { |
19 | 20 | public function __construct( |
20 | 21 | public readonly string $handlerClass, |
@@ -95,16 +96,35 @@ private function castArgumentType(mixed $argument, ReflectionParameter $paramete |
95 | 96 |
|
96 | 97 | $typeName = $type->getName(); |
97 | 98 |
|
98 | | - if (enum_exists($typeName) && is_subclass_of($typeName, \BackedEnum::class)) { |
99 | | - try { |
100 | | - return $typeName::from($argument); |
101 | | - } catch (\ValueError $e) { |
102 | | - $valueStr = is_scalar($argument) ? strval($argument) : gettype($argument); |
103 | | - throw new InvalidArgumentException( |
104 | | - "Invalid value '{$valueStr}' for enum {$typeName}.", |
105 | | - 0, |
106 | | - $e |
107 | | - ); |
| 99 | + if (enum_exists($typeName)) { |
| 100 | + if (is_object($argument) && $argument instanceof $typeName) { |
| 101 | + return $argument; |
| 102 | + } |
| 103 | + |
| 104 | + if (is_subclass_of($typeName, \BackedEnum::class)) { |
| 105 | + $value = $typeName::tryFrom($argument); |
| 106 | + if ($value === null) { |
| 107 | + throw new InvalidArgumentException( |
| 108 | + "Invalid value '{$argument}' for backed enum {$typeName}. Expected one of its backing values.", |
| 109 | + ); |
| 110 | + } |
| 111 | + return $value; |
| 112 | + } else { |
| 113 | + if (is_string($argument)) { |
| 114 | + foreach ($typeName::cases() as $case) { |
| 115 | + if ($case->name === $argument) { |
| 116 | + return $case; |
| 117 | + } |
| 118 | + } |
| 119 | + $validNames = array_map(fn($c) => $c->name, $typeName::cases()); |
| 120 | + throw new InvalidArgumentException( |
| 121 | + "Invalid value '{$argument}' for unit enum {$typeName}. Expected one of: " . implode(', ', $validNames) . "." |
| 122 | + ); |
| 123 | + } else { |
| 124 | + throw new InvalidArgumentException( |
| 125 | + "Invalid value type '{$argument}' for unit enum {$typeName}. Expected a string matching a case name." |
| 126 | + ); |
| 127 | + } |
108 | 128 | } |
109 | 129 | } |
110 | 130 |
|
@@ -179,4 +199,18 @@ private function castToArray(mixed $argument): array |
179 | 199 | } |
180 | 200 | throw new InvalidArgumentException('Cannot cast value to array. Expected array.'); |
181 | 201 | } |
| 202 | + |
| 203 | + public function toArray(): array |
| 204 | + { |
| 205 | + return [ |
| 206 | + 'handlerClass' => $this->handlerClass, |
| 207 | + 'handlerMethod' => $this->handlerMethod, |
| 208 | + 'isManual' => $this->isManual, |
| 209 | + ]; |
| 210 | + } |
| 211 | + |
| 212 | + public function jsonSerialize(): array |
| 213 | + { |
| 214 | + return $this->toArray(); |
| 215 | + } |
182 | 216 | } |
0 commit comments