From 70afc5ce3b6424119d09d1c862caa9623bc2e122 Mon Sep 17 00:00:00 2001 From: dcb6 Date: Fri, 13 Sep 2024 11:48:07 -0400 Subject: [PATCH 01/19] working before small change --- .../serde-demo/.github/workflows/ci.yml | 46 +++ seed/php-sdk/serde-demo/.gitignore | 4 + .../serde-demo/.mock/definition/api.yml | 4 + .../serde-demo/.mock/definition/imdb.yml | 42 +++ .../php-sdk/serde-demo/.mock/fern.config.json | 1 + seed/php-sdk/serde-demo/.mock/generators.yml | 1 + seed/php-sdk/serde-demo/composer.json | 40 +++ seed/php-sdk/serde-demo/phpstan.neon | 5 + seed/php-sdk/serde-demo/phpunit.xml | 7 + .../php-sdk/serde-demo/snippet-templates.json | 0 seed/php-sdk/serde-demo/snippet.json | 0 .../php-sdk/serde-demo/src/Core/ArrayType.php | 14 + .../serde-demo/src/Core/BaseApiRequest.php | 22 ++ seed/php-sdk/serde-demo/src/Core/DateType.php | 14 + .../serde-demo/src/Core/HttpMethod.php | 12 + .../serde-demo/src/Core/JsonApiRequest.php | 25 ++ .../serde-demo/src/Core/JsonProperty.php | 12 + .../php-sdk/serde-demo/src/Core/RawClient.php | 123 +++++++ .../src/Placeholder/Placeholder.php | 11 + .../src/Types/ExampleNestedType.php | 42 +++ .../serde-demo/src/Types/ExampleType.php | 329 ++++++++++++++++++ .../serde-demo/src/Types/WeatherReport.php | 8 + .../tests/Seed/Core/RawClientTest.php | 101 ++++++ .../tests/Seed/Types/ExampleTypeTest.php | 68 ++++ 24 files changed, 931 insertions(+) create mode 100644 seed/php-sdk/serde-demo/.github/workflows/ci.yml create mode 100644 seed/php-sdk/serde-demo/.gitignore create mode 100644 seed/php-sdk/serde-demo/.mock/definition/api.yml create mode 100644 seed/php-sdk/serde-demo/.mock/definition/imdb.yml create mode 100644 seed/php-sdk/serde-demo/.mock/fern.config.json create mode 100644 seed/php-sdk/serde-demo/.mock/generators.yml create mode 100644 seed/php-sdk/serde-demo/composer.json create mode 100644 seed/php-sdk/serde-demo/phpstan.neon create mode 100644 seed/php-sdk/serde-demo/phpunit.xml create mode 100644 seed/php-sdk/serde-demo/snippet-templates.json create mode 100644 seed/php-sdk/serde-demo/snippet.json create mode 100644 seed/php-sdk/serde-demo/src/Core/ArrayType.php create mode 100644 seed/php-sdk/serde-demo/src/Core/BaseApiRequest.php create mode 100644 seed/php-sdk/serde-demo/src/Core/DateType.php create mode 100644 seed/php-sdk/serde-demo/src/Core/HttpMethod.php create mode 100644 seed/php-sdk/serde-demo/src/Core/JsonApiRequest.php create mode 100644 seed/php-sdk/serde-demo/src/Core/JsonProperty.php create mode 100644 seed/php-sdk/serde-demo/src/Core/RawClient.php create mode 100644 seed/php-sdk/serde-demo/src/Placeholder/Placeholder.php create mode 100644 seed/php-sdk/serde-demo/src/Types/ExampleNestedType.php create mode 100644 seed/php-sdk/serde-demo/src/Types/ExampleType.php create mode 100644 seed/php-sdk/serde-demo/src/Types/WeatherReport.php create mode 100644 seed/php-sdk/serde-demo/tests/Seed/Core/RawClientTest.php create mode 100644 seed/php-sdk/serde-demo/tests/Seed/Types/ExampleTypeTest.php diff --git a/seed/php-sdk/serde-demo/.github/workflows/ci.yml b/seed/php-sdk/serde-demo/.github/workflows/ci.yml new file mode 100644 index 00000000000..4b99e5562ee --- /dev/null +++ b/seed/php-sdk/serde-demo/.github/workflows/ci.yml @@ -0,0 +1,46 @@ +name: ci + +on: [push] + +jobs: + compile: + runs-on: ubuntu-latest + + steps: + - name: Checkout repo + uses: actions/checkout@v4 + + - name: Setup Composer + uses: php-actions/composer@v6 + with: + php_version: "8.1" + version: "2.7.9" + + - name: Install tools + run: | + composer install + + - name: Build + run: | + composer build + + unit-tests: + runs-on: ubuntu-latest + + steps: + - name: Checkout repo + uses: actions/checkout@v4 + + - name: Setup Composer + uses: php-actions/composer@v6 + with: + php_version: "8.1" + version: "2.7.9" + + - name: Install tools + run: | + composer install + + - name: Run Tests + run: | + composer test \ No newline at end of file diff --git a/seed/php-sdk/serde-demo/.gitignore b/seed/php-sdk/serde-demo/.gitignore new file mode 100644 index 00000000000..f38efc46ade --- /dev/null +++ b/seed/php-sdk/serde-demo/.gitignore @@ -0,0 +1,4 @@ +.php-cs-fixer.cache +.phpunit.result.cache +composer.lock +vendor/ \ No newline at end of file diff --git a/seed/php-sdk/serde-demo/.mock/definition/api.yml b/seed/php-sdk/serde-demo/.mock/definition/api.yml new file mode 100644 index 00000000000..c437dc0ab29 --- /dev/null +++ b/seed/php-sdk/serde-demo/.mock/definition/api.yml @@ -0,0 +1,4 @@ +name: api +error-discrimination: + strategy: status-code +auth: bearer diff --git a/seed/php-sdk/serde-demo/.mock/definition/imdb.yml b/seed/php-sdk/serde-demo/.mock/definition/imdb.yml new file mode 100644 index 00000000000..7919173fe57 --- /dev/null +++ b/seed/php-sdk/serde-demo/.mock/definition/imdb.yml @@ -0,0 +1,42 @@ +types: + MovieId: string + + Movie: + properties: + id: MovieId + title: string + rating: + type: double + docs: The rating scale is one to five stars + + CreateMovieRequest: + properties: + title: string + rating: double + +service: + auth: false + base-path: /movies + endpoints: + createMovie: + docs: Add a movie to the database + method: POST + path: /create-movie + request: CreateMovieRequest + response: + type: MovieId + status-code: 201 + + getMovie: + method: GET + path: /{movieId} + path-parameters: + movieId: MovieId + response: Movie + errors: + - MovieDoesNotExistError + +errors: + MovieDoesNotExistError: + status-code: 404 + type: MovieId diff --git a/seed/php-sdk/serde-demo/.mock/fern.config.json b/seed/php-sdk/serde-demo/.mock/fern.config.json new file mode 100644 index 00000000000..4c8e54ac313 --- /dev/null +++ b/seed/php-sdk/serde-demo/.mock/fern.config.json @@ -0,0 +1 @@ +{"organization": "fern-test", "version": "*"} \ No newline at end of file diff --git a/seed/php-sdk/serde-demo/.mock/generators.yml b/seed/php-sdk/serde-demo/.mock/generators.yml new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/seed/php-sdk/serde-demo/.mock/generators.yml @@ -0,0 +1 @@ +{} diff --git a/seed/php-sdk/serde-demo/composer.json b/seed/php-sdk/serde-demo/composer.json new file mode 100644 index 00000000000..7f5821806d4 --- /dev/null +++ b/seed/php-sdk/serde-demo/composer.json @@ -0,0 +1,40 @@ + +{ + "name": "seed/seed", + "version": "0.0.1", + "description": "Seed PHP Library", + "keywords": [ + "seed", + "api", + "sdk" + ], + "license": [], + "require": { + "php": "^8.1", + "ext-json": "*", + "guzzlehttp/guzzle": "^7.9" + }, + "require-dev": { + "phpunit/phpunit": "^9.0", + "friendsofphp/php-cs-fixer": "3.5.0", + "phpstan/phpstan": "^1.12" + }, + "autoload": { + "psr-4": { + "Seed\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "\\Seed\\Tests\\": "tests/" + } + }, + "scripts": { + "build": [ + "@php -l src", + "@php -l tests" + ], + "test": "phpunit", + "analyze": "phpstan analyze src" + } +} diff --git a/seed/php-sdk/serde-demo/phpstan.neon b/seed/php-sdk/serde-demo/phpstan.neon new file mode 100644 index 00000000000..29a11a92a19 --- /dev/null +++ b/seed/php-sdk/serde-demo/phpstan.neon @@ -0,0 +1,5 @@ +parameters: + level: max + paths: + - src + - tests \ No newline at end of file diff --git a/seed/php-sdk/serde-demo/phpunit.xml b/seed/php-sdk/serde-demo/phpunit.xml new file mode 100644 index 00000000000..54630a51163 --- /dev/null +++ b/seed/php-sdk/serde-demo/phpunit.xml @@ -0,0 +1,7 @@ + + + + tests + + + \ No newline at end of file diff --git a/seed/php-sdk/serde-demo/snippet-templates.json b/seed/php-sdk/serde-demo/snippet-templates.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/php-sdk/serde-demo/snippet.json b/seed/php-sdk/serde-demo/snippet.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/php-sdk/serde-demo/src/Core/ArrayType.php b/seed/php-sdk/serde-demo/src/Core/ArrayType.php new file mode 100644 index 00000000000..ba358598a29 --- /dev/null +++ b/seed/php-sdk/serde-demo/src/Core/ArrayType.php @@ -0,0 +1,14 @@ + 'valueType'] for maps, or ['valueType'] for lists + */ + public function __construct(public array $type) {} +} diff --git a/seed/php-sdk/serde-demo/src/Core/BaseApiRequest.php b/seed/php-sdk/serde-demo/src/Core/BaseApiRequest.php new file mode 100644 index 00000000000..2ace034ec90 --- /dev/null +++ b/seed/php-sdk/serde-demo/src/Core/BaseApiRequest.php @@ -0,0 +1,22 @@ + $headers Additional headers for the request (optional) + * @param array $query Query parameters for the request (optional) + */ + public function __construct( + public readonly string $baseUrl, + public readonly string $path, + public readonly HttpMethod $method, + public readonly array $headers = [], + public readonly array $query = [], + ) { + } +} diff --git a/seed/php-sdk/serde-demo/src/Core/DateType.php b/seed/php-sdk/serde-demo/src/Core/DateType.php new file mode 100644 index 00000000000..97a6eb888ee --- /dev/null +++ b/seed/php-sdk/serde-demo/src/Core/DateType.php @@ -0,0 +1,14 @@ + $headers Additional headers for the request (optional) + * @param array $query Query parameters for the request (optional) + * @param mixed|null $body The JSON request body (optional) + */ + public function __construct( + string $baseUrl, + string $path, + HttpMethod $method, + array $headers = [], + array $query = [], + public readonly mixed $body = null + ) { + parent::__construct($baseUrl, $path, $method, $headers, $query); + } +} diff --git a/seed/php-sdk/serde-demo/src/Core/JsonProperty.php b/seed/php-sdk/serde-demo/src/Core/JsonProperty.php new file mode 100644 index 00000000000..b129573f765 --- /dev/null +++ b/seed/php-sdk/serde-demo/src/Core/JsonProperty.php @@ -0,0 +1,12 @@ + $headers The HTTP headers sent with the request. + */ + public function __construct( + private readonly ClientInterface $client, + private readonly array $headers = [], + ) { + } + + /** + * @throws ClientExceptionInterface + */ + public function sendRequest( + BaseApiRequest $request, + ): ResponseInterface { + $httpRequest = $this->buildRequest($request); + return $this->client->send($httpRequest); + } + + private function buildRequest( + BaseApiRequest $request + ): Request { + $url = $this->buildUrl($request); + $headers = $this->encodeHeaders($request); + $body = $this->encodeRequestBody($request); + return new Request( + $request->method->name, + $url, + $headers, + $body, + ); + } + + /** + * @return array + */ + private function encodeHeaders( + BaseApiRequest $request + ): array { + return match (get_class($request)) { + JsonApiRequest::class => array_merge( + ["Content-Type" => "application/json"], + $this->headers, + $request->headers + ), + default => throw new InvalidArgumentException('Unsupported request type: ' . get_class($request)), + }; + } + + private function encodeRequestBody( + BaseApiRequest $request + ): ?StreamInterface { + return match (get_class($request)) { + JsonApiRequest::class => $request->body != null ? Utils::streamFor(json_encode($request->body)) : null, + default => throw new InvalidArgumentException('Unsupported request type: '.get_class($request)), + }; + } + + private function buildUrl( + BaseApiRequest $request + ): string { + $baseUrl = $request->baseUrl; + $trimmedBaseUrl = rtrim($baseUrl, '/'); + $trimmedBasePath = ltrim($request->path, '/'); + $url = "{$trimmedBaseUrl}/{$trimmedBasePath}"; + + if (!empty($request->query)) { + $url .= '?' . $this->encodeQuery($request->query); + } + + return $url; + } + + /** + * @param array $query + */ + private function encodeQuery( + array $query + ): string { + $parts = []; + foreach ($query as $key => $value) { + if (is_array($value)) { + foreach ($value as $item) { + $parts[] = urlencode($key).'='.$this->encodeQueryValue($item); + } + } else { + $parts[] = urlencode($key).'='.$this->encodeQueryValue($value); + } + } + return implode('&', $parts); + } + + private function encodeQueryValue( + mixed $value + ): string { + if (is_string($value)) { + return urlencode($value); + } + if (is_scalar($value)) { + return urlencode((string)$value); + } + if (is_null($value)) { + return 'null'; + } + // Unreachable, but included for a best effort. + return urlencode(strval(json_encode($value))); + } +} diff --git a/seed/php-sdk/serde-demo/src/Placeholder/Placeholder.php b/seed/php-sdk/serde-demo/src/Placeholder/Placeholder.php new file mode 100644 index 00000000000..a0eb33a6b60 --- /dev/null +++ b/seed/php-sdk/serde-demo/src/Placeholder/Placeholder.php @@ -0,0 +1,11 @@ +id = $data['id']; + $instance->name = $data['name']; + + return $instance; + } + + /** + * Serializes the object to an array for JSON encoding. + * + * @return array + */ + public function toArray(): array + { + return [ + 'id' => $this->id, + 'name' => $this->name, + ]; + } +} diff --git a/seed/php-sdk/serde-demo/src/Types/ExampleType.php b/seed/php-sdk/serde-demo/src/Types/ExampleType.php new file mode 100644 index 00000000000..50ae3ea7fd7 --- /dev/null +++ b/seed/php-sdk/serde-demo/src/Types/ExampleType.php @@ -0,0 +1,329 @@ + 'int'])] + #[JsonProperty('string_int_map')] + public array $stringIntMap, + + #[ArrayType([['string']])] + #[JsonProperty('nested_string_list')] + public array $nestedStringList, + + #[ArrayType(['int' => ['int' => ExampleNestedType::class]])] + #[JsonProperty('nested_type_map')] + public array $nestedTypeMap, + + #[JsonProperty('optional_name')] + public ?string $optionalName = null + ) {} + + /** + * Deserializes an array (e.g. from json_decode) into an ExampleType object. + * + * @param array $data The array to deserialize. + * @return self + */ + public static function fromArray(array $data): self + { + $instance = new self(); + $reflectionClass = new ReflectionClass(self::class); + foreach ($reflectionClass->getProperties() as $property) { + $jsonKey = self::getJsonKey($property); + if (isset($data[$jsonKey])) { + $value = $data[$jsonKey]; + + // Handle DateType annotation + $dateTypeAttr = $property->getAttributes(DateType::class)[0] ?? null; + if ($dateTypeAttr) { + $dateType = $dateTypeAttr->newInstance()->type; + if ($dateType === DateType::TYPE_DATE) { + $value = DateTime::createFromFormat('Y-m-d', $value); + } else { + $value = new DateTime($value); + } + } + + // Handle ArrayType annotation + $arrayTypeAttr = $property->getAttributes(ArrayType::class)[0] ?? null; + if (is_array($value) && $arrayTypeAttr) { + $arrayType = $arrayTypeAttr->newInstance()->type; + $value = self::deserializeGenericArray($value, $arrayType); + } + + $property->setAccessible(true); + $property->setValue($instance, $value); + } + } + return $instance; + } + + /** + * Serializes the object to an array for JSON encoding. + * + * @return array + */ + public function toArray(): array + { + $result = []; + $reflectionClass = new ReflectionClass(self::class); + foreach ($reflectionClass->getProperties() as $property) { + $jsonKey = self::getJsonKey($property); + $value = $property->getValue($this); + + // Handle DateTime properties + $dateTypeAttr = $property->getAttributes(DateType::class)[0] ?? null; + if ($dateTypeAttr) { + $dateType = $dateTypeAttr->newInstance()->type; + if ($value instanceof DateTime) { + if ($dateType === DateType::TYPE_DATE) { + $value = $value->format('Y-m-d'); + } else { + $value = $value->format(DateTimeInterface::RFC3339); +// $value = $value->format(DateTimeInterface::RFC3339); + } + } + } + + // Handle arrays + $arrayTypeAttr = $property->getAttributes(ArrayType::class)[0] ?? null; + if ($arrayTypeAttr && is_array($value)) { + $arrayType = $arrayTypeAttr->newInstance()->type; + $value = self::serializeGenericArray($value, $arrayType); + } + + $result[$jsonKey] = $value; + } + return $result; + } + + /** + * Casts the key to the appropriate type based on the key type. + * Example: If the key type is 'int', the key will be cast to an integer. + * + * @param mixed $key The key to be cast. + * @param string $keyType The type to cast the key to ('string', 'int', 'float'). + * @return mixed The casted key. + */ + private static function castKey(mixed $key, string $keyType): mixed + { + if ($keyType === 'int') { + return (int)$key; + } elseif ($keyType === 'float') { + return (float)$key; + } elseif ($keyType === 'string') { + return (string)$key; + } + + return $key; + } + + /** + * Serializes the given array based on the type annotation. + * Distinguishes between lists (e.g., ['valueType']) and maps (e.g., ['keyType' => 'valueType']). + * + * @param array $data The array to be serialized. + * @param array $type The type definition from the annotation (e.g., ['string' => 'int']). + * @return array The serialized array. + */ + private static function serializeGenericArray(array $data, array $type): array + { + // If the type is a map (['keyType' => 'valueType']), use serializeMap. + if (self::isMapType($type)) { + return self::serializeMap($data, $type); + } + + // Otherwise, it's a list (['valueType']), so use serializeList. + return self::serializeList($data, $type); + } + + /** + * Serializes a map (associative array) where the key and value types are defined. + * Example: ['string' => 'int'] represents a map from string to int. + * + * @param array $data The associative array to serialize. + * @param array $type The type definition for the map. + * @return array The serialized map. + */ + private static function serializeMap(array $data, array $type): array + { + $keyType = array_key_first($type); // Extract key type, e.g., 'string' + $valueType = $type[$keyType]; // Extract value type, e.g., 'int' + + $result = []; + foreach ($data as $key => $item) { + // Cast the key to its proper type + $key = self::castKey($key, $keyType); + + // Recursively serialize the value based on its type + if (is_array($valueType)) { + $result[$key] = self::serializeGenericArray($item, $valueType); + } elseif (is_object($item) && method_exists($item, 'toArray')) { + $result[$key] = $item->toArray(); + } else { + $result[$key] = $item; + } + } + + return $result; + } + + /** + * Serializes a list (indexed array) where only the value type is defined. + * Example: ['valueType'] represents a list of items of type 'valueType'. + * + * @param array $data The list to serialize. + * @param array $type The type definition for the list. + * @return array The serialized list. + */ + private static function serializeList(array $data, array $type): array + { + $valueType = $type[0]; // Extract value type, e.g., 'string', 'int' + + return array_map(function ($item) use ($valueType) { + // Recursively serialize nested arrays or objects + if (is_array($valueType)) { + return self::serializeGenericArray($item, $valueType); + } elseif (is_object($item) && method_exists($item, 'toArray')) { + return $item->toArray(); + } else { + return $item; + } + }, $data); + } + + /** + * Deserializes the given array based on the type annotation. + * Distinguishes between lists (e.g., ['valueType']) and maps (e.g., ['keyType' => 'valueType']). + * + * @param array $data The array to be deserialized. + * @param array $type The type definition from the annotation (e.g., ['string' => 'int']). + * @return array The deserialized array. + */ + private static function deserializeGenericArray(array $data, array $type): array + { + // If the type is a map (['keyType' => 'valueType']), use deserializeMap. + if (self::isMapType($type)) { + return self::deserializeMap($data, $type); + } + + // Otherwise, it's a list (['valueType']), so use deserializeList. + return self::deserializeList($data, $type); + } + + /** + * Deserializes a map (associative array) where the key and value types are defined. + * Example: ['string' => 'int'] represents a map from string to int. + * + * @param array $data The associative array to deserialize. + * @param array $type The type definition for the map. + * @return array The deserialized map. + */ + private static function deserializeMap(array $data, array $type): array + { + $keyType = array_key_first($type); // Extract key type, e.g., 'string' + $valueType = $type[$keyType]; // Extract value type, e.g., 'int' + + $result = []; + foreach ($data as $key => $item) { + // Cast the key to its proper type + $key = self::castKey($key, $keyType); + + // Recursively deserialize the value based on its type + if (is_array($valueType)) { + $result[$key] = self::deserializeGenericArray($item, $valueType); + } elseif (class_exists($valueType)) { + // If the valueType is a class, instantiate it using fromArray + $result[$key] = $valueType::fromArray($item); + } else { + $result[$key] = $item; + } + } + + return $result; + } + + /** + * Deserializes a list (indexed array) where only the value type is defined. + * Example: ['valueType'] represents a list of items of type 'valueType'. + * + * @param array $data The list to deserialize. + * @param array $type The type definition for the list. + * @return array The deserialized list. + */ + private static function deserializeList(array $data, array $type): array + { + $valueType = $type[0]; // Extract value type, e.g., 'string', 'int' + + return array_map(function ($item) use ($valueType) { + // Recursively deserialize nested arrays or objects + if (is_array($valueType)) { + return self::deserializeGenericArray($item, $valueType); + } elseif (class_exists($valueType)) { + return $valueType::fromArray($item); + } else { + return $item; + } + }, $data); + } + + /** + * Determines if the given type represents a map. + * A map is represented as an associative array (e.g., ['keyType' => 'valueType']). + * + * @param array $type The type definition from the annotation. + * @return bool True if the type is a map, false if it's a list. + */ + private static function isMapType(array $type): bool + { + return count($type) === 1 && array_is_list($type) === false; + } + + /** + * Helper function to retrieve the JSON key for a property (uses JsonProperty if available). + * + * @param ReflectionProperty $property + * @return string + */ + private static function getJsonKey(ReflectionProperty $property): string + { + $jsonPropertyAttr = $property->getAttributes(JsonProperty::class)[0] ?? null; + return $jsonPropertyAttr ? $jsonPropertyAttr->newInstance()->name : $property->getName(); + } +} diff --git a/seed/php-sdk/serde-demo/src/Types/WeatherReport.php b/seed/php-sdk/serde-demo/src/Types/WeatherReport.php new file mode 100644 index 00000000000..f799308134b --- /dev/null +++ b/seed/php-sdk/serde-demo/src/Types/WeatherReport.php @@ -0,0 +1,8 @@ +mockHandler = new MockHandler(); + $handlerStack = HandlerStack::create($this->mockHandler); + $client = new Client(['handler' => $handlerStack]); + $this->rawClient = new RawClient($client); + } + + public function testHeaders(): void + { + $this->mockHandler->append(new Response(200)); + + $request = new JsonApiRequest( + $this->baseUrl, + '/test', + HttpMethod::GET, + ['X-Custom-Header' => 'TestValue'] + ); + + $this->sendRequest($request); + + $lastRequest = $this->mockHandler->getLastRequest(); + assert($lastRequest instanceof RequestInterface); + $this->assertEquals('application/json', $lastRequest->getHeaderLine('Content-Type')); + $this->assertEquals('TestValue', $lastRequest->getHeaderLine('X-Custom-Header')); + } + + public function testQueryParameters(): void + { + $this->mockHandler->append(new Response(200)); + + $request = new JsonApiRequest( + $this->baseUrl, + '/test', + HttpMethod::GET, + [], + ['param1' => 'value1', 'param2' => ['a', 'b'], 'param3' => 'true'] + ); + + $this->sendRequest($request); + + $lastRequest = $this->mockHandler->getLastRequest(); + assert($lastRequest instanceof RequestInterface); + $this->assertEquals( + 'https://api.example.com/test?param1=value1¶m2=a¶m2=b¶m3=true', + (string)$lastRequest->getUri() + ); + } + + public function testJsonBody(): void + { + $this->mockHandler->append(new Response(200)); + + $body = ['key' => 'value']; + $request = new JsonApiRequest( + $this->baseUrl, + '/test', + HttpMethod::POST, + [], + [], + $body + ); + + $this->sendRequest($request); + + $lastRequest = $this->mockHandler->getLastRequest(); + assert($lastRequest instanceof RequestInterface); + $this->assertEquals('application/json', $lastRequest->getHeaderLine('Content-Type')); + $this->assertEquals(json_encode($body), (string)$lastRequest->getBody()); + } + + private function sendRequest(BaseApiRequest $request): void + { + try { + $this->rawClient->sendRequest($request); + } catch (\Throwable $e) { + $this->fail('An exception was thrown: ' . $e->getMessage()); + } + } +} diff --git a/seed/php-sdk/serde-demo/tests/Seed/Types/ExampleTypeTest.php b/seed/php-sdk/serde-demo/tests/Seed/Types/ExampleTypeTest.php new file mode 100644 index 00000000000..b594a82788c --- /dev/null +++ b/seed/php-sdk/serde-demo/tests/Seed/Types/ExampleTypeTest.php @@ -0,0 +1,68 @@ + 'Test Example', + 'optional_name' => null, + 'age' => 30, + 'price' => 99.99, + 'is_active' => true, + 'start_date' => '2024-09-10', + 'created_at' => '2024-09-10T12:00:00+00:00', + 'string_list' => ['one', 'two', 'three'], + 'string_int_map' => ['key1' => 1, 'key2' => 2], + 'nested_string_list' => [['one', 'two'], ['three', 'four']], + 'nested_type_map' => [ + 1 => [ + 10 => ['id' => 10, 'name' => 'NestedType 10'], + 20 => ['id' => 20, 'name' => 'NestedType 20'] + ], + 2 => [ + 30 => ['id' => 30, 'name' => 'NestedType 30'], + 40 => ['id' => 40, 'name' => 'NestedType 40'] + ] + ] + ]; + + // Convert the original data into JSON + $json = json_encode($originalData); + + // Deserialize the JSON into an ExampleType object using fromArray + $deserializedObject = ExampleType::fromArray(json_decode($json, true)); + + // Serialize the object back into JSON using toArray + $serializedData = $deserializedObject->toArray(); + $serializedJson = json_encode($serializedData); + + // Assert that the serialized JSON matches the original JSON + $this->assertJsonStringEqualsJsonString($json, $serializedJson, 'The serialized JSON does not match the original JSON.'); + + // Additional assertions can be added to check specific properties + $this->assertEquals('Test Example', $deserializedObject->name); + $this->assertNull($deserializedObject->optionalName); + $this->assertEquals(30, $deserializedObject->age); + $this->assertEquals(99.99, $deserializedObject->price); + $this->assertTrue($deserializedObject->isActive); + $this->assertEquals('2024-09-10', $deserializedObject->startDate->format('Y-m-d')); + $this->assertEquals('2024-09-10 12:00:00', $deserializedObject->createdAt->format('Y-m-d H:i:s')); + $this->assertEquals(['one', 'two', 'three'], $deserializedObject->stringList); + $this->assertEquals(['key1' => 1, 'key2' => 2], $deserializedObject->stringIntMap); + + // Test nested structures + $this->assertEquals([['one', 'two'], ['three', 'four']], $deserializedObject->nestedStringList); + + // Check a nested ExampleNestedType object + $this->assertEquals(10, $deserializedObject->nestedTypeMap[1][10]->id); + $this->assertEquals('NestedType 10', $deserializedObject->nestedTypeMap[1][10]->name); + $this->assertEquals(20, $deserializedObject->nestedTypeMap[1][20]->id); + $this->assertEquals('NestedType 20', $deserializedObject->nestedTypeMap[1][20]->name); + } +} From 7dac73e34cdf4625bdb4bce8f83ba184d4d25620 Mon Sep 17 00:00:00 2001 From: dcb6 Date: Fri, 13 Sep 2024 12:12:25 -0400 Subject: [PATCH 02/19] working with SerializableType --- .../serde-demo/src/Core/SerializableType.php | 307 ++++++++++++++++++ .../src/Types/ExampleNestedType.php | 40 +-- .../serde-demo/src/Types/ExampleType.php | 276 +--------------- .../tests/Seed/Types/ExampleTypeTest.php | 40 ++- 4 files changed, 340 insertions(+), 323 deletions(-) create mode 100644 seed/php-sdk/serde-demo/src/Core/SerializableType.php diff --git a/seed/php-sdk/serde-demo/src/Core/SerializableType.php b/seed/php-sdk/serde-demo/src/Core/SerializableType.php new file mode 100644 index 00000000000..6278843f5db --- /dev/null +++ b/seed/php-sdk/serde-demo/src/Core/SerializableType.php @@ -0,0 +1,307 @@ +toArray(); + return json_encode($arrayData); + } + + /** + * Deserializes a JSON string into an object of the calling class. + * + * @param string $json The JSON string to deserialize. + * @return static + */ + public static function fromJson(string $json): static + { + $arrayData = json_decode($json, true); + return static::fromArray($arrayData); + } + + /** + * Deserializes an array into an object of the calling class. + * + * @param array $data The array to deserialize. + * @return static + */ + public static function fromArray(array $data): static + { + $reflectionClass = new ReflectionClass(static::class); + $constructor = $reflectionClass->getConstructor(); + $parameters = $constructor->getParameters(); + $args = []; + + foreach ($parameters as $parameter) { + $propertyName = $parameter->getName(); + + if ($reflectionClass->hasProperty($propertyName)) { + $property = $reflectionClass->getProperty($propertyName); + } else { + // Skip if the property does not exist + continue; + } + + $jsonKey = static::getJsonKey($property); + if (array_key_exists($jsonKey, $data)) { + $value = $data[$jsonKey]; + + // Handle DateType annotation + $dateTypeAttr = $property->getAttributes(DateType::class)[0] ?? null; + if ($dateTypeAttr) { + $dateType = $dateTypeAttr->newInstance()->type; + if ($dateType === DateType::TYPE_DATE) { + $value = DateTime::createFromFormat('Y-m-d', $value); + } else { + $value = new DateTime($value); + } + } + + // Handle ArrayType annotation + $arrayTypeAttr = $property->getAttributes(ArrayType::class)[0] ?? null; + if (is_array($value) && $arrayTypeAttr) { + $arrayType = $arrayTypeAttr->newInstance()->type; + $value = static::deserializeGenericArray($value, $arrayType); + } + + $args[$parameter->getPosition()] = $value; + } else { + // Use default value if available, else null + if ($parameter->isDefaultValueAvailable()) { + $args[$parameter->getPosition()] = $parameter->getDefaultValue(); + } else { + $args[$parameter->getPosition()] = null; + } + } + } + + // Instantiate the object with the collected arguments + return new static(...$args); + } + + /** + * Serializes the object to an array for JSON encoding. + * + * @return array + */ + public function toArray(): array + { + $result = []; + $reflectionClass = new ReflectionClass($this); + + foreach ($reflectionClass->getProperties() as $property) { + $property->setAccessible(true); + $jsonKey = static::getJsonKey($property); + $value = $property->getValue($this); + + // Handle DateTime properties + $dateTypeAttr = $property->getAttributes(DateType::class)[0] ?? null; + if ($dateTypeAttr && $value instanceof DateTimeInterface) { + $dateType = $dateTypeAttr->newInstance()->type; + if ($dateType === DateType::TYPE_DATE) { + $value = $value->format('Y-m-d'); + } else { + $value = $value->format(DateTimeInterface::RFC3339); + } + } + + // Handle arrays with type annotations + $arrayTypeAttr = $property->getAttributes(ArrayType::class)[0] ?? null; + if ($arrayTypeAttr && is_array($value)) { + $arrayType = $arrayTypeAttr->newInstance()->type; + $value = static::serializeGenericArray($value, $arrayType); + } + + $result[$jsonKey] = $value; + } + + return $result; + } + + /** + * Helper function to retrieve the JSON key for a property. + * + * @param ReflectionProperty $property + * @return string + */ + private static function getJsonKey(ReflectionProperty $property): string + { + $jsonPropertyAttr = $property->getAttributes(JsonProperty::class)[0] ?? null; + return $jsonPropertyAttr ? $jsonPropertyAttr->newInstance()->name : $property->getName(); + } + + /** + * Casts the key to the appropriate type based on the key type. + * + * @param mixed $key The key to be cast. + * @param string $keyType The type to cast the key to ('string', 'int', 'float'). + * @return mixed The casted key. + */ + private static function castKey(mixed $key, string $keyType): mixed + { + return match ($keyType) { + 'int' => (int)$key, + 'float' => (float)$key, + 'string' => (string)$key, + default => $key, + }; + } + + /** + * Determines if the given type represents a map. + * + * @param array $type The type definition from the annotation. + * @return bool True if the type is a map, false if it's a list. + */ + private static function isMapType(array $type): bool + { + return count($type) === 1 && !array_is_list($type); + } + + /** + * Serializes the given array based on the type annotation. + * + * @param array $data The array to be serialized. + * @param array $type The type definition from the annotation. + * @return array The serialized array. + */ + private static function serializeGenericArray(array $data, array $type): array + { + return self::isMapType($type) + ? self::serializeMap($data, $type) + : self::serializeList($data, $type); + } + + /** + * Serializes a map (associative array) where key and value types are defined. + * + * @param array $data The associative array to serialize. + * @param array $type The type definition for the map. + * @return array The serialized map. + */ + private static function serializeMap(array $data, array $type): array + { + $keyType = array_key_first($type); + $valueType = $type[$keyType]; + $result = []; + + foreach ($data as $key => $item) { + $key = self::castKey($key, $keyType); + + if (is_array($valueType)) { + $result[$key] = self::serializeGenericArray($item, $valueType); + } elseif (is_object($item) && method_exists($item, 'toArray')) { + $result[$key] = $item->toArray(); + } else { + $result[$key] = $item; + } + } + + return $result; + } + + /** + * Serializes a list (indexed array) where only the value type is defined. + * + * @param array $data The list to serialize. + * @param array $type The type definition for the list. + * @return array The serialized list. + */ + private static function serializeList(array $data, array $type): array + { + $valueType = $type[0]; + + return array_map(function ($item) use ($valueType) { + if (is_array($valueType)) { + return self::serializeGenericArray($item, $valueType); + } elseif (is_object($item) && method_exists($item, 'toArray')) { + return $item->toArray(); + } else { + return $item; + } + }, $data); + } + + /** + * Deserializes the given array based on the type annotation. + * + * @param array $data The array to be deserialized. + * @param array $type The type definition from the annotation. + * @return array The deserialized array. + */ + private static function deserializeGenericArray(array $data, array $type): array + { + return self::isMapType($type) + ? self::deserializeMap($data, $type) + : self::deserializeList($data, $type); + } + + /** + * Deserializes a map (associative array) where key and value types are defined. + * + * @param array $data The associative array to deserialize. + * @param array $type The type definition for the map. + * @return array The deserialized map. + */ + private static function deserializeMap(array $data, array $type): array + { + $keyType = array_key_first($type); + $valueType = $type[$keyType]; + $result = []; + + foreach ($data as $key => $item) { + $key = self::castKey($key, $keyType); + + if (is_array($valueType)) { + $result[$key] = self::deserializeGenericArray($item, $valueType); + } elseif (class_exists($valueType) && method_exists($valueType, 'fromArray')) { + $result[$key] = $valueType::fromArray($item); + } else { + $result[$key] = $item; + } + } + + return $result; + } + + /** + * Deserializes a list (indexed array) where only the value type is defined. + * + * @param array $data The list to deserialize. + * @param array $type The type definition for the list. + * @return array The deserialized list. + */ + private static function deserializeList(array $data, array $type): array + { + $valueType = $type[0]; + + return array_map(function ($item) use ($valueType) { + if (is_array($valueType)) { + return self::deserializeGenericArray($item, $valueType); + } elseif (class_exists($valueType) && method_exists($valueType, 'fromArray')) { + $result = $valueType::fromArray($item); + return $result; + } else { + return $item; + } + }, $data); + } +} \ No newline at end of file diff --git a/seed/php-sdk/serde-demo/src/Types/ExampleNestedType.php b/seed/php-sdk/serde-demo/src/Types/ExampleNestedType.php index b743075a36b..5569297622b 100644 --- a/seed/php-sdk/serde-demo/src/Types/ExampleNestedType.php +++ b/seed/php-sdk/serde-demo/src/Types/ExampleNestedType.php @@ -2,41 +2,15 @@ namespace Seed\Types; -use JetBrains\PhpStorm\ArrayShape; +use Seed\Core\JsonProperty; +use Seed\Core\SerializableType; -class ExampleNestedType +class ExampleNestedType extends SerializableType { - /** @var int */ - public int $id; - - /** @var string */ - public string $name; - - /** - * Deserializes an array into an ExampleNestedType object. - * - * @param array $data The array to deserialize. - * @return self - */ - public static function fromArray(array $data): self - { - $instance = new self(); - $instance->id = $data['id']; - $instance->name = $data['name']; - - return $instance; - } - - /** - * Serializes the object to an array for JSON encoding. - * - * @return array - */ - public function toArray(): array + public function __construct( + #[JsonProperty('nested_field')] + public string $nestedField + ) { - return [ - 'id' => $this->id, - 'name' => $this->name, - ]; } } diff --git a/seed/php-sdk/serde-demo/src/Types/ExampleType.php b/seed/php-sdk/serde-demo/src/Types/ExampleType.php index 50ae3ea7fd7..90277686f53 100644 --- a/seed/php-sdk/serde-demo/src/Types/ExampleType.php +++ b/seed/php-sdk/serde-demo/src/Types/ExampleType.php @@ -9,8 +9,9 @@ use Seed\Core\ArrayType; use Seed\Core\DateType; use Seed\Core\JsonProperty; +use Seed\Core\SerializableType; -class ExampleType +class ExampleType extends SerializableType { public function __construct( #[JsonProperty('name')] @@ -53,277 +54,4 @@ public function __construct( #[JsonProperty('optional_name')] public ?string $optionalName = null ) {} - - /** - * Deserializes an array (e.g. from json_decode) into an ExampleType object. - * - * @param array $data The array to deserialize. - * @return self - */ - public static function fromArray(array $data): self - { - $instance = new self(); - $reflectionClass = new ReflectionClass(self::class); - foreach ($reflectionClass->getProperties() as $property) { - $jsonKey = self::getJsonKey($property); - if (isset($data[$jsonKey])) { - $value = $data[$jsonKey]; - - // Handle DateType annotation - $dateTypeAttr = $property->getAttributes(DateType::class)[0] ?? null; - if ($dateTypeAttr) { - $dateType = $dateTypeAttr->newInstance()->type; - if ($dateType === DateType::TYPE_DATE) { - $value = DateTime::createFromFormat('Y-m-d', $value); - } else { - $value = new DateTime($value); - } - } - - // Handle ArrayType annotation - $arrayTypeAttr = $property->getAttributes(ArrayType::class)[0] ?? null; - if (is_array($value) && $arrayTypeAttr) { - $arrayType = $arrayTypeAttr->newInstance()->type; - $value = self::deserializeGenericArray($value, $arrayType); - } - - $property->setAccessible(true); - $property->setValue($instance, $value); - } - } - return $instance; - } - - /** - * Serializes the object to an array for JSON encoding. - * - * @return array - */ - public function toArray(): array - { - $result = []; - $reflectionClass = new ReflectionClass(self::class); - foreach ($reflectionClass->getProperties() as $property) { - $jsonKey = self::getJsonKey($property); - $value = $property->getValue($this); - - // Handle DateTime properties - $dateTypeAttr = $property->getAttributes(DateType::class)[0] ?? null; - if ($dateTypeAttr) { - $dateType = $dateTypeAttr->newInstance()->type; - if ($value instanceof DateTime) { - if ($dateType === DateType::TYPE_DATE) { - $value = $value->format('Y-m-d'); - } else { - $value = $value->format(DateTimeInterface::RFC3339); -// $value = $value->format(DateTimeInterface::RFC3339); - } - } - } - - // Handle arrays - $arrayTypeAttr = $property->getAttributes(ArrayType::class)[0] ?? null; - if ($arrayTypeAttr && is_array($value)) { - $arrayType = $arrayTypeAttr->newInstance()->type; - $value = self::serializeGenericArray($value, $arrayType); - } - - $result[$jsonKey] = $value; - } - return $result; - } - - /** - * Casts the key to the appropriate type based on the key type. - * Example: If the key type is 'int', the key will be cast to an integer. - * - * @param mixed $key The key to be cast. - * @param string $keyType The type to cast the key to ('string', 'int', 'float'). - * @return mixed The casted key. - */ - private static function castKey(mixed $key, string $keyType): mixed - { - if ($keyType === 'int') { - return (int)$key; - } elseif ($keyType === 'float') { - return (float)$key; - } elseif ($keyType === 'string') { - return (string)$key; - } - - return $key; - } - - /** - * Serializes the given array based on the type annotation. - * Distinguishes between lists (e.g., ['valueType']) and maps (e.g., ['keyType' => 'valueType']). - * - * @param array $data The array to be serialized. - * @param array $type The type definition from the annotation (e.g., ['string' => 'int']). - * @return array The serialized array. - */ - private static function serializeGenericArray(array $data, array $type): array - { - // If the type is a map (['keyType' => 'valueType']), use serializeMap. - if (self::isMapType($type)) { - return self::serializeMap($data, $type); - } - - // Otherwise, it's a list (['valueType']), so use serializeList. - return self::serializeList($data, $type); - } - - /** - * Serializes a map (associative array) where the key and value types are defined. - * Example: ['string' => 'int'] represents a map from string to int. - * - * @param array $data The associative array to serialize. - * @param array $type The type definition for the map. - * @return array The serialized map. - */ - private static function serializeMap(array $data, array $type): array - { - $keyType = array_key_first($type); // Extract key type, e.g., 'string' - $valueType = $type[$keyType]; // Extract value type, e.g., 'int' - - $result = []; - foreach ($data as $key => $item) { - // Cast the key to its proper type - $key = self::castKey($key, $keyType); - - // Recursively serialize the value based on its type - if (is_array($valueType)) { - $result[$key] = self::serializeGenericArray($item, $valueType); - } elseif (is_object($item) && method_exists($item, 'toArray')) { - $result[$key] = $item->toArray(); - } else { - $result[$key] = $item; - } - } - - return $result; - } - - /** - * Serializes a list (indexed array) where only the value type is defined. - * Example: ['valueType'] represents a list of items of type 'valueType'. - * - * @param array $data The list to serialize. - * @param array $type The type definition for the list. - * @return array The serialized list. - */ - private static function serializeList(array $data, array $type): array - { - $valueType = $type[0]; // Extract value type, e.g., 'string', 'int' - - return array_map(function ($item) use ($valueType) { - // Recursively serialize nested arrays or objects - if (is_array($valueType)) { - return self::serializeGenericArray($item, $valueType); - } elseif (is_object($item) && method_exists($item, 'toArray')) { - return $item->toArray(); - } else { - return $item; - } - }, $data); - } - - /** - * Deserializes the given array based on the type annotation. - * Distinguishes between lists (e.g., ['valueType']) and maps (e.g., ['keyType' => 'valueType']). - * - * @param array $data The array to be deserialized. - * @param array $type The type definition from the annotation (e.g., ['string' => 'int']). - * @return array The deserialized array. - */ - private static function deserializeGenericArray(array $data, array $type): array - { - // If the type is a map (['keyType' => 'valueType']), use deserializeMap. - if (self::isMapType($type)) { - return self::deserializeMap($data, $type); - } - - // Otherwise, it's a list (['valueType']), so use deserializeList. - return self::deserializeList($data, $type); - } - - /** - * Deserializes a map (associative array) where the key and value types are defined. - * Example: ['string' => 'int'] represents a map from string to int. - * - * @param array $data The associative array to deserialize. - * @param array $type The type definition for the map. - * @return array The deserialized map. - */ - private static function deserializeMap(array $data, array $type): array - { - $keyType = array_key_first($type); // Extract key type, e.g., 'string' - $valueType = $type[$keyType]; // Extract value type, e.g., 'int' - - $result = []; - foreach ($data as $key => $item) { - // Cast the key to its proper type - $key = self::castKey($key, $keyType); - - // Recursively deserialize the value based on its type - if (is_array($valueType)) { - $result[$key] = self::deserializeGenericArray($item, $valueType); - } elseif (class_exists($valueType)) { - // If the valueType is a class, instantiate it using fromArray - $result[$key] = $valueType::fromArray($item); - } else { - $result[$key] = $item; - } - } - - return $result; - } - - /** - * Deserializes a list (indexed array) where only the value type is defined. - * Example: ['valueType'] represents a list of items of type 'valueType'. - * - * @param array $data The list to deserialize. - * @param array $type The type definition for the list. - * @return array The deserialized list. - */ - private static function deserializeList(array $data, array $type): array - { - $valueType = $type[0]; // Extract value type, e.g., 'string', 'int' - - return array_map(function ($item) use ($valueType) { - // Recursively deserialize nested arrays or objects - if (is_array($valueType)) { - return self::deserializeGenericArray($item, $valueType); - } elseif (class_exists($valueType)) { - return $valueType::fromArray($item); - } else { - return $item; - } - }, $data); - } - - /** - * Determines if the given type represents a map. - * A map is represented as an associative array (e.g., ['keyType' => 'valueType']). - * - * @param array $type The type definition from the annotation. - * @return bool True if the type is a map, false if it's a list. - */ - private static function isMapType(array $type): bool - { - return count($type) === 1 && array_is_list($type) === false; - } - - /** - * Helper function to retrieve the JSON key for a property (uses JsonProperty if available). - * - * @param ReflectionProperty $property - * @return string - */ - private static function getJsonKey(ReflectionProperty $property): string - { - $jsonPropertyAttr = $property->getAttributes(JsonProperty::class)[0] ?? null; - return $jsonPropertyAttr ? $jsonPropertyAttr->newInstance()->name : $property->getName(); - } } diff --git a/seed/php-sdk/serde-demo/tests/Seed/Types/ExampleTypeTest.php b/seed/php-sdk/serde-demo/tests/Seed/Types/ExampleTypeTest.php index b594a82788c..318b40dc0a7 100644 --- a/seed/php-sdk/serde-demo/tests/Seed/Types/ExampleTypeTest.php +++ b/seed/php-sdk/serde-demo/tests/Seed/Types/ExampleTypeTest.php @@ -22,12 +22,12 @@ public function testSerializationAndDeserialization() 'nested_string_list' => [['one', 'two'], ['three', 'four']], 'nested_type_map' => [ 1 => [ - 10 => ['id' => 10, 'name' => 'NestedType 10'], - 20 => ['id' => 20, 'name' => 'NestedType 20'] + 10 => ['nested_field' => 'NestedType 10'], + 20 => ['nested_field' => 'NestedType 20'] ], 2 => [ - 30 => ['id' => 30, 'name' => 'NestedType 30'], - 40 => ['id' => 40, 'name' => 'NestedType 40'] + 30 => ['nested_field' => 'NestedType 30'], + 40 => ['nested_field' => 'NestedType 40'] ] ] ]; @@ -35,17 +35,16 @@ public function testSerializationAndDeserialization() // Convert the original data into JSON $json = json_encode($originalData); - // Deserialize the JSON into an ExampleType object using fromArray - $deserializedObject = ExampleType::fromArray(json_decode($json, true)); + // Deserialize the JSON into an ExampleType object using fromJson + $deserializedObject = ExampleType::fromJson($json); - // Serialize the object back into JSON using toArray - $serializedData = $deserializedObject->toArray(); - $serializedJson = json_encode($serializedData); + // Serialize the object back into JSON using toJson + $serializedJson = $deserializedObject->toJson(); // Assert that the serialized JSON matches the original JSON $this->assertJsonStringEqualsJsonString($json, $serializedJson, 'The serialized JSON does not match the original JSON.'); - // Additional assertions can be added to check specific properties + // Additional assertions to check specific properties $this->assertEquals('Test Example', $deserializedObject->name); $this->assertNull($deserializedObject->optionalName); $this->assertEquals(30, $deserializedObject->age); @@ -59,10 +58,19 @@ public function testSerializationAndDeserialization() // Test nested structures $this->assertEquals([['one', 'two'], ['three', 'four']], $deserializedObject->nestedStringList); - // Check a nested ExampleNestedType object - $this->assertEquals(10, $deserializedObject->nestedTypeMap[1][10]->id); - $this->assertEquals('NestedType 10', $deserializedObject->nestedTypeMap[1][10]->name); - $this->assertEquals(20, $deserializedObject->nestedTypeMap[1][20]->id); - $this->assertEquals('NestedType 20', $deserializedObject->nestedTypeMap[1][20]->name); + // Check nested ExampleNestedType objects + $nestedTypeMap = $deserializedObject->nestedTypeMap; + + $this->assertInstanceOf(ExampleNestedType::class, $nestedTypeMap[1][10]); + $this->assertEquals('NestedType 10', $nestedTypeMap[1][10]->nestedField); + + $this->assertInstanceOf(ExampleNestedType::class, $nestedTypeMap[1][20]); + $this->assertEquals('NestedType 20', $nestedTypeMap[1][20]->nestedField); + + $this->assertInstanceOf(ExampleNestedType::class, $nestedTypeMap[2][30]); + $this->assertEquals('NestedType 30', $nestedTypeMap[2][30]->nestedField); + + $this->assertInstanceOf(ExampleNestedType::class, $nestedTypeMap[2][40]); + $this->assertEquals('NestedType 40', $nestedTypeMap[2][40]->nestedField); } -} +} \ No newline at end of file From 145c5e4ebed9619407243add5ba5224307332479 Mon Sep 17 00:00:00 2001 From: dcb6 Date: Fri, 13 Sep 2024 13:34:09 -0400 Subject: [PATCH 03/19] reduce warnings in SerializableType --- .../serde-demo/src/Core/SerializableType.php | 34 +++++++++++++------ .../serde-demo/src/Types/ExampleType.php | 29 ++++++++++------ 2 files changed, 42 insertions(+), 21 deletions(-) diff --git a/seed/php-sdk/serde-demo/src/Core/SerializableType.php b/seed/php-sdk/serde-demo/src/Core/SerializableType.php index 6278843f5db..b29e0f4ef4c 100644 --- a/seed/php-sdk/serde-demo/src/Core/SerializableType.php +++ b/seed/php-sdk/serde-demo/src/Core/SerializableType.php @@ -4,6 +4,9 @@ use DateTime; use DateTimeInterface; +use InvalidArgumentException; +use JsonException; +use LogicException; use ReflectionClass; use ReflectionProperty; @@ -18,11 +21,12 @@ abstract class SerializableType * Serializes the object to a JSON string. * * @return string + * @throws JsonException */ public function toJson(): string { $arrayData = $this->toArray(); - return json_encode($arrayData); + return json_encode($arrayData, JSON_THROW_ON_ERROR); } /** @@ -30,10 +34,17 @@ public function toJson(): string * * @param string $json The JSON string to deserialize. * @return static + * + * @throws InvalidArgumentException if the JSON is invalid or does not decode to an array. */ public static function fromJson(string $json): static { $arrayData = json_decode($json, true); + + if (!is_array($arrayData)) { + throw new InvalidArgumentException('Invalid JSON provided or JSON does not decode to an array.'); + } + return static::fromArray($arrayData); } @@ -42,11 +53,16 @@ public static function fromJson(string $json): static * * @param array $data The array to deserialize. * @return static + * + * @throws LogicException if the class does not have a constructor. */ public static function fromArray(array $data): static { $reflectionClass = new ReflectionClass(static::class); $constructor = $reflectionClass->getConstructor(); + if ($constructor === null) { + throw new LogicException('The class ' . static::class . ' must have a constructor.'); + } $parameters = $constructor->getParameters(); $args = []; @@ -60,7 +76,7 @@ public static function fromArray(array $data): static continue; } - $jsonKey = static::getJsonKey($property); + $jsonKey = SerializableType::getJsonKey($property); if (array_key_exists($jsonKey, $data)) { $value = $data[$jsonKey]; @@ -79,7 +95,7 @@ public static function fromArray(array $data): static $arrayTypeAttr = $property->getAttributes(ArrayType::class)[0] ?? null; if (is_array($value) && $arrayTypeAttr) { $arrayType = $arrayTypeAttr->newInstance()->type; - $value = static::deserializeGenericArray($value, $arrayType); + $value = SerializableType::deserializeGenericArray($value, $arrayType); } $args[$parameter->getPosition()] = $value; @@ -108,8 +124,7 @@ public function toArray(): array $reflectionClass = new ReflectionClass($this); foreach ($reflectionClass->getProperties() as $property) { - $property->setAccessible(true); - $jsonKey = static::getJsonKey($property); + $jsonKey = SerializableType::getJsonKey($property); $value = $property->getValue($this); // Handle DateTime properties @@ -127,7 +142,7 @@ public function toArray(): array $arrayTypeAttr = $property->getAttributes(ArrayType::class)[0] ?? null; if ($arrayTypeAttr && is_array($value)) { $arrayType = $arrayTypeAttr->newInstance()->type; - $value = static::serializeGenericArray($value, $arrayType); + $value = SerializableType::serializeGenericArray($value, $arrayType); } $result[$jsonKey] = $value; @@ -204,7 +219,7 @@ private static function serializeMap(array $data, array $type): array $result = []; foreach ($data as $key => $item) { - $key = self::castKey($key, $keyType); + $key = SerializableType::castKey($key, $keyType); if (is_array($valueType)) { $result[$key] = self::serializeGenericArray($item, $valueType); @@ -268,7 +283,7 @@ private static function deserializeMap(array $data, array $type): array $result = []; foreach ($data as $key => $item) { - $key = self::castKey($key, $keyType); + $key = SerializableType::castKey($key, (string) $keyType); if (is_array($valueType)) { $result[$key] = self::deserializeGenericArray($item, $valueType); @@ -297,8 +312,7 @@ private static function deserializeList(array $data, array $type): array if (is_array($valueType)) { return self::deserializeGenericArray($item, $valueType); } elseif (class_exists($valueType) && method_exists($valueType, 'fromArray')) { - $result = $valueType::fromArray($item); - return $result; + return $valueType::fromArray($item); } else { return $item; } diff --git a/seed/php-sdk/serde-demo/src/Types/ExampleType.php b/seed/php-sdk/serde-demo/src/Types/ExampleType.php index 90277686f53..c7209527968 100644 --- a/seed/php-sdk/serde-demo/src/Types/ExampleType.php +++ b/seed/php-sdk/serde-demo/src/Types/ExampleType.php @@ -13,18 +13,24 @@ class ExampleType extends SerializableType { + /** + * @param string[] $stringList + * @param array $stringIntMap + * @param string[][] $nestedStringList + * @param array> $nestedTypeMap + */ public function __construct( #[JsonProperty('name')] - public string $name, + public string $name, #[JsonProperty('age')] - public int $age, + public int $age, #[JsonProperty('price')] - public float $price, + public float $price, #[JsonProperty('is_active')] - public bool $isActive, + public bool $isActive, #[DateType(DateType::TYPE_DATE)] #[JsonProperty('start_date')] @@ -36,22 +42,23 @@ public function __construct( #[ArrayType(['string'])] #[JsonProperty('string_list')] - /** @var string[] $stringList */ - public array $stringList, + public array $stringList, #[ArrayType(['string' => 'int'])] #[JsonProperty('string_int_map')] - public array $stringIntMap, + public array $stringIntMap, #[ArrayType([['string']])] #[JsonProperty('nested_string_list')] - public array $nestedStringList, + public array $nestedStringList, #[ArrayType(['int' => ['int' => ExampleNestedType::class]])] #[JsonProperty('nested_type_map')] - public array $nestedTypeMap, + public array $nestedTypeMap, #[JsonProperty('optional_name')] - public ?string $optionalName = null - ) {} + public ?string $optionalName = null + ) + { + } } From 297f683e2470c238f58ba4a09a7e6843c3f0ce60 Mon Sep 17 00:00:00 2001 From: dcb6 Date: Fri, 13 Sep 2024 15:53:51 -0400 Subject: [PATCH 04/19] first test working --- .../serde-demo/src/Core/SerializableType.php | 209 +++++++++-- .../serde-demo/src/Types/ExampleType.php | 8 +- .../tests/Seed/Core/SerializableTypeTest.php | 351 ++++++++++++++++++ 3 files changed, 523 insertions(+), 45 deletions(-) create mode 100644 seed/php-sdk/serde-demo/tests/Seed/Core/SerializableTypeTest.php diff --git a/seed/php-sdk/serde-demo/src/Core/SerializableType.php b/seed/php-sdk/serde-demo/src/Core/SerializableType.php index b29e0f4ef4c..22aec5c5cd2 100644 --- a/seed/php-sdk/serde-demo/src/Core/SerializableType.php +++ b/seed/php-sdk/serde-demo/src/Core/SerializableType.php @@ -3,7 +3,6 @@ namespace Seed\Core; use DateTime; -use DateTimeInterface; use InvalidArgumentException; use JsonException; use LogicException; @@ -127,14 +126,19 @@ public function toArray(): array $jsonKey = SerializableType::getJsonKey($property); $value = $property->getValue($this); + // Skip properties with null values + if ($value === null) { + continue; + } + // Handle DateTime properties $dateTypeAttr = $property->getAttributes(DateType::class)[0] ?? null; - if ($dateTypeAttr && $value instanceof DateTimeInterface) { + if ($dateTypeAttr && $value instanceof DateTime) { $dateType = $dateTypeAttr->newInstance()->type; if ($dateType === DateType::TYPE_DATE) { $value = $value->format('Y-m-d'); } else { - $value = $value->format(DateTimeInterface::RFC3339); + $value = $value->format(DateTime::RFC3339); } } @@ -233,25 +237,35 @@ private static function serializeMap(array $data, array $type): array return $result; } - /** - * Serializes a list (indexed array) where only the value type is defined. - * - * @param array $data The list to serialize. - * @param array $type The type definition for the list. - * @return array The serialized list. - */ private static function serializeList(array $data, array $type): array { - $valueType = $type[0]; + $valueTypes = self::parseTypeExpression($type[0]); - return array_map(function ($item) use ($valueType) { - if (is_array($valueType)) { - return self::serializeGenericArray($item, $valueType); - } elseif (is_object($item) && method_exists($item, 'toArray')) { - return $item->toArray(); - } else { - return $item; + return array_map(function ($item) use ($valueTypes) { + foreach ($valueTypes as $expectedType) { + if ($expectedType === 'null' && $item === null) { + return null; + } + + if (($expectedType === 'date' || $expectedType === 'datetime') && $item instanceof DateTime) { + $format = $expectedType === 'date' ? 'Y-m-d' : DateTime::RFC3339; + return $item->format($format); + } + + if (class_exists($expectedType) && $item instanceof $expectedType) { + if (method_exists($item, 'toArray')) { + return $item->toArray(); + } else { + throw new \InvalidArgumentException("Class $expectedType must implement toArray method."); + } + } + + if (gettype($item) === $expectedType) { + return $item; + } } + + throw new \InvalidArgumentException("Unable to serialize item of type '" . gettype($item) . "'."); }, $data); } @@ -269,29 +283,72 @@ private static function deserializeGenericArray(array $data, array $type): array : self::deserializeList($data, $type); } - /** - * Deserializes a map (associative array) where key and value types are defined. - * - * @param array $data The associative array to deserialize. - * @param array $type The type definition for the map. - * @return array The deserialized map. - */ + private static function deserializeValue($item, $typeDef) + { + if (is_array($typeDef)) { + // Type definition is an array (complex type like map or list) + return self::deserializeGenericArray($item, $typeDef); + } else { + // Type definition is a string (possibly with union types) + $valueTypes = self::parseTypeExpression($typeDef); + + foreach ($valueTypes as $expectedType) { + // Handle 'null' type + if ($expectedType === 'null' && $item === null) { + return null; + } + + // Handle 'date' and 'datetime' types + if ($expectedType === 'date' && is_string($item)) { + $date = DateTime::createFromFormat('Y-m-d', $item); + if ($date !== false) { + return $date; + } + } elseif ($expectedType === 'datetime' && is_string($item)) { + try { + return new DateTime($item); + } catch (\Exception $e) { + // Invalid datetime + } + } + + // Handle class types + if (class_exists($expectedType) && is_array($item)) { + if (method_exists($expectedType, 'fromArray')) { + return $expectedType::fromArray($item); + } + } + + // Handle scalar types using is_* functions + if (($expectedType === 'int' && is_int($item)) || + ($expectedType === 'bool' && is_bool($item)) || + ($expectedType === 'float' && is_float($item)) || + ($expectedType === 'string' && is_string($item))) { + return $item; + } + } + + // If no matching type is found, throw an exception + throw new \InvalidArgumentException("Unable to deserialize value: type mismatch."); + } + } + private static function deserializeMap(array $data, array $type): array { $keyType = array_key_first($type); - $valueType = $type[$keyType]; + $valueTypeDef = $type[$keyType]; $result = []; foreach ($data as $key => $item) { $key = SerializableType::castKey($key, (string) $keyType); - if (is_array($valueType)) { - $result[$key] = self::deserializeGenericArray($item, $valueType); - } elseif (class_exists($valueType) && method_exists($valueType, 'fromArray')) { - $result[$key] = $valueType::fromArray($item); - } else { - $result[$key] = $item; + try { + $deserializedItem = self::deserializeValue($item, $valueTypeDef); + } catch (\InvalidArgumentException $e) { + throw new \InvalidArgumentException("Unable to deserialize map item with key '$key': " . $e->getMessage()); } + + $result[$key] = $deserializedItem; } return $result; @@ -304,18 +361,88 @@ private static function deserializeMap(array $data, array $type): array * @param array $type The type definition for the list. * @return array The deserialized list. */ - private static function deserializeList(array $data, array $type): array + private static function deserializeList(array $data, array $typeDef): array { - $valueType = $type[0]; + $valueTypes = self::parseTypeDefinition($typeDef[0]); - return array_map(function ($item) use ($valueType) { - if (is_array($valueType)) { - return self::deserializeGenericArray($item, $valueType); - } elseif (class_exists($valueType) && method_exists($valueType, 'fromArray')) { - return $valueType::fromArray($item); - } else { - return $item; + return array_map(function ($item) use ($valueTypes) { + foreach ($valueTypes as $expectedType) { + // Handle 'null' type + if ($expectedType === 'null' && $item === null) { + return null; + } + + // Handle 'date' and 'datetime' types + if ($expectedType === 'date' && is_string($item)) { + $date = DateTime::createFromFormat('Y-m-d', $item); + if ($date !== false) { + return $date; + } + } elseif ($expectedType === 'datetime' && is_string($item)) { + try { + return new DateTime($item); + } catch (\Exception $e) { + // Not a valid datetime + } + } + + // Handle class types + if (class_exists($expectedType) && is_array($item)) { + if (method_exists($expectedType, 'fromArray')) { + return $expectedType::fromArray($item); + } + } + + // Handle scalar types + if (in_array($expectedType, ['string', 'int', 'float', 'bool']) && gettype($item) === $expectedType) { + return $item; + } } + + // If no matching type is found, throw an exception + throw new \InvalidArgumentException("Unable to deserialize item in array: type mismatch."); }, $data); } + + /** + * @param $type + * @return array|string[] + */ + private static function parseTypeDefinition($type) + { + if (is_array($type)) { + $parsed = []; + foreach ($type as $key => $value) { + // Parse the key + if (is_string($key)) { + $parsedKeys = self::parseTypeExpression($key); // This is an array of types + } else { + $parsedKeys = [null]; + } + // Parse the value + $parsedValue = self::parseTypeDefinition($value); + + foreach ($parsedKeys as $parsedKey) { + if ($parsedKey !== null) { + $parsed[$parsedKey] = $parsedValue; + } else { + $parsed[] = $parsedValue; + } + } + } + return $parsed; + } else { + return self::parseTypeExpression($type); + } + } + + /** + * @param string $typeExpr + * @return array + */ + private static function parseTypeExpression(string $typeExpr): array + { + // Split the type expression by '|' to handle union types + return array_map('trim', explode('|', $typeExpr)); + } } \ No newline at end of file diff --git a/seed/php-sdk/serde-demo/src/Types/ExampleType.php b/seed/php-sdk/serde-demo/src/Types/ExampleType.php index c7209527968..ed13f27c16f 100644 --- a/seed/php-sdk/serde-demo/src/Types/ExampleType.php +++ b/seed/php-sdk/serde-demo/src/Types/ExampleType.php @@ -3,9 +3,6 @@ namespace Seed\Types; use DateTime; -use DateTimeInterface; -use ReflectionClass; -use ReflectionProperty; use Seed\Core\ArrayType; use Seed\Core\DateType; use Seed\Core\JsonProperty; @@ -52,10 +49,13 @@ public function __construct( #[JsonProperty('nested_string_list')] public array $nestedStringList, - #[ArrayType(['int' => ['int' => ExampleNestedType::class]])] + #[ArrayType(['int' => ['int' => ExampleNestedType::class | "null" | "date" | "datetime"]])] #[JsonProperty('nested_type_map')] public array $nestedTypeMap, + #[JsonProperty('weather_report')] + public string $weatherReport, + #[JsonProperty('optional_name')] public ?string $optionalName = null ) diff --git a/seed/php-sdk/serde-demo/tests/Seed/Core/SerializableTypeTest.php b/seed/php-sdk/serde-demo/tests/Seed/Core/SerializableTypeTest.php new file mode 100644 index 00000000000..bf8394e5cd9 --- /dev/null +++ b/seed/php-sdk/serde-demo/tests/Seed/Core/SerializableTypeTest.php @@ -0,0 +1,351 @@ + $mapProperty + * @param array $objectArray + * @param array> $nestedArray + * @param array $datesArray + */ +class TestType extends SerializableType +{ + public function __construct( + #[JsonProperty('simple_property')] + public string $simpleProperty, + + #[DateType(DateType::TYPE_DATE)] + #[JsonProperty('date_property')] + public DateTime $dateProperty, + + #[DateType(DateType::TYPE_DATETIME)] + #[JsonProperty('datetime_property')] + public DateTime $datetimeProperty, + + #[ArrayType(['string'])] + #[JsonProperty('string_array')] + public array $stringArray, + + #[ArrayType(['string' => 'int'])] + #[JsonProperty('map_property')] + public array $mapProperty, + + #[ArrayType(['int' => TestNestedType::class . '|null'])] + #[JsonProperty('object_array')] + public array $objectArray, + + #[ArrayType(['int' => ['int' => 'string|null']])] + #[JsonProperty('nested_array')] + public array $nestedArray, + + #[ArrayType(['date|null'])] + #[JsonProperty('dates_array')] + public array $datesArray, + + #[JsonProperty('nullable_property')] + public ?string $nullableProperty = null // Move optional parameter to the end + ) {} +} + +/** + * @param (string|null)[] $nullableStringArray + */ +class NullableArrayType extends SerializableType +{ + public function __construct( + #[ArrayType(['string|null'])] + #[JsonProperty('nullable_string_array')] + public array $nullableStringArray + ) {} +} + +/** + * @param DateTime[] $dates + */ +class DateArrayType extends SerializableType +{ + public function __construct( + #[ArrayType(['date'])] + #[JsonProperty('dates')] + public array $dates + ) {} +} + +/** + * @param array $mixedArray + */ +class UnionArrayType extends SerializableType +{ + public function __construct( + #[ArrayType(['int' => 'string|int|null'])] + #[JsonProperty('mixed_array')] + public array $mixedArray + ) {} +} + +class NestedUnionArrayType extends SerializableType +{ + /** + * @param array> $nestedArray + */ + public function __construct( + #[ArrayType(['int' => ['int' => TestNestedType::class . '|null|date|datetime']])] + #[JsonProperty('nested_array')] + public array $nestedArray + ) {} +} + +class NullPropertyType extends SerializableType +{ + public function __construct( + #[JsonProperty('non_null_property')] + public string $nonNullProperty, + + #[JsonProperty('null_property')] + public ?string $nullProperty = null + ) {} +} + +/** + * @param array $mixedDates + */ +class MixedDateArrayType extends SerializableType +{ + public function __construct( + #[ArrayType(['int' => 'datetime|string|null'])] + #[JsonProperty('mixed_dates')] + public array $mixedDates + ) {} +} + +// Now, define the test class + +class SerializableTypeTest extends TestCase +{ + public function testSerializationAndDeserialization() + { + // Create test data + $data = [ + 'simple_property' => 'Test String', + // 'nullable_property' is omitted to test null serialization + 'date_property' => '2023-01-01', + 'datetime_property' => '2023-01-01T12:34:56+00:00', + 'string_array' => ['one', 'two', 'three'], + 'map_property' => ['key1' => 1, 'key2' => 2], + 'object_array' => [ + 1 => ['nested_property' => 'Nested One'], + 2 => null, // Testing nullable objects in array + ], + 'nested_array' => [ + 1 => [1 => 'value1', 2 => null], // Testing nullable strings in nested array + 2 => [3 => 'value3', 4 => 'value4'] + ], + 'dates_array' => ['2023-01-01', null, '2023-03-01'] // Testing nullable dates in array + ]; + + // Convert data to JSON + $json = json_encode($data); + + // Deserialize JSON to object + $object = TestType::fromJson($json); + + // Serialize object back to JSON + $serializedJson = $object->toJson(); + + // Compare serialized JSON with original JSON + $this->assertJsonStringEqualsJsonString($json, $serializedJson); + + // Check that nullable property is null and not included in JSON + $this->assertNull($object->nullableProperty); + $this->assertFalse(array_key_exists('nullable_property', json_decode($serializedJson, true))); + + // Check date properties + $this->assertEquals('2023-01-01', $object->dateProperty->format('Y-m-d')); + $this->assertEquals('2023-01-01 12:34:56', $object->datetimeProperty->format('Y-m-d H:i:s')); + + // Check arrays + $this->assertEquals(['one', 'two', 'three'], $object->stringArray); + $this->assertEquals(['key1' => 1, 'key2' => 2], $object->mapProperty); + + // Check object array with nullable elements + $this->assertInstanceOf(TestNestedType::class, $object->objectArray[1]); + $this->assertEquals('Nested One', $object->objectArray[1]->nestedProperty); + $this->assertNull($object->objectArray[2]); + + // Check nested array with nullable strings + $this->assertEquals('value1', $object->nestedArray[1][1]); + $this->assertNull($object->nestedArray[1][2]); + $this->assertEquals('value3', $object->nestedArray[2][3]); + $this->assertEquals('value4', $object->nestedArray[2][4]); + + // Check dates array with nullable DateTime objects + $this->assertInstanceOf(DateTime::class, $object->datesArray[0]); + $this->assertEquals('2023-01-01', $object->datesArray[0]->format('Y-m-d')); + $this->assertNull($object->datesArray[1]); + $this->assertInstanceOf(DateTime::class, $object->datesArray[2]); + $this->assertEquals('2023-03-01', $object->datesArray[2]->format('Y-m-d')); + } + + public function testNullableTypesInArrays() + { + $data = [ + 'nullable_string_array' => ['one', null, 'three'] + ]; + + $json = json_encode($data); + + $object = NullableArrayType::fromJson($json); + + $this->assertEquals(['one', null, 'three'], $object->nullableStringArray); + + $serializedJson = $object->toJson(); + + $this->assertJsonStringEqualsJsonString($json, $serializedJson); + } + + public function testDateTimeTypesInArrays() + { + $data = [ + 'dates' => ['2023-01-01', '2023-02-01', '2023-03-01'] + ]; + + $json = json_encode($data); + + $object = DateArrayType::fromJson($json); + + $this->assertInstanceOf(DateTime::class, $object->dates[0]); + $this->assertEquals('2023-01-01', $object->dates[0]->format('Y-m-d')); + $this->assertEquals('2023-02-01', $object->dates[1]->format('Y-m-d')); + $this->assertEquals('2023-03-01', $object->dates[2]->format('Y-m-d')); + + $serializedJson = $object->toJson(); + + $this->assertJsonStringEqualsJsonString($json, $serializedJson); + } + + public function testUnionTypesInArrays() + { + $data = [ + 'mixed_array' => [1 => 'one', 2 => 2, 3 => null] + ]; + + $json = json_encode($data); + + $object = UnionArrayType::fromJson($json); + + $this->assertEquals('one', $object->mixedArray[1]); + $this->assertEquals(2, $object->mixedArray[2]); + $this->assertNull($object->mixedArray[3]); + + $serializedJson = $object->toJson(); + + $this->assertJsonStringEqualsJsonString($json, $serializedJson); + } + + public function testNestedUnionTypesInArrays() + { + $data = [ + 'nested_array' => [ + 1 => [ + 1 => ['value' => 'Nested One'], + 2 => null, + 3 => '2023-01-01T12:00:00+00:00', // datetime + 4 => '2023-01-02' // date + ], + 2 => [ + 5 => ['value' => 'Nested Two'], + 6 => '2023-02-01T15:30:00+00:00', // datetime + 7 => '2023-02-02' // date + ] + ] + ]; + + $json = json_encode($data); + + $object = NestedUnionArrayType::fromJson($json); + + // Level 1 + $this->assertInstanceOf(TestNestedType::class, $object->nestedArray[1][1]); + $this->assertEquals('Nested One', $object->nestedArray[1][1]->value); + + $this->assertNull($object->nestedArray[1][2]); + + $this->assertInstanceOf(DateTime::class, $object->nestedArray[1][3]); + $this->assertEquals('2023-01-01 12:00:00', $object->nestedArray[1][3]->format('Y-m-d H:i:s')); + + $this->assertInstanceOf(DateTime::class, $object->nestedArray[1][4]); + $this->assertEquals('2023-01-02', $object->nestedArray[1][4]->format('Y-m-d')); + + // Level 2 + $this->assertInstanceOf(TestNestedType::class, $object->nestedArray[2][5]); + $this->assertEquals('Nested Two', $object->nestedArray[2][5]->value); + + $this->assertInstanceOf(DateTime::class, $object->nestedArray[2][6]); + $this->assertEquals('2023-02-01 15:30:00', $object->nestedArray[2][6]->format('Y-m-d H:i:s')); + + $this->assertInstanceOf(DateTime::class, $object->nestedArray[2][7]); + $this->assertEquals('2023-02-02', $object->nestedArray[2][7]->format('Y-m-d')); + + $serializedJson = $object->toJson(); + + $this->assertJsonStringEqualsJsonString($json, $serializedJson); + } + + public function testNullPropertiesAreOmitted() + { + $object = new NullPropertyType('Test String'); + + $json = $object->toJson(); + + $data = json_decode($json, true); + + $this->assertArrayHasKey('non_null_property', $data); + $this->assertArrayNotHasKey('null_property', $data); + + $this->assertEquals('Test String', $data['non_null_property']); + } + + public function testDateTimeTypesInUnionArrays() + { + $data = [ + 'mixed_dates' => [ + 1 => '2023-01-01T12:00:00+00:00', // datetime + 2 => null, // null + 3 => 'Some String' // string + ] + ]; + + $json = json_encode($data); + + $object = MixedDateArrayType::fromJson($json); + + $this->assertInstanceOf(DateTime::class, $object->mixedDates[1]); + $this->assertEquals('2023-01-01 12:00:00', $object->mixedDates[1]->format('Y-m-d H:i:s')); + + $this->assertNull($object->mixedDates[2]); + + $this->assertEquals('Some String', $object->mixedDates[3]); + + $serializedJson = $object->toJson(); + + $this->assertJsonStringEqualsJsonString($json, $serializedJson); + } +} \ No newline at end of file From e7c81dbaed2ceffdef0010f8583fe9822f1b9531 Mon Sep 17 00:00:00 2001 From: dcb6 Date: Sun, 15 Sep 2024 12:08:07 -0400 Subject: [PATCH 05/19] fully working --- seed/php-sdk/imdb/src/Core/ArrayType.php | 35 ++ .../src/Core/DateType.php | 0 .../src/Core/JsonProperty.php | 0 .../imdb/src/Core/SerializableType.php | 386 +++++++++++++++ .../src/Types/ExampleNestedType.php | 0 .../src/Types/ExampleType.php | 0 .../src/Types/WeatherReport.php | 0 .../imdb/tests/Seed/Core/RawClientTest.php | 6 +- .../SerializableType/DateArrayTypeTest.php | 48 ++ .../Core/SerializableType/EmptyArraysTest.php | 58 +++ .../SerializableType/InvalidTypesTest.php | 36 ++ .../MixedDateArrayTypeTest.php | 50 ++ .../NestedUnionArrayTypeTest.php | 81 ++++ .../SerializableType/NullPropertyTypeTest.php | 37 ++ .../NullableArrayTypeTest.php | 41 ++ .../Core/SerializableType/ScalarTypesTest.php | 73 +++ .../Core/SerializableType/TestTypeTest.php | 140 ++++++ .../SerializableType/UnionArrayTypeTest.php | 47 ++ .../tests/Seed/Types/ExampleTypeTest.php | 0 .../serde-demo/.github/workflows/ci.yml | 46 -- seed/php-sdk/serde-demo/.gitignore | 4 - .../serde-demo/.mock/definition/api.yml | 4 - .../serde-demo/.mock/definition/imdb.yml | 42 -- .../php-sdk/serde-demo/.mock/fern.config.json | 1 - seed/php-sdk/serde-demo/.mock/generators.yml | 1 - seed/php-sdk/serde-demo/composer.json | 40 -- seed/php-sdk/serde-demo/phpstan.neon | 5 - seed/php-sdk/serde-demo/phpunit.xml | 7 - .../php-sdk/serde-demo/snippet-templates.json | 0 seed/php-sdk/serde-demo/snippet.json | 0 .../php-sdk/serde-demo/src/Core/ArrayType.php | 14 - .../serde-demo/src/Core/BaseApiRequest.php | 22 - .../serde-demo/src/Core/HttpMethod.php | 12 - .../serde-demo/src/Core/JsonApiRequest.php | 25 - .../php-sdk/serde-demo/src/Core/RawClient.php | 123 ----- .../serde-demo/src/Core/SerializableType.php | 448 ------------------ .../src/Placeholder/Placeholder.php | 11 - .../tests/Seed/Core/RawClientTest.php | 101 ---- .../tests/Seed/Core/SerializableTypeTest.php | 351 -------------- 39 files changed, 1033 insertions(+), 1262 deletions(-) create mode 100644 seed/php-sdk/imdb/src/Core/ArrayType.php rename seed/php-sdk/{serde-demo => imdb}/src/Core/DateType.php (100%) rename seed/php-sdk/{serde-demo => imdb}/src/Core/JsonProperty.php (100%) create mode 100644 seed/php-sdk/imdb/src/Core/SerializableType.php rename seed/php-sdk/{serde-demo => imdb}/src/Types/ExampleNestedType.php (100%) rename seed/php-sdk/{serde-demo => imdb}/src/Types/ExampleType.php (100%) rename seed/php-sdk/{serde-demo => imdb}/src/Types/WeatherReport.php (100%) create mode 100644 seed/php-sdk/imdb/tests/Seed/Core/SerializableType/DateArrayTypeTest.php create mode 100644 seed/php-sdk/imdb/tests/Seed/Core/SerializableType/EmptyArraysTest.php create mode 100644 seed/php-sdk/imdb/tests/Seed/Core/SerializableType/InvalidTypesTest.php create mode 100644 seed/php-sdk/imdb/tests/Seed/Core/SerializableType/MixedDateArrayTypeTest.php create mode 100644 seed/php-sdk/imdb/tests/Seed/Core/SerializableType/NestedUnionArrayTypeTest.php create mode 100644 seed/php-sdk/imdb/tests/Seed/Core/SerializableType/NullPropertyTypeTest.php create mode 100644 seed/php-sdk/imdb/tests/Seed/Core/SerializableType/NullableArrayTypeTest.php create mode 100644 seed/php-sdk/imdb/tests/Seed/Core/SerializableType/ScalarTypesTest.php create mode 100644 seed/php-sdk/imdb/tests/Seed/Core/SerializableType/TestTypeTest.php create mode 100644 seed/php-sdk/imdb/tests/Seed/Core/SerializableType/UnionArrayTypeTest.php rename seed/php-sdk/{serde-demo => imdb}/tests/Seed/Types/ExampleTypeTest.php (100%) delete mode 100644 seed/php-sdk/serde-demo/.github/workflows/ci.yml delete mode 100644 seed/php-sdk/serde-demo/.gitignore delete mode 100644 seed/php-sdk/serde-demo/.mock/definition/api.yml delete mode 100644 seed/php-sdk/serde-demo/.mock/definition/imdb.yml delete mode 100644 seed/php-sdk/serde-demo/.mock/fern.config.json delete mode 100644 seed/php-sdk/serde-demo/.mock/generators.yml delete mode 100644 seed/php-sdk/serde-demo/composer.json delete mode 100644 seed/php-sdk/serde-demo/phpstan.neon delete mode 100644 seed/php-sdk/serde-demo/phpunit.xml delete mode 100644 seed/php-sdk/serde-demo/snippet-templates.json delete mode 100644 seed/php-sdk/serde-demo/snippet.json delete mode 100644 seed/php-sdk/serde-demo/src/Core/ArrayType.php delete mode 100644 seed/php-sdk/serde-demo/src/Core/BaseApiRequest.php delete mode 100644 seed/php-sdk/serde-demo/src/Core/HttpMethod.php delete mode 100644 seed/php-sdk/serde-demo/src/Core/JsonApiRequest.php delete mode 100644 seed/php-sdk/serde-demo/src/Core/RawClient.php delete mode 100644 seed/php-sdk/serde-demo/src/Core/SerializableType.php delete mode 100644 seed/php-sdk/serde-demo/src/Placeholder/Placeholder.php delete mode 100644 seed/php-sdk/serde-demo/tests/Seed/Core/RawClientTest.php delete mode 100644 seed/php-sdk/serde-demo/tests/Seed/Core/SerializableTypeTest.php diff --git a/seed/php-sdk/imdb/src/Core/ArrayType.php b/seed/php-sdk/imdb/src/Core/ArrayType.php new file mode 100644 index 00000000000..ff8257183cc --- /dev/null +++ b/seed/php-sdk/imdb/src/Core/ArrayType.php @@ -0,0 +1,35 @@ + 'valueType'] for maps, or ['valueType'] for lists + */ + public function __construct(public array $type) {} +} + +class Union { + /** + * @var string[] + */ + public array $types; + public function __construct(string ...$strings) { + $this->types = $strings; + } + + /** + * Check if a given type is part of the union. + * + * @param mixed $type + * @return bool + */ + public function contains($type): bool + { + return in_array($type, $this->types, true); + } +} \ No newline at end of file diff --git a/seed/php-sdk/serde-demo/src/Core/DateType.php b/seed/php-sdk/imdb/src/Core/DateType.php similarity index 100% rename from seed/php-sdk/serde-demo/src/Core/DateType.php rename to seed/php-sdk/imdb/src/Core/DateType.php diff --git a/seed/php-sdk/serde-demo/src/Core/JsonProperty.php b/seed/php-sdk/imdb/src/Core/JsonProperty.php similarity index 100% rename from seed/php-sdk/serde-demo/src/Core/JsonProperty.php rename to seed/php-sdk/imdb/src/Core/JsonProperty.php diff --git a/seed/php-sdk/imdb/src/Core/SerializableType.php b/seed/php-sdk/imdb/src/Core/SerializableType.php new file mode 100644 index 00000000000..57b1823e53a --- /dev/null +++ b/seed/php-sdk/imdb/src/Core/SerializableType.php @@ -0,0 +1,386 @@ +toArray(); + return json_encode($arrayData, JSON_THROW_ON_ERROR); + } + + /** + * Serializes the object to an array for JSON encoding. + * + * @return array + */ + public function toArray(): array + { + $result = []; + $reflectionClass = new \ReflectionClass($this); + + foreach ($reflectionClass->getProperties() as $property) { + $jsonKey = self::getJsonKey($property); + $value = $property->getValue($this); + + // Handle DateTime properties + $dateTypeAttr = $property->getAttributes(DateType::class)[0] ?? null; + if ($dateTypeAttr && $value instanceof DateTime) { + $dateType = $dateTypeAttr->newInstance()->type; + $value = ($dateType === DateType::TYPE_DATE) + ? $value->format('Y-m-d') + : $value->format(DateTime::RFC3339); + } + + // Handle arrays with type annotations + $arrayTypeAttr = $property->getAttributes(ArrayType::class)[0] ?? null; + if ($arrayTypeAttr && is_array($value)) { + $arrayType = $arrayTypeAttr->newInstance()->type; + $value = self::serializeGenericArray($value, $arrayType); + } + + if ($value !== null) { + $result[$jsonKey] = $value; + } + } + + return $result; + } + + /** + * Serializes the given array based on the type annotation. + * + * @param array $data The array to be serialized. + * @param array $type The type definition from the annotation. + * @return array The serialized array. + */ + private static function serializeGenericArray(array $data, array $type): array + { + return self::isMapType($type) + ? self::serializeMap($data, $type) + : self::serializeList($data, $type); + } + + /** + * Serializes a value based on the type definition. + * + * @param mixed $data The value to serialize. + * @param mixed $type The type definition. + * @return mixed The serialized value. + */ + private static function serializeValue($data, $type) + { + if ($type instanceof Union) { + foreach ($type->types as $unionType) { + try { + return self::serializeSingleValue($data, $unionType); + } catch (Exception $e) { + continue; + } + } + throw new \InvalidArgumentException("Cannot serialize value with any of the union types."); + } + + return self::serializeSingleValue($data, $type); + } + + /** + * Serializes a single value based on its type. + * + * @param mixed $data The value to serialize. + * @param string $type The expected type. + * @return mixed The serialized value. + */ + private static function serializeSingleValue($data, $type) + { + if (is_array($type)) { + return self::serializeGenericArray($data, $type); + } + if ($type === 'null' && $data === null) { + return null; + } + + if (($type === 'date' || $type === 'datetime') && $data instanceof DateTime) { + return $type === 'date' ? $data->format('Y-m-d') : $data->format(DateTime::RFC3339); + } + + if (class_exists($type) && $data instanceof $type) { + if (method_exists($data, 'toArray')) { + return $data->toArray(); + } else { + throw new \InvalidArgumentException("Class $type must implement toArray method."); + } + } + + if (gettype($data) === $type) { + return $data; + } + + throw new \InvalidArgumentException("Unable to serialize value of type '" . gettype($data) . "' as '$type'."); + } + + /** + * Serializes a map (associative array) where key and value types are defined. + * + * @param array $data The associative array to serialize. + * @param array $type The type definition for the map. + * @return array The serialized map. + */ + private static function serializeMap(array $data, array $type): array + { + $keyType = array_key_first($type); + $valueType = $type[$keyType]; + $result = []; + + foreach ($data as $key => $item) { + $key = self::castKey($key, $keyType); + $result[$key] = self::serializeValue($item, $valueType); + } + + return $result; + } + + /** + * Serializes a list (indexed array) where only the value type is defined. + * + * @param array $data The list to serialize. + * @param array $type The type definition for the list. + * @return array The serialized list. + */ + private static function serializeList(array $data, array $type): array + { + $valueType = $type[0]; + return array_map(fn($item) => self::serializeValue($item, $valueType), $data); + } + + /** + * Helper function to retrieve the JSON key for a property. + * + * @param ReflectionProperty $property + * @return string + */ + private static function getJsonKey(ReflectionProperty $property): string + { + $jsonPropertyAttr = $property->getAttributes(JsonProperty::class)[0] ?? null; + return $jsonPropertyAttr ? $jsonPropertyAttr->newInstance()->name : $property->getName(); + } + + /** + * Casts the key to the appropriate type based on the key type. + * + * @param mixed $key The key to be cast. + * @param string $keyType The type to cast the key to ('string', 'integer', 'float'). + * @return mixed The casted key. + */ + private static function castKey(mixed $key, string $keyType): mixed + { + return match ($keyType) { + 'integer' => (int)$key, + 'float' => (float)$key, + 'string' => (string)$key, + default => $key, + }; + } + + /** + * Determines if the given type represents a map. + * + * @param array $type The type definition from the annotation. + * @return bool True if the type is a map, false if it's a list. + */ + private static function isMapType(array $type): bool + { + return count($type) === 1 && !array_is_list($type); + } + + /** + * Deserializes a JSON string into an object of the calling class. + * + * @param string $json The JSON string to deserialize. + * @return static + */ + public static function fromJson(string $json): static + { + $arrayData = json_decode($json, true); + + if (!is_array($arrayData)) { + throw new InvalidArgumentException('Invalid JSON provided or JSON does not decode to an array.'); + } + + return static::fromArray($arrayData); + } + + /** + * Deserializes an array into an object of the calling class. + * + * @param array $data The array to deserialize. + * @return static + */ + public static function fromArray(array $data): static + { + $reflectionClass = new \ReflectionClass(static::class); + $constructor = $reflectionClass->getConstructor(); + $parameters = $constructor->getParameters(); + $args = []; + + foreach ($parameters as $parameter) { + $propertyName = $parameter->getName(); + + if ($reflectionClass->hasProperty($propertyName)) { + $property = $reflectionClass->getProperty($propertyName); + } else { + continue; + } + + $jsonKey = self::getJsonKey($property); + if (array_key_exists($jsonKey, $data)) { + $value = $data[$jsonKey]; + + // Handle DateType annotation + $dateTypeAttr = $property->getAttributes(DateType::class)[0] ?? null; + if ($dateTypeAttr) { + $dateType = $dateTypeAttr->newInstance()->type; + $value = ($dateType === DateType::TYPE_DATE) + ? DateTime::createFromFormat('!Y-m-d', $value) + : new DateTime($value); + } + + // Handle ArrayType annotation + $arrayTypeAttr = $property->getAttributes(ArrayType::class)[0] ?? null; + if (is_array($value) && $arrayTypeAttr) { + $arrayType = $arrayTypeAttr->newInstance()->type; + $value = self::deserializeGenericArray($value, $arrayType); + } + + $args[$parameter->getPosition()] = $value; + } else { + $args[$parameter->getPosition()] = $parameter->isDefaultValueAvailable() ? $parameter->getDefaultValue() : null; + } + } + + return new static(...$args); + } + + /** + * Deserializes the given array based on the type annotation. + * + * @param array $data The array to be deserialized. + * @param array $type The type definition from the annotation. + * @return array The deserialized array. + */ + private static function deserializeGenericArray(array $data, array $type): array + { + return self::isMapType($type) + ? self::deserializeMap($data, $type) + : self::deserializeList($data, $type); + } + + /** + * Deserializes a value based on the type definition. + * + * @param mixed $data The data to deserialize. + * @param array|Union|string $type The type definition. + * @return mixed The deserialized value. + */ + private static function deserializeValue(mixed $data, array|Union|string $type): mixed + { + if (is_array($type)) { + return self::deserializeGenericArray((array)$data, $type); + } + if ($type instanceof Union) { + foreach ($type->types as $unionType) { + try { + return self::deserializeSingleValue($data, $unionType); + } catch (Exception $e) { + continue; + } + } + throw new \InvalidArgumentException("Cannot deserialize value with any of the union types."); + } + + return self::deserializeSingleValue($data, $type); + } + + /** + * Deserializes a single value based on its type. + * + * @param mixed $data The data to deserialize. + * @param string $type The expected type. + * @return mixed The deserialized value. + */ + private static function deserializeSingleValue(mixed $data, string $type) + { + if ($type === 'null' && $data === null) { + return null; + } + + if ($type === 'date' && is_string($data)) { + return DateTime::createFromFormat('!Y-m-d', $data); + } + + if ($type === 'datetime' && is_string($data)) { + return new DateTime($data); + } + + if (class_exists($type) && is_array($data)) { + return $type::fromArray($data); + } + + if (gettype($data) === $type) { + return $data; + } + + throw new \InvalidArgumentException("Unable to deserialize value of type '" . gettype($data) . "' as '$type'."); + } + + /** + * Deserializes a map (associative array) where key and value types are defined. + * + * @param array $data The associative array to deserialize. + * @param array $type The type definition for the map. + * @return array The deserialized map. + */ + private static function deserializeMap(array $data, array $type): array + { + $keyType = array_key_first($type); + $valueType = $type[$keyType]; + $result = []; + + foreach ($data as $key => $item) { + $key = self::castKey($key, $keyType); + $result[$key] = self::deserializeValue($item, $valueType); + } + + return $result; + } + + /** + * Deserializes a list (indexed array) where only the value type is defined. + * + * @param array $data The list to deserialize. + * @param array $type The type definition for the list. + * @return array The deserialized list. + */ + private static function deserializeList(array $data, array $type): array + { + $valueType = $type[0]; + return array_map(fn($item) => self::deserializeValue($item, $valueType), $data); + } +} \ No newline at end of file diff --git a/seed/php-sdk/serde-demo/src/Types/ExampleNestedType.php b/seed/php-sdk/imdb/src/Types/ExampleNestedType.php similarity index 100% rename from seed/php-sdk/serde-demo/src/Types/ExampleNestedType.php rename to seed/php-sdk/imdb/src/Types/ExampleNestedType.php diff --git a/seed/php-sdk/serde-demo/src/Types/ExampleType.php b/seed/php-sdk/imdb/src/Types/ExampleType.php similarity index 100% rename from seed/php-sdk/serde-demo/src/Types/ExampleType.php rename to seed/php-sdk/imdb/src/Types/ExampleType.php diff --git a/seed/php-sdk/serde-demo/src/Types/WeatherReport.php b/seed/php-sdk/imdb/src/Types/WeatherReport.php similarity index 100% rename from seed/php-sdk/serde-demo/src/Types/WeatherReport.php rename to seed/php-sdk/imdb/src/Types/WeatherReport.php diff --git a/seed/php-sdk/imdb/tests/Seed/Core/RawClientTest.php b/seed/php-sdk/imdb/tests/Seed/Core/RawClientTest.php index 5cae4a4299b..7b0e35d60ec 100644 --- a/seed/php-sdk/imdb/tests/Seed/Core/RawClientTest.php +++ b/seed/php-sdk/imdb/tests/Seed/Core/RawClientTest.php @@ -1,6 +1,6 @@ ['2023-01-01', '2023-02-01', '2023-03-01'] + ]; + + $json = json_encode($data, JSON_THROW_ON_ERROR); + + $object = DateArrayType::fromJson($json); + + $this->assertInstanceOf(DateTime::class, $object->dates[0], 'dates[0] should be a DateTime instance.'); + $this->assertEquals('2023-01-01', $object->dates[0]->format('Y-m-d'), 'dates[0] should have the correct date.'); + $this->assertInstanceOf(DateTime::class, $object->dates[1], 'dates[1] should be a DateTime instance.'); + $this->assertEquals('2023-02-01', $object->dates[1]->format('Y-m-d'), 'dates[1] should have the correct date.'); + $this->assertInstanceOf(DateTime::class, $object->dates[2], 'dates[2] should be a DateTime instance.'); + $this->assertEquals('2023-03-01', $object->dates[2]->format('Y-m-d'), 'dates[2] should have the correct date.'); + + $serializedJson = $object->toJson(); + + $this->assertJsonStringEqualsJsonString($json, $serializedJson, 'Serialized JSON does not match original JSON for dates array.'); + } +} \ No newline at end of file diff --git a/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/EmptyArraysTest.php b/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/EmptyArraysTest.php new file mode 100644 index 00000000000..7735feaa598 --- /dev/null +++ b/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/EmptyArraysTest.php @@ -0,0 +1,58 @@ + new Union('string', 'null')])] + #[JsonProperty('empty_map_array')] + public array $emptyMapArray, + + #[ArrayType([new Union('date', 'null')])] + #[JsonProperty('empty_dates_array')] + public array $emptyDatesArray + ) + { + } +} + +class EmptyArraysTestTest extends TestCase +{ + public function testEmptyArrays() + { + // Create test data with empty arrays + $data = [ + 'empty_string_array' => [], + 'empty_map_array' => [], + 'empty_dates_array' => [] + ]; + + // Convert data to JSON + $json = json_encode($data, JSON_THROW_ON_ERROR); + + // Deserialize JSON to object + $object = EmptyArraysTest::fromJson($json); + + // Serialize object back to JSON + $serializedJson = $object->toJson(); + + // Compare serialized JSON with original JSON + $this->assertJsonStringEqualsJsonString($json, $serializedJson, 'Serialized JSON does not match original JSON for EmptyArraysTest.'); + + // Check that arrays are empty + $this->assertEmpty($object->emptyStringArray, 'empty_string_array should be empty.'); + $this->assertEmpty($object->emptyMapArray, 'empty_map_array should be empty.'); + $this->assertEmpty($object->emptyDatesArray, 'empty_dates_array should be empty.'); + } +} \ No newline at end of file diff --git a/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/InvalidTypesTest.php b/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/InvalidTypesTest.php new file mode 100644 index 00000000000..cb3c19f080e --- /dev/null +++ b/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/InvalidTypesTest.php @@ -0,0 +1,36 @@ + 'not_an_integer' + ]; + + $json = json_encode($data, JSON_THROW_ON_ERROR); + + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage("Unable to deserialize value of type 'string' as 'integer'."); + + // Attempt to deserialize invalid data + $object = InvalidTypesTest::fromJson($json); + } +} \ No newline at end of file diff --git a/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/MixedDateArrayTypeTest.php b/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/MixedDateArrayTypeTest.php new file mode 100644 index 00000000000..639f80759a9 --- /dev/null +++ b/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/MixedDateArrayTypeTest.php @@ -0,0 +1,50 @@ + new Union('datetime', 'string', 'null')])] + #[JsonProperty('mixed_dates')] + public array $mixedDates + ) + { + } +} + +class MixedDateArrayTypeTest extends TestCase +{ + public function testDateTimeTypesInUnionArrays() + { + $data = [ + 'mixed_dates' => [ + 1 => '2023-01-01T12:00:00+00:00', + 2 => null, + 3 => 'Some String' + ] + ]; + + $json = json_encode($data, JSON_THROW_ON_ERROR); + + $object = MixedDateArrayType::fromJson($json); + + $this->assertInstanceOf(DateTime::class, $object->mixedDates[1], 'mixed_dates[1] should be a DateTime instance.'); + $this->assertEquals('2023-01-01 12:00:00', $object->mixedDates[1]->format('Y-m-d H:i:s'), 'mixed_dates[1] should have the correct datetime.'); + + $this->assertNull($object->mixedDates[2], 'mixed_dates[2] should be null.'); + + $this->assertEquals('Some String', $object->mixedDates[3], 'mixed_dates[3] should be "Some String".'); + + $serializedJson = $object->toJson(); + + $this->assertJsonStringEqualsJsonString($json, $serializedJson, 'Serialized JSON does not match original JSON for mixed_dates.'); + } +} \ No newline at end of file diff --git a/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/NestedUnionArrayTypeTest.php b/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/NestedUnionArrayTypeTest.php new file mode 100644 index 00000000000..137f709bba0 --- /dev/null +++ b/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/NestedUnionArrayTypeTest.php @@ -0,0 +1,81 @@ +> $nestedArray + */ + public function __construct( + #[ArrayType(['integer' => ['integer' => new Union(TestNestedType::class, 'null', 'date')]])] + #[JsonProperty('nested_array')] + public array $nestedArray + ) + { + } +} + +class NestedUnionArrayTypeTest extends TestCase +{ + public function testNestedUnionTypesInArrays() + { + $data = [ + 'nested_array' => [ + 1 => [ + 1 => ['nested_property' => 'Nested One'], + 2 => null, + 4 => '2023-01-02' + ], + 2 => [ + 5 => ['nested_property' => 'Nested Two'], + 7 => '2023-02-02' + ] + ] + ]; + + $json = json_encode($data, JSON_THROW_ON_ERROR); + + $object = NestedUnionArrayType::fromJson($json); + + // Level 1 + $this->assertInstanceOf(TestNestedType::class, $object->nestedArray[1][1], 'nested_array[1][1] should be an instance of TestNestedType.'); + $this->assertEquals('Nested One', $object->nestedArray[1][1]->nestedProperty, 'nested_array[1][1]->nestedProperty should match the original data.'); + + $this->assertNull($object->nestedArray[1][2], 'nested_array[1][2] should be null.'); + + // ensure dates are set with the default time + $this->assertInstanceOf(DateTime::class, $object->nestedArray[1][4], 'nested_array[1][4] should be a DateTime instance.'); + $this->assertEquals('2023-01-02 00:00:00', $object->nestedArray[1][4]->format('Y-m-d H:i:s'), 'nested_array[1][4] should have the correct datetime.'); + + // Level 2 + $this->assertInstanceOf(TestNestedType::class, $object->nestedArray[2][5], 'nested_array[2][5] should be an instance of TestNestedType.'); + $this->assertEquals('Nested Two', $object->nestedArray[2][5]->nestedProperty, 'nested_array[2][5]->nestedProperty should match the original data.'); + + $this->assertInstanceOf(DateTime::class, $object->nestedArray[2][7], 'nested_array[1][4] should be a DateTime instance.'); + $this->assertEquals('2023-02-02', $object->nestedArray[2][7]->format('Y-m-d'), 'nested_array[1][4] should have the correct date.'); + + $serializedJson = $object->toJson(); + + $this->assertJsonStringEqualsJsonString($json, $serializedJson, 'Serialized JSON does not match original JSON for nested_array.'); + } +} \ No newline at end of file diff --git a/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/NullPropertyTypeTest.php b/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/NullPropertyTypeTest.php new file mode 100644 index 00000000000..5fb0f597e55 --- /dev/null +++ b/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/NullPropertyTypeTest.php @@ -0,0 +1,37 @@ +toJson(); + + $data = json_decode($json, true, JSON_THROW_ON_ERROR); + + $this->assertArrayHasKey('non_null_property', $data, 'non_null_property should be present in the serialized JSON.'); + $this->assertArrayNotHasKey('null_property', $data, 'null_property should be omitted from the serialized JSON.'); + + $this->assertEquals('Test String', $data['non_null_property'], 'non_null_property should have the correct value.'); + } +} \ No newline at end of file diff --git a/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/NullableArrayTypeTest.php b/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/NullableArrayTypeTest.php new file mode 100644 index 00000000000..94c6c7b46bf --- /dev/null +++ b/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/NullableArrayTypeTest.php @@ -0,0 +1,41 @@ + ['one', null, 'three'] + ]; + + $json = json_encode($data, JSON_THROW_ON_ERROR); + + $object = NullableArrayType::fromJson($json); + + $this->assertEquals(['one', null, 'three'], $object->nullableStringArray, 'nullable_string_array should match the original data.'); + + $serializedJson = $object->toJson(); + + $this->assertJsonStringEqualsJsonString($json, $serializedJson, 'Serialized JSON does not match original JSON for nullable_string_array.'); + } +} \ No newline at end of file diff --git a/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/ScalarTypesTest.php b/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/ScalarTypesTest.php new file mode 100644 index 00000000000..685f1ab4763 --- /dev/null +++ b/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/ScalarTypesTest.php @@ -0,0 +1,73 @@ + 42, + 'float_property' => 3.14159, + 'boolean_property' => true, + 'string_property' => 'Hello, World!', + 'nullable_boolean_property' => null, + 'int_float_array' => [1, 2.5, 3, 4.75] + ]; + + // Convert data to JSON + $json = json_encode($data, JSON_THROW_ON_ERROR); + + // Deserialize JSON to object + $object = ScalarTypesTest::fromJson($json); + + // Serialize object back to JSON + $serializedJson = $object->toJson(); + + // Compare serialized JSON with original JSON + $this->assertJsonStringEqualsJsonString($json, $serializedJson, 'Serialized JSON does not match original JSON for ScalarTypesTest.'); + + // Check scalar properties + $this->assertEquals(42, $object->integerProperty, 'integer_property should be 42.'); + $this->assertEquals(3.14159, $object->floatProperty, 'float_property should be 3.14159.'); + $this->assertTrue($object->booleanProperty, 'boolean_property should be true.'); + $this->assertEquals('Hello, World!', $object->stringProperty, 'string_property should be "Hello, World!".'); + $this->assertNull($object->nullableBooleanProperty, 'nullable_boolean_property should be null.'); + + // Check int_float_array + $this->assertEquals([1, 2.5, 3, 4.75], $object->intFloatArray, 'int_float_array should match the original data.'); + } +} \ No newline at end of file diff --git a/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/TestTypeTest.php b/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/TestTypeTest.php new file mode 100644 index 00000000000..dc0b5bb5dba --- /dev/null +++ b/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/TestTypeTest.php @@ -0,0 +1,140 @@ + 'integer'])] + #[JsonProperty('map_property')] + public array $mapProperty, + + // Array of objects or null using Union + #[ArrayType(['integer' => new Union(TestNestedType1::class, 'null')])] + #[JsonProperty('object_array')] + public array $objectArray, + + // Nested array with union types (string|null) + #[ArrayType(['integer' => ['integer' => new Union('string', 'null')]])] + #[JsonProperty('nested_array')] + public array $nestedArray, + + // Array of dates or null using Union + #[ArrayType([new Union('date', 'null')])] + #[JsonProperty('dates_array')] + public array $datesArray, + + #[JsonProperty('nullable_property')] + public ?string $nullableProperty = null // Optional parameter at the end + ) + { + } +} + +class TestTypeTest extends TestCase +{ + /** + * Test serialization and deserialization of all types in TestType + */ + public function testSerializationAndDeserialization(): void + { + // Create test data + $data = [ + 'simple_property' => 'Test String', + // 'nullable_property' is omitted to test null serialization + 'date_property' => '2023-01-01', + 'datetime_property' => '2023-01-01T12:34:56+00:00', + 'string_array' => ['one', 'two', 'three'], + 'map_property' => ['key1' => 1, 'key2' => 2], + 'object_array' => [ + 1 => ['nested_property' => 'Nested One'], + 2 => null, // Testing nullable objects in array + ], + 'nested_array' => [ + 1 => [1 => 'value1', 2 => null], // Testing nullable strings in nested array + 2 => [3 => 'value3', 4 => 'value4'] + ], + 'dates_array' => ['2023-01-01', null, '2023-03-01'] // Testing nullable dates in array + ]; + + // Convert data to JSON + $json = json_encode($data, JSON_THROW_ON_ERROR); + + // Deserialize JSON to object + $object = TestType::fromJson($json); + + // Serialize object back to JSON + $serializedJson = $object->toJson(); + + // Compare serialized JSON with original JSON + $this->assertJsonStringEqualsJsonString($json, $serializedJson, 'The serialized JSON does not match the original JSON.'); + + // Check that nullable property is null and not included in JSON + $this->assertNull($object->nullableProperty, 'Nullable property should be null.'); + $this->assertFalse(array_key_exists('nullable_property', json_decode($serializedJson, true)), 'Nullable property should be omitted from JSON.'); + + // Check date properties + $this->assertInstanceOf(DateTime::class, $object->dateProperty, 'date_property should be a DateTime instance.'); + $this->assertEquals('2023-01-01', $object->dateProperty->format('Y-m-d'), 'date_property should have the correct date.'); + + $this->assertInstanceOf(DateTime::class, $object->datetimeProperty, 'datetime_property should be a DateTime instance.'); + $this->assertEquals('2023-01-01 12:34:56', $object->datetimeProperty->format('Y-m-d H:i:s'), 'datetime_property should have the correct datetime.'); + + // Check scalar arrays + $this->assertEquals(['one', 'two', 'three'], $object->stringArray, 'string_array should match the original data.'); + $this->assertEquals(['key1' => 1, 'key2' => 2], $object->mapProperty, 'map_property should match the original data.'); + + // Check object array with nullable elements + $this->assertInstanceOf(TestNestedType1::class, $object->objectArray[1], 'object_array[1] should be an instance of TestNestedType1.'); + $this->assertEquals('Nested One', $object->objectArray[1]->nestedProperty, 'object_array[1]->nestedProperty should match the original data.'); + $this->assertNull($object->objectArray[2], 'object_array[2] should be null.'); + + // Check nested array with nullable strings + $this->assertEquals('value1', $object->nestedArray[1][1], 'nested_array[1][1] should match the original data.'); + $this->assertNull($object->nestedArray[1][2], 'nested_array[1][2] should be null.'); + $this->assertEquals('value3', $object->nestedArray[2][3], 'nested_array[2][3] should match the original data.'); + $this->assertEquals('value4', $object->nestedArray[2][4], 'nested_array[2][4] should match the original data.'); + + // Check dates array with nullable DateTime objects + $this->assertInstanceOf(DateTime::class, $object->datesArray[0], 'dates_array[0] should be a DateTime instance.'); + $this->assertEquals('2023-01-01', $object->datesArray[0]->format('Y-m-d'), 'dates_array[0] should have the correct date.'); + $this->assertNull($object->datesArray[1], 'dates_array[1] should be null.'); + $this->assertInstanceOf(DateTime::class, $object->datesArray[2], 'dates_array[2] should be a DateTime instance.'); + $this->assertEquals('2023-03-01', $object->datesArray[2]->format('Y-m-d'), 'dates_array[2] should have the correct date.'); + } +} \ No newline at end of file diff --git a/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/UnionArrayTypeTest.php b/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/UnionArrayTypeTest.php new file mode 100644 index 00000000000..4fb966fcbfc --- /dev/null +++ b/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/UnionArrayTypeTest.php @@ -0,0 +1,47 @@ + new Union('string', 'integer', 'null')])] + #[JsonProperty('mixed_array')] + public array $mixedArray + ) + { + } +} + +class UnionArrayTypeTest extends TestCase +{ + public function testUnionTypesInArrays() + { + $data = [ + 'mixed_array' => [ + 1 => 'one', + 2 => 2, + 3 => null + ] + ]; + + $json = json_encode($data, JSON_THROW_ON_ERROR); + + $object = UnionArrayType::fromJson($json); + + $this->assertEquals('one', $object->mixedArray[1], 'mixed_array[1] should be "one".'); + $this->assertEquals(2, $object->mixedArray[2], 'mixed_array[2] should be 2.'); + $this->assertNull($object->mixedArray[3], 'mixed_array[3] should be null.'); + + $serializedJson = $object->toJson(); + + $this->assertJsonStringEqualsJsonString($json, $serializedJson, 'Serialized JSON does not match original JSON for mixed_array.'); + } +} \ No newline at end of file diff --git a/seed/php-sdk/serde-demo/tests/Seed/Types/ExampleTypeTest.php b/seed/php-sdk/imdb/tests/Seed/Types/ExampleTypeTest.php similarity index 100% rename from seed/php-sdk/serde-demo/tests/Seed/Types/ExampleTypeTest.php rename to seed/php-sdk/imdb/tests/Seed/Types/ExampleTypeTest.php diff --git a/seed/php-sdk/serde-demo/.github/workflows/ci.yml b/seed/php-sdk/serde-demo/.github/workflows/ci.yml deleted file mode 100644 index 4b99e5562ee..00000000000 --- a/seed/php-sdk/serde-demo/.github/workflows/ci.yml +++ /dev/null @@ -1,46 +0,0 @@ -name: ci - -on: [push] - -jobs: - compile: - runs-on: ubuntu-latest - - steps: - - name: Checkout repo - uses: actions/checkout@v4 - - - name: Setup Composer - uses: php-actions/composer@v6 - with: - php_version: "8.1" - version: "2.7.9" - - - name: Install tools - run: | - composer install - - - name: Build - run: | - composer build - - unit-tests: - runs-on: ubuntu-latest - - steps: - - name: Checkout repo - uses: actions/checkout@v4 - - - name: Setup Composer - uses: php-actions/composer@v6 - with: - php_version: "8.1" - version: "2.7.9" - - - name: Install tools - run: | - composer install - - - name: Run Tests - run: | - composer test \ No newline at end of file diff --git a/seed/php-sdk/serde-demo/.gitignore b/seed/php-sdk/serde-demo/.gitignore deleted file mode 100644 index f38efc46ade..00000000000 --- a/seed/php-sdk/serde-demo/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -.php-cs-fixer.cache -.phpunit.result.cache -composer.lock -vendor/ \ No newline at end of file diff --git a/seed/php-sdk/serde-demo/.mock/definition/api.yml b/seed/php-sdk/serde-demo/.mock/definition/api.yml deleted file mode 100644 index c437dc0ab29..00000000000 --- a/seed/php-sdk/serde-demo/.mock/definition/api.yml +++ /dev/null @@ -1,4 +0,0 @@ -name: api -error-discrimination: - strategy: status-code -auth: bearer diff --git a/seed/php-sdk/serde-demo/.mock/definition/imdb.yml b/seed/php-sdk/serde-demo/.mock/definition/imdb.yml deleted file mode 100644 index 7919173fe57..00000000000 --- a/seed/php-sdk/serde-demo/.mock/definition/imdb.yml +++ /dev/null @@ -1,42 +0,0 @@ -types: - MovieId: string - - Movie: - properties: - id: MovieId - title: string - rating: - type: double - docs: The rating scale is one to five stars - - CreateMovieRequest: - properties: - title: string - rating: double - -service: - auth: false - base-path: /movies - endpoints: - createMovie: - docs: Add a movie to the database - method: POST - path: /create-movie - request: CreateMovieRequest - response: - type: MovieId - status-code: 201 - - getMovie: - method: GET - path: /{movieId} - path-parameters: - movieId: MovieId - response: Movie - errors: - - MovieDoesNotExistError - -errors: - MovieDoesNotExistError: - status-code: 404 - type: MovieId diff --git a/seed/php-sdk/serde-demo/.mock/fern.config.json b/seed/php-sdk/serde-demo/.mock/fern.config.json deleted file mode 100644 index 4c8e54ac313..00000000000 --- a/seed/php-sdk/serde-demo/.mock/fern.config.json +++ /dev/null @@ -1 +0,0 @@ -{"organization": "fern-test", "version": "*"} \ No newline at end of file diff --git a/seed/php-sdk/serde-demo/.mock/generators.yml b/seed/php-sdk/serde-demo/.mock/generators.yml deleted file mode 100644 index 0967ef424bc..00000000000 --- a/seed/php-sdk/serde-demo/.mock/generators.yml +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/seed/php-sdk/serde-demo/composer.json b/seed/php-sdk/serde-demo/composer.json deleted file mode 100644 index 7f5821806d4..00000000000 --- a/seed/php-sdk/serde-demo/composer.json +++ /dev/null @@ -1,40 +0,0 @@ - -{ - "name": "seed/seed", - "version": "0.0.1", - "description": "Seed PHP Library", - "keywords": [ - "seed", - "api", - "sdk" - ], - "license": [], - "require": { - "php": "^8.1", - "ext-json": "*", - "guzzlehttp/guzzle": "^7.9" - }, - "require-dev": { - "phpunit/phpunit": "^9.0", - "friendsofphp/php-cs-fixer": "3.5.0", - "phpstan/phpstan": "^1.12" - }, - "autoload": { - "psr-4": { - "Seed\\": "src/" - } - }, - "autoload-dev": { - "psr-4": { - "\\Seed\\Tests\\": "tests/" - } - }, - "scripts": { - "build": [ - "@php -l src", - "@php -l tests" - ], - "test": "phpunit", - "analyze": "phpstan analyze src" - } -} diff --git a/seed/php-sdk/serde-demo/phpstan.neon b/seed/php-sdk/serde-demo/phpstan.neon deleted file mode 100644 index 29a11a92a19..00000000000 --- a/seed/php-sdk/serde-demo/phpstan.neon +++ /dev/null @@ -1,5 +0,0 @@ -parameters: - level: max - paths: - - src - - tests \ No newline at end of file diff --git a/seed/php-sdk/serde-demo/phpunit.xml b/seed/php-sdk/serde-demo/phpunit.xml deleted file mode 100644 index 54630a51163..00000000000 --- a/seed/php-sdk/serde-demo/phpunit.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - tests - - - \ No newline at end of file diff --git a/seed/php-sdk/serde-demo/snippet-templates.json b/seed/php-sdk/serde-demo/snippet-templates.json deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/seed/php-sdk/serde-demo/snippet.json b/seed/php-sdk/serde-demo/snippet.json deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/seed/php-sdk/serde-demo/src/Core/ArrayType.php b/seed/php-sdk/serde-demo/src/Core/ArrayType.php deleted file mode 100644 index ba358598a29..00000000000 --- a/seed/php-sdk/serde-demo/src/Core/ArrayType.php +++ /dev/null @@ -1,14 +0,0 @@ - 'valueType'] for maps, or ['valueType'] for lists - */ - public function __construct(public array $type) {} -} diff --git a/seed/php-sdk/serde-demo/src/Core/BaseApiRequest.php b/seed/php-sdk/serde-demo/src/Core/BaseApiRequest.php deleted file mode 100644 index 2ace034ec90..00000000000 --- a/seed/php-sdk/serde-demo/src/Core/BaseApiRequest.php +++ /dev/null @@ -1,22 +0,0 @@ - $headers Additional headers for the request (optional) - * @param array $query Query parameters for the request (optional) - */ - public function __construct( - public readonly string $baseUrl, - public readonly string $path, - public readonly HttpMethod $method, - public readonly array $headers = [], - public readonly array $query = [], - ) { - } -} diff --git a/seed/php-sdk/serde-demo/src/Core/HttpMethod.php b/seed/php-sdk/serde-demo/src/Core/HttpMethod.php deleted file mode 100644 index 22cd7d22cd5..00000000000 --- a/seed/php-sdk/serde-demo/src/Core/HttpMethod.php +++ /dev/null @@ -1,12 +0,0 @@ - $headers Additional headers for the request (optional) - * @param array $query Query parameters for the request (optional) - * @param mixed|null $body The JSON request body (optional) - */ - public function __construct( - string $baseUrl, - string $path, - HttpMethod $method, - array $headers = [], - array $query = [], - public readonly mixed $body = null - ) { - parent::__construct($baseUrl, $path, $method, $headers, $query); - } -} diff --git a/seed/php-sdk/serde-demo/src/Core/RawClient.php b/seed/php-sdk/serde-demo/src/Core/RawClient.php deleted file mode 100644 index 94a2e71f81c..00000000000 --- a/seed/php-sdk/serde-demo/src/Core/RawClient.php +++ /dev/null @@ -1,123 +0,0 @@ - $headers The HTTP headers sent with the request. - */ - public function __construct( - private readonly ClientInterface $client, - private readonly array $headers = [], - ) { - } - - /** - * @throws ClientExceptionInterface - */ - public function sendRequest( - BaseApiRequest $request, - ): ResponseInterface { - $httpRequest = $this->buildRequest($request); - return $this->client->send($httpRequest); - } - - private function buildRequest( - BaseApiRequest $request - ): Request { - $url = $this->buildUrl($request); - $headers = $this->encodeHeaders($request); - $body = $this->encodeRequestBody($request); - return new Request( - $request->method->name, - $url, - $headers, - $body, - ); - } - - /** - * @return array - */ - private function encodeHeaders( - BaseApiRequest $request - ): array { - return match (get_class($request)) { - JsonApiRequest::class => array_merge( - ["Content-Type" => "application/json"], - $this->headers, - $request->headers - ), - default => throw new InvalidArgumentException('Unsupported request type: ' . get_class($request)), - }; - } - - private function encodeRequestBody( - BaseApiRequest $request - ): ?StreamInterface { - return match (get_class($request)) { - JsonApiRequest::class => $request->body != null ? Utils::streamFor(json_encode($request->body)) : null, - default => throw new InvalidArgumentException('Unsupported request type: '.get_class($request)), - }; - } - - private function buildUrl( - BaseApiRequest $request - ): string { - $baseUrl = $request->baseUrl; - $trimmedBaseUrl = rtrim($baseUrl, '/'); - $trimmedBasePath = ltrim($request->path, '/'); - $url = "{$trimmedBaseUrl}/{$trimmedBasePath}"; - - if (!empty($request->query)) { - $url .= '?' . $this->encodeQuery($request->query); - } - - return $url; - } - - /** - * @param array $query - */ - private function encodeQuery( - array $query - ): string { - $parts = []; - foreach ($query as $key => $value) { - if (is_array($value)) { - foreach ($value as $item) { - $parts[] = urlencode($key).'='.$this->encodeQueryValue($item); - } - } else { - $parts[] = urlencode($key).'='.$this->encodeQueryValue($value); - } - } - return implode('&', $parts); - } - - private function encodeQueryValue( - mixed $value - ): string { - if (is_string($value)) { - return urlencode($value); - } - if (is_scalar($value)) { - return urlencode((string)$value); - } - if (is_null($value)) { - return 'null'; - } - // Unreachable, but included for a best effort. - return urlencode(strval(json_encode($value))); - } -} diff --git a/seed/php-sdk/serde-demo/src/Core/SerializableType.php b/seed/php-sdk/serde-demo/src/Core/SerializableType.php deleted file mode 100644 index 22aec5c5cd2..00000000000 --- a/seed/php-sdk/serde-demo/src/Core/SerializableType.php +++ /dev/null @@ -1,448 +0,0 @@ -toArray(); - return json_encode($arrayData, JSON_THROW_ON_ERROR); - } - - /** - * Deserializes a JSON string into an object of the calling class. - * - * @param string $json The JSON string to deserialize. - * @return static - * - * @throws InvalidArgumentException if the JSON is invalid or does not decode to an array. - */ - public static function fromJson(string $json): static - { - $arrayData = json_decode($json, true); - - if (!is_array($arrayData)) { - throw new InvalidArgumentException('Invalid JSON provided or JSON does not decode to an array.'); - } - - return static::fromArray($arrayData); - } - - /** - * Deserializes an array into an object of the calling class. - * - * @param array $data The array to deserialize. - * @return static - * - * @throws LogicException if the class does not have a constructor. - */ - public static function fromArray(array $data): static - { - $reflectionClass = new ReflectionClass(static::class); - $constructor = $reflectionClass->getConstructor(); - if ($constructor === null) { - throw new LogicException('The class ' . static::class . ' must have a constructor.'); - } - $parameters = $constructor->getParameters(); - $args = []; - - foreach ($parameters as $parameter) { - $propertyName = $parameter->getName(); - - if ($reflectionClass->hasProperty($propertyName)) { - $property = $reflectionClass->getProperty($propertyName); - } else { - // Skip if the property does not exist - continue; - } - - $jsonKey = SerializableType::getJsonKey($property); - if (array_key_exists($jsonKey, $data)) { - $value = $data[$jsonKey]; - - // Handle DateType annotation - $dateTypeAttr = $property->getAttributes(DateType::class)[0] ?? null; - if ($dateTypeAttr) { - $dateType = $dateTypeAttr->newInstance()->type; - if ($dateType === DateType::TYPE_DATE) { - $value = DateTime::createFromFormat('Y-m-d', $value); - } else { - $value = new DateTime($value); - } - } - - // Handle ArrayType annotation - $arrayTypeAttr = $property->getAttributes(ArrayType::class)[0] ?? null; - if (is_array($value) && $arrayTypeAttr) { - $arrayType = $arrayTypeAttr->newInstance()->type; - $value = SerializableType::deserializeGenericArray($value, $arrayType); - } - - $args[$parameter->getPosition()] = $value; - } else { - // Use default value if available, else null - if ($parameter->isDefaultValueAvailable()) { - $args[$parameter->getPosition()] = $parameter->getDefaultValue(); - } else { - $args[$parameter->getPosition()] = null; - } - } - } - - // Instantiate the object with the collected arguments - return new static(...$args); - } - - /** - * Serializes the object to an array for JSON encoding. - * - * @return array - */ - public function toArray(): array - { - $result = []; - $reflectionClass = new ReflectionClass($this); - - foreach ($reflectionClass->getProperties() as $property) { - $jsonKey = SerializableType::getJsonKey($property); - $value = $property->getValue($this); - - // Skip properties with null values - if ($value === null) { - continue; - } - - // Handle DateTime properties - $dateTypeAttr = $property->getAttributes(DateType::class)[0] ?? null; - if ($dateTypeAttr && $value instanceof DateTime) { - $dateType = $dateTypeAttr->newInstance()->type; - if ($dateType === DateType::TYPE_DATE) { - $value = $value->format('Y-m-d'); - } else { - $value = $value->format(DateTime::RFC3339); - } - } - - // Handle arrays with type annotations - $arrayTypeAttr = $property->getAttributes(ArrayType::class)[0] ?? null; - if ($arrayTypeAttr && is_array($value)) { - $arrayType = $arrayTypeAttr->newInstance()->type; - $value = SerializableType::serializeGenericArray($value, $arrayType); - } - - $result[$jsonKey] = $value; - } - - return $result; - } - - /** - * Helper function to retrieve the JSON key for a property. - * - * @param ReflectionProperty $property - * @return string - */ - private static function getJsonKey(ReflectionProperty $property): string - { - $jsonPropertyAttr = $property->getAttributes(JsonProperty::class)[0] ?? null; - return $jsonPropertyAttr ? $jsonPropertyAttr->newInstance()->name : $property->getName(); - } - - /** - * Casts the key to the appropriate type based on the key type. - * - * @param mixed $key The key to be cast. - * @param string $keyType The type to cast the key to ('string', 'int', 'float'). - * @return mixed The casted key. - */ - private static function castKey(mixed $key, string $keyType): mixed - { - return match ($keyType) { - 'int' => (int)$key, - 'float' => (float)$key, - 'string' => (string)$key, - default => $key, - }; - } - - /** - * Determines if the given type represents a map. - * - * @param array $type The type definition from the annotation. - * @return bool True if the type is a map, false if it's a list. - */ - private static function isMapType(array $type): bool - { - return count($type) === 1 && !array_is_list($type); - } - - /** - * Serializes the given array based on the type annotation. - * - * @param array $data The array to be serialized. - * @param array $type The type definition from the annotation. - * @return array The serialized array. - */ - private static function serializeGenericArray(array $data, array $type): array - { - return self::isMapType($type) - ? self::serializeMap($data, $type) - : self::serializeList($data, $type); - } - - /** - * Serializes a map (associative array) where key and value types are defined. - * - * @param array $data The associative array to serialize. - * @param array $type The type definition for the map. - * @return array The serialized map. - */ - private static function serializeMap(array $data, array $type): array - { - $keyType = array_key_first($type); - $valueType = $type[$keyType]; - $result = []; - - foreach ($data as $key => $item) { - $key = SerializableType::castKey($key, $keyType); - - if (is_array($valueType)) { - $result[$key] = self::serializeGenericArray($item, $valueType); - } elseif (is_object($item) && method_exists($item, 'toArray')) { - $result[$key] = $item->toArray(); - } else { - $result[$key] = $item; - } - } - - return $result; - } - - private static function serializeList(array $data, array $type): array - { - $valueTypes = self::parseTypeExpression($type[0]); - - return array_map(function ($item) use ($valueTypes) { - foreach ($valueTypes as $expectedType) { - if ($expectedType === 'null' && $item === null) { - return null; - } - - if (($expectedType === 'date' || $expectedType === 'datetime') && $item instanceof DateTime) { - $format = $expectedType === 'date' ? 'Y-m-d' : DateTime::RFC3339; - return $item->format($format); - } - - if (class_exists($expectedType) && $item instanceof $expectedType) { - if (method_exists($item, 'toArray')) { - return $item->toArray(); - } else { - throw new \InvalidArgumentException("Class $expectedType must implement toArray method."); - } - } - - if (gettype($item) === $expectedType) { - return $item; - } - } - - throw new \InvalidArgumentException("Unable to serialize item of type '" . gettype($item) . "'."); - }, $data); - } - - /** - * Deserializes the given array based on the type annotation. - * - * @param array $data The array to be deserialized. - * @param array $type The type definition from the annotation. - * @return array The deserialized array. - */ - private static function deserializeGenericArray(array $data, array $type): array - { - return self::isMapType($type) - ? self::deserializeMap($data, $type) - : self::deserializeList($data, $type); - } - - private static function deserializeValue($item, $typeDef) - { - if (is_array($typeDef)) { - // Type definition is an array (complex type like map or list) - return self::deserializeGenericArray($item, $typeDef); - } else { - // Type definition is a string (possibly with union types) - $valueTypes = self::parseTypeExpression($typeDef); - - foreach ($valueTypes as $expectedType) { - // Handle 'null' type - if ($expectedType === 'null' && $item === null) { - return null; - } - - // Handle 'date' and 'datetime' types - if ($expectedType === 'date' && is_string($item)) { - $date = DateTime::createFromFormat('Y-m-d', $item); - if ($date !== false) { - return $date; - } - } elseif ($expectedType === 'datetime' && is_string($item)) { - try { - return new DateTime($item); - } catch (\Exception $e) { - // Invalid datetime - } - } - - // Handle class types - if (class_exists($expectedType) && is_array($item)) { - if (method_exists($expectedType, 'fromArray')) { - return $expectedType::fromArray($item); - } - } - - // Handle scalar types using is_* functions - if (($expectedType === 'int' && is_int($item)) || - ($expectedType === 'bool' && is_bool($item)) || - ($expectedType === 'float' && is_float($item)) || - ($expectedType === 'string' && is_string($item))) { - return $item; - } - } - - // If no matching type is found, throw an exception - throw new \InvalidArgumentException("Unable to deserialize value: type mismatch."); - } - } - - private static function deserializeMap(array $data, array $type): array - { - $keyType = array_key_first($type); - $valueTypeDef = $type[$keyType]; - $result = []; - - foreach ($data as $key => $item) { - $key = SerializableType::castKey($key, (string) $keyType); - - try { - $deserializedItem = self::deserializeValue($item, $valueTypeDef); - } catch (\InvalidArgumentException $e) { - throw new \InvalidArgumentException("Unable to deserialize map item with key '$key': " . $e->getMessage()); - } - - $result[$key] = $deserializedItem; - } - - return $result; - } - - /** - * Deserializes a list (indexed array) where only the value type is defined. - * - * @param array $data The list to deserialize. - * @param array $type The type definition for the list. - * @return array The deserialized list. - */ - private static function deserializeList(array $data, array $typeDef): array - { - $valueTypes = self::parseTypeDefinition($typeDef[0]); - - return array_map(function ($item) use ($valueTypes) { - foreach ($valueTypes as $expectedType) { - // Handle 'null' type - if ($expectedType === 'null' && $item === null) { - return null; - } - - // Handle 'date' and 'datetime' types - if ($expectedType === 'date' && is_string($item)) { - $date = DateTime::createFromFormat('Y-m-d', $item); - if ($date !== false) { - return $date; - } - } elseif ($expectedType === 'datetime' && is_string($item)) { - try { - return new DateTime($item); - } catch (\Exception $e) { - // Not a valid datetime - } - } - - // Handle class types - if (class_exists($expectedType) && is_array($item)) { - if (method_exists($expectedType, 'fromArray')) { - return $expectedType::fromArray($item); - } - } - - // Handle scalar types - if (in_array($expectedType, ['string', 'int', 'float', 'bool']) && gettype($item) === $expectedType) { - return $item; - } - } - - // If no matching type is found, throw an exception - throw new \InvalidArgumentException("Unable to deserialize item in array: type mismatch."); - }, $data); - } - - /** - * @param $type - * @return array|string[] - */ - private static function parseTypeDefinition($type) - { - if (is_array($type)) { - $parsed = []; - foreach ($type as $key => $value) { - // Parse the key - if (is_string($key)) { - $parsedKeys = self::parseTypeExpression($key); // This is an array of types - } else { - $parsedKeys = [null]; - } - // Parse the value - $parsedValue = self::parseTypeDefinition($value); - - foreach ($parsedKeys as $parsedKey) { - if ($parsedKey !== null) { - $parsed[$parsedKey] = $parsedValue; - } else { - $parsed[] = $parsedValue; - } - } - } - return $parsed; - } else { - return self::parseTypeExpression($type); - } - } - - /** - * @param string $typeExpr - * @return array - */ - private static function parseTypeExpression(string $typeExpr): array - { - // Split the type expression by '|' to handle union types - return array_map('trim', explode('|', $typeExpr)); - } -} \ No newline at end of file diff --git a/seed/php-sdk/serde-demo/src/Placeholder/Placeholder.php b/seed/php-sdk/serde-demo/src/Placeholder/Placeholder.php deleted file mode 100644 index a0eb33a6b60..00000000000 --- a/seed/php-sdk/serde-demo/src/Placeholder/Placeholder.php +++ /dev/null @@ -1,11 +0,0 @@ -mockHandler = new MockHandler(); - $handlerStack = HandlerStack::create($this->mockHandler); - $client = new Client(['handler' => $handlerStack]); - $this->rawClient = new RawClient($client); - } - - public function testHeaders(): void - { - $this->mockHandler->append(new Response(200)); - - $request = new JsonApiRequest( - $this->baseUrl, - '/test', - HttpMethod::GET, - ['X-Custom-Header' => 'TestValue'] - ); - - $this->sendRequest($request); - - $lastRequest = $this->mockHandler->getLastRequest(); - assert($lastRequest instanceof RequestInterface); - $this->assertEquals('application/json', $lastRequest->getHeaderLine('Content-Type')); - $this->assertEquals('TestValue', $lastRequest->getHeaderLine('X-Custom-Header')); - } - - public function testQueryParameters(): void - { - $this->mockHandler->append(new Response(200)); - - $request = new JsonApiRequest( - $this->baseUrl, - '/test', - HttpMethod::GET, - [], - ['param1' => 'value1', 'param2' => ['a', 'b'], 'param3' => 'true'] - ); - - $this->sendRequest($request); - - $lastRequest = $this->mockHandler->getLastRequest(); - assert($lastRequest instanceof RequestInterface); - $this->assertEquals( - 'https://api.example.com/test?param1=value1¶m2=a¶m2=b¶m3=true', - (string)$lastRequest->getUri() - ); - } - - public function testJsonBody(): void - { - $this->mockHandler->append(new Response(200)); - - $body = ['key' => 'value']; - $request = new JsonApiRequest( - $this->baseUrl, - '/test', - HttpMethod::POST, - [], - [], - $body - ); - - $this->sendRequest($request); - - $lastRequest = $this->mockHandler->getLastRequest(); - assert($lastRequest instanceof RequestInterface); - $this->assertEquals('application/json', $lastRequest->getHeaderLine('Content-Type')); - $this->assertEquals(json_encode($body), (string)$lastRequest->getBody()); - } - - private function sendRequest(BaseApiRequest $request): void - { - try { - $this->rawClient->sendRequest($request); - } catch (\Throwable $e) { - $this->fail('An exception was thrown: ' . $e->getMessage()); - } - } -} diff --git a/seed/php-sdk/serde-demo/tests/Seed/Core/SerializableTypeTest.php b/seed/php-sdk/serde-demo/tests/Seed/Core/SerializableTypeTest.php deleted file mode 100644 index bf8394e5cd9..00000000000 --- a/seed/php-sdk/serde-demo/tests/Seed/Core/SerializableTypeTest.php +++ /dev/null @@ -1,351 +0,0 @@ - $mapProperty - * @param array $objectArray - * @param array> $nestedArray - * @param array $datesArray - */ -class TestType extends SerializableType -{ - public function __construct( - #[JsonProperty('simple_property')] - public string $simpleProperty, - - #[DateType(DateType::TYPE_DATE)] - #[JsonProperty('date_property')] - public DateTime $dateProperty, - - #[DateType(DateType::TYPE_DATETIME)] - #[JsonProperty('datetime_property')] - public DateTime $datetimeProperty, - - #[ArrayType(['string'])] - #[JsonProperty('string_array')] - public array $stringArray, - - #[ArrayType(['string' => 'int'])] - #[JsonProperty('map_property')] - public array $mapProperty, - - #[ArrayType(['int' => TestNestedType::class . '|null'])] - #[JsonProperty('object_array')] - public array $objectArray, - - #[ArrayType(['int' => ['int' => 'string|null']])] - #[JsonProperty('nested_array')] - public array $nestedArray, - - #[ArrayType(['date|null'])] - #[JsonProperty('dates_array')] - public array $datesArray, - - #[JsonProperty('nullable_property')] - public ?string $nullableProperty = null // Move optional parameter to the end - ) {} -} - -/** - * @param (string|null)[] $nullableStringArray - */ -class NullableArrayType extends SerializableType -{ - public function __construct( - #[ArrayType(['string|null'])] - #[JsonProperty('nullable_string_array')] - public array $nullableStringArray - ) {} -} - -/** - * @param DateTime[] $dates - */ -class DateArrayType extends SerializableType -{ - public function __construct( - #[ArrayType(['date'])] - #[JsonProperty('dates')] - public array $dates - ) {} -} - -/** - * @param array $mixedArray - */ -class UnionArrayType extends SerializableType -{ - public function __construct( - #[ArrayType(['int' => 'string|int|null'])] - #[JsonProperty('mixed_array')] - public array $mixedArray - ) {} -} - -class NestedUnionArrayType extends SerializableType -{ - /** - * @param array> $nestedArray - */ - public function __construct( - #[ArrayType(['int' => ['int' => TestNestedType::class . '|null|date|datetime']])] - #[JsonProperty('nested_array')] - public array $nestedArray - ) {} -} - -class NullPropertyType extends SerializableType -{ - public function __construct( - #[JsonProperty('non_null_property')] - public string $nonNullProperty, - - #[JsonProperty('null_property')] - public ?string $nullProperty = null - ) {} -} - -/** - * @param array $mixedDates - */ -class MixedDateArrayType extends SerializableType -{ - public function __construct( - #[ArrayType(['int' => 'datetime|string|null'])] - #[JsonProperty('mixed_dates')] - public array $mixedDates - ) {} -} - -// Now, define the test class - -class SerializableTypeTest extends TestCase -{ - public function testSerializationAndDeserialization() - { - // Create test data - $data = [ - 'simple_property' => 'Test String', - // 'nullable_property' is omitted to test null serialization - 'date_property' => '2023-01-01', - 'datetime_property' => '2023-01-01T12:34:56+00:00', - 'string_array' => ['one', 'two', 'three'], - 'map_property' => ['key1' => 1, 'key2' => 2], - 'object_array' => [ - 1 => ['nested_property' => 'Nested One'], - 2 => null, // Testing nullable objects in array - ], - 'nested_array' => [ - 1 => [1 => 'value1', 2 => null], // Testing nullable strings in nested array - 2 => [3 => 'value3', 4 => 'value4'] - ], - 'dates_array' => ['2023-01-01', null, '2023-03-01'] // Testing nullable dates in array - ]; - - // Convert data to JSON - $json = json_encode($data); - - // Deserialize JSON to object - $object = TestType::fromJson($json); - - // Serialize object back to JSON - $serializedJson = $object->toJson(); - - // Compare serialized JSON with original JSON - $this->assertJsonStringEqualsJsonString($json, $serializedJson); - - // Check that nullable property is null and not included in JSON - $this->assertNull($object->nullableProperty); - $this->assertFalse(array_key_exists('nullable_property', json_decode($serializedJson, true))); - - // Check date properties - $this->assertEquals('2023-01-01', $object->dateProperty->format('Y-m-d')); - $this->assertEquals('2023-01-01 12:34:56', $object->datetimeProperty->format('Y-m-d H:i:s')); - - // Check arrays - $this->assertEquals(['one', 'two', 'three'], $object->stringArray); - $this->assertEquals(['key1' => 1, 'key2' => 2], $object->mapProperty); - - // Check object array with nullable elements - $this->assertInstanceOf(TestNestedType::class, $object->objectArray[1]); - $this->assertEquals('Nested One', $object->objectArray[1]->nestedProperty); - $this->assertNull($object->objectArray[2]); - - // Check nested array with nullable strings - $this->assertEquals('value1', $object->nestedArray[1][1]); - $this->assertNull($object->nestedArray[1][2]); - $this->assertEquals('value3', $object->nestedArray[2][3]); - $this->assertEquals('value4', $object->nestedArray[2][4]); - - // Check dates array with nullable DateTime objects - $this->assertInstanceOf(DateTime::class, $object->datesArray[0]); - $this->assertEquals('2023-01-01', $object->datesArray[0]->format('Y-m-d')); - $this->assertNull($object->datesArray[1]); - $this->assertInstanceOf(DateTime::class, $object->datesArray[2]); - $this->assertEquals('2023-03-01', $object->datesArray[2]->format('Y-m-d')); - } - - public function testNullableTypesInArrays() - { - $data = [ - 'nullable_string_array' => ['one', null, 'three'] - ]; - - $json = json_encode($data); - - $object = NullableArrayType::fromJson($json); - - $this->assertEquals(['one', null, 'three'], $object->nullableStringArray); - - $serializedJson = $object->toJson(); - - $this->assertJsonStringEqualsJsonString($json, $serializedJson); - } - - public function testDateTimeTypesInArrays() - { - $data = [ - 'dates' => ['2023-01-01', '2023-02-01', '2023-03-01'] - ]; - - $json = json_encode($data); - - $object = DateArrayType::fromJson($json); - - $this->assertInstanceOf(DateTime::class, $object->dates[0]); - $this->assertEquals('2023-01-01', $object->dates[0]->format('Y-m-d')); - $this->assertEquals('2023-02-01', $object->dates[1]->format('Y-m-d')); - $this->assertEquals('2023-03-01', $object->dates[2]->format('Y-m-d')); - - $serializedJson = $object->toJson(); - - $this->assertJsonStringEqualsJsonString($json, $serializedJson); - } - - public function testUnionTypesInArrays() - { - $data = [ - 'mixed_array' => [1 => 'one', 2 => 2, 3 => null] - ]; - - $json = json_encode($data); - - $object = UnionArrayType::fromJson($json); - - $this->assertEquals('one', $object->mixedArray[1]); - $this->assertEquals(2, $object->mixedArray[2]); - $this->assertNull($object->mixedArray[3]); - - $serializedJson = $object->toJson(); - - $this->assertJsonStringEqualsJsonString($json, $serializedJson); - } - - public function testNestedUnionTypesInArrays() - { - $data = [ - 'nested_array' => [ - 1 => [ - 1 => ['value' => 'Nested One'], - 2 => null, - 3 => '2023-01-01T12:00:00+00:00', // datetime - 4 => '2023-01-02' // date - ], - 2 => [ - 5 => ['value' => 'Nested Two'], - 6 => '2023-02-01T15:30:00+00:00', // datetime - 7 => '2023-02-02' // date - ] - ] - ]; - - $json = json_encode($data); - - $object = NestedUnionArrayType::fromJson($json); - - // Level 1 - $this->assertInstanceOf(TestNestedType::class, $object->nestedArray[1][1]); - $this->assertEquals('Nested One', $object->nestedArray[1][1]->value); - - $this->assertNull($object->nestedArray[1][2]); - - $this->assertInstanceOf(DateTime::class, $object->nestedArray[1][3]); - $this->assertEquals('2023-01-01 12:00:00', $object->nestedArray[1][3]->format('Y-m-d H:i:s')); - - $this->assertInstanceOf(DateTime::class, $object->nestedArray[1][4]); - $this->assertEquals('2023-01-02', $object->nestedArray[1][4]->format('Y-m-d')); - - // Level 2 - $this->assertInstanceOf(TestNestedType::class, $object->nestedArray[2][5]); - $this->assertEquals('Nested Two', $object->nestedArray[2][5]->value); - - $this->assertInstanceOf(DateTime::class, $object->nestedArray[2][6]); - $this->assertEquals('2023-02-01 15:30:00', $object->nestedArray[2][6]->format('Y-m-d H:i:s')); - - $this->assertInstanceOf(DateTime::class, $object->nestedArray[2][7]); - $this->assertEquals('2023-02-02', $object->nestedArray[2][7]->format('Y-m-d')); - - $serializedJson = $object->toJson(); - - $this->assertJsonStringEqualsJsonString($json, $serializedJson); - } - - public function testNullPropertiesAreOmitted() - { - $object = new NullPropertyType('Test String'); - - $json = $object->toJson(); - - $data = json_decode($json, true); - - $this->assertArrayHasKey('non_null_property', $data); - $this->assertArrayNotHasKey('null_property', $data); - - $this->assertEquals('Test String', $data['non_null_property']); - } - - public function testDateTimeTypesInUnionArrays() - { - $data = [ - 'mixed_dates' => [ - 1 => '2023-01-01T12:00:00+00:00', // datetime - 2 => null, // null - 3 => 'Some String' // string - ] - ]; - - $json = json_encode($data); - - $object = MixedDateArrayType::fromJson($json); - - $this->assertInstanceOf(DateTime::class, $object->mixedDates[1]); - $this->assertEquals('2023-01-01 12:00:00', $object->mixedDates[1]->format('Y-m-d H:i:s')); - - $this->assertNull($object->mixedDates[2]); - - $this->assertEquals('Some String', $object->mixedDates[3]); - - $serializedJson = $object->toJson(); - - $this->assertJsonStringEqualsJsonString($json, $serializedJson); - } -} \ No newline at end of file From bc3fe692ff4d8d23b54fb6666c85a7dcadc210de Mon Sep 17 00:00:00 2001 From: dcb6 Date: Sun, 15 Sep 2024 12:25:47 -0400 Subject: [PATCH 06/19] cleanup --- seed/php-sdk/imdb/src/Core/ArrayType.php | 11 ----------- seed/php-sdk/imdb/src/Types/ExampleType.php | 13 +++++++++++-- seed/php-sdk/imdb/src/Types/WeatherReport.php | 7 ++++++- .../Seed/Core/SerializableType/EmptyArraysTest.php | 5 ----- .../SerializableType/NestedUnionArrayTypeTest.php | 3 --- .../Core/SerializableType/NullableArrayTypeTest.php | 1 - .../Seed/Core/SerializableType/ScalarTypesTest.php | 4 ---- .../Seed/Core/SerializableType/TestTypeTest.php | 4 ---- .../imdb/tests/Seed/Types/ExampleTypeTest.php | 4 ++-- 9 files changed, 19 insertions(+), 33 deletions(-) diff --git a/seed/php-sdk/imdb/src/Core/ArrayType.php b/seed/php-sdk/imdb/src/Core/ArrayType.php index ff8257183cc..17b6b2e48c3 100644 --- a/seed/php-sdk/imdb/src/Core/ArrayType.php +++ b/seed/php-sdk/imdb/src/Core/ArrayType.php @@ -21,15 +21,4 @@ class Union { public function __construct(string ...$strings) { $this->types = $strings; } - - /** - * Check if a given type is part of the union. - * - * @param mixed $type - * @return bool - */ - public function contains($type): bool - { - return in_array($type, $this->types, true); - } } \ No newline at end of file diff --git a/seed/php-sdk/imdb/src/Types/ExampleType.php b/seed/php-sdk/imdb/src/Types/ExampleType.php index ed13f27c16f..a266defc040 100644 --- a/seed/php-sdk/imdb/src/Types/ExampleType.php +++ b/seed/php-sdk/imdb/src/Types/ExampleType.php @@ -7,14 +7,23 @@ use Seed\Core\DateType; use Seed\Core\JsonProperty; use Seed\Core\SerializableType; +use Seed\Core\Union; class ExampleType extends SerializableType { /** + * @param string $name + * @param int $age + * @param float $price + * @param bool $isActive + * @param DateTime $startDate + * @param DateTime $createdAt * @param string[] $stringList * @param array $stringIntMap * @param string[][] $nestedStringList * @param array> $nestedTypeMap + * @param WeatherReport $weatherReport + * @param string|null $optionalName */ public function __construct( #[JsonProperty('name')] @@ -41,7 +50,7 @@ public function __construct( #[JsonProperty('string_list')] public array $stringList, - #[ArrayType(['string' => 'int'])] + #[ArrayType(['string' => 'integer'])] #[JsonProperty('string_int_map')] public array $stringIntMap, @@ -49,7 +58,7 @@ public function __construct( #[JsonProperty('nested_string_list')] public array $nestedStringList, - #[ArrayType(['int' => ['int' => ExampleNestedType::class | "null" | "date" | "datetime"]])] + #[ArrayType(['integer' => ['integer' => new Union("null", "date", ExampleNestedType::class)]])] #[JsonProperty('nested_type_map')] public array $nestedTypeMap, diff --git a/seed/php-sdk/imdb/src/Types/WeatherReport.php b/seed/php-sdk/imdb/src/Types/WeatherReport.php index f799308134b..e1fcf8fb1e4 100644 --- a/seed/php-sdk/imdb/src/Types/WeatherReport.php +++ b/seed/php-sdk/imdb/src/Types/WeatherReport.php @@ -3,6 +3,11 @@ namespace Seed\Types; enum WeatherReport: string { - case SOMETHING = "string"; + case CLEAR = "clear"; + case CLOUDY = "cloudy"; + case RAINY = "rainy"; + case SNOWY = "snowy"; + case WINDY = "windy"; + case THUNDERSTORM = "thunderstorm"; } diff --git a/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/EmptyArraysTest.php b/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/EmptyArraysTest.php index 7735feaa598..2f7c0fca75d 100644 --- a/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/EmptyArraysTest.php +++ b/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/EmptyArraysTest.php @@ -31,23 +31,18 @@ class EmptyArraysTestTest extends TestCase { public function testEmptyArrays() { - // Create test data with empty arrays $data = [ 'empty_string_array' => [], 'empty_map_array' => [], 'empty_dates_array' => [] ]; - // Convert data to JSON $json = json_encode($data, JSON_THROW_ON_ERROR); - // Deserialize JSON to object $object = EmptyArraysTest::fromJson($json); - // Serialize object back to JSON $serializedJson = $object->toJson(); - // Compare serialized JSON with original JSON $this->assertJsonStringEqualsJsonString($json, $serializedJson, 'Serialized JSON does not match original JSON for EmptyArraysTest.'); // Check that arrays are empty diff --git a/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/NestedUnionArrayTypeTest.php b/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/NestedUnionArrayTypeTest.php index 137f709bba0..0a6b087c476 100644 --- a/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/NestedUnionArrayTypeTest.php +++ b/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/NestedUnionArrayTypeTest.php @@ -23,9 +23,6 @@ public function __construct( class NestedUnionArrayType extends SerializableType { - /** - * @param array> $nestedArray - */ public function __construct( #[ArrayType(['integer' => ['integer' => new Union(TestNestedType::class, 'null', 'date')]])] #[JsonProperty('nested_array')] diff --git a/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/NullableArrayTypeTest.php b/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/NullableArrayTypeTest.php index 94c6c7b46bf..ed37f15d026 100644 --- a/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/NullableArrayTypeTest.php +++ b/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/NullableArrayTypeTest.php @@ -11,7 +11,6 @@ class NullableArrayType extends SerializableType { public function __construct( - // Array of strings or null using Union #[ArrayType([new Union('string', 'null')])] #[JsonProperty('nullable_string_array')] public array $nullableStringArray diff --git a/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/ScalarTypesTest.php b/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/ScalarTypesTest.php index 685f1ab4763..02dd2fdc661 100644 --- a/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/ScalarTypesTest.php +++ b/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/ScalarTypesTest.php @@ -48,16 +48,12 @@ public function testAllScalarTypesIncludingFloat() 'int_float_array' => [1, 2.5, 3, 4.75] ]; - // Convert data to JSON $json = json_encode($data, JSON_THROW_ON_ERROR); - // Deserialize JSON to object $object = ScalarTypesTest::fromJson($json); - // Serialize object back to JSON $serializedJson = $object->toJson(); - // Compare serialized JSON with original JSON $this->assertJsonStringEqualsJsonString($json, $serializedJson, 'Serialized JSON does not match original JSON for ScalarTypesTest.'); // Check scalar properties diff --git a/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/TestTypeTest.php b/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/TestTypeTest.php index dc0b5bb5dba..976742213ab 100644 --- a/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/TestTypeTest.php +++ b/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/TestTypeTest.php @@ -92,16 +92,12 @@ public function testSerializationAndDeserialization(): void 'dates_array' => ['2023-01-01', null, '2023-03-01'] // Testing nullable dates in array ]; - // Convert data to JSON $json = json_encode($data, JSON_THROW_ON_ERROR); - // Deserialize JSON to object $object = TestType::fromJson($json); - // Serialize object back to JSON $serializedJson = $object->toJson(); - // Compare serialized JSON with original JSON $this->assertJsonStringEqualsJsonString($json, $serializedJson, 'The serialized JSON does not match the original JSON.'); // Check that nullable property is null and not included in JSON diff --git a/seed/php-sdk/imdb/tests/Seed/Types/ExampleTypeTest.php b/seed/php-sdk/imdb/tests/Seed/Types/ExampleTypeTest.php index 318b40dc0a7..09c55f3f7d3 100644 --- a/seed/php-sdk/imdb/tests/Seed/Types/ExampleTypeTest.php +++ b/seed/php-sdk/imdb/tests/Seed/Types/ExampleTypeTest.php @@ -11,7 +11,6 @@ public function testSerializationAndDeserialization() // Define the original data for ExampleType with nested ExampleNestedType $originalData = [ 'name' => 'Test Example', - 'optional_name' => null, 'age' => 30, 'price' => 99.99, 'is_active' => true, @@ -29,7 +28,8 @@ public function testSerializationAndDeserialization() 30 => ['nested_field' => 'NestedType 30'], 40 => ['nested_field' => 'NestedType 40'] ] - ] + ], + 'weather_report' => 'clear' ]; // Convert the original data into JSON From 3f779f359ec7e854682193084ba78fa8f08e2764 Mon Sep 17 00:00:00 2001 From: dcb6 Date: Sun, 15 Sep 2024 12:28:24 -0400 Subject: [PATCH 07/19] update param comments --- seed/php-sdk/imdb/src/Types/ExampleType.php | 6 ------ 1 file changed, 6 deletions(-) diff --git a/seed/php-sdk/imdb/src/Types/ExampleType.php b/seed/php-sdk/imdb/src/Types/ExampleType.php index a266defc040..69947b3aeb8 100644 --- a/seed/php-sdk/imdb/src/Types/ExampleType.php +++ b/seed/php-sdk/imdb/src/Types/ExampleType.php @@ -12,12 +12,6 @@ class ExampleType extends SerializableType { /** - * @param string $name - * @param int $age - * @param float $price - * @param bool $isActive - * @param DateTime $startDate - * @param DateTime $createdAt * @param string[] $stringList * @param array $stringIntMap * @param string[][] $nestedStringList From 00d2c6e7f8cf8fd5538f04b2f576d73b5f3cb777 Mon Sep 17 00:00:00 2001 From: dcb6 Date: Mon, 16 Sep 2024 12:19:47 -0400 Subject: [PATCH 08/19] check in --- .../imdb/tests/Seed/Core/RawClientTest.php | 6 +- .../serde-demo/.github/workflows/ci.yml | 46 ++++++ seed/php-sdk/serde-demo/.gitignore | 4 + .../serde-demo/.mock/definition/api.yml | 4 + .../serde-demo/.mock/definition/imdb.yml | 42 ++++++ .../php-sdk/serde-demo/.mock/fern.config.json | 1 + seed/php-sdk/serde-demo/.mock/generators.yml | 1 + seed/php-sdk/serde-demo/composer.json | 35 +++++ seed/php-sdk/serde-demo/phpstan.neon | 5 + seed/php-sdk/serde-demo/phpunit.xml | 7 + .../php-sdk/serde-demo/snippet-templates.json | 0 seed/php-sdk/serde-demo/snippet.json | 0 .../src/Core/ArrayType.php | 13 +- .../serde-demo/src/Core/BaseApiRequest.php | 23 +++ seed/php-sdk/serde-demo/src/Core/Constant.php | 12 ++ .../src/Core/DateType.php | 4 +- .../serde-demo/src/Core/HttpMethod.php | 12 ++ .../serde-demo/src/Core/JsonApiRequest.php | 26 ++++ .../src/Core/JsonProperty.php | 4 +- .../php-sdk/serde-demo/src/Core/RawClient.php | 131 ++++++++++++++++++ .../src/Core/SerializableType.php | 16 +-- seed/php-sdk/serde-demo/src/Core/Union.php | 16 +++ .../src/Placeholder/Placeholder.php | 11 ++ .../src/Types/ExampleNestedType.php | 0 .../src/Types/ExampleType.php | 2 +- .../src/Types/WeatherReport.php | 3 +- .../tests/Seed/Core/RawClientTest.php | 97 +++++++++++++ .../SerializableType/DateArrayTypeTest.php | 4 +- .../Core/SerializableType/EmptyArraysTest.php | 10 +- .../SerializableType/InvalidTypesTest.php | 11 +- .../MixedDateArrayTypeTest.php | 2 +- .../NestedUnionArrayTypeTest.php | 3 +- .../SerializableType/NullPropertyTypeTest.php | 2 +- .../NullableArrayTypeTest.php | 2 +- .../Core/SerializableType/ScalarTypesTest.php | 2 +- .../Core/SerializableType/TestTypeTest.php | 0 .../SerializableType/UnionArrayTypeTest.php | 2 +- .../tests/Seed/Types/ExampleTypeTest.php | 2 +- 38 files changed, 518 insertions(+), 43 deletions(-) create mode 100644 seed/php-sdk/serde-demo/.github/workflows/ci.yml create mode 100644 seed/php-sdk/serde-demo/.gitignore create mode 100644 seed/php-sdk/serde-demo/.mock/definition/api.yml create mode 100644 seed/php-sdk/serde-demo/.mock/definition/imdb.yml create mode 100644 seed/php-sdk/serde-demo/.mock/fern.config.json create mode 100644 seed/php-sdk/serde-demo/.mock/generators.yml create mode 100644 seed/php-sdk/serde-demo/composer.json create mode 100644 seed/php-sdk/serde-demo/phpstan.neon create mode 100644 seed/php-sdk/serde-demo/phpunit.xml create mode 100644 seed/php-sdk/serde-demo/snippet-templates.json create mode 100644 seed/php-sdk/serde-demo/snippet.json rename seed/php-sdk/{imdb => serde-demo}/src/Core/ArrayType.php (51%) create mode 100644 seed/php-sdk/serde-demo/src/Core/BaseApiRequest.php create mode 100644 seed/php-sdk/serde-demo/src/Core/Constant.php rename seed/php-sdk/{imdb => serde-demo}/src/Core/DateType.php (74%) create mode 100644 seed/php-sdk/serde-demo/src/Core/HttpMethod.php create mode 100644 seed/php-sdk/serde-demo/src/Core/JsonApiRequest.php rename seed/php-sdk/{imdb => serde-demo}/src/Core/JsonProperty.php (62%) create mode 100644 seed/php-sdk/serde-demo/src/Core/RawClient.php rename seed/php-sdk/{imdb => serde-demo}/src/Core/SerializableType.php (95%) create mode 100644 seed/php-sdk/serde-demo/src/Core/Union.php create mode 100644 seed/php-sdk/serde-demo/src/Placeholder/Placeholder.php rename seed/php-sdk/{imdb => serde-demo}/src/Types/ExampleNestedType.php (100%) rename seed/php-sdk/{imdb => serde-demo}/src/Types/ExampleType.php (97%) rename seed/php-sdk/{imdb => serde-demo}/src/Types/WeatherReport.php (87%) create mode 100644 seed/php-sdk/serde-demo/tests/Seed/Core/RawClientTest.php rename seed/php-sdk/{imdb => serde-demo}/tests/Seed/Core/SerializableType/DateArrayTypeTest.php (93%) rename seed/php-sdk/{imdb => serde-demo}/tests/Seed/Core/SerializableType/EmptyArraysTest.php (87%) rename seed/php-sdk/{imdb => serde-demo}/tests/Seed/Core/SerializableType/InvalidTypesTest.php (60%) rename seed/php-sdk/{imdb => serde-demo}/tests/Seed/Core/SerializableType/MixedDateArrayTypeTest.php (96%) rename seed/php-sdk/{imdb => serde-demo}/tests/Seed/Core/SerializableType/NestedUnionArrayTypeTest.php (93%) rename seed/php-sdk/{imdb => serde-demo}/tests/Seed/Core/SerializableType/NullPropertyTypeTest.php (94%) rename seed/php-sdk/{imdb => serde-demo}/tests/Seed/Core/SerializableType/NullableArrayTypeTest.php (95%) rename seed/php-sdk/{imdb => serde-demo}/tests/Seed/Core/SerializableType/ScalarTypesTest.php (97%) rename seed/php-sdk/{imdb => serde-demo}/tests/Seed/Core/SerializableType/TestTypeTest.php (100%) rename seed/php-sdk/{imdb => serde-demo}/tests/Seed/Core/SerializableType/UnionArrayTypeTest.php (96%) rename seed/php-sdk/{imdb => serde-demo}/tests/Seed/Types/ExampleTypeTest.php (99%) diff --git a/seed/php-sdk/imdb/tests/Seed/Core/RawClientTest.php b/seed/php-sdk/imdb/tests/Seed/Core/RawClientTest.php index 7b0e35d60ec..5cae4a4299b 100644 --- a/seed/php-sdk/imdb/tests/Seed/Core/RawClientTest.php +++ b/seed/php-sdk/imdb/tests/Seed/Core/RawClientTest.php @@ -1,6 +1,6 @@ + + + tests + + + \ No newline at end of file diff --git a/seed/php-sdk/serde-demo/snippet-templates.json b/seed/php-sdk/serde-demo/snippet-templates.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/php-sdk/serde-demo/snippet.json b/seed/php-sdk/serde-demo/snippet.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/php-sdk/imdb/src/Core/ArrayType.php b/seed/php-sdk/serde-demo/src/Core/ArrayType.php similarity index 51% rename from seed/php-sdk/imdb/src/Core/ArrayType.php rename to seed/php-sdk/serde-demo/src/Core/ArrayType.php index 17b6b2e48c3..5f3459b9391 100644 --- a/seed/php-sdk/imdb/src/Core/ArrayType.php +++ b/seed/php-sdk/serde-demo/src/Core/ArrayType.php @@ -10,15 +10,8 @@ class ArrayType /** * @param array $type Array in the form ['keyType' => 'valueType'] for maps, or ['valueType'] for lists */ - public function __construct(public array $type) {} + public function __construct(public array $type) + { + } } -class Union { - /** - * @var string[] - */ - public array $types; - public function __construct(string ...$strings) { - $this->types = $strings; - } -} \ No newline at end of file diff --git a/seed/php-sdk/serde-demo/src/Core/BaseApiRequest.php b/seed/php-sdk/serde-demo/src/Core/BaseApiRequest.php new file mode 100644 index 00000000000..047b04f82ff --- /dev/null +++ b/seed/php-sdk/serde-demo/src/Core/BaseApiRequest.php @@ -0,0 +1,23 @@ + $headers Additional headers for the request (optional) + * @param array $query Query parameters for the request (optional) + */ + public function __construct( + public readonly string $baseUrl, + public readonly string $path, + public readonly HttpMethod $method, + public readonly array $headers = [], + public readonly array $query = [], + ) + { + } +} diff --git a/seed/php-sdk/serde-demo/src/Core/Constant.php b/seed/php-sdk/serde-demo/src/Core/Constant.php new file mode 100644 index 00000000000..211ddbaed6f --- /dev/null +++ b/seed/php-sdk/serde-demo/src/Core/Constant.php @@ -0,0 +1,12 @@ + $headers Additional headers for the request (optional) + * @param array $query Query parameters for the request (optional) + * @param mixed|null $body The JSON request body (optional) + */ + public function __construct( + string $baseUrl, + string $path, + HttpMethod $method, + array $headers = [], + array $query = [], + public readonly mixed $body = null + ) + { + parent::__construct($baseUrl, $path, $method, $headers, $query); + } +} diff --git a/seed/php-sdk/imdb/src/Core/JsonProperty.php b/seed/php-sdk/serde-demo/src/Core/JsonProperty.php similarity index 62% rename from seed/php-sdk/imdb/src/Core/JsonProperty.php rename to seed/php-sdk/serde-demo/src/Core/JsonProperty.php index b129573f765..a3485a4fa2b 100644 --- a/seed/php-sdk/imdb/src/Core/JsonProperty.php +++ b/seed/php-sdk/serde-demo/src/Core/JsonProperty.php @@ -7,6 +7,8 @@ #[Attribute(Attribute::TARGET_PROPERTY)] class JsonProperty { - public function __construct(public string $name) {} + public function __construct(public string $name) + { + } } diff --git a/seed/php-sdk/serde-demo/src/Core/RawClient.php b/seed/php-sdk/serde-demo/src/Core/RawClient.php new file mode 100644 index 00000000000..9eb401d4cd7 --- /dev/null +++ b/seed/php-sdk/serde-demo/src/Core/RawClient.php @@ -0,0 +1,131 @@ + $headers The HTTP headers sent with the request. + */ + public function __construct( + private readonly ClientInterface $client, + private readonly array $headers = [], + ) + { + } + + /** + * @throws ClientExceptionInterface + */ + public function sendRequest( + BaseApiRequest $request, + ): ResponseInterface + { + $httpRequest = $this->buildRequest($request); + return $this->client->send($httpRequest); + } + + private function buildRequest( + BaseApiRequest $request + ): Request + { + $url = $this->buildUrl($request); + $headers = $this->encodeHeaders($request); + $body = $this->encodeRequestBody($request); + return new Request( + $request->method->name, + $url, + $headers, + $body, + ); + } + + /** + * @return array + */ + private function encodeHeaders( + BaseApiRequest $request + ): array + { + return match (get_class($request)) { + JsonApiRequest::class => array_merge( + ["Content-Type" => "application/json"], + $this->headers, + $request->headers + ), + default => throw new InvalidArgumentException('Unsupported request type: ' . get_class($request)), + }; + } + + private function encodeRequestBody( + BaseApiRequest $request + ): ?StreamInterface + { + return match (get_class($request)) { + JsonApiRequest::class => $request->body != null ? Utils::streamFor(json_encode($request->body)) : null, + default => throw new InvalidArgumentException('Unsupported request type: ' . get_class($request)), + }; + } + + private function buildUrl( + BaseApiRequest $request + ): string + { + $baseUrl = $request->baseUrl; + $trimmedBaseUrl = rtrim($baseUrl, '/'); + $trimmedBasePath = ltrim($request->path, '/'); + $url = "{$trimmedBaseUrl}/{$trimmedBasePath}"; + + if (!empty($request->query)) { + $url .= '?' . $this->encodeQuery($request->query); + } + + return $url; + } + + /** + * @param array $query + */ + private function encodeQuery( + array $query + ): string + { + $parts = []; + foreach ($query as $key => $value) { + if (is_array($value)) { + foreach ($value as $item) { + $parts[] = urlencode($key) . '=' . $this->encodeQueryValue($item); + } + } else { + $parts[] = urlencode($key) . '=' . $this->encodeQueryValue($value); + } + } + return implode('&', $parts); + } + + private function encodeQueryValue( + mixed $value + ): string + { + if (is_string($value)) { + return urlencode($value); + } + if (is_scalar($value)) { + return urlencode((string)$value); + } + if (is_null($value)) { + return 'null'; + } + // Unreachable, but included for a best effort. + return urlencode(strval(json_encode($value))); + } +} diff --git a/seed/php-sdk/imdb/src/Core/SerializableType.php b/seed/php-sdk/serde-demo/src/Core/SerializableType.php similarity index 95% rename from seed/php-sdk/imdb/src/Core/SerializableType.php rename to seed/php-sdk/serde-demo/src/Core/SerializableType.php index 57b1823e53a..ea4d33f4176 100644 --- a/seed/php-sdk/imdb/src/Core/SerializableType.php +++ b/seed/php-sdk/serde-demo/src/Core/SerializableType.php @@ -45,8 +45,8 @@ public function toArray(): array if ($dateTypeAttr && $value instanceof DateTime) { $dateType = $dateTypeAttr->newInstance()->type; $value = ($dateType === DateType::TYPE_DATE) - ? $value->format('Y-m-d') - : $value->format(DateTime::RFC3339); + ? $value->format(Constant::DateFormat) + : $value->format(Constant::DateTimeFormat); } // Handle arrays with type annotations @@ -108,7 +108,7 @@ private static function serializeValue($data, $type) * @param string $type The expected type. * @return mixed The serialized value. */ - private static function serializeSingleValue($data, $type) + private static function serializeSingleValue(mixed $data, mixed $type): mixed { if (is_array($type)) { return self::serializeGenericArray($data, $type); @@ -118,7 +118,7 @@ private static function serializeSingleValue($data, $type) } if (($type === 'date' || $type === 'datetime') && $data instanceof DateTime) { - return $type === 'date' ? $data->format('Y-m-d') : $data->format(DateTime::RFC3339); + return $type === 'date' ? $data->format(Constant::DateFormat) : $data->format(Constant::DateTimeFormat); } if (class_exists($type) && $data instanceof $type) { @@ -258,7 +258,7 @@ public static function fromArray(array $data): static if ($dateTypeAttr) { $dateType = $dateTypeAttr->newInstance()->type; $value = ($dateType === DateType::TYPE_DATE) - ? DateTime::createFromFormat('!Y-m-d', $value) + ? DateTime::createFromFormat(Constant::DeserializationDateFormat, $value) : new DateTime($value); } @@ -325,14 +325,14 @@ private static function deserializeValue(mixed $data, array|Union|string $type): * @param string $type The expected type. * @return mixed The deserialized value. */ - private static function deserializeSingleValue(mixed $data, string $type) + private static function deserializeSingleValue(mixed $data, string $type): mixed { if ($type === 'null' && $data === null) { return null; } if ($type === 'date' && is_string($data)) { - return DateTime::createFromFormat('!Y-m-d', $data); + return DateTime::createFromFormat(Constant::DeserializationDateFormat, $data); } if ($type === 'datetime' && is_string($data)) { @@ -364,7 +364,7 @@ private static function deserializeMap(array $data, array $type): array $result = []; foreach ($data as $key => $item) { - $key = self::castKey($key, $keyType); + $key = self::castKey($key, (string)$keyType); $result[$key] = self::deserializeValue($item, $valueType); } diff --git a/seed/php-sdk/serde-demo/src/Core/Union.php b/seed/php-sdk/serde-demo/src/Core/Union.php new file mode 100644 index 00000000000..4d652718ddc --- /dev/null +++ b/seed/php-sdk/serde-demo/src/Core/Union.php @@ -0,0 +1,16 @@ +types = $strings; + } +} \ No newline at end of file diff --git a/seed/php-sdk/serde-demo/src/Placeholder/Placeholder.php b/seed/php-sdk/serde-demo/src/Placeholder/Placeholder.php new file mode 100644 index 00000000000..a0eb33a6b60 --- /dev/null +++ b/seed/php-sdk/serde-demo/src/Placeholder/Placeholder.php @@ -0,0 +1,11 @@ +mockHandler = new MockHandler(); + $handlerStack = HandlerStack::create($this->mockHandler); + $client = new Client(['handler' => $handlerStack]); + $this->rawClient = new RawClient($client); + } + + public function testHeaders(): void + { + $this->mockHandler->append(new Response(200)); + + $request = new JsonApiRequest( + $this->baseUrl, + '/test', + HttpMethod::GET, + ['X-Custom-Header' => 'TestValue'] + ); + + $this->sendRequest($request); + + $lastRequest = $this->mockHandler->getLastRequest(); + assert($lastRequest instanceof RequestInterface); + $this->assertEquals('application/json', $lastRequest->getHeaderLine('Content-Type')); + $this->assertEquals('TestValue', $lastRequest->getHeaderLine('X-Custom-Header')); + } + + public function testQueryParameters(): void + { + $this->mockHandler->append(new Response(200)); + + $request = new JsonApiRequest( + $this->baseUrl, + '/test', + HttpMethod::GET, + [], + ['param1' => 'value1', 'param2' => ['a', 'b'], 'param3' => 'true'] + ); + + $this->sendRequest($request); + + $lastRequest = $this->mockHandler->getLastRequest(); + assert($lastRequest instanceof RequestInterface); + $this->assertEquals( + 'https://api.example.com/test?param1=value1¶m2=a¶m2=b¶m3=true', + (string)$lastRequest->getUri() + ); + } + + public function testJsonBody(): void + { + $this->mockHandler->append(new Response(200)); + + $body = ['key' => 'value']; + $request = new JsonApiRequest( + $this->baseUrl, + '/test', + HttpMethod::POST, + [], + [], + $body + ); + + $this->sendRequest($request); + + $lastRequest = $this->mockHandler->getLastRequest(); + assert($lastRequest instanceof RequestInterface); + $this->assertEquals('application/json', $lastRequest->getHeaderLine('Content-Type')); + $this->assertEquals(json_encode($body), (string)$lastRequest->getBody()); + } + + private function sendRequest(BaseApiRequest $request): void + { + try { + $this->rawClient->sendRequest($request); + } catch (\Throwable $e) { + $this->fail('An exception was thrown: ' . $e->getMessage()); + } + } +} diff --git a/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/DateArrayTypeTest.php b/seed/php-sdk/serde-demo/tests/Seed/Core/SerializableType/DateArrayTypeTest.php similarity index 93% rename from seed/php-sdk/imdb/tests/Seed/Core/SerializableType/DateArrayTypeTest.php rename to seed/php-sdk/serde-demo/tests/Seed/Core/SerializableType/DateArrayTypeTest.php index 1fbb18f36a1..122e1ac4568 100644 --- a/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/DateArrayTypeTest.php +++ b/seed/php-sdk/serde-demo/tests/Seed/Core/SerializableType/DateArrayTypeTest.php @@ -1,6 +1,6 @@ ['2023-01-01', '2023-02-01', '2023-03-01'] diff --git a/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/EmptyArraysTest.php b/seed/php-sdk/serde-demo/tests/Seed/Core/SerializableType/EmptyArraysTest.php similarity index 87% rename from seed/php-sdk/imdb/tests/Seed/Core/SerializableType/EmptyArraysTest.php rename to seed/php-sdk/serde-demo/tests/Seed/Core/SerializableType/EmptyArraysTest.php index 2f7c0fca75d..f2749fa3400 100644 --- a/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/EmptyArraysTest.php +++ b/seed/php-sdk/serde-demo/tests/Seed/Core/SerializableType/EmptyArraysTest.php @@ -8,7 +8,7 @@ use Seed\Core\ArrayType; use Seed\Core\Union; -class EmptyArraysTest extends SerializableType +class EmptyArraysType extends SerializableType { public function __construct( #[ArrayType(['string'])] @@ -27,9 +27,9 @@ public function __construct( } } -class EmptyArraysTestTest extends TestCase +class EmptyArraysTest extends TestCase { - public function testEmptyArrays() + public function testEmptyArrays(): void { $data = [ 'empty_string_array' => [], @@ -39,11 +39,11 @@ public function testEmptyArrays() $json = json_encode($data, JSON_THROW_ON_ERROR); - $object = EmptyArraysTest::fromJson($json); + $object = EmptyArraysType::fromJson($json); $serializedJson = $object->toJson(); - $this->assertJsonStringEqualsJsonString($json, $serializedJson, 'Serialized JSON does not match original JSON for EmptyArraysTest.'); + $this->assertJsonStringEqualsJsonString($json, $serializedJson, 'Serialized JSON does not match original JSON for EmptyArraysType.'); // Check that arrays are empty $this->assertEmpty($object->emptyStringArray, 'empty_string_array should be empty.'); diff --git a/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/InvalidTypesTest.php b/seed/php-sdk/serde-demo/tests/Seed/Core/SerializableType/InvalidTypesTest.php similarity index 60% rename from seed/php-sdk/imdb/tests/Seed/Core/SerializableType/InvalidTypesTest.php rename to seed/php-sdk/serde-demo/tests/Seed/Core/SerializableType/InvalidTypesTest.php index cb3c19f080e..1ca5f98ba96 100644 --- a/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/InvalidTypesTest.php +++ b/seed/php-sdk/serde-demo/tests/Seed/Core/SerializableType/InvalidTypesTest.php @@ -6,7 +6,7 @@ use Seed\Core\SerializableType; use Seed\Core\JsonProperty; -class InvalidTypesTest extends SerializableType +class InvalidType extends SerializableType { public function __construct( #[JsonProperty('integer_property')] @@ -16,9 +16,9 @@ public function __construct( } } -class InvalidTypesTestTest extends TestCase +class InvalidTypesTest extends TestCase { - public function testInvalidTypesThrowExceptions() + public function testInvalidTypesThrowExceptions(): void { // Create test data with invalid type for integer_property (string instead of int) $data = [ @@ -27,10 +27,9 @@ public function testInvalidTypesThrowExceptions() $json = json_encode($data, JSON_THROW_ON_ERROR); - $this->expectException(\InvalidArgumentException::class); - $this->expectExceptionMessage("Unable to deserialize value of type 'string' as 'integer'."); + $this->expectException(\TypeError::class); // Attempt to deserialize invalid data - $object = InvalidTypesTest::fromJson($json); + InvalidType::fromJson($json); } } \ No newline at end of file diff --git a/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/MixedDateArrayTypeTest.php b/seed/php-sdk/serde-demo/tests/Seed/Core/SerializableType/MixedDateArrayTypeTest.php similarity index 96% rename from seed/php-sdk/imdb/tests/Seed/Core/SerializableType/MixedDateArrayTypeTest.php rename to seed/php-sdk/serde-demo/tests/Seed/Core/SerializableType/MixedDateArrayTypeTest.php index 639f80759a9..7a00c070b6b 100644 --- a/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/MixedDateArrayTypeTest.php +++ b/seed/php-sdk/serde-demo/tests/Seed/Core/SerializableType/MixedDateArrayTypeTest.php @@ -22,7 +22,7 @@ public function __construct( class MixedDateArrayTypeTest extends TestCase { - public function testDateTimeTypesInUnionArrays() + public function testDateTimeTypesInUnionArrays(): void { $data = [ 'mixed_dates' => [ diff --git a/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/NestedUnionArrayTypeTest.php b/seed/php-sdk/serde-demo/tests/Seed/Core/SerializableType/NestedUnionArrayTypeTest.php similarity index 93% rename from seed/php-sdk/imdb/tests/Seed/Core/SerializableType/NestedUnionArrayTypeTest.php rename to seed/php-sdk/serde-demo/tests/Seed/Core/SerializableType/NestedUnionArrayTypeTest.php index 0a6b087c476..4cc2603ba81 100644 --- a/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/NestedUnionArrayTypeTest.php +++ b/seed/php-sdk/serde-demo/tests/Seed/Core/SerializableType/NestedUnionArrayTypeTest.php @@ -3,6 +3,7 @@ namespace Seed\Core\SerializableType; use PHPUnit\Framework\TestCase; +use Seed\Core\Constant; use Seed\Core\SerializableType; use Seed\Core\JsonProperty; use Seed\Core\ArrayType; @@ -62,7 +63,7 @@ public function testNestedUnionTypesInArrays() // ensure dates are set with the default time $this->assertInstanceOf(DateTime::class, $object->nestedArray[1][4], 'nested_array[1][4] should be a DateTime instance.'); - $this->assertEquals('2023-01-02 00:00:00', $object->nestedArray[1][4]->format('Y-m-d H:i:s'), 'nested_array[1][4] should have the correct datetime.'); + $this->assertEquals('2023-01-02T00:00:00+00:00', $object->nestedArray[1][4]->format(Constant::DateTimeFormat), 'nested_array[1][4] should have the correct datetime.'); // Level 2 $this->assertInstanceOf(TestNestedType::class, $object->nestedArray[2][5], 'nested_array[2][5] should be an instance of TestNestedType.'); diff --git a/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/NullPropertyTypeTest.php b/seed/php-sdk/serde-demo/tests/Seed/Core/SerializableType/NullPropertyTypeTest.php similarity index 94% rename from seed/php-sdk/imdb/tests/Seed/Core/SerializableType/NullPropertyTypeTest.php rename to seed/php-sdk/serde-demo/tests/Seed/Core/SerializableType/NullPropertyTypeTest.php index 5fb0f597e55..f489d0ef996 100644 --- a/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/NullPropertyTypeTest.php +++ b/seed/php-sdk/serde-demo/tests/Seed/Core/SerializableType/NullPropertyTypeTest.php @@ -21,7 +21,7 @@ public function __construct( class NullPropertyTypeTest extends TestCase { - public function testNullPropertiesAreOmitted() + public function testNullPropertiesAreOmitted(): void { $object = new NullPropertyType('Test String', null); diff --git a/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/NullableArrayTypeTest.php b/seed/php-sdk/serde-demo/tests/Seed/Core/SerializableType/NullableArrayTypeTest.php similarity index 95% rename from seed/php-sdk/imdb/tests/Seed/Core/SerializableType/NullableArrayTypeTest.php rename to seed/php-sdk/serde-demo/tests/Seed/Core/SerializableType/NullableArrayTypeTest.php index ed37f15d026..7aa80308934 100644 --- a/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/NullableArrayTypeTest.php +++ b/seed/php-sdk/serde-demo/tests/Seed/Core/SerializableType/NullableArrayTypeTest.php @@ -21,7 +21,7 @@ public function __construct( class NullableArrayTypeTest extends TestCase { - public function testNullableTypesInArrays() + public function testNullableTypesInArrays(): void { $data = [ 'nullable_string_array' => ['one', null, 'three'] diff --git a/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/ScalarTypesTest.php b/seed/php-sdk/serde-demo/tests/Seed/Core/SerializableType/ScalarTypesTest.php similarity index 97% rename from seed/php-sdk/imdb/tests/Seed/Core/SerializableType/ScalarTypesTest.php rename to seed/php-sdk/serde-demo/tests/Seed/Core/SerializableType/ScalarTypesTest.php index 02dd2fdc661..617f1fc1722 100644 --- a/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/ScalarTypesTest.php +++ b/seed/php-sdk/serde-demo/tests/Seed/Core/SerializableType/ScalarTypesTest.php @@ -36,7 +36,7 @@ public function __construct( class ScalarTypesTestTest extends TestCase { - public function testAllScalarTypesIncludingFloat() + public function testAllScalarTypesIncludingFloat(): void { // Create test data $data = [ diff --git a/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/TestTypeTest.php b/seed/php-sdk/serde-demo/tests/Seed/Core/SerializableType/TestTypeTest.php similarity index 100% rename from seed/php-sdk/imdb/tests/Seed/Core/SerializableType/TestTypeTest.php rename to seed/php-sdk/serde-demo/tests/Seed/Core/SerializableType/TestTypeTest.php diff --git a/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/UnionArrayTypeTest.php b/seed/php-sdk/serde-demo/tests/Seed/Core/SerializableType/UnionArrayTypeTest.php similarity index 96% rename from seed/php-sdk/imdb/tests/Seed/Core/SerializableType/UnionArrayTypeTest.php rename to seed/php-sdk/serde-demo/tests/Seed/Core/SerializableType/UnionArrayTypeTest.php index 4fb966fcbfc..633f3ddecf8 100644 --- a/seed/php-sdk/imdb/tests/Seed/Core/SerializableType/UnionArrayTypeTest.php +++ b/seed/php-sdk/serde-demo/tests/Seed/Core/SerializableType/UnionArrayTypeTest.php @@ -22,7 +22,7 @@ public function __construct( class UnionArrayTypeTest extends TestCase { - public function testUnionTypesInArrays() + public function testUnionTypesInArrays(): void { $data = [ 'mixed_array' => [ diff --git a/seed/php-sdk/imdb/tests/Seed/Types/ExampleTypeTest.php b/seed/php-sdk/serde-demo/tests/Seed/Types/ExampleTypeTest.php similarity index 99% rename from seed/php-sdk/imdb/tests/Seed/Types/ExampleTypeTest.php rename to seed/php-sdk/serde-demo/tests/Seed/Types/ExampleTypeTest.php index 09c55f3f7d3..c664115130b 100644 --- a/seed/php-sdk/imdb/tests/Seed/Types/ExampleTypeTest.php +++ b/seed/php-sdk/serde-demo/tests/Seed/Types/ExampleTypeTest.php @@ -1,6 +1,6 @@ Date: Mon, 16 Sep 2024 18:07:43 -0400 Subject: [PATCH 09/19] merge --- generators/php/sdk/src/SdkGeneratorContext.ts | 70 ++++++++++++++++++- 1 file changed, 68 insertions(+), 2 deletions(-) diff --git a/generators/php/sdk/src/SdkGeneratorContext.ts b/generators/php/sdk/src/SdkGeneratorContext.ts index dc1e3389761..87ac1b52b13 100644 --- a/generators/php/sdk/src/SdkGeneratorContext.ts +++ b/generators/php/sdk/src/SdkGeneratorContext.ts @@ -1,11 +1,20 @@ -import { AbstractPhpGeneratorContext } from "@fern-api/php-codegen"; +import { DeclaredErrorName, HttpService, ServiceId } from "@fern-fern/ir-sdk/api"; +import { AbstractPhpGeneratorContext, FileLocation } from "@fern-api/php-codegen"; import { GeneratorNotificationService } from "@fern-api/generator-commons"; import { FernGeneratorExec } from "@fern-fern/generator-exec-sdk"; import { IntermediateRepresentation } from "@fern-fern/ir-sdk/api"; import { SdkCustomConfigSchema } from "./SdkCustomConfig"; -import { AsIsFiles } from "@fern-api/php-codegen"; +import { AsIsFiles, php } from "@fern-api/php-codegen"; +import { camelCase, upperFirst } from "lodash-es"; +import { RawClient } from "./core/RawClient"; +import { GuzzleClient } from "./external/GuzzleClient"; +import { RelativeFilePath } from "@fern-api/fs-utils"; +import { ErrorId, ErrorDeclaration } from "@fern-fern/ir-sdk/api"; +import { TYPES_DIRECTORY, ERRORS_DIRECTORY } from "./constants"; export class SdkGeneratorContext extends AbstractPhpGeneratorContext { + public guzzleClient: GuzzleClient; + public rawClient: RawClient; public constructor( public readonly ir: IntermediateRepresentation, public readonly config: FernGeneratorExec.config.GeneratorConfig, @@ -13,6 +22,43 @@ export class SdkGeneratorContext extends AbstractPhpGeneratorContext Date: Mon, 16 Sep 2024 18:18:51 -0400 Subject: [PATCH 10/19] check in --- generators/php/model/src/generateModels.ts | 25 ++++++++++++++++------ pnpm-lock.yaml | 2 -- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/generators/php/model/src/generateModels.ts b/generators/php/model/src/generateModels.ts index 881abefafe4..f94c2f4878a 100644 --- a/generators/php/model/src/generateModels.ts +++ b/generators/php/model/src/generateModels.ts @@ -1,13 +1,26 @@ import { PhpFile } from "@fern-api/php-codegen"; +import { EnumTypeDeclaration } from "@fern-fern/ir-sdk/api"; import { ModelGeneratorContext } from "./ModelGeneratorContext"; export function generateModels({ context }: { context: ModelGeneratorContext }): PhpFile[] { const files: PhpFile[] = []; - files.push( - new PhpFile({ - namespace: context.getNamespace(), - customConfig: context.customConfig - }) - ); + for (const [typeId, typeDeclaration] of Object.entries(context.ir.types)) { + const file = typeDeclaration.shape._visit({ + alias: () => undefined, + enum: (etd: EnumTypeDeclaration) => { + return undefined; + // return new EnumGenerator(context, typeDeclaration, etd).generate(); + }, + object: (otd) => { + return new ObjectGenerator(context, typeDeclaration, otd).generate(); + }, + undiscriminatedUnion: () => undefined, + union: () => undefined, + _other: () => undefined + }); + if (file != null) { + files.push(file); + } + } return files; } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6861415617f..0d1832db71c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -3298,8 +3298,6 @@ importers: specifier: ^2.0.5 version: 2.0.5(@types/node@18.7.18)(jsdom@20.0.3)(sass@1.72.0)(terser@5.31.5) - packages/cli/cli/dist/prod: {} - packages/cli/configuration: dependencies: '@fern-api/core-utils': From 742c5ed0438d2905464a330fc2c8fecf46a37738 Mon Sep 17 00:00:00 2001 From: dcb6 Date: Tue, 17 Sep 2024 10:43:05 -0400 Subject: [PATCH 11/19] check in --- generators/php/codegen/src/ast/Field.ts | 4 +- generators/php/codegen/src/ast/Parameter.ts | 6 +- generators/php/model/src/generateModels.ts | 3 +- .../php/model/src/object/ObjectGenerator.ts | 81 +++++++++++++++++++ generators/php/sdk/src/SdkGeneratorContext.ts | 20 ----- seed/php-sdk/imdb/src/Core/Constant.php | 2 +- .../imdb/src/Core/SerializableType.php | 4 +- .../imdb/src/Placeholder/Placeholder.php | 11 --- .../src/Seed/Types/CreateMovieRequest.php | 28 +++++++ seed/php-sdk/imdb/src/Seed/Types/Movie.php | 36 +++++++++ 10 files changed, 155 insertions(+), 40 deletions(-) create mode 100644 generators/php/model/src/object/ObjectGenerator.ts delete mode 100644 seed/php-sdk/imdb/src/Placeholder/Placeholder.php create mode 100644 seed/php-sdk/imdb/src/Seed/Types/CreateMovieRequest.php create mode 100644 seed/php-sdk/imdb/src/Seed/Types/Movie.php diff --git a/generators/php/codegen/src/ast/Field.ts b/generators/php/codegen/src/ast/Field.ts index 5e7492e61f2..ddda80840f2 100644 --- a/generators/php/codegen/src/ast/Field.ts +++ b/generators/php/codegen/src/ast/Field.ts @@ -49,7 +49,7 @@ export class Field extends AstNode { } this.type.write(writer); - writer.write(` ${this.name}`); + writer.write(` ${this.name.startsWith("$") ? "" : "$"}${this.name}`); if (this.initializer != null) { writer.write(" = "); @@ -63,7 +63,7 @@ export class Field extends AstNode { comment.addTag({ tagType: "var", type: this.type, - name: this.name, + name: `${this.name.startsWith("$") ? "" : "$"}${this.name}`, docs: this.docs }); comment.write(writer); diff --git a/generators/php/codegen/src/ast/Parameter.ts b/generators/php/codegen/src/ast/Parameter.ts index 1a123ef935b..3d89714bee1 100644 --- a/generators/php/codegen/src/ast/Parameter.ts +++ b/generators/php/codegen/src/ast/Parameter.ts @@ -44,7 +44,7 @@ export class Parameter extends AstNode { return { tagType: "param", type: this.type, - name: this.name, + name: `${this.name.startsWith("$") ? "" : "$"}${this.name}`, docs: this.docs }; } @@ -57,10 +57,12 @@ export class Parameter extends AstNode { writer.write("readonly "); } this.type.write(writer); - writer.write(` ${this.name}`); + writer.write(` ${this.name.startsWith("$") ? "" : "$"}${this.name}`); if (this.initializer != null) { writer.write(" = "); this.initializer.write(writer); + } else if (this.type.isOptional()) { + writer.write(" = null"); } } } diff --git a/generators/php/model/src/generateModels.ts b/generators/php/model/src/generateModels.ts index d0b50693ec8..535ac4d668c 100644 --- a/generators/php/model/src/generateModels.ts +++ b/generators/php/model/src/generateModels.ts @@ -1,8 +1,7 @@ -import { RelativeFilePath } from "@fern-api/fs-utils"; import { PhpFile } from "@fern-api/php-codegen"; import { EnumTypeDeclaration } from "@fern-fern/ir-sdk/api"; import { ModelGeneratorContext } from "./ModelGeneratorContext"; -import { php } from "@fern-api/php-codegen"; +import { ObjectGenerator } from "./object/ObjectGenerator"; export function generateModels({ context }: { context: ModelGeneratorContext }): PhpFile[] { const files: PhpFile[] = []; diff --git a/generators/php/model/src/object/ObjectGenerator.ts b/generators/php/model/src/object/ObjectGenerator.ts new file mode 100644 index 00000000000..225da11e900 --- /dev/null +++ b/generators/php/model/src/object/ObjectGenerator.ts @@ -0,0 +1,81 @@ +import { join, RelativeFilePath } from "@fern-api/fs-utils"; +import { PhpFile } from "@fern-api/php-codegen"; +import { FileGenerator } from "@fern-api/php-codegen"; +import { php } from "@fern-api/php-codegen"; +import { + ExampleObjectType, + NameAndWireValue, + ObjectProperty, + ObjectTypeDeclaration, + TypeDeclaration +} from "@fern-fern/ir-sdk/api"; +import { ModelCustomConfigSchema } from "../ModelCustomConfig"; +import { ModelGeneratorContext } from "../ModelGeneratorContext"; + +export class ObjectGenerator extends FileGenerator { + private readonly typeDeclaration: TypeDeclaration; + private readonly classReference: php.ClassReference; + constructor( + context: ModelGeneratorContext, + typeDeclaration: TypeDeclaration, + private readonly objectDeclaration: ObjectTypeDeclaration + ) { + super(context); + this.typeDeclaration = typeDeclaration; + this.classReference = this.context.phpTypeMapper.convertToClassReference(this.typeDeclaration.name); + } + + public doGenerate(): PhpFile { + const clazz = php.class_({ + ...this.classReference, + docs: this.typeDeclaration.docs + }); + // todo: handle extended properties + const requiredProperties = this.objectDeclaration.properties.filter( + (property) => !this.context.isOptional(property.valueType) + ); + const optionalProperties = this.objectDeclaration.properties.filter((property) => + this.context.isOptional(property.valueType) + ); + const orderedProperties = [...requiredProperties, ...optionalProperties]; + orderedProperties.forEach((property) => { + clazz.addField( + php.field({ + name: property.name.name.camelCase.safeName, + type: this.context.phpTypeMapper.convert({ reference: property.valueType }), + access: "public", + docs: property.docs, + readonly_: true + // jsonPropertyName: property.name.wireValue + }) + ); + }); + const parameters = orderedProperties.map((property) => + php.parameter({ + name: property.name.name.camelCase.safeName, + type: this.context.phpTypeMapper.convert({ reference: property.valueType }), + docs: property.docs + }) + ); + clazz.addConstructor({ + parameters, + body: php.codeblock((writer) => { + orderedProperties.forEach((property) => { + const propertyName = property.name.name.camelCase.safeName; + writer.writeTextStatement(`$this->${propertyName} = $${propertyName}`); + }); + }) + }); + + return new PhpFile({ + clazz, + rootNamespace: this.context.getRootNamespace(), + directory: this.context.getLocationForTypeId(this.typeDeclaration.name.typeId).directory, + customConfig: this.context.customConfig + }); + } + + protected getFilepath(): RelativeFilePath { + return this.context.getLocationForTypeId(this.typeDeclaration.name.typeId).directory; + } +} diff --git a/generators/php/sdk/src/SdkGeneratorContext.ts b/generators/php/sdk/src/SdkGeneratorContext.ts index 737cf1715b9..a5dec0b1165 100644 --- a/generators/php/sdk/src/SdkGeneratorContext.ts +++ b/generators/php/sdk/src/SdkGeneratorContext.ts @@ -98,24 +98,4 @@ export class SdkGeneratorContext extends AbstractPhpGeneratorContexttitle = $title; + $this->rating = $rating; + } +} diff --git a/seed/php-sdk/imdb/src/Seed/Types/Movie.php b/seed/php-sdk/imdb/src/Seed/Types/Movie.php new file mode 100644 index 00000000000..b8327fad71d --- /dev/null +++ b/seed/php-sdk/imdb/src/Seed/Types/Movie.php @@ -0,0 +1,36 @@ +id = $id; + $this->title = $title; + $this->rating = $rating; + } +} From 1c972de097f85e20f54268aef599394565546918 Mon Sep 17 00:00:00 2001 From: dcb6 Date: Tue, 17 Sep 2024 17:20:36 -0400 Subject: [PATCH 12/19] full seed run --- .../model/src/object/ObjectGenerator.ts | 1 - .../src/asIs/SerializableType.Template.php | 25 +- generators/php/codegen/src/ast/Array.ts | 28 +++ generators/php/codegen/src/ast/Attribute.ts | 39 +++ generators/php/codegen/src/ast/Class.ts | 12 +- generators/php/codegen/src/ast/Enum.ts | 77 ++++++ generators/php/codegen/src/ast/Field.ts | 21 +- generators/php/codegen/src/ast/Map.ts | 19 +- generators/php/codegen/src/ast/Type.ts | 33 +-- generators/php/codegen/src/ast/index.ts | 3 + .../context/AbstractPhpGeneratorContext.ts | 41 +++- .../php/codegen/src/context/PhpTypeMapper.ts | 2 +- generators/php/codegen/src/php.ts | 30 ++- generators/php/codegen/src/project/PhpFile.ts | 5 +- .../php/model/src/enum/EnumGenerator.ts | 40 +++ generators/php/model/src/generateModels.ts | 4 +- .../php/model/src/object/ObjectGenerator.ts | 90 ++++++- seed/php-model/alias-extends/src/Child.php | 24 ++ .../src/Core/SerializableType.php | 21 +- seed/php-model/alias-extends/src/Parent.php | 24 ++ .../src/Placeholder/Placeholder.php | 11 - .../alias/src/Core/SerializableType.php | 21 +- .../alias/src/Placeholder/Placeholder.php | 11 - seed/php-model/alias/src/Type.php | 36 +++ .../any-auth/src/Auth/TokenResponse.php | 45 ++++ .../any-auth/src/Core/SerializableType.php | 21 +- .../any-auth/src/Placeholder/Placeholder.php | 11 - seed/php-model/any-auth/src/User/User.php | 33 +++ .../src/Core/SerializableType.php | 21 +- .../src/Placeholder/Placeholder.php | 11 - .../audiences/src/Core/SerializableType.php | 21 +- .../src/FolderA/Service/Response.php | 25 ++ .../audiences/src/FolderB/Common/Foo.php | 25 ++ .../src/FolderC/Common/FolderCFoo.php | 24 ++ .../src/FolderD/Service/Response.php | 24 ++ .../audiences/src/Foo/FilteredType.php | 33 +++ .../audiences/src/Foo/ImportingType.php | 24 ++ .../audiences/src/Placeholder/Placeholder.php | 11 - .../src/Core/SerializableType.php | 21 +- .../src/Placeholder/Placeholder.php | 11 - .../src/Core/SerializableType.php | 21 +- .../Errors/UnauthorizedRequestErrorBody.php | 24 ++ .../src/Placeholder/Placeholder.php | 11 - .../basic-auth/src/Core/SerializableType.php | 21 +- .../Errors/UnauthorizedRequestErrorBody.php | 24 ++ .../src/Placeholder/Placeholder.php | 11 - .../src/Core/SerializableType.php | 21 +- .../src/Placeholder/Placeholder.php | 11 - .../bytes/src/Core/SerializableType.php | 21 +- .../bytes/src/Placeholder/Placeholder.php | 11 - .../circular-references-advanced/src/A/A.php | 12 + .../src/Ast/ObjectFieldValue.php | 36 +++ .../src/Ast/ObjectValue.php | 12 + .../src/Ast/PrimitiveValue.php | 9 + .../src/Core/SerializableType.php | 21 +- .../src/ImportingA.php | 25 ++ .../src/Placeholder/Placeholder.php | 11 - .../src/RootType.php | 24 ++ .../php-model/circular-references/src/A/A.php | 12 + .../src/Ast/ObjectValue.php | 12 + .../src/Ast/PrimitiveValue.php | 9 + .../src/Core/SerializableType.php | 21 +- .../circular-references/src/ImportingA.php | 25 ++ .../src/Placeholder/Placeholder.php | 11 - .../circular-references/src/RootType.php | 24 ++ .../src/Core/SerializableType.php | 21 +- .../src/FolderA/Service/Response.php | 25 ++ .../src/FolderB/Common/Foo.php | 25 ++ .../src/FolderC/Common/Foo.php | 24 ++ .../src/FolderD/Service/Response.php | 25 ++ .../src/Foo/ImportingType.php | 24 ++ .../src/Placeholder/Placeholder.php | 11 - .../custom-auth/src/Core/SerializableType.php | 21 +- .../Errors/UnauthorizedRequestErrorBody.php | 24 ++ .../src/Placeholder/Placeholder.php | 11 - seed/php-model/enum/src/Color.php | 9 + .../enum/src/Core/SerializableType.php | 21 +- seed/php-model/enum/src/Operand.php | 10 + .../enum/src/Placeholder/Placeholder.php | 11 - .../src/Core/SerializableType.php | 21 +- .../src/Errors/PropertyBasedErrorTestBody.php | 24 ++ .../src/Placeholder/Placeholder.php | 11 - seed/php-model/examples/src/BasicType.php | 9 + .../examples/src/Commons/Types/Metadata.php | 43 ++++ seed/php-model/examples/src/ComplexType.php | 10 + .../examples/src/Core/SerializableType.php | 21 +- seed/php-model/examples/src/Identifier.php | 42 ++++ .../examples/src/Placeholder/Placeholder.php | 11 - seed/php-model/examples/src/Types/Actor.php | 33 +++ seed/php-model/examples/src/Types/Actress.php | 33 +++ .../examples/src/Types/Directory.php | 45 ++++ seed/php-model/examples/src/Types/Entity.php | 33 +++ .../examples/src/Types/ExceptionInfo.php | 42 ++++ .../examples/src/Types/ExtendedMovie.php | 25 ++ seed/php-model/examples/src/Types/File.php | 33 +++ .../examples/src/Types/Migration.php | 34 +++ .../examples/src/Types/MigrationStatus.php | 10 + seed/php-model/examples/src/Types/Moment.php | 44 ++++ seed/php-model/examples/src/Types/Movie.php | 106 ++++++++ seed/php-model/examples/src/Types/Node.php | 45 ++++ seed/php-model/examples/src/Types/Request.php | 24 ++ .../php-model/examples/src/Types/Response.php | 35 +++ .../examples/src/Types/ResponseType.php | 24 ++ .../examples/src/Types/StuntDouble.php | 33 +++ seed/php-model/examples/src/Types/Tree.php | 26 ++ .../exhaustive/src/Core/SerializableType.php | 21 +- .../GeneralErrors/BadObjectRequestInfo.php | 24 ++ .../src/Placeholder/Placeholder.php | 11 - .../src/Types/Enum/WeatherReport.php | 11 + .../src/Types/Object/DoubleOptional.php | 24 ++ .../Object/NestedObjectWithOptionalField.php | 34 +++ .../Object/NestedObjectWithRequiredField.php | 34 +++ .../src/Types/Object/ObjectWithMapOfMap.php | 25 ++ .../Types/Object/ObjectWithOptionalField.php | 135 ++++++++++ .../Types/Object/ObjectWithRequiredField.php | 24 ++ .../exhaustive/src/Types/Union/Cat.php | 33 +++ .../exhaustive/src/Types/Union/Dog.php | 33 +++ .../extends/src/Core/SerializableType.php | 21 +- seed/php-model/extends/src/Docs.php | 24 ++ seed/php-model/extends/src/ExampleType.php | 24 ++ seed/php-model/extends/src/Json.php | 24 ++ seed/php-model/extends/src/NestedType.php | 24 ++ .../extends/src/Placeholder/Placeholder.php | 11 - .../src/Core/SerializableType.php | 21 +- .../extra-properties/src/Failure.php | 24 ++ .../src/Placeholder/Placeholder.php | 11 - .../extra-properties/src/User/User.php | 24 ++ .../src/Core/SerializableType.php | 21 +- .../src/Placeholder/Placeholder.php | 11 - .../file-upload/.mock/definition/service.yml | 15 ++ .../file-upload/src/Core/SerializableType.php | 21 +- .../src/Placeholder/Placeholder.php | 11 - .../file-upload/src/Service/MyObject.php | 24 ++ .../file-upload/src/Service/ObjectType.php | 9 + .../folders/src/Core/SerializableType.php | 21 +- .../folders/src/Placeholder/Placeholder.php | 11 - .../grpc-proto-exhaustive/src/Column.php | 53 ++++ .../src/Core/SerializableType.php | 21 +- .../src/DeleteResponse.php | 12 + .../src/DescribeResponse.php | 53 ++++ .../src/FetchResponse.php | 45 ++++ .../grpc-proto-exhaustive/src/IndexedData.php | 34 +++ .../grpc-proto-exhaustive/src/ListElement.php | 24 ++ .../src/ListResponse.php | 55 +++++ .../src/NamespaceSummary.php | 24 ++ .../grpc-proto-exhaustive/src/Pagination.php | 24 ++ .../src/Placeholder/Placeholder.php | 11 - .../grpc-proto-exhaustive/src/QueryColumn.php | 62 +++++ .../src/QueryResponse.php | 55 +++++ .../grpc-proto-exhaustive/src/QueryResult.php | 35 +++ .../src/ScoredColumn.php | 62 +++++ .../src/UpdateResponse.php | 12 + .../src/UploadResponse.php | 24 ++ .../grpc-proto-exhaustive/src/Usage.php | 24 ++ .../grpc-proto/src/Core/SerializableType.php | 21 +- .../grpc-proto/src/CreateResponse.php | 25 ++ .../src/Placeholder/Placeholder.php | 11 - seed/php-model/grpc-proto/src/UserModel.php | 60 +++++ .../src/Core/SerializableType.php | 21 +- .../src/Payment/Currency.php | 9 + .../src/Placeholder/Placeholder.php | 11 - .../imdb/src/Core/SerializableType.php | 21 +- .../imdb/src/Imdb}/CreateMovieRequest.php | 13 +- .../imdb/src/Imdb}/Movie.php | 16 +- .../imdb/src/Placeholder/Placeholder.php | 11 - .../literal/src/Core/SerializableType.php | 21 +- .../literal/src/Inlined/ANestedLiteral.php | 24 ++ .../literal/src/Inlined/ATopLevelLiteral.php | 25 ++ .../literal/src/Placeholder/Placeholder.php | 11 - .../literal/src/Reference/SendRequest.php | 60 +++++ seed/php-model/literal/src/SendResponse.php | 42 ++++ .../mixed-case/src/Core/SerializableType.php | 21 +- .../src/Placeholder/Placeholder.php | 11 - .../mixed-case/src/Service/NestedUser.php | 34 +++ .../mixed-case/src/Service/Organization.php | 24 ++ .../mixed-case/src/Service/ResourceStatus.php | 9 + .../php-model/mixed-case/src/Service/User.php | 43 ++++ .../src/Core/SerializableType.php | 21 +- .../CreateOrganizationRequest.php | 24 ++ .../src/Organization/Organization.php | 44 ++++ .../src/Placeholder/Placeholder.php | 11 - .../src/User/Events/Event.php | 33 +++ .../src/User/Events/Metadata/Metadata.php | 33 +++ .../mixed-file-directory/src/User/User.php | 42 ++++ .../src/Core/SerializableType.php | 21 +- .../php-model/multi-line-docs/src/Operand.php | 10 + .../src/Placeholder/Placeholder.php | 11 - .../multi-line-docs/src/User/User.php | 56 +++++ .../src/Core/SerializableType.php | 21 +- .../src/Placeholder/Placeholder.php | 11 - .../src/Core/SerializableType.php | 21 +- .../src/Placeholder/Placeholder.php | 11 - .../src/Core/SerializableType.php | 21 +- .../src/Placeholder/Placeholder.php | 11 - .../src/Auth/TokenResponse.php | 36 +++ .../src/Core/SerializableType.php | 21 +- .../src/Placeholder/Placeholder.php | 11 - .../src/Auth/TokenResponse.php | 45 ++++ .../src/Core/SerializableType.php | 21 +- .../src/Placeholder/Placeholder.php | 11 - .../src/Auth/TokenResponse.php | 45 ++++ .../src/Core/SerializableType.php | 21 +- .../src/Placeholder/Placeholder.php | 11 - .../src/Auth/TokenResponse.php | 45 ++++ .../src/Core/SerializableType.php | 21 +- .../src/Placeholder/Placeholder.php | 11 - .../object/src/Core/SerializableType.php | 21 +- seed/php-model/object/src/Name.php | 33 +++ .../object/src/Placeholder/Placeholder.php | 11 - seed/php-model/object/src/Type.php | 230 ++++++++++++++++++ .../src/Commons/Metadata/Metadata.php | 34 +++ .../src/Core/SerializableType.php | 21 +- .../src/File/Directory/Directory.php | 45 ++++ .../objects-with-imports/src/File/File.php | 43 ++++ .../src/File/FileInfo.php | 9 + .../objects-with-imports/src/Node.php | 43 ++++ .../src/Placeholder/Placeholder.php | 11 - .../objects-with-imports/src/Tree.php | 26 ++ .../optional/src/Core/SerializableType.php | 21 +- .../optional/src/Placeholder/Placeholder.php | 11 - .../package-yml/src/Core/SerializableType.php | 21 +- .../php-model/package-yml/src/EchoRequest.php | 33 +++ .../src/Placeholder/Placeholder.php | 11 - .../pagination/src/Core/SerializableType.php | 21 +- .../src/Placeholder/Placeholder.php | 11 - .../pagination/src/UsernameCursor.php | 25 ++ .../php-model/pagination/src/UsernamePage.php | 34 +++ .../ListUsersExtendedOptionalListResponse.php | 24 ++ .../src/Users/ListUsersExtendedResponse.php | 24 ++ .../src/Users/ListUsersPaginationResponse.php | 54 ++++ .../pagination/src/Users/NextPage.php | 33 +++ seed/php-model/pagination/src/Users/Order.php | 9 + seed/php-model/pagination/src/Users/Page.php | 52 ++++ seed/php-model/pagination/src/Users/User.php | 33 +++ .../src/Users/UserListContainer.php | 26 ++ .../src/Users/UserOptionalListContainer.php | 26 ++ .../src/Users/UserOptionalListPage.php | 34 +++ .../pagination/src/Users/UserPage.php | 34 +++ .../src/Users/UsernameContainer.php | 25 ++ .../pagination/src/Users/WithCursor.php | 24 ++ .../pagination/src/Users/WithPage.php | 24 ++ .../plain-text/src/Core/SerializableType.php | 21 +- .../src/Placeholder/Placeholder.php | 11 - .../src/Core/SerializableType.php | 21 +- .../src/Placeholder/Placeholder.php | 11 - .../query-parameters/src/User/NestedUser.php | 34 +++ .../query-parameters/src/User/User.php | 34 +++ .../src/Core/SerializableType.php | 21 +- .../reserved-keywords/src/Package/Package.php | 24 ++ .../reserved-keywords/src/Package/Record.php | 34 +++ .../src/Placeholder/Placeholder.php | 11 - .../src/Core/SerializableType.php | 21 +- .../src/Placeholder/Placeholder.php | 11 - .../response-property/src/Service/Movie.php | 33 +++ .../src/Service/Response.php | 25 ++ .../src/Service/WithDocs.php | 24 ++ .../response-property/src/StringResponse.php | 24 ++ .../response-property/src/WithMetadata.php | 25 ++ seed/php-model/simple-fhir/src/Account.php | 53 ++++ .../simple-fhir/src/BaseResource.php | 44 ++++ .../simple-fhir/src/Core/SerializableType.php | 21 +- seed/php-model/simple-fhir/src/Memo.php | 34 +++ seed/php-model/simple-fhir/src/Patient.php | 44 ++++ .../src/Placeholder/Placeholder.php | 11 - .../simple-fhir/src/Practitioner.php | 33 +++ seed/php-model/simple-fhir/src/Script.php | 33 +++ .../src/Core/SerializableType.php | 21 +- .../src/Placeholder/Placeholder.php | 11 - .../src/Core/SerializableType.php | 21 +- .../src/Placeholder/Placeholder.php | 11 - .../src/Core/SerializableType.php | 21 +- .../src/Dummy/RegularResponse.php | 33 +++ .../src/Dummy/StreamResponse.php | 33 +++ .../src/Placeholder/Placeholder.php | 11 - .../streaming/src/Core/SerializableType.php | 21 +- .../streaming/src/Dummy/StreamResponse.php | 33 +++ .../streaming/src/Placeholder/Placeholder.php | 11 - .../Commons/BinaryTreeNodeAndTreeValue.php | 34 +++ .../trace/src/Commons/BinaryTreeNodeValue.php | 51 ++++ .../trace/src/Commons/BinaryTreeValue.php | 35 +++ .../trace/src/Commons/DebugKeyValuePairs.php | 33 +++ .../trace/src/Commons/DebugMapValue.php | 26 ++ .../DoublyLinkedListNodeAndListValue.php | 34 +++ .../src/Commons/DoublyLinkedListNodeValue.php | 51 ++++ .../src/Commons/DoublyLinkedListValue.php | 35 +++ seed/php-model/trace/src/Commons/FileInfo.php | 33 +++ .../trace/src/Commons/GenericValue.php | 33 +++ .../trace/src/Commons/KeyValuePair.php | 33 +++ seed/php-model/trace/src/Commons/Language.php | 10 + seed/php-model/trace/src/Commons/ListType.php | 33 +++ seed/php-model/trace/src/Commons/MapType.php | 33 +++ seed/php-model/trace/src/Commons/MapValue.php | 26 ++ .../SinglyLinkedListNodeAndListValue.php | 34 +++ .../src/Commons/SinglyLinkedListNodeValue.php | 42 ++++ .../src/Commons/SinglyLinkedListValue.php | 35 +++ seed/php-model/trace/src/Commons/TestCase.php | 34 +++ .../Commons/TestCaseWithExpectedResult.php | 34 +++ .../trace/src/Core/SerializableType.php | 21 +- .../src/LangServer/LangServerRequest.php | 24 ++ .../src/LangServer/LangServerResponse.php | 24 ++ .../trace/src/Migration/Migration.php | 34 +++ .../trace/src/Migration/MigrationStatus.php | 10 + .../trace/src/Placeholder/Placeholder.php | 11 - .../php-model/trace/src/Playlist/Playlist.php | 33 +++ .../src/Playlist/PlaylistCreateRequest.php | 34 +++ .../src/Playlist/ReservedKeywordEnum.php | 9 + .../src/Playlist/UpdatePlaylistRequest.php | 34 +++ .../src/Problem/CreateProblemRequest.php | 84 +++++++ .../src/Problem/GenericCreateProblemError.php | 42 ++++ .../GetDefaultStarterFilesResponse.php | 27 ++ .../trace/src/Problem/ProblemDescription.php | 25 ++ .../trace/src/Problem/ProblemFiles.php | 35 +++ .../trace/src/Problem/ProblemInfo.php | 111 +++++++++ .../src/Problem/UpdateProblemResponse.php | 24 ++ .../trace/src/Problem/VariableTypeAndName.php | 33 +++ .../Submission/BuildingExecutorResponse.php | 34 +++ .../trace/src/Submission/CompileError.php | 24 ++ .../Submission/CustomTestCasesUnsupported.php | 33 +++ .../trace/src/Submission/ErroredResponse.php | 33 +++ .../trace/src/Submission/ExceptionInfo.php | 42 ++++ .../Submission/ExecutionSessionResponse.php | 53 ++++ .../src/Submission/ExecutionSessionState.php | 71 ++++++ .../src/Submission/ExecutionSessionStatus.php | 13 + .../ExistingSubmissionExecuting.php | 24 ++ .../src/Submission/ExpressionLocation.php | 33 +++ .../trace/src/Submission/FinishedResponse.php | 24 ++ .../GetExecutionSessionStateResponse.php | 44 ++++ .../Submission/GetSubmissionStateResponse.php | 54 ++++ .../GetTraceResponsesPageRequest.php | 24 ++ .../trace/src/Submission/GradedResponse.php | 35 +++ .../trace/src/Submission/GradedResponseV2.php | 34 +++ .../src/Submission/GradedTestCaseUpdate.php | 33 +++ .../Submission/InitializeProblemRequest.php | 33 +++ .../trace/src/Submission/InternalError.php | 25 ++ .../src/Submission/InvalidRequestResponse.php | 33 +++ .../LightweightStackframeInformation.php | 33 +++ .../RecordedResponseNotification.php | 42 ++++ .../src/Submission/RecordedTestCaseUpdate.php | 33 +++ .../RecordingResponseNotification.php | 62 +++++ .../trace/src/Submission/RunningResponse.php | 34 +++ .../src/Submission/RunningSubmissionState.php | 12 + .../trace/src/Submission/RuntimeError.php | 24 ++ seed/php-model/trace/src/Submission/Scope.php | 25 ++ .../trace/src/Submission/StackFrame.php | 44 ++++ .../trace/src/Submission/StackInformation.php | 34 +++ .../trace/src/Submission/StderrResponse.php | 33 +++ .../trace/src/Submission/StdoutResponse.php | 33 +++ .../trace/src/Submission/StopRequest.php | 24 ++ .../trace/src/Submission/StoppedResponse.php | 24 ++ .../src/Submission/SubmissionFileInfo.php | 42 ++++ .../src/Submission/SubmissionIdNotFound.php | 24 ++ .../src/Submission/SubmissionTypeEnum.php | 8 + .../trace/src/Submission/SubmitRequestV2.php | 72 ++++++ .../src/Submission/TerminatedResponse.php | 12 + .../src/Submission/TestCaseHiddenGrade.php | 24 ++ .../src/Submission/TestCaseNonHiddenGrade.php | 51 ++++ .../trace/src/Submission/TestCaseResult.php | 42 ++++ .../Submission/TestCaseResultWithStdout.php | 34 +++ .../src/Submission/TestSubmissionState.php | 53 ++++ .../src/Submission/TestSubmissionStatusV2.php | 54 ++++ .../src/Submission/TestSubmissionUpdate.php | 35 +++ .../trace/src/Submission/TraceResponse.php | 71 ++++++ .../trace/src/Submission/TraceResponseV2.php | 81 ++++++ .../src/Submission/TraceResponsesPage.php | 37 +++ .../src/Submission/TraceResponsesPageV2.php | 37 +++ .../trace/src/Submission/TracedFile.php | 33 +++ .../trace/src/Submission/TracedTestCase.php | 34 +++ .../Submission/UnexpectedLanguageError.php | 34 +++ .../trace/src/Submission/WorkspaceFiles.php | 35 +++ .../src/Submission/WorkspaceRanResponse.php | 34 +++ .../src/Submission/WorkspaceRunDetails.php | 43 ++++ .../WorkspaceStarterFilesResponse.php | 27 ++ .../WorkspaceStarterFilesResponseV2.php | 27 ++ .../Submission/WorkspaceSubmissionState.php | 24 ++ .../WorkspaceSubmissionStatusV2.php | 26 ++ .../Submission/WorkspaceSubmissionUpdate.php | 35 +++ .../src/Submission/WorkspaceSubmitRequest.php | 54 ++++ .../src/Submission/WorkspaceTracedUpdate.php | 24 ++ .../trace/src/V2/Problem/BasicCustomFiles.php | 56 +++++ .../src/V2/Problem/BasicTestCaseTemplate.php | 52 ++++ .../src/V2/Problem/CreateProblemRequestV2.php | 83 +++++++ .../Problem/DeepEqualityCorrectnessCheck.php | 24 ++ .../src/V2/Problem/DefaultProvidedFile.php | 35 +++ .../trace/src/V2/Problem/FileInfoV2.php | 51 ++++ seed/php-model/trace/src/V2/Problem/Files.php | 26 ++ .../src/V2/Problem/FunctionImplementation.php | 33 +++ ...tionImplementationForMultipleLanguages.php | 27 ++ .../trace/src/V2/Problem/GeneratedFiles.php | 45 ++++ .../Problem/GetBasicSolutionFileRequest.php | 34 +++ .../Problem/GetBasicSolutionFileResponse.php | 27 ++ .../Problem/GetFunctionSignatureRequest.php | 24 ++ .../Problem/GetFunctionSignatureResponse.php | 26 ++ .../GetGeneratedTestCaseFileRequest.php | 35 +++ ...etGeneratedTestCaseTemplateFileRequest.php | 25 ++ .../V2/Problem/LightweightProblemInfoV2.php | 52 ++++ .../V2/Problem/NonVoidFunctionDefinition.php | 35 +++ .../V2/Problem/NonVoidFunctionSignature.php | 35 +++ .../trace/src/V2/Problem/Parameter.php | 42 ++++ .../trace/src/V2/Problem/ProblemInfoV2.php | 111 +++++++++ .../trace/src/V2/Problem/TestCaseExpects.php | 24 ++ .../src/V2/Problem/TestCaseImplementation.php | 34 +++ .../TestCaseImplementationDescription.php | 25 ++ .../trace/src/V2/Problem/TestCaseMetadata.php | 42 ++++ .../trace/src/V2/Problem/TestCaseTemplate.php | 43 ++++ .../trace/src/V2/Problem/TestCaseV2.php | 54 ++++ ...TestCaseWithActualResultImplementation.php | 34 +++ .../src/V2/Problem/VoidFunctionDefinition.php | 36 +++ ...unctionDefinitionThatTakesActualResult.php | 39 +++ .../src/V2/Problem/VoidFunctionSignature.php | 26 ++ ...FunctionSignatureThatTakesActualResult.php | 35 +++ .../src/V2/V3/Problem/BasicCustomFiles.php | 56 +++++ .../V2/V3/Problem/BasicTestCaseTemplate.php | 52 ++++ .../V2/V3/Problem/CreateProblemRequestV2.php | 83 +++++++ .../Problem/DeepEqualityCorrectnessCheck.php | 24 ++ .../src/V2/V3/Problem/DefaultProvidedFile.php | 35 +++ .../trace/src/V2/V3/Problem/FileInfoV2.php | 51 ++++ .../trace/src/V2/V3/Problem/Files.php | 26 ++ .../V2/V3/Problem/FunctionImplementation.php | 33 +++ ...tionImplementationForMultipleLanguages.php | 27 ++ .../src/V2/V3/Problem/GeneratedFiles.php | 45 ++++ .../Problem/GetBasicSolutionFileRequest.php | 34 +++ .../Problem/GetBasicSolutionFileResponse.php | 27 ++ .../Problem/GetFunctionSignatureRequest.php | 24 ++ .../Problem/GetFunctionSignatureResponse.php | 26 ++ .../GetGeneratedTestCaseFileRequest.php | 35 +++ ...etGeneratedTestCaseTemplateFileRequest.php | 25 ++ .../V3/Problem/LightweightProblemInfoV2.php | 52 ++++ .../V3/Problem/NonVoidFunctionDefinition.php | 35 +++ .../V3/Problem/NonVoidFunctionSignature.php | 35 +++ .../trace/src/V2/V3/Problem/Parameter.php | 42 ++++ .../trace/src/V2/V3/Problem/ProblemInfoV2.php | 111 +++++++++ .../src/V2/V3/Problem/TestCaseExpects.php | 24 ++ .../V2/V3/Problem/TestCaseImplementation.php | 34 +++ .../TestCaseImplementationDescription.php | 25 ++ .../src/V2/V3/Problem/TestCaseMetadata.php | 42 ++++ .../src/V2/V3/Problem/TestCaseTemplate.php | 43 ++++ .../trace/src/V2/V3/Problem/TestCaseV2.php | 54 ++++ ...TestCaseWithActualResultImplementation.php | 34 +++ .../V2/V3/Problem/VoidFunctionDefinition.php | 36 +++ ...unctionDefinitionThatTakesActualResult.php | 39 +++ .../V2/V3/Problem/VoidFunctionSignature.php | 26 ++ ...FunctionSignatureThatTakesActualResult.php | 35 +++ .../src/Core/SerializableType.php | 21 +- .../src/Placeholder/Placeholder.php | 11 - .../src/Union/KeyType.php | 9 + .../unions/src/Core/SerializableType.php | 21 +- .../unions/src/Placeholder/Placeholder.php | 11 - seed/php-model/unions/src/Types/Bar.php | 24 ++ seed/php-model/unions/src/Types/Foo.php | 24 ++ seed/php-model/unions/src/Union/Circle.php | 24 ++ .../unions/src/Union/GetShapeRequest.php | 24 ++ seed/php-model/unions/src/Union/Square.php | 24 ++ .../unknown/src/Core/SerializableType.php | 21 +- .../unknown/src/Placeholder/Placeholder.php | 11 - .../unknown/src/Unknown/MyObject.php | 24 ++ .../validation/src/Core/SerializableType.php | 21 +- .../src/Placeholder/Placeholder.php | 11 - seed/php-model/validation/src/Shape.php | 10 + seed/php-model/validation/src/Type.php | 55 +++++ .../variables/src/Core/SerializableType.php | 21 +- .../variables/src/Placeholder/Placeholder.php | 11 - .../src/Core/SerializableType.php | 21 +- .../src/Placeholder/Placeholder.php | 11 - .../version-no-default/src/User/User.php | 33 +++ .../version/src/Core/SerializableType.php | 21 +- .../version/src/Placeholder/Placeholder.php | 11 - seed/php-model/version/src/User/User.php | 33 +++ .../websocket/src/Core/SerializableType.php | 21 +- .../websocket/src/Placeholder/Placeholder.php | 11 - .../src/Core/SerializableType.php | 21 +- .../src/Placeholder/Placeholder.php | 11 - seed/php-sdk/alias-extends/src/SeedClient.php | 6 +- .../php-sdk/alias-extends/src/Types/Child.php | 24 ++ .../alias-extends/src/Types/Parent.php | 24 ++ .../alias/src/Core/SerializableType.php | 21 +- .../alias/src/Placeholder/Placeholder.php | 11 - seed/php-sdk/alias/src/SeedClient.php | 6 +- seed/php-sdk/alias/src/Types/Type.php | 36 +++ .../any-auth/src/Auth/Types/TokenResponse.php | 45 ++++ .../any-auth/src/Core/SerializableType.php | 21 +- .../any-auth/src/Placeholder/Placeholder.php | 11 - seed/php-sdk/any-auth/src/SeedClient.php | 6 +- seed/php-sdk/any-auth/src/User/Types/User.php | 33 +++ .../src/Core/SerializableType.php | 21 +- .../src/Placeholder/Placeholder.php | 11 - .../api-wide-base-path/src/SeedClient.php | 6 +- .../audiences/src/Core/SerializableType.php | 21 +- .../src/FolderA/Service/Types/Response.php | 25 ++ .../src/FolderB/Common/Types/Foo.php | 25 ++ .../src/FolderC/Common/Types/FolderCFoo.php | 24 ++ .../src/FolderD/Service/Types/Response.php | 24 ++ .../audiences/src/Foo/Types/FilteredType.php | 33 +++ .../audiences/src/Foo/Types/ImportingType.php | 24 ++ .../audiences/src/Placeholder/Placeholder.php | 11 - seed/php-sdk/audiences/src/SeedClient.php | 6 +- .../src/Core/SerializableType.php | 21 +- .../src/Placeholder/Placeholder.php | 11 - .../src/SeedClient.php | 7 +- .../src/Core/SerializableType.php | 21 +- .../Types/UnauthorizedRequestErrorBody.php | 24 ++ .../src/Placeholder/Placeholder.php | 11 - .../src/SeedClient.php | 6 +- .../basic-auth/src/Core/SerializableType.php | 21 +- .../Types/UnauthorizedRequestErrorBody.php | 24 ++ .../src/Placeholder/Placeholder.php | 11 - seed/php-sdk/basic-auth/src/SeedClient.php | 6 +- .../src/Core/SerializableType.php | 21 +- .../src/Placeholder/Placeholder.php | 11 - .../src/SeedClient.php | 6 +- .../bytes/src/Core/SerializableType.php | 21 +- .../bytes/src/Placeholder/Placeholder.php | 11 - seed/php-sdk/bytes/src/SeedClient.php | 6 +- .../src/A/Types/A.php | 12 + .../src/Ast/Types/ObjectFieldValue.php | 36 +++ .../src/Ast/Types/ObjectValue.php | 12 + .../src/Ast/Types/PrimitiveValue.php | 9 + .../src/Core/SerializableType.php | 21 +- .../src/Placeholder/Placeholder.php | 11 - .../src/SeedClient.php | 6 +- .../src/Types/ImportingA.php | 25 ++ .../src/Types/RootType.php | 24 ++ .../circular-references/src/A/Types/A.php | 12 + .../src/Ast/Types/ObjectValue.php | 12 + .../src/Ast/Types/PrimitiveValue.php | 9 + .../src/Core/SerializableType.php | 21 +- .../src/Placeholder/Placeholder.php | 11 - .../circular-references/src/SeedClient.php | 6 +- .../src/Types/ImportingA.php | 25 ++ .../src/Types/RootType.php | 24 ++ .../src/Core/SerializableType.php | 21 +- .../src/FolderA/Service/Types/Response.php | 25 ++ .../src/FolderB/Common/Types/Foo.php | 25 ++ .../src/FolderC/Common/Types/Foo.php | 24 ++ .../src/FolderD/Service/Types/Response.php | 25 ++ .../src/Foo/Types/ImportingType.php | 24 ++ .../src/Placeholder/Placeholder.php | 11 - .../src/SeedClient.php | 6 +- .../custom-auth/src/Core/SerializableType.php | 21 +- .../Types/UnauthorizedRequestErrorBody.php | 24 ++ .../src/Placeholder/Placeholder.php | 11 - seed/php-sdk/custom-auth/src/SeedClient.php | 6 +- .../enum/src/Core/SerializableType.php | 21 +- .../enum/src/Placeholder/Placeholder.php | 11 - seed/php-sdk/enum/src/SeedClient.php | 6 +- seed/php-sdk/enum/src/Types/Color.php | 9 + seed/php-sdk/enum/src/Types/Operand.php | 10 + .../src/Core/SerializableType.php | 21 +- .../Types/PropertyBasedErrorTestBody.php | 24 ++ .../src/Placeholder/Placeholder.php | 11 - .../php-sdk/error-property/src/SeedClient.php | 6 +- .../src/Commons/Types/Types/Metadata.php | 43 ++++ .../examples/src/Core/SerializableType.php | 21 +- .../examples/src/Placeholder/Placeholder.php | 11 - seed/php-sdk/examples/src/SeedClient.php | 6 +- seed/php-sdk/examples/src/Types/BasicType.php | 9 + .../examples/src/Types/ComplexType.php | 10 + .../php-sdk/examples/src/Types/Identifier.php | 42 ++++ .../examples/src/Types/Types/Actor.php | 33 +++ .../examples/src/Types/Types/Actress.php | 33 +++ .../examples/src/Types/Types/Directory.php | 45 ++++ .../examples/src/Types/Types/Entity.php | 33 +++ .../src/Types/Types/ExceptionInfo.php | 42 ++++ .../src/Types/Types/ExtendedMovie.php | 25 ++ .../php-sdk/examples/src/Types/Types/File.php | 33 +++ .../examples/src/Types/Types/Migration.php | 34 +++ .../src/Types/Types/MigrationStatus.php | 10 + .../examples/src/Types/Types/Moment.php | 44 ++++ .../examples/src/Types/Types/Movie.php | 106 ++++++++ .../php-sdk/examples/src/Types/Types/Node.php | 45 ++++ .../examples/src/Types/Types/Request.php | 24 ++ .../examples/src/Types/Types/Response.php | 35 +++ .../examples/src/Types/Types/ResponseType.php | 24 ++ .../examples/src/Types/Types/StuntDouble.php | 33 +++ .../php-sdk/examples/src/Types/Types/Tree.php | 26 ++ .../exhaustive/src/Core/SerializableType.php | 21 +- .../Types/BadObjectRequestInfo.php | 24 ++ .../src/Placeholder/Placeholder.php | 11 - seed/php-sdk/exhaustive/src/SeedClient.php | 6 +- .../src/Types/Enum/Types/WeatherReport.php | 11 + .../src/Types/Object/Types/DoubleOptional.php | 24 ++ .../Types/NestedObjectWithOptionalField.php | 34 +++ .../Types/NestedObjectWithRequiredField.php | 34 +++ .../Types/Object/Types/ObjectWithMapOfMap.php | 25 ++ .../Object/Types/ObjectWithOptionalField.php | 135 ++++++++++ .../Object/Types/ObjectWithRequiredField.php | 24 ++ .../exhaustive/src/Types/Union/Types/Cat.php | 33 +++ .../exhaustive/src/Types/Union/Types/Dog.php | 33 +++ .../extends/src/Core/SerializableType.php | 21 +- .../extends/src/Placeholder/Placeholder.php | 11 - seed/php-sdk/extends/src/SeedClient.php | 6 +- seed/php-sdk/extends/src/Types/Docs.php | 24 ++ .../php-sdk/extends/src/Types/ExampleType.php | 24 ++ seed/php-sdk/extends/src/Types/Json.php | 24 ++ seed/php-sdk/extends/src/Types/NestedType.php | 24 ++ .../src/Core/SerializableType.php | 21 +- .../src/Placeholder/Placeholder.php | 11 - .../extra-properties/src/SeedClient.php | 6 +- .../extra-properties/src/Types/Failure.php | 24 ++ .../extra-properties/src/User/Types/User.php | 24 ++ .../src/Core/SerializableType.php | 21 +- .../src/Placeholder/Placeholder.php | 11 - seed/php-sdk/file-download/src/SeedClient.php | 6 +- .../file-upload/.mock/definition/service.yml | 15 ++ .../file-upload/src/Core/SerializableType.php | 21 +- .../src/Placeholder/Placeholder.php | 11 - seed/php-sdk/file-upload/src/SeedClient.php | 6 +- .../src/Service/Types/MyObject.php | 24 ++ .../src/Service/Types/ObjectType.php | 9 + .../folders/src/Core/SerializableType.php | 21 +- .../folders/src/Placeholder/Placeholder.php | 11 - seed/php-sdk/folders/src/SeedClient.php | 6 +- .../src/Core/SerializableType.php | 21 +- .../src/Placeholder/Placeholder.php | 11 - .../grpc-proto-exhaustive/src/SeedClient.php | 6 +- .../src/Types/Column.php | 53 ++++ .../src/Types/DeleteResponse.php | 12 + .../src/Types/DescribeResponse.php | 53 ++++ .../src/Types/FetchResponse.php | 45 ++++ .../src/Types/IndexedData.php | 34 +++ .../src/Types/ListElement.php | 24 ++ .../src/Types/ListResponse.php | 55 +++++ .../src/Types/NamespaceSummary.php | 24 ++ .../src/Types/Pagination.php | 24 ++ .../src/Types/QueryColumn.php | 62 +++++ .../src/Types/QueryResponse.php | 55 +++++ .../src/Types/QueryResult.php | 35 +++ .../src/Types/ScoredColumn.php | 62 +++++ .../src/Types/UpdateResponse.php | 12 + .../src/Types/UploadResponse.php | 24 ++ .../grpc-proto-exhaustive/src/Types/Usage.php | 24 ++ .../grpc-proto/src/Core/SerializableType.php | 21 +- .../src/Placeholder/Placeholder.php | 11 - seed/php-sdk/grpc-proto/src/SeedClient.php | 6 +- .../grpc-proto/src/Types/CreateResponse.php | 25 ++ .../grpc-proto/src/Types/UserModel.php | 60 +++++ .../src/Core/SerializableType.php | 21 +- .../src/Payment/Types/Currency.php | 9 + .../src/Placeholder/Placeholder.php | 11 - .../idempotency-headers/src/SeedClient.php | 6 +- seed/php-sdk/imdb/src/Core/Constant.php | 2 +- .../imdb/src/Core/SerializableType.php | 25 +- .../src/Imdb/Types/CreateMovieRequest.php | 33 +++ seed/php-sdk/imdb/src/Imdb/Types/Movie.php | 42 ++++ seed/php-sdk/imdb/src/SeedClient.php | 6 +- .../literal/src/Core/SerializableType.php | 21 +- .../src/Inlined/Types/ANestedLiteral.php | 24 ++ .../src/Inlined/Types/ATopLevelLiteral.php | 25 ++ .../literal/src/Placeholder/Placeholder.php | 11 - .../src/Reference/Types/SendRequest.php | 60 +++++ seed/php-sdk/literal/src/SeedClient.php | 8 +- .../literal/src/Types/SendResponse.php | 42 ++++ .../mixed-case/src/Core/SerializableType.php | 21 +- .../src/Placeholder/Placeholder.php | 11 - seed/php-sdk/mixed-case/src/SeedClient.php | 6 +- .../src/Service/Types/NestedUser.php | 34 +++ .../src/Service/Types/Organization.php | 24 ++ .../src/Service/Types/ResourceStatus.php | 9 + .../mixed-case/src/Service/Types/User.php | 43 ++++ .../src/Core/SerializableType.php | 21 +- .../Types/CreateOrganizationRequest.php | 24 ++ .../src/Organization/Types/Organization.php | 44 ++++ .../src/Placeholder/Placeholder.php | 11 - .../mixed-file-directory/src/SeedClient.php | 6 +- .../User/Events/Metadata/Types/Metadata.php | 33 +++ .../src/User/Events/Types/Event.php | 33 +++ .../src/User/Types/User.php | 42 ++++ .../src/Core/SerializableType.php | 21 +- .../src/Placeholder/Placeholder.php | 11 - .../multi-line-docs/src/SeedClient.php | 6 +- .../multi-line-docs/src/Types/Operand.php | 10 + .../multi-line-docs/src/User/Types/User.php | 56 +++++ .../src/Core/SerializableType.php | 21 +- .../src/Placeholder/Placeholder.php | 11 - .../src/SeedClient.php | 6 +- .../src/Core/SerializableType.php | 21 +- .../src/Placeholder/Placeholder.php | 11 - .../multi-url-environment/src/SeedClient.php | 6 +- .../src/Core/SerializableType.php | 21 +- .../src/Placeholder/Placeholder.php | 11 - .../php-sdk/no-environment/src/SeedClient.php | 6 +- .../src/Auth/Types/TokenResponse.php | 36 +++ .../src/Core/SerializableType.php | 21 +- .../src/Placeholder/Placeholder.php | 11 - .../src/SeedClient.php | 6 +- .../src/Auth/Types/TokenResponse.php | 45 ++++ .../src/Core/SerializableType.php | 21 +- .../src/Placeholder/Placeholder.php | 11 - .../src/SeedClient.php | 6 +- .../src/Auth/Types/TokenResponse.php | 45 ++++ .../src/Core/SerializableType.php | 21 +- .../src/Placeholder/Placeholder.php | 11 - .../src/SeedClient.php | 6 +- .../src/Auth/Types/TokenResponse.php | 45 ++++ .../src/Core/SerializableType.php | 21 +- .../src/Placeholder/Placeholder.php | 11 - .../src/SeedClient.php | 6 +- .../object/src/Core/SerializableType.php | 21 +- .../object/src/Placeholder/Placeholder.php | 11 - seed/php-sdk/object/src/SeedClient.php | 6 +- seed/php-sdk/object/src/Types/Name.php | 33 +++ seed/php-sdk/object/src/Types/Type.php | 230 ++++++++++++++++++ .../src/Commons/Metadata/Types/Metadata.php | 34 +++ .../src/Core/SerializableType.php | 21 +- .../src/File/Directory/Types/Directory.php | 45 ++++ .../src/File/Types/File.php | 43 ++++ .../src/File/Types/FileInfo.php | 9 + .../src/Placeholder/Placeholder.php | 11 - .../objects-with-imports/src/SeedClient.php | 6 +- .../objects-with-imports/src/Types/Node.php | 43 ++++ .../objects-with-imports/src/Types/Tree.php | 26 ++ .../optional/src/Core/SerializableType.php | 21 +- .../optional/src/Placeholder/Placeholder.php | 11 - seed/php-sdk/optional/src/SeedClient.php | 6 +- .../package-yml/src/Core/SerializableType.php | 21 +- .../src/Placeholder/Placeholder.php | 11 - seed/php-sdk/package-yml/src/SeedClient.php | 6 +- .../package-yml/src/Types/EchoRequest.php | 33 +++ .../pagination/src/Core/SerializableType.php | 21 +- .../src/Placeholder/Placeholder.php | 11 - seed/php-sdk/pagination/src/SeedClient.php | 6 +- .../pagination/src/Types/UsernameCursor.php | 25 ++ .../pagination/src/Types/UsernamePage.php | 34 +++ .../ListUsersExtendedOptionalListResponse.php | 24 ++ .../Users/Types/ListUsersExtendedResponse.php | 24 ++ .../Types/ListUsersPaginationResponse.php | 54 ++++ .../pagination/src/Users/Types/NextPage.php | 33 +++ .../pagination/src/Users/Types/Order.php | 9 + .../pagination/src/Users/Types/Page.php | 52 ++++ .../pagination/src/Users/Types/User.php | 33 +++ .../src/Users/Types/UserListContainer.php | 26 ++ .../Users/Types/UserOptionalListContainer.php | 26 ++ .../src/Users/Types/UserOptionalListPage.php | 34 +++ .../pagination/src/Users/Types/UserPage.php | 34 +++ .../src/Users/Types/UsernameContainer.php | 25 ++ .../pagination/src/Users/Types/WithCursor.php | 24 ++ .../pagination/src/Users/Types/WithPage.php | 24 ++ .../plain-text/src/Core/SerializableType.php | 21 +- .../src/Placeholder/Placeholder.php | 11 - seed/php-sdk/plain-text/src/SeedClient.php | 6 +- .../src/Core/SerializableType.php | 21 +- .../src/Placeholder/Placeholder.php | 11 - .../query-parameters/src/SeedClient.php | 6 +- .../src/User/Types/NestedUser.php | 34 +++ .../query-parameters/src/User/Types/User.php | 34 +++ .../src/Core/SerializableType.php | 21 +- .../src/Package/Types/Package.php | 24 ++ .../src/Package/Types/Record.php | 34 +++ .../src/Placeholder/Placeholder.php | 11 - .../reserved-keywords/src/SeedClient.php | 6 +- .../src/Core/SerializableType.php | 21 +- .../src/Placeholder/Placeholder.php | 11 - .../response-property/src/SeedClient.php | 6 +- .../src/Service/Types/Movie.php | 33 +++ .../src/Service/Types/Response.php | 25 ++ .../src/Service/Types/WithDocs.php | 24 ++ .../src/Types/StringResponse.php | 24 ++ .../src/Types/WithMetadata.php | 25 ++ seed/php-sdk/serde-demo/src/Core/DateType.php | 2 +- .../simple-fhir/src/Core/SerializableType.php | 21 +- .../src/Placeholder/Placeholder.php | 11 - seed/php-sdk/simple-fhir/src/SeedClient.php | 6 +- .../php-sdk/simple-fhir/src/Types/Account.php | 53 ++++ .../simple-fhir/src/Types/BaseResource.php | 44 ++++ seed/php-sdk/simple-fhir/src/Types/Memo.php | 34 +++ .../php-sdk/simple-fhir/src/Types/Patient.php | 44 ++++ .../simple-fhir/src/Types/Practitioner.php | 33 +++ seed/php-sdk/simple-fhir/src/Types/Script.php | 33 +++ .../src/Core/SerializableType.php | 21 +- .../src/Placeholder/Placeholder.php | 11 - .../src/SeedClient.php | 6 +- .../src/Core/SerializableType.php | 21 +- .../src/Placeholder/Placeholder.php | 11 - .../src/SeedClient.php | 6 +- .../src/Core/SerializableType.php | 21 +- .../src/Dummy/Types/RegularResponse.php | 33 +++ .../src/Dummy/Types/StreamResponse.php | 33 +++ .../src/Placeholder/Placeholder.php | 11 - .../streaming-parameter/src/SeedClient.php | 6 +- .../streaming/src/Core/SerializableType.php | 21 +- .../src/Dummy/Types/StreamResponse.php | 33 +++ .../streaming/src/Placeholder/Placeholder.php | 11 - seed/php-sdk/streaming/src/SeedClient.php | 6 +- .../Types/BinaryTreeNodeAndTreeValue.php | 34 +++ .../src/Commons/Types/BinaryTreeNodeValue.php | 51 ++++ .../src/Commons/Types/BinaryTreeValue.php | 35 +++ .../src/Commons/Types/DebugKeyValuePairs.php | 33 +++ .../trace/src/Commons/Types/DebugMapValue.php | 26 ++ .../DoublyLinkedListNodeAndListValue.php | 34 +++ .../Types/DoublyLinkedListNodeValue.php | 51 ++++ .../Commons/Types/DoublyLinkedListValue.php | 35 +++ .../trace/src/Commons/Types/FileInfo.php | 33 +++ .../trace/src/Commons/Types/GenericValue.php | 33 +++ .../trace/src/Commons/Types/KeyValuePair.php | 33 +++ .../trace/src/Commons/Types/Language.php | 10 + .../trace/src/Commons/Types/ListType.php | 33 +++ .../trace/src/Commons/Types/MapType.php | 33 +++ .../trace/src/Commons/Types/MapValue.php | 26 ++ .../SinglyLinkedListNodeAndListValue.php | 34 +++ .../Types/SinglyLinkedListNodeValue.php | 42 ++++ .../Commons/Types/SinglyLinkedListValue.php | 35 +++ .../trace/src/Commons/Types/TestCase.php | 34 +++ .../Types/TestCaseWithExpectedResult.php | 34 +++ .../trace/src/Core/SerializableType.php | 21 +- .../LangServer/Types/LangServerRequest.php | 24 ++ .../LangServer/Types/LangServerResponse.php | 24 ++ .../trace/src/Migration/Types/Migration.php | 34 +++ .../src/Migration/Types/MigrationStatus.php | 10 + .../trace/src/Placeholder/Placeholder.php | 11 - .../trace/src/Playlist/Types/Playlist.php | 33 +++ .../Playlist/Types/PlaylistCreateRequest.php | 34 +++ .../Playlist/Types/ReservedKeywordEnum.php | 9 + .../Playlist/Types/UpdatePlaylistRequest.php | 34 +++ .../Problem/Types/CreateProblemRequest.php | 84 +++++++ .../Types/GenericCreateProblemError.php | 42 ++++ .../Types/GetDefaultStarterFilesResponse.php | 27 ++ .../src/Problem/Types/ProblemDescription.php | 25 ++ .../trace/src/Problem/Types/ProblemFiles.php | 35 +++ .../trace/src/Problem/Types/ProblemInfo.php | 111 +++++++++ .../Problem/Types/UpdateProblemResponse.php | 24 ++ .../src/Problem/Types/VariableTypeAndName.php | 33 +++ seed/php-sdk/trace/src/SeedClient.php | 7 +- .../Types/BuildingExecutorResponse.php | 34 +++ .../src/Submission/Types/CompileError.php | 24 ++ .../Types/CustomTestCasesUnsupported.php | 33 +++ .../src/Submission/Types/ErroredResponse.php | 33 +++ .../src/Submission/Types/ExceptionInfo.php | 42 ++++ .../Types/ExecutionSessionResponse.php | 53 ++++ .../Types/ExecutionSessionState.php | 71 ++++++ .../Types/ExecutionSessionStatus.php | 13 + .../Types/ExistingSubmissionExecuting.php | 24 ++ .../Submission/Types/ExpressionLocation.php | 33 +++ .../src/Submission/Types/FinishedResponse.php | 24 ++ .../GetExecutionSessionStateResponse.php | 44 ++++ .../Types/GetSubmissionStateResponse.php | 54 ++++ .../Types/GetTraceResponsesPageRequest.php | 24 ++ .../src/Submission/Types/GradedResponse.php | 35 +++ .../src/Submission/Types/GradedResponseV2.php | 34 +++ .../Submission/Types/GradedTestCaseUpdate.php | 33 +++ .../Types/InitializeProblemRequest.php | 33 +++ .../src/Submission/Types/InternalError.php | 25 ++ .../Types/InvalidRequestResponse.php | 33 +++ .../LightweightStackframeInformation.php | 33 +++ .../Types/RecordedResponseNotification.php | 42 ++++ .../Types/RecordedTestCaseUpdate.php | 33 +++ .../Types/RecordingResponseNotification.php | 62 +++++ .../src/Submission/Types/RunningResponse.php | 34 +++ .../Types/RunningSubmissionState.php | 12 + .../src/Submission/Types/RuntimeError.php | 24 ++ .../trace/src/Submission/Types/Scope.php | 25 ++ .../trace/src/Submission/Types/StackFrame.php | 44 ++++ .../src/Submission/Types/StackInformation.php | 34 +++ .../src/Submission/Types/StderrResponse.php | 33 +++ .../src/Submission/Types/StdoutResponse.php | 33 +++ .../src/Submission/Types/StopRequest.php | 24 ++ .../src/Submission/Types/StoppedResponse.php | 24 ++ .../Submission/Types/SubmissionFileInfo.php | 42 ++++ .../Submission/Types/SubmissionIdNotFound.php | 24 ++ .../Submission/Types/SubmissionTypeEnum.php | 8 + .../src/Submission/Types/SubmitRequestV2.php | 72 ++++++ .../Submission/Types/TerminatedResponse.php | 12 + .../Submission/Types/TestCaseHiddenGrade.php | 24 ++ .../Types/TestCaseNonHiddenGrade.php | 51 ++++ .../src/Submission/Types/TestCaseResult.php | 42 ++++ .../Types/TestCaseResultWithStdout.php | 34 +++ .../Submission/Types/TestSubmissionState.php | 53 ++++ .../Types/TestSubmissionStatusV2.php | 54 ++++ .../Submission/Types/TestSubmissionUpdate.php | 35 +++ .../src/Submission/Types/TraceResponse.php | 71 ++++++ .../src/Submission/Types/TraceResponseV2.php | 81 ++++++ .../Submission/Types/TraceResponsesPage.php | 37 +++ .../Submission/Types/TraceResponsesPageV2.php | 37 +++ .../trace/src/Submission/Types/TracedFile.php | 33 +++ .../src/Submission/Types/TracedTestCase.php | 34 +++ .../Types/UnexpectedLanguageError.php | 34 +++ .../src/Submission/Types/WorkspaceFiles.php | 35 +++ .../Submission/Types/WorkspaceRanResponse.php | 34 +++ .../Submission/Types/WorkspaceRunDetails.php | 43 ++++ .../Types/WorkspaceStarterFilesResponse.php | 27 ++ .../Types/WorkspaceStarterFilesResponseV2.php | 27 ++ .../Types/WorkspaceSubmissionState.php | 24 ++ .../Types/WorkspaceSubmissionStatusV2.php | 26 ++ .../Types/WorkspaceSubmissionUpdate.php | 35 +++ .../Types/WorkspaceSubmitRequest.php | 54 ++++ .../Types/WorkspaceTracedUpdate.php | 24 ++ .../src/V2/Problem/Types/BasicCustomFiles.php | 56 +++++ .../Problem/Types/BasicTestCaseTemplate.php | 52 ++++ .../Problem/Types/CreateProblemRequestV2.php | 83 +++++++ .../Types/DeepEqualityCorrectnessCheck.php | 24 ++ .../V2/Problem/Types/DefaultProvidedFile.php | 35 +++ .../trace/src/V2/Problem/Types/FileInfoV2.php | 51 ++++ .../trace/src/V2/Problem/Types/Files.php | 26 ++ .../Problem/Types/FunctionImplementation.php | 33 +++ ...tionImplementationForMultipleLanguages.php | 27 ++ .../src/V2/Problem/Types/GeneratedFiles.php | 45 ++++ .../Types/GetBasicSolutionFileRequest.php | 34 +++ .../Types/GetBasicSolutionFileResponse.php | 27 ++ .../Types/GetFunctionSignatureRequest.php | 24 ++ .../Types/GetFunctionSignatureResponse.php | 26 ++ .../Types/GetGeneratedTestCaseFileRequest.php | 35 +++ ...etGeneratedTestCaseTemplateFileRequest.php | 25 ++ .../Types/LightweightProblemInfoV2.php | 52 ++++ .../Types/NonVoidFunctionDefinition.php | 35 +++ .../Types/NonVoidFunctionSignature.php | 35 +++ .../trace/src/V2/Problem/Types/Parameter.php | 42 ++++ .../src/V2/Problem/Types/ProblemInfoV2.php | 111 +++++++++ .../src/V2/Problem/Types/TestCaseExpects.php | 24 ++ .../Problem/Types/TestCaseImplementation.php | 34 +++ .../TestCaseImplementationDescription.php | 25 ++ .../src/V2/Problem/Types/TestCaseMetadata.php | 42 ++++ .../src/V2/Problem/Types/TestCaseTemplate.php | 43 ++++ .../trace/src/V2/Problem/Types/TestCaseV2.php | 54 ++++ ...TestCaseWithActualResultImplementation.php | 34 +++ .../Problem/Types/VoidFunctionDefinition.php | 36 +++ ...unctionDefinitionThatTakesActualResult.php | 39 +++ .../Problem/Types/VoidFunctionSignature.php | 26 ++ ...FunctionSignatureThatTakesActualResult.php | 35 +++ .../V2/V3/Problem/Types/BasicCustomFiles.php | 56 +++++ .../Problem/Types/BasicTestCaseTemplate.php | 52 ++++ .../Problem/Types/CreateProblemRequestV2.php | 83 +++++++ .../Types/DeepEqualityCorrectnessCheck.php | 24 ++ .../V3/Problem/Types/DefaultProvidedFile.php | 35 +++ .../src/V2/V3/Problem/Types/FileInfoV2.php | 51 ++++ .../trace/src/V2/V3/Problem/Types/Files.php | 26 ++ .../Problem/Types/FunctionImplementation.php | 33 +++ ...tionImplementationForMultipleLanguages.php | 27 ++ .../V2/V3/Problem/Types/GeneratedFiles.php | 45 ++++ .../Types/GetBasicSolutionFileRequest.php | 34 +++ .../Types/GetBasicSolutionFileResponse.php | 27 ++ .../Types/GetFunctionSignatureRequest.php | 24 ++ .../Types/GetFunctionSignatureResponse.php | 26 ++ .../Types/GetGeneratedTestCaseFileRequest.php | 35 +++ ...etGeneratedTestCaseTemplateFileRequest.php | 25 ++ .../Types/LightweightProblemInfoV2.php | 52 ++++ .../Types/NonVoidFunctionDefinition.php | 35 +++ .../Types/NonVoidFunctionSignature.php | 35 +++ .../src/V2/V3/Problem/Types/Parameter.php | 42 ++++ .../src/V2/V3/Problem/Types/ProblemInfoV2.php | 111 +++++++++ .../V2/V3/Problem/Types/TestCaseExpects.php | 24 ++ .../Problem/Types/TestCaseImplementation.php | 34 +++ .../TestCaseImplementationDescription.php | 25 ++ .../V2/V3/Problem/Types/TestCaseMetadata.php | 42 ++++ .../V2/V3/Problem/Types/TestCaseTemplate.php | 43 ++++ .../src/V2/V3/Problem/Types/TestCaseV2.php | 54 ++++ ...TestCaseWithActualResultImplementation.php | 34 +++ .../Problem/Types/VoidFunctionDefinition.php | 36 +++ ...unctionDefinitionThatTakesActualResult.php | 39 +++ .../Problem/Types/VoidFunctionSignature.php | 26 ++ ...FunctionSignatureThatTakesActualResult.php | 35 +++ .../src/Core/SerializableType.php | 21 +- .../src/Placeholder/Placeholder.php | 11 - .../undiscriminated-unions/src/SeedClient.php | 6 +- .../src/Union/Types/KeyType.php | 9 + .../unions/src/Core/SerializableType.php | 21 +- .../unions/src/Placeholder/Placeholder.php | 11 - seed/php-sdk/unions/src/SeedClient.php | 6 +- seed/php-sdk/unions/src/Types/Types/Bar.php | 24 ++ seed/php-sdk/unions/src/Types/Types/Foo.php | 24 ++ .../php-sdk/unions/src/Union/Types/Circle.php | 24 ++ .../src/Union/Types/GetShapeRequest.php | 24 ++ .../php-sdk/unions/src/Union/Types/Square.php | 24 ++ .../unknown/src/Core/SerializableType.php | 21 +- .../unknown/src/Placeholder/Placeholder.php | 11 - seed/php-sdk/unknown/src/SeedClient.php | 6 +- .../unknown/src/Unknown/Types/MyObject.php | 24 ++ .../validation/src/Core/SerializableType.php | 21 +- .../src/Placeholder/Placeholder.php | 11 - seed/php-sdk/validation/src/SeedClient.php | 6 +- seed/php-sdk/validation/src/Types/Shape.php | 10 + seed/php-sdk/validation/src/Types/Type.php | 55 +++++ .../variables/src/Core/SerializableType.php | 21 +- .../variables/src/Placeholder/Placeholder.php | 11 - seed/php-sdk/variables/src/SeedClient.php | 6 +- .../src/Core/SerializableType.php | 21 +- .../src/Placeholder/Placeholder.php | 11 - .../version-no-default/src/SeedClient.php | 6 +- .../src/User/Types/User.php | 33 +++ .../version/src/Core/SerializableType.php | 21 +- .../version/src/Placeholder/Placeholder.php | 11 - seed/php-sdk/version/src/SeedClient.php | 6 +- seed/php-sdk/version/src/User/Types/User.php | 33 +++ .../websocket/src/Core/SerializableType.php | 21 +- .../websocket/src/Placeholder/Placeholder.php | 11 - seed/php-sdk/websocket/src/SeedClient.php | 6 +- 983 files changed, 25092 insertions(+), 2437 deletions(-) create mode 100644 generators/php/codegen/src/ast/Array.ts create mode 100644 generators/php/codegen/src/ast/Attribute.ts create mode 100644 generators/php/codegen/src/ast/Enum.ts create mode 100644 generators/php/model/src/enum/EnumGenerator.ts create mode 100644 seed/php-model/alias-extends/src/Child.php create mode 100644 seed/php-model/alias-extends/src/Parent.php delete mode 100644 seed/php-model/alias-extends/src/Placeholder/Placeholder.php delete mode 100644 seed/php-model/alias/src/Placeholder/Placeholder.php create mode 100644 seed/php-model/alias/src/Type.php create mode 100644 seed/php-model/any-auth/src/Auth/TokenResponse.php delete mode 100644 seed/php-model/any-auth/src/Placeholder/Placeholder.php create mode 100644 seed/php-model/any-auth/src/User/User.php delete mode 100644 seed/php-model/api-wide-base-path/src/Placeholder/Placeholder.php create mode 100644 seed/php-model/audiences/src/FolderA/Service/Response.php create mode 100644 seed/php-model/audiences/src/FolderB/Common/Foo.php create mode 100644 seed/php-model/audiences/src/FolderC/Common/FolderCFoo.php create mode 100644 seed/php-model/audiences/src/FolderD/Service/Response.php create mode 100644 seed/php-model/audiences/src/Foo/FilteredType.php create mode 100644 seed/php-model/audiences/src/Foo/ImportingType.php delete mode 100644 seed/php-model/audiences/src/Placeholder/Placeholder.php delete mode 100644 seed/php-model/auth-environment-variables/src/Placeholder/Placeholder.php create mode 100644 seed/php-model/basic-auth-environment-variables/src/Errors/UnauthorizedRequestErrorBody.php delete mode 100644 seed/php-model/basic-auth-environment-variables/src/Placeholder/Placeholder.php create mode 100644 seed/php-model/basic-auth/src/Errors/UnauthorizedRequestErrorBody.php delete mode 100644 seed/php-model/basic-auth/src/Placeholder/Placeholder.php delete mode 100644 seed/php-model/bearer-token-environment-variable/src/Placeholder/Placeholder.php delete mode 100644 seed/php-model/bytes/src/Placeholder/Placeholder.php create mode 100644 seed/php-model/circular-references-advanced/src/A/A.php create mode 100644 seed/php-model/circular-references-advanced/src/Ast/ObjectFieldValue.php create mode 100644 seed/php-model/circular-references-advanced/src/Ast/ObjectValue.php create mode 100644 seed/php-model/circular-references-advanced/src/Ast/PrimitiveValue.php create mode 100644 seed/php-model/circular-references-advanced/src/ImportingA.php delete mode 100644 seed/php-model/circular-references-advanced/src/Placeholder/Placeholder.php create mode 100644 seed/php-model/circular-references-advanced/src/RootType.php create mode 100644 seed/php-model/circular-references/src/A/A.php create mode 100644 seed/php-model/circular-references/src/Ast/ObjectValue.php create mode 100644 seed/php-model/circular-references/src/Ast/PrimitiveValue.php create mode 100644 seed/php-model/circular-references/src/ImportingA.php delete mode 100644 seed/php-model/circular-references/src/Placeholder/Placeholder.php create mode 100644 seed/php-model/circular-references/src/RootType.php create mode 100644 seed/php-model/cross-package-type-names/src/FolderA/Service/Response.php create mode 100644 seed/php-model/cross-package-type-names/src/FolderB/Common/Foo.php create mode 100644 seed/php-model/cross-package-type-names/src/FolderC/Common/Foo.php create mode 100644 seed/php-model/cross-package-type-names/src/FolderD/Service/Response.php create mode 100644 seed/php-model/cross-package-type-names/src/Foo/ImportingType.php delete mode 100644 seed/php-model/cross-package-type-names/src/Placeholder/Placeholder.php create mode 100644 seed/php-model/custom-auth/src/Errors/UnauthorizedRequestErrorBody.php delete mode 100644 seed/php-model/custom-auth/src/Placeholder/Placeholder.php create mode 100644 seed/php-model/enum/src/Color.php create mode 100644 seed/php-model/enum/src/Operand.php delete mode 100644 seed/php-model/enum/src/Placeholder/Placeholder.php create mode 100644 seed/php-model/error-property/src/Errors/PropertyBasedErrorTestBody.php delete mode 100644 seed/php-model/error-property/src/Placeholder/Placeholder.php create mode 100644 seed/php-model/examples/src/BasicType.php create mode 100644 seed/php-model/examples/src/Commons/Types/Metadata.php create mode 100644 seed/php-model/examples/src/ComplexType.php create mode 100644 seed/php-model/examples/src/Identifier.php delete mode 100644 seed/php-model/examples/src/Placeholder/Placeholder.php create mode 100644 seed/php-model/examples/src/Types/Actor.php create mode 100644 seed/php-model/examples/src/Types/Actress.php create mode 100644 seed/php-model/examples/src/Types/Directory.php create mode 100644 seed/php-model/examples/src/Types/Entity.php create mode 100644 seed/php-model/examples/src/Types/ExceptionInfo.php create mode 100644 seed/php-model/examples/src/Types/ExtendedMovie.php create mode 100644 seed/php-model/examples/src/Types/File.php create mode 100644 seed/php-model/examples/src/Types/Migration.php create mode 100644 seed/php-model/examples/src/Types/MigrationStatus.php create mode 100644 seed/php-model/examples/src/Types/Moment.php create mode 100644 seed/php-model/examples/src/Types/Movie.php create mode 100644 seed/php-model/examples/src/Types/Node.php create mode 100644 seed/php-model/examples/src/Types/Request.php create mode 100644 seed/php-model/examples/src/Types/Response.php create mode 100644 seed/php-model/examples/src/Types/ResponseType.php create mode 100644 seed/php-model/examples/src/Types/StuntDouble.php create mode 100644 seed/php-model/examples/src/Types/Tree.php create mode 100644 seed/php-model/exhaustive/src/GeneralErrors/BadObjectRequestInfo.php delete mode 100644 seed/php-model/exhaustive/src/Placeholder/Placeholder.php create mode 100644 seed/php-model/exhaustive/src/Types/Enum/WeatherReport.php create mode 100644 seed/php-model/exhaustive/src/Types/Object/DoubleOptional.php create mode 100644 seed/php-model/exhaustive/src/Types/Object/NestedObjectWithOptionalField.php create mode 100644 seed/php-model/exhaustive/src/Types/Object/NestedObjectWithRequiredField.php create mode 100644 seed/php-model/exhaustive/src/Types/Object/ObjectWithMapOfMap.php create mode 100644 seed/php-model/exhaustive/src/Types/Object/ObjectWithOptionalField.php create mode 100644 seed/php-model/exhaustive/src/Types/Object/ObjectWithRequiredField.php create mode 100644 seed/php-model/exhaustive/src/Types/Union/Cat.php create mode 100644 seed/php-model/exhaustive/src/Types/Union/Dog.php create mode 100644 seed/php-model/extends/src/Docs.php create mode 100644 seed/php-model/extends/src/ExampleType.php create mode 100644 seed/php-model/extends/src/Json.php create mode 100644 seed/php-model/extends/src/NestedType.php delete mode 100644 seed/php-model/extends/src/Placeholder/Placeholder.php create mode 100644 seed/php-model/extra-properties/src/Failure.php delete mode 100644 seed/php-model/extra-properties/src/Placeholder/Placeholder.php create mode 100644 seed/php-model/extra-properties/src/User/User.php delete mode 100644 seed/php-model/file-download/src/Placeholder/Placeholder.php delete mode 100644 seed/php-model/file-upload/src/Placeholder/Placeholder.php create mode 100644 seed/php-model/file-upload/src/Service/MyObject.php create mode 100644 seed/php-model/file-upload/src/Service/ObjectType.php delete mode 100644 seed/php-model/folders/src/Placeholder/Placeholder.php create mode 100644 seed/php-model/grpc-proto-exhaustive/src/Column.php create mode 100644 seed/php-model/grpc-proto-exhaustive/src/DeleteResponse.php create mode 100644 seed/php-model/grpc-proto-exhaustive/src/DescribeResponse.php create mode 100644 seed/php-model/grpc-proto-exhaustive/src/FetchResponse.php create mode 100644 seed/php-model/grpc-proto-exhaustive/src/IndexedData.php create mode 100644 seed/php-model/grpc-proto-exhaustive/src/ListElement.php create mode 100644 seed/php-model/grpc-proto-exhaustive/src/ListResponse.php create mode 100644 seed/php-model/grpc-proto-exhaustive/src/NamespaceSummary.php create mode 100644 seed/php-model/grpc-proto-exhaustive/src/Pagination.php delete mode 100644 seed/php-model/grpc-proto-exhaustive/src/Placeholder/Placeholder.php create mode 100644 seed/php-model/grpc-proto-exhaustive/src/QueryColumn.php create mode 100644 seed/php-model/grpc-proto-exhaustive/src/QueryResponse.php create mode 100644 seed/php-model/grpc-proto-exhaustive/src/QueryResult.php create mode 100644 seed/php-model/grpc-proto-exhaustive/src/ScoredColumn.php create mode 100644 seed/php-model/grpc-proto-exhaustive/src/UpdateResponse.php create mode 100644 seed/php-model/grpc-proto-exhaustive/src/UploadResponse.php create mode 100644 seed/php-model/grpc-proto-exhaustive/src/Usage.php create mode 100644 seed/php-model/grpc-proto/src/CreateResponse.php delete mode 100644 seed/php-model/grpc-proto/src/Placeholder/Placeholder.php create mode 100644 seed/php-model/grpc-proto/src/UserModel.php create mode 100644 seed/php-model/idempotency-headers/src/Payment/Currency.php delete mode 100644 seed/php-model/idempotency-headers/src/Placeholder/Placeholder.php rename seed/{php-sdk/imdb/src/Seed/Types => php-model/imdb/src/Imdb}/CreateMovieRequest.php (57%) rename seed/{php-sdk/imdb/src/Seed/Types => php-model/imdb/src/Imdb}/Movie.php (64%) delete mode 100644 seed/php-model/imdb/src/Placeholder/Placeholder.php create mode 100644 seed/php-model/literal/src/Inlined/ANestedLiteral.php create mode 100644 seed/php-model/literal/src/Inlined/ATopLevelLiteral.php delete mode 100644 seed/php-model/literal/src/Placeholder/Placeholder.php create mode 100644 seed/php-model/literal/src/Reference/SendRequest.php create mode 100644 seed/php-model/literal/src/SendResponse.php delete mode 100644 seed/php-model/mixed-case/src/Placeholder/Placeholder.php create mode 100644 seed/php-model/mixed-case/src/Service/NestedUser.php create mode 100644 seed/php-model/mixed-case/src/Service/Organization.php create mode 100644 seed/php-model/mixed-case/src/Service/ResourceStatus.php create mode 100644 seed/php-model/mixed-case/src/Service/User.php create mode 100644 seed/php-model/mixed-file-directory/src/Organization/CreateOrganizationRequest.php create mode 100644 seed/php-model/mixed-file-directory/src/Organization/Organization.php delete mode 100644 seed/php-model/mixed-file-directory/src/Placeholder/Placeholder.php create mode 100644 seed/php-model/mixed-file-directory/src/User/Events/Event.php create mode 100644 seed/php-model/mixed-file-directory/src/User/Events/Metadata/Metadata.php create mode 100644 seed/php-model/mixed-file-directory/src/User/User.php create mode 100644 seed/php-model/multi-line-docs/src/Operand.php delete mode 100644 seed/php-model/multi-line-docs/src/Placeholder/Placeholder.php create mode 100644 seed/php-model/multi-line-docs/src/User/User.php delete mode 100644 seed/php-model/multi-url-environment-no-default/src/Placeholder/Placeholder.php delete mode 100644 seed/php-model/multi-url-environment/src/Placeholder/Placeholder.php delete mode 100644 seed/php-model/no-environment/src/Placeholder/Placeholder.php create mode 100644 seed/php-model/oauth-client-credentials-default/src/Auth/TokenResponse.php delete mode 100644 seed/php-model/oauth-client-credentials-default/src/Placeholder/Placeholder.php create mode 100644 seed/php-model/oauth-client-credentials-environment-variables/src/Auth/TokenResponse.php delete mode 100644 seed/php-model/oauth-client-credentials-environment-variables/src/Placeholder/Placeholder.php create mode 100644 seed/php-model/oauth-client-credentials-nested-root/src/Auth/TokenResponse.php delete mode 100644 seed/php-model/oauth-client-credentials-nested-root/src/Placeholder/Placeholder.php create mode 100644 seed/php-model/oauth-client-credentials/src/Auth/TokenResponse.php delete mode 100644 seed/php-model/oauth-client-credentials/src/Placeholder/Placeholder.php create mode 100644 seed/php-model/object/src/Name.php delete mode 100644 seed/php-model/object/src/Placeholder/Placeholder.php create mode 100644 seed/php-model/object/src/Type.php create mode 100644 seed/php-model/objects-with-imports/src/Commons/Metadata/Metadata.php create mode 100644 seed/php-model/objects-with-imports/src/File/Directory/Directory.php create mode 100644 seed/php-model/objects-with-imports/src/File/File.php create mode 100644 seed/php-model/objects-with-imports/src/File/FileInfo.php create mode 100644 seed/php-model/objects-with-imports/src/Node.php delete mode 100644 seed/php-model/objects-with-imports/src/Placeholder/Placeholder.php create mode 100644 seed/php-model/objects-with-imports/src/Tree.php delete mode 100644 seed/php-model/optional/src/Placeholder/Placeholder.php create mode 100644 seed/php-model/package-yml/src/EchoRequest.php delete mode 100644 seed/php-model/package-yml/src/Placeholder/Placeholder.php delete mode 100644 seed/php-model/pagination/src/Placeholder/Placeholder.php create mode 100644 seed/php-model/pagination/src/UsernameCursor.php create mode 100644 seed/php-model/pagination/src/UsernamePage.php create mode 100644 seed/php-model/pagination/src/Users/ListUsersExtendedOptionalListResponse.php create mode 100644 seed/php-model/pagination/src/Users/ListUsersExtendedResponse.php create mode 100644 seed/php-model/pagination/src/Users/ListUsersPaginationResponse.php create mode 100644 seed/php-model/pagination/src/Users/NextPage.php create mode 100644 seed/php-model/pagination/src/Users/Order.php create mode 100644 seed/php-model/pagination/src/Users/Page.php create mode 100644 seed/php-model/pagination/src/Users/User.php create mode 100644 seed/php-model/pagination/src/Users/UserListContainer.php create mode 100644 seed/php-model/pagination/src/Users/UserOptionalListContainer.php create mode 100644 seed/php-model/pagination/src/Users/UserOptionalListPage.php create mode 100644 seed/php-model/pagination/src/Users/UserPage.php create mode 100644 seed/php-model/pagination/src/Users/UsernameContainer.php create mode 100644 seed/php-model/pagination/src/Users/WithCursor.php create mode 100644 seed/php-model/pagination/src/Users/WithPage.php delete mode 100644 seed/php-model/plain-text/src/Placeholder/Placeholder.php delete mode 100644 seed/php-model/query-parameters/src/Placeholder/Placeholder.php create mode 100644 seed/php-model/query-parameters/src/User/NestedUser.php create mode 100644 seed/php-model/query-parameters/src/User/User.php create mode 100644 seed/php-model/reserved-keywords/src/Package/Package.php create mode 100644 seed/php-model/reserved-keywords/src/Package/Record.php delete mode 100644 seed/php-model/reserved-keywords/src/Placeholder/Placeholder.php delete mode 100644 seed/php-model/response-property/src/Placeholder/Placeholder.php create mode 100644 seed/php-model/response-property/src/Service/Movie.php create mode 100644 seed/php-model/response-property/src/Service/Response.php create mode 100644 seed/php-model/response-property/src/Service/WithDocs.php create mode 100644 seed/php-model/response-property/src/StringResponse.php create mode 100644 seed/php-model/response-property/src/WithMetadata.php create mode 100644 seed/php-model/simple-fhir/src/Account.php create mode 100644 seed/php-model/simple-fhir/src/BaseResource.php create mode 100644 seed/php-model/simple-fhir/src/Memo.php create mode 100644 seed/php-model/simple-fhir/src/Patient.php delete mode 100644 seed/php-model/simple-fhir/src/Placeholder/Placeholder.php create mode 100644 seed/php-model/simple-fhir/src/Practitioner.php create mode 100644 seed/php-model/simple-fhir/src/Script.php delete mode 100644 seed/php-model/single-url-environment-default/src/Placeholder/Placeholder.php delete mode 100644 seed/php-model/single-url-environment-no-default/src/Placeholder/Placeholder.php create mode 100644 seed/php-model/streaming-parameter/src/Dummy/RegularResponse.php create mode 100644 seed/php-model/streaming-parameter/src/Dummy/StreamResponse.php delete mode 100644 seed/php-model/streaming-parameter/src/Placeholder/Placeholder.php create mode 100644 seed/php-model/streaming/src/Dummy/StreamResponse.php delete mode 100644 seed/php-model/streaming/src/Placeholder/Placeholder.php create mode 100644 seed/php-model/trace/src/Commons/BinaryTreeNodeAndTreeValue.php create mode 100644 seed/php-model/trace/src/Commons/BinaryTreeNodeValue.php create mode 100644 seed/php-model/trace/src/Commons/BinaryTreeValue.php create mode 100644 seed/php-model/trace/src/Commons/DebugKeyValuePairs.php create mode 100644 seed/php-model/trace/src/Commons/DebugMapValue.php create mode 100644 seed/php-model/trace/src/Commons/DoublyLinkedListNodeAndListValue.php create mode 100644 seed/php-model/trace/src/Commons/DoublyLinkedListNodeValue.php create mode 100644 seed/php-model/trace/src/Commons/DoublyLinkedListValue.php create mode 100644 seed/php-model/trace/src/Commons/FileInfo.php create mode 100644 seed/php-model/trace/src/Commons/GenericValue.php create mode 100644 seed/php-model/trace/src/Commons/KeyValuePair.php create mode 100644 seed/php-model/trace/src/Commons/Language.php create mode 100644 seed/php-model/trace/src/Commons/ListType.php create mode 100644 seed/php-model/trace/src/Commons/MapType.php create mode 100644 seed/php-model/trace/src/Commons/MapValue.php create mode 100644 seed/php-model/trace/src/Commons/SinglyLinkedListNodeAndListValue.php create mode 100644 seed/php-model/trace/src/Commons/SinglyLinkedListNodeValue.php create mode 100644 seed/php-model/trace/src/Commons/SinglyLinkedListValue.php create mode 100644 seed/php-model/trace/src/Commons/TestCase.php create mode 100644 seed/php-model/trace/src/Commons/TestCaseWithExpectedResult.php create mode 100644 seed/php-model/trace/src/LangServer/LangServerRequest.php create mode 100644 seed/php-model/trace/src/LangServer/LangServerResponse.php create mode 100644 seed/php-model/trace/src/Migration/Migration.php create mode 100644 seed/php-model/trace/src/Migration/MigrationStatus.php delete mode 100644 seed/php-model/trace/src/Placeholder/Placeholder.php create mode 100644 seed/php-model/trace/src/Playlist/Playlist.php create mode 100644 seed/php-model/trace/src/Playlist/PlaylistCreateRequest.php create mode 100644 seed/php-model/trace/src/Playlist/ReservedKeywordEnum.php create mode 100644 seed/php-model/trace/src/Playlist/UpdatePlaylistRequest.php create mode 100644 seed/php-model/trace/src/Problem/CreateProblemRequest.php create mode 100644 seed/php-model/trace/src/Problem/GenericCreateProblemError.php create mode 100644 seed/php-model/trace/src/Problem/GetDefaultStarterFilesResponse.php create mode 100644 seed/php-model/trace/src/Problem/ProblemDescription.php create mode 100644 seed/php-model/trace/src/Problem/ProblemFiles.php create mode 100644 seed/php-model/trace/src/Problem/ProblemInfo.php create mode 100644 seed/php-model/trace/src/Problem/UpdateProblemResponse.php create mode 100644 seed/php-model/trace/src/Problem/VariableTypeAndName.php create mode 100644 seed/php-model/trace/src/Submission/BuildingExecutorResponse.php create mode 100644 seed/php-model/trace/src/Submission/CompileError.php create mode 100644 seed/php-model/trace/src/Submission/CustomTestCasesUnsupported.php create mode 100644 seed/php-model/trace/src/Submission/ErroredResponse.php create mode 100644 seed/php-model/trace/src/Submission/ExceptionInfo.php create mode 100644 seed/php-model/trace/src/Submission/ExecutionSessionResponse.php create mode 100644 seed/php-model/trace/src/Submission/ExecutionSessionState.php create mode 100644 seed/php-model/trace/src/Submission/ExecutionSessionStatus.php create mode 100644 seed/php-model/trace/src/Submission/ExistingSubmissionExecuting.php create mode 100644 seed/php-model/trace/src/Submission/ExpressionLocation.php create mode 100644 seed/php-model/trace/src/Submission/FinishedResponse.php create mode 100644 seed/php-model/trace/src/Submission/GetExecutionSessionStateResponse.php create mode 100644 seed/php-model/trace/src/Submission/GetSubmissionStateResponse.php create mode 100644 seed/php-model/trace/src/Submission/GetTraceResponsesPageRequest.php create mode 100644 seed/php-model/trace/src/Submission/GradedResponse.php create mode 100644 seed/php-model/trace/src/Submission/GradedResponseV2.php create mode 100644 seed/php-model/trace/src/Submission/GradedTestCaseUpdate.php create mode 100644 seed/php-model/trace/src/Submission/InitializeProblemRequest.php create mode 100644 seed/php-model/trace/src/Submission/InternalError.php create mode 100644 seed/php-model/trace/src/Submission/InvalidRequestResponse.php create mode 100644 seed/php-model/trace/src/Submission/LightweightStackframeInformation.php create mode 100644 seed/php-model/trace/src/Submission/RecordedResponseNotification.php create mode 100644 seed/php-model/trace/src/Submission/RecordedTestCaseUpdate.php create mode 100644 seed/php-model/trace/src/Submission/RecordingResponseNotification.php create mode 100644 seed/php-model/trace/src/Submission/RunningResponse.php create mode 100644 seed/php-model/trace/src/Submission/RunningSubmissionState.php create mode 100644 seed/php-model/trace/src/Submission/RuntimeError.php create mode 100644 seed/php-model/trace/src/Submission/Scope.php create mode 100644 seed/php-model/trace/src/Submission/StackFrame.php create mode 100644 seed/php-model/trace/src/Submission/StackInformation.php create mode 100644 seed/php-model/trace/src/Submission/StderrResponse.php create mode 100644 seed/php-model/trace/src/Submission/StdoutResponse.php create mode 100644 seed/php-model/trace/src/Submission/StopRequest.php create mode 100644 seed/php-model/trace/src/Submission/StoppedResponse.php create mode 100644 seed/php-model/trace/src/Submission/SubmissionFileInfo.php create mode 100644 seed/php-model/trace/src/Submission/SubmissionIdNotFound.php create mode 100644 seed/php-model/trace/src/Submission/SubmissionTypeEnum.php create mode 100644 seed/php-model/trace/src/Submission/SubmitRequestV2.php create mode 100644 seed/php-model/trace/src/Submission/TerminatedResponse.php create mode 100644 seed/php-model/trace/src/Submission/TestCaseHiddenGrade.php create mode 100644 seed/php-model/trace/src/Submission/TestCaseNonHiddenGrade.php create mode 100644 seed/php-model/trace/src/Submission/TestCaseResult.php create mode 100644 seed/php-model/trace/src/Submission/TestCaseResultWithStdout.php create mode 100644 seed/php-model/trace/src/Submission/TestSubmissionState.php create mode 100644 seed/php-model/trace/src/Submission/TestSubmissionStatusV2.php create mode 100644 seed/php-model/trace/src/Submission/TestSubmissionUpdate.php create mode 100644 seed/php-model/trace/src/Submission/TraceResponse.php create mode 100644 seed/php-model/trace/src/Submission/TraceResponseV2.php create mode 100644 seed/php-model/trace/src/Submission/TraceResponsesPage.php create mode 100644 seed/php-model/trace/src/Submission/TraceResponsesPageV2.php create mode 100644 seed/php-model/trace/src/Submission/TracedFile.php create mode 100644 seed/php-model/trace/src/Submission/TracedTestCase.php create mode 100644 seed/php-model/trace/src/Submission/UnexpectedLanguageError.php create mode 100644 seed/php-model/trace/src/Submission/WorkspaceFiles.php create mode 100644 seed/php-model/trace/src/Submission/WorkspaceRanResponse.php create mode 100644 seed/php-model/trace/src/Submission/WorkspaceRunDetails.php create mode 100644 seed/php-model/trace/src/Submission/WorkspaceStarterFilesResponse.php create mode 100644 seed/php-model/trace/src/Submission/WorkspaceStarterFilesResponseV2.php create mode 100644 seed/php-model/trace/src/Submission/WorkspaceSubmissionState.php create mode 100644 seed/php-model/trace/src/Submission/WorkspaceSubmissionStatusV2.php create mode 100644 seed/php-model/trace/src/Submission/WorkspaceSubmissionUpdate.php create mode 100644 seed/php-model/trace/src/Submission/WorkspaceSubmitRequest.php create mode 100644 seed/php-model/trace/src/Submission/WorkspaceTracedUpdate.php create mode 100644 seed/php-model/trace/src/V2/Problem/BasicCustomFiles.php create mode 100644 seed/php-model/trace/src/V2/Problem/BasicTestCaseTemplate.php create mode 100644 seed/php-model/trace/src/V2/Problem/CreateProblemRequestV2.php create mode 100644 seed/php-model/trace/src/V2/Problem/DeepEqualityCorrectnessCheck.php create mode 100644 seed/php-model/trace/src/V2/Problem/DefaultProvidedFile.php create mode 100644 seed/php-model/trace/src/V2/Problem/FileInfoV2.php create mode 100644 seed/php-model/trace/src/V2/Problem/Files.php create mode 100644 seed/php-model/trace/src/V2/Problem/FunctionImplementation.php create mode 100644 seed/php-model/trace/src/V2/Problem/FunctionImplementationForMultipleLanguages.php create mode 100644 seed/php-model/trace/src/V2/Problem/GeneratedFiles.php create mode 100644 seed/php-model/trace/src/V2/Problem/GetBasicSolutionFileRequest.php create mode 100644 seed/php-model/trace/src/V2/Problem/GetBasicSolutionFileResponse.php create mode 100644 seed/php-model/trace/src/V2/Problem/GetFunctionSignatureRequest.php create mode 100644 seed/php-model/trace/src/V2/Problem/GetFunctionSignatureResponse.php create mode 100644 seed/php-model/trace/src/V2/Problem/GetGeneratedTestCaseFileRequest.php create mode 100644 seed/php-model/trace/src/V2/Problem/GetGeneratedTestCaseTemplateFileRequest.php create mode 100644 seed/php-model/trace/src/V2/Problem/LightweightProblemInfoV2.php create mode 100644 seed/php-model/trace/src/V2/Problem/NonVoidFunctionDefinition.php create mode 100644 seed/php-model/trace/src/V2/Problem/NonVoidFunctionSignature.php create mode 100644 seed/php-model/trace/src/V2/Problem/Parameter.php create mode 100644 seed/php-model/trace/src/V2/Problem/ProblemInfoV2.php create mode 100644 seed/php-model/trace/src/V2/Problem/TestCaseExpects.php create mode 100644 seed/php-model/trace/src/V2/Problem/TestCaseImplementation.php create mode 100644 seed/php-model/trace/src/V2/Problem/TestCaseImplementationDescription.php create mode 100644 seed/php-model/trace/src/V2/Problem/TestCaseMetadata.php create mode 100644 seed/php-model/trace/src/V2/Problem/TestCaseTemplate.php create mode 100644 seed/php-model/trace/src/V2/Problem/TestCaseV2.php create mode 100644 seed/php-model/trace/src/V2/Problem/TestCaseWithActualResultImplementation.php create mode 100644 seed/php-model/trace/src/V2/Problem/VoidFunctionDefinition.php create mode 100644 seed/php-model/trace/src/V2/Problem/VoidFunctionDefinitionThatTakesActualResult.php create mode 100644 seed/php-model/trace/src/V2/Problem/VoidFunctionSignature.php create mode 100644 seed/php-model/trace/src/V2/Problem/VoidFunctionSignatureThatTakesActualResult.php create mode 100644 seed/php-model/trace/src/V2/V3/Problem/BasicCustomFiles.php create mode 100644 seed/php-model/trace/src/V2/V3/Problem/BasicTestCaseTemplate.php create mode 100644 seed/php-model/trace/src/V2/V3/Problem/CreateProblemRequestV2.php create mode 100644 seed/php-model/trace/src/V2/V3/Problem/DeepEqualityCorrectnessCheck.php create mode 100644 seed/php-model/trace/src/V2/V3/Problem/DefaultProvidedFile.php create mode 100644 seed/php-model/trace/src/V2/V3/Problem/FileInfoV2.php create mode 100644 seed/php-model/trace/src/V2/V3/Problem/Files.php create mode 100644 seed/php-model/trace/src/V2/V3/Problem/FunctionImplementation.php create mode 100644 seed/php-model/trace/src/V2/V3/Problem/FunctionImplementationForMultipleLanguages.php create mode 100644 seed/php-model/trace/src/V2/V3/Problem/GeneratedFiles.php create mode 100644 seed/php-model/trace/src/V2/V3/Problem/GetBasicSolutionFileRequest.php create mode 100644 seed/php-model/trace/src/V2/V3/Problem/GetBasicSolutionFileResponse.php create mode 100644 seed/php-model/trace/src/V2/V3/Problem/GetFunctionSignatureRequest.php create mode 100644 seed/php-model/trace/src/V2/V3/Problem/GetFunctionSignatureResponse.php create mode 100644 seed/php-model/trace/src/V2/V3/Problem/GetGeneratedTestCaseFileRequest.php create mode 100644 seed/php-model/trace/src/V2/V3/Problem/GetGeneratedTestCaseTemplateFileRequest.php create mode 100644 seed/php-model/trace/src/V2/V3/Problem/LightweightProblemInfoV2.php create mode 100644 seed/php-model/trace/src/V2/V3/Problem/NonVoidFunctionDefinition.php create mode 100644 seed/php-model/trace/src/V2/V3/Problem/NonVoidFunctionSignature.php create mode 100644 seed/php-model/trace/src/V2/V3/Problem/Parameter.php create mode 100644 seed/php-model/trace/src/V2/V3/Problem/ProblemInfoV2.php create mode 100644 seed/php-model/trace/src/V2/V3/Problem/TestCaseExpects.php create mode 100644 seed/php-model/trace/src/V2/V3/Problem/TestCaseImplementation.php create mode 100644 seed/php-model/trace/src/V2/V3/Problem/TestCaseImplementationDescription.php create mode 100644 seed/php-model/trace/src/V2/V3/Problem/TestCaseMetadata.php create mode 100644 seed/php-model/trace/src/V2/V3/Problem/TestCaseTemplate.php create mode 100644 seed/php-model/trace/src/V2/V3/Problem/TestCaseV2.php create mode 100644 seed/php-model/trace/src/V2/V3/Problem/TestCaseWithActualResultImplementation.php create mode 100644 seed/php-model/trace/src/V2/V3/Problem/VoidFunctionDefinition.php create mode 100644 seed/php-model/trace/src/V2/V3/Problem/VoidFunctionDefinitionThatTakesActualResult.php create mode 100644 seed/php-model/trace/src/V2/V3/Problem/VoidFunctionSignature.php create mode 100644 seed/php-model/trace/src/V2/V3/Problem/VoidFunctionSignatureThatTakesActualResult.php delete mode 100644 seed/php-model/undiscriminated-unions/src/Placeholder/Placeholder.php create mode 100644 seed/php-model/undiscriminated-unions/src/Union/KeyType.php delete mode 100644 seed/php-model/unions/src/Placeholder/Placeholder.php create mode 100644 seed/php-model/unions/src/Types/Bar.php create mode 100644 seed/php-model/unions/src/Types/Foo.php create mode 100644 seed/php-model/unions/src/Union/Circle.php create mode 100644 seed/php-model/unions/src/Union/GetShapeRequest.php create mode 100644 seed/php-model/unions/src/Union/Square.php delete mode 100644 seed/php-model/unknown/src/Placeholder/Placeholder.php create mode 100644 seed/php-model/unknown/src/Unknown/MyObject.php delete mode 100644 seed/php-model/validation/src/Placeholder/Placeholder.php create mode 100644 seed/php-model/validation/src/Shape.php create mode 100644 seed/php-model/validation/src/Type.php delete mode 100644 seed/php-model/variables/src/Placeholder/Placeholder.php delete mode 100644 seed/php-model/version-no-default/src/Placeholder/Placeholder.php create mode 100644 seed/php-model/version-no-default/src/User/User.php delete mode 100644 seed/php-model/version/src/Placeholder/Placeholder.php create mode 100644 seed/php-model/version/src/User/User.php delete mode 100644 seed/php-model/websocket/src/Placeholder/Placeholder.php delete mode 100644 seed/php-sdk/alias-extends/src/Placeholder/Placeholder.php create mode 100644 seed/php-sdk/alias-extends/src/Types/Child.php create mode 100644 seed/php-sdk/alias-extends/src/Types/Parent.php delete mode 100644 seed/php-sdk/alias/src/Placeholder/Placeholder.php create mode 100644 seed/php-sdk/alias/src/Types/Type.php create mode 100644 seed/php-sdk/any-auth/src/Auth/Types/TokenResponse.php delete mode 100644 seed/php-sdk/any-auth/src/Placeholder/Placeholder.php create mode 100644 seed/php-sdk/any-auth/src/User/Types/User.php delete mode 100644 seed/php-sdk/api-wide-base-path/src/Placeholder/Placeholder.php create mode 100644 seed/php-sdk/audiences/src/FolderA/Service/Types/Response.php create mode 100644 seed/php-sdk/audiences/src/FolderB/Common/Types/Foo.php create mode 100644 seed/php-sdk/audiences/src/FolderC/Common/Types/FolderCFoo.php create mode 100644 seed/php-sdk/audiences/src/FolderD/Service/Types/Response.php create mode 100644 seed/php-sdk/audiences/src/Foo/Types/FilteredType.php create mode 100644 seed/php-sdk/audiences/src/Foo/Types/ImportingType.php delete mode 100644 seed/php-sdk/audiences/src/Placeholder/Placeholder.php delete mode 100644 seed/php-sdk/auth-environment-variables/src/Placeholder/Placeholder.php create mode 100644 seed/php-sdk/basic-auth-environment-variables/src/Errors/Types/UnauthorizedRequestErrorBody.php delete mode 100644 seed/php-sdk/basic-auth-environment-variables/src/Placeholder/Placeholder.php create mode 100644 seed/php-sdk/basic-auth/src/Errors/Types/UnauthorizedRequestErrorBody.php delete mode 100644 seed/php-sdk/basic-auth/src/Placeholder/Placeholder.php delete mode 100644 seed/php-sdk/bearer-token-environment-variable/src/Placeholder/Placeholder.php delete mode 100644 seed/php-sdk/bytes/src/Placeholder/Placeholder.php create mode 100644 seed/php-sdk/circular-references-advanced/src/A/Types/A.php create mode 100644 seed/php-sdk/circular-references-advanced/src/Ast/Types/ObjectFieldValue.php create mode 100644 seed/php-sdk/circular-references-advanced/src/Ast/Types/ObjectValue.php create mode 100644 seed/php-sdk/circular-references-advanced/src/Ast/Types/PrimitiveValue.php delete mode 100644 seed/php-sdk/circular-references-advanced/src/Placeholder/Placeholder.php create mode 100644 seed/php-sdk/circular-references-advanced/src/Types/ImportingA.php create mode 100644 seed/php-sdk/circular-references-advanced/src/Types/RootType.php create mode 100644 seed/php-sdk/circular-references/src/A/Types/A.php create mode 100644 seed/php-sdk/circular-references/src/Ast/Types/ObjectValue.php create mode 100644 seed/php-sdk/circular-references/src/Ast/Types/PrimitiveValue.php delete mode 100644 seed/php-sdk/circular-references/src/Placeholder/Placeholder.php create mode 100644 seed/php-sdk/circular-references/src/Types/ImportingA.php create mode 100644 seed/php-sdk/circular-references/src/Types/RootType.php create mode 100644 seed/php-sdk/cross-package-type-names/src/FolderA/Service/Types/Response.php create mode 100644 seed/php-sdk/cross-package-type-names/src/FolderB/Common/Types/Foo.php create mode 100644 seed/php-sdk/cross-package-type-names/src/FolderC/Common/Types/Foo.php create mode 100644 seed/php-sdk/cross-package-type-names/src/FolderD/Service/Types/Response.php create mode 100644 seed/php-sdk/cross-package-type-names/src/Foo/Types/ImportingType.php delete mode 100644 seed/php-sdk/cross-package-type-names/src/Placeholder/Placeholder.php create mode 100644 seed/php-sdk/custom-auth/src/Errors/Types/UnauthorizedRequestErrorBody.php delete mode 100644 seed/php-sdk/custom-auth/src/Placeholder/Placeholder.php delete mode 100644 seed/php-sdk/enum/src/Placeholder/Placeholder.php create mode 100644 seed/php-sdk/enum/src/Types/Color.php create mode 100644 seed/php-sdk/enum/src/Types/Operand.php create mode 100644 seed/php-sdk/error-property/src/Errors/Types/PropertyBasedErrorTestBody.php delete mode 100644 seed/php-sdk/error-property/src/Placeholder/Placeholder.php create mode 100644 seed/php-sdk/examples/src/Commons/Types/Types/Metadata.php delete mode 100644 seed/php-sdk/examples/src/Placeholder/Placeholder.php create mode 100644 seed/php-sdk/examples/src/Types/BasicType.php create mode 100644 seed/php-sdk/examples/src/Types/ComplexType.php create mode 100644 seed/php-sdk/examples/src/Types/Identifier.php create mode 100644 seed/php-sdk/examples/src/Types/Types/Actor.php create mode 100644 seed/php-sdk/examples/src/Types/Types/Actress.php create mode 100644 seed/php-sdk/examples/src/Types/Types/Directory.php create mode 100644 seed/php-sdk/examples/src/Types/Types/Entity.php create mode 100644 seed/php-sdk/examples/src/Types/Types/ExceptionInfo.php create mode 100644 seed/php-sdk/examples/src/Types/Types/ExtendedMovie.php create mode 100644 seed/php-sdk/examples/src/Types/Types/File.php create mode 100644 seed/php-sdk/examples/src/Types/Types/Migration.php create mode 100644 seed/php-sdk/examples/src/Types/Types/MigrationStatus.php create mode 100644 seed/php-sdk/examples/src/Types/Types/Moment.php create mode 100644 seed/php-sdk/examples/src/Types/Types/Movie.php create mode 100644 seed/php-sdk/examples/src/Types/Types/Node.php create mode 100644 seed/php-sdk/examples/src/Types/Types/Request.php create mode 100644 seed/php-sdk/examples/src/Types/Types/Response.php create mode 100644 seed/php-sdk/examples/src/Types/Types/ResponseType.php create mode 100644 seed/php-sdk/examples/src/Types/Types/StuntDouble.php create mode 100644 seed/php-sdk/examples/src/Types/Types/Tree.php create mode 100644 seed/php-sdk/exhaustive/src/GeneralErrors/Types/BadObjectRequestInfo.php delete mode 100644 seed/php-sdk/exhaustive/src/Placeholder/Placeholder.php create mode 100644 seed/php-sdk/exhaustive/src/Types/Enum/Types/WeatherReport.php create mode 100644 seed/php-sdk/exhaustive/src/Types/Object/Types/DoubleOptional.php create mode 100644 seed/php-sdk/exhaustive/src/Types/Object/Types/NestedObjectWithOptionalField.php create mode 100644 seed/php-sdk/exhaustive/src/Types/Object/Types/NestedObjectWithRequiredField.php create mode 100644 seed/php-sdk/exhaustive/src/Types/Object/Types/ObjectWithMapOfMap.php create mode 100644 seed/php-sdk/exhaustive/src/Types/Object/Types/ObjectWithOptionalField.php create mode 100644 seed/php-sdk/exhaustive/src/Types/Object/Types/ObjectWithRequiredField.php create mode 100644 seed/php-sdk/exhaustive/src/Types/Union/Types/Cat.php create mode 100644 seed/php-sdk/exhaustive/src/Types/Union/Types/Dog.php delete mode 100644 seed/php-sdk/extends/src/Placeholder/Placeholder.php create mode 100644 seed/php-sdk/extends/src/Types/Docs.php create mode 100644 seed/php-sdk/extends/src/Types/ExampleType.php create mode 100644 seed/php-sdk/extends/src/Types/Json.php create mode 100644 seed/php-sdk/extends/src/Types/NestedType.php delete mode 100644 seed/php-sdk/extra-properties/src/Placeholder/Placeholder.php create mode 100644 seed/php-sdk/extra-properties/src/Types/Failure.php create mode 100644 seed/php-sdk/extra-properties/src/User/Types/User.php delete mode 100644 seed/php-sdk/file-download/src/Placeholder/Placeholder.php delete mode 100644 seed/php-sdk/file-upload/src/Placeholder/Placeholder.php create mode 100644 seed/php-sdk/file-upload/src/Service/Types/MyObject.php create mode 100644 seed/php-sdk/file-upload/src/Service/Types/ObjectType.php delete mode 100644 seed/php-sdk/folders/src/Placeholder/Placeholder.php delete mode 100644 seed/php-sdk/grpc-proto-exhaustive/src/Placeholder/Placeholder.php create mode 100644 seed/php-sdk/grpc-proto-exhaustive/src/Types/Column.php create mode 100644 seed/php-sdk/grpc-proto-exhaustive/src/Types/DeleteResponse.php create mode 100644 seed/php-sdk/grpc-proto-exhaustive/src/Types/DescribeResponse.php create mode 100644 seed/php-sdk/grpc-proto-exhaustive/src/Types/FetchResponse.php create mode 100644 seed/php-sdk/grpc-proto-exhaustive/src/Types/IndexedData.php create mode 100644 seed/php-sdk/grpc-proto-exhaustive/src/Types/ListElement.php create mode 100644 seed/php-sdk/grpc-proto-exhaustive/src/Types/ListResponse.php create mode 100644 seed/php-sdk/grpc-proto-exhaustive/src/Types/NamespaceSummary.php create mode 100644 seed/php-sdk/grpc-proto-exhaustive/src/Types/Pagination.php create mode 100644 seed/php-sdk/grpc-proto-exhaustive/src/Types/QueryColumn.php create mode 100644 seed/php-sdk/grpc-proto-exhaustive/src/Types/QueryResponse.php create mode 100644 seed/php-sdk/grpc-proto-exhaustive/src/Types/QueryResult.php create mode 100644 seed/php-sdk/grpc-proto-exhaustive/src/Types/ScoredColumn.php create mode 100644 seed/php-sdk/grpc-proto-exhaustive/src/Types/UpdateResponse.php create mode 100644 seed/php-sdk/grpc-proto-exhaustive/src/Types/UploadResponse.php create mode 100644 seed/php-sdk/grpc-proto-exhaustive/src/Types/Usage.php delete mode 100644 seed/php-sdk/grpc-proto/src/Placeholder/Placeholder.php create mode 100644 seed/php-sdk/grpc-proto/src/Types/CreateResponse.php create mode 100644 seed/php-sdk/grpc-proto/src/Types/UserModel.php create mode 100644 seed/php-sdk/idempotency-headers/src/Payment/Types/Currency.php delete mode 100644 seed/php-sdk/idempotency-headers/src/Placeholder/Placeholder.php create mode 100644 seed/php-sdk/imdb/src/Imdb/Types/CreateMovieRequest.php create mode 100644 seed/php-sdk/imdb/src/Imdb/Types/Movie.php create mode 100644 seed/php-sdk/literal/src/Inlined/Types/ANestedLiteral.php create mode 100644 seed/php-sdk/literal/src/Inlined/Types/ATopLevelLiteral.php delete mode 100644 seed/php-sdk/literal/src/Placeholder/Placeholder.php create mode 100644 seed/php-sdk/literal/src/Reference/Types/SendRequest.php create mode 100644 seed/php-sdk/literal/src/Types/SendResponse.php delete mode 100644 seed/php-sdk/mixed-case/src/Placeholder/Placeholder.php create mode 100644 seed/php-sdk/mixed-case/src/Service/Types/NestedUser.php create mode 100644 seed/php-sdk/mixed-case/src/Service/Types/Organization.php create mode 100644 seed/php-sdk/mixed-case/src/Service/Types/ResourceStatus.php create mode 100644 seed/php-sdk/mixed-case/src/Service/Types/User.php create mode 100644 seed/php-sdk/mixed-file-directory/src/Organization/Types/CreateOrganizationRequest.php create mode 100644 seed/php-sdk/mixed-file-directory/src/Organization/Types/Organization.php delete mode 100644 seed/php-sdk/mixed-file-directory/src/Placeholder/Placeholder.php create mode 100644 seed/php-sdk/mixed-file-directory/src/User/Events/Metadata/Types/Metadata.php create mode 100644 seed/php-sdk/mixed-file-directory/src/User/Events/Types/Event.php create mode 100644 seed/php-sdk/mixed-file-directory/src/User/Types/User.php delete mode 100644 seed/php-sdk/multi-line-docs/src/Placeholder/Placeholder.php create mode 100644 seed/php-sdk/multi-line-docs/src/Types/Operand.php create mode 100644 seed/php-sdk/multi-line-docs/src/User/Types/User.php delete mode 100644 seed/php-sdk/multi-url-environment-no-default/src/Placeholder/Placeholder.php delete mode 100644 seed/php-sdk/multi-url-environment/src/Placeholder/Placeholder.php delete mode 100644 seed/php-sdk/no-environment/src/Placeholder/Placeholder.php create mode 100644 seed/php-sdk/oauth-client-credentials-default/src/Auth/Types/TokenResponse.php delete mode 100644 seed/php-sdk/oauth-client-credentials-default/src/Placeholder/Placeholder.php create mode 100644 seed/php-sdk/oauth-client-credentials-environment-variables/src/Auth/Types/TokenResponse.php delete mode 100644 seed/php-sdk/oauth-client-credentials-environment-variables/src/Placeholder/Placeholder.php create mode 100644 seed/php-sdk/oauth-client-credentials-nested-root/src/Auth/Types/TokenResponse.php delete mode 100644 seed/php-sdk/oauth-client-credentials-nested-root/src/Placeholder/Placeholder.php create mode 100644 seed/php-sdk/oauth-client-credentials/src/Auth/Types/TokenResponse.php delete mode 100644 seed/php-sdk/oauth-client-credentials/src/Placeholder/Placeholder.php delete mode 100644 seed/php-sdk/object/src/Placeholder/Placeholder.php create mode 100644 seed/php-sdk/object/src/Types/Name.php create mode 100644 seed/php-sdk/object/src/Types/Type.php create mode 100644 seed/php-sdk/objects-with-imports/src/Commons/Metadata/Types/Metadata.php create mode 100644 seed/php-sdk/objects-with-imports/src/File/Directory/Types/Directory.php create mode 100644 seed/php-sdk/objects-with-imports/src/File/Types/File.php create mode 100644 seed/php-sdk/objects-with-imports/src/File/Types/FileInfo.php delete mode 100644 seed/php-sdk/objects-with-imports/src/Placeholder/Placeholder.php create mode 100644 seed/php-sdk/objects-with-imports/src/Types/Node.php create mode 100644 seed/php-sdk/objects-with-imports/src/Types/Tree.php delete mode 100644 seed/php-sdk/optional/src/Placeholder/Placeholder.php delete mode 100644 seed/php-sdk/package-yml/src/Placeholder/Placeholder.php create mode 100644 seed/php-sdk/package-yml/src/Types/EchoRequest.php delete mode 100644 seed/php-sdk/pagination/src/Placeholder/Placeholder.php create mode 100644 seed/php-sdk/pagination/src/Types/UsernameCursor.php create mode 100644 seed/php-sdk/pagination/src/Types/UsernamePage.php create mode 100644 seed/php-sdk/pagination/src/Users/Types/ListUsersExtendedOptionalListResponse.php create mode 100644 seed/php-sdk/pagination/src/Users/Types/ListUsersExtendedResponse.php create mode 100644 seed/php-sdk/pagination/src/Users/Types/ListUsersPaginationResponse.php create mode 100644 seed/php-sdk/pagination/src/Users/Types/NextPage.php create mode 100644 seed/php-sdk/pagination/src/Users/Types/Order.php create mode 100644 seed/php-sdk/pagination/src/Users/Types/Page.php create mode 100644 seed/php-sdk/pagination/src/Users/Types/User.php create mode 100644 seed/php-sdk/pagination/src/Users/Types/UserListContainer.php create mode 100644 seed/php-sdk/pagination/src/Users/Types/UserOptionalListContainer.php create mode 100644 seed/php-sdk/pagination/src/Users/Types/UserOptionalListPage.php create mode 100644 seed/php-sdk/pagination/src/Users/Types/UserPage.php create mode 100644 seed/php-sdk/pagination/src/Users/Types/UsernameContainer.php create mode 100644 seed/php-sdk/pagination/src/Users/Types/WithCursor.php create mode 100644 seed/php-sdk/pagination/src/Users/Types/WithPage.php delete mode 100644 seed/php-sdk/plain-text/src/Placeholder/Placeholder.php delete mode 100644 seed/php-sdk/query-parameters/src/Placeholder/Placeholder.php create mode 100644 seed/php-sdk/query-parameters/src/User/Types/NestedUser.php create mode 100644 seed/php-sdk/query-parameters/src/User/Types/User.php create mode 100644 seed/php-sdk/reserved-keywords/src/Package/Types/Package.php create mode 100644 seed/php-sdk/reserved-keywords/src/Package/Types/Record.php delete mode 100644 seed/php-sdk/reserved-keywords/src/Placeholder/Placeholder.php delete mode 100644 seed/php-sdk/response-property/src/Placeholder/Placeholder.php create mode 100644 seed/php-sdk/response-property/src/Service/Types/Movie.php create mode 100644 seed/php-sdk/response-property/src/Service/Types/Response.php create mode 100644 seed/php-sdk/response-property/src/Service/Types/WithDocs.php create mode 100644 seed/php-sdk/response-property/src/Types/StringResponse.php create mode 100644 seed/php-sdk/response-property/src/Types/WithMetadata.php delete mode 100644 seed/php-sdk/simple-fhir/src/Placeholder/Placeholder.php create mode 100644 seed/php-sdk/simple-fhir/src/Types/Account.php create mode 100644 seed/php-sdk/simple-fhir/src/Types/BaseResource.php create mode 100644 seed/php-sdk/simple-fhir/src/Types/Memo.php create mode 100644 seed/php-sdk/simple-fhir/src/Types/Patient.php create mode 100644 seed/php-sdk/simple-fhir/src/Types/Practitioner.php create mode 100644 seed/php-sdk/simple-fhir/src/Types/Script.php delete mode 100644 seed/php-sdk/single-url-environment-default/src/Placeholder/Placeholder.php delete mode 100644 seed/php-sdk/single-url-environment-no-default/src/Placeholder/Placeholder.php create mode 100644 seed/php-sdk/streaming-parameter/src/Dummy/Types/RegularResponse.php create mode 100644 seed/php-sdk/streaming-parameter/src/Dummy/Types/StreamResponse.php delete mode 100644 seed/php-sdk/streaming-parameter/src/Placeholder/Placeholder.php create mode 100644 seed/php-sdk/streaming/src/Dummy/Types/StreamResponse.php delete mode 100644 seed/php-sdk/streaming/src/Placeholder/Placeholder.php create mode 100644 seed/php-sdk/trace/src/Commons/Types/BinaryTreeNodeAndTreeValue.php create mode 100644 seed/php-sdk/trace/src/Commons/Types/BinaryTreeNodeValue.php create mode 100644 seed/php-sdk/trace/src/Commons/Types/BinaryTreeValue.php create mode 100644 seed/php-sdk/trace/src/Commons/Types/DebugKeyValuePairs.php create mode 100644 seed/php-sdk/trace/src/Commons/Types/DebugMapValue.php create mode 100644 seed/php-sdk/trace/src/Commons/Types/DoublyLinkedListNodeAndListValue.php create mode 100644 seed/php-sdk/trace/src/Commons/Types/DoublyLinkedListNodeValue.php create mode 100644 seed/php-sdk/trace/src/Commons/Types/DoublyLinkedListValue.php create mode 100644 seed/php-sdk/trace/src/Commons/Types/FileInfo.php create mode 100644 seed/php-sdk/trace/src/Commons/Types/GenericValue.php create mode 100644 seed/php-sdk/trace/src/Commons/Types/KeyValuePair.php create mode 100644 seed/php-sdk/trace/src/Commons/Types/Language.php create mode 100644 seed/php-sdk/trace/src/Commons/Types/ListType.php create mode 100644 seed/php-sdk/trace/src/Commons/Types/MapType.php create mode 100644 seed/php-sdk/trace/src/Commons/Types/MapValue.php create mode 100644 seed/php-sdk/trace/src/Commons/Types/SinglyLinkedListNodeAndListValue.php create mode 100644 seed/php-sdk/trace/src/Commons/Types/SinglyLinkedListNodeValue.php create mode 100644 seed/php-sdk/trace/src/Commons/Types/SinglyLinkedListValue.php create mode 100644 seed/php-sdk/trace/src/Commons/Types/TestCase.php create mode 100644 seed/php-sdk/trace/src/Commons/Types/TestCaseWithExpectedResult.php create mode 100644 seed/php-sdk/trace/src/LangServer/Types/LangServerRequest.php create mode 100644 seed/php-sdk/trace/src/LangServer/Types/LangServerResponse.php create mode 100644 seed/php-sdk/trace/src/Migration/Types/Migration.php create mode 100644 seed/php-sdk/trace/src/Migration/Types/MigrationStatus.php delete mode 100644 seed/php-sdk/trace/src/Placeholder/Placeholder.php create mode 100644 seed/php-sdk/trace/src/Playlist/Types/Playlist.php create mode 100644 seed/php-sdk/trace/src/Playlist/Types/PlaylistCreateRequest.php create mode 100644 seed/php-sdk/trace/src/Playlist/Types/ReservedKeywordEnum.php create mode 100644 seed/php-sdk/trace/src/Playlist/Types/UpdatePlaylistRequest.php create mode 100644 seed/php-sdk/trace/src/Problem/Types/CreateProblemRequest.php create mode 100644 seed/php-sdk/trace/src/Problem/Types/GenericCreateProblemError.php create mode 100644 seed/php-sdk/trace/src/Problem/Types/GetDefaultStarterFilesResponse.php create mode 100644 seed/php-sdk/trace/src/Problem/Types/ProblemDescription.php create mode 100644 seed/php-sdk/trace/src/Problem/Types/ProblemFiles.php create mode 100644 seed/php-sdk/trace/src/Problem/Types/ProblemInfo.php create mode 100644 seed/php-sdk/trace/src/Problem/Types/UpdateProblemResponse.php create mode 100644 seed/php-sdk/trace/src/Problem/Types/VariableTypeAndName.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/BuildingExecutorResponse.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/CompileError.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/CustomTestCasesUnsupported.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/ErroredResponse.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/ExceptionInfo.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/ExecutionSessionResponse.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/ExecutionSessionState.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/ExecutionSessionStatus.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/ExistingSubmissionExecuting.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/ExpressionLocation.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/FinishedResponse.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/GetExecutionSessionStateResponse.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/GetSubmissionStateResponse.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/GetTraceResponsesPageRequest.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/GradedResponse.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/GradedResponseV2.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/GradedTestCaseUpdate.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/InitializeProblemRequest.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/InternalError.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/InvalidRequestResponse.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/LightweightStackframeInformation.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/RecordedResponseNotification.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/RecordedTestCaseUpdate.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/RecordingResponseNotification.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/RunningResponse.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/RunningSubmissionState.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/RuntimeError.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/Scope.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/StackFrame.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/StackInformation.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/StderrResponse.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/StdoutResponse.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/StopRequest.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/StoppedResponse.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/SubmissionFileInfo.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/SubmissionIdNotFound.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/SubmissionTypeEnum.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/SubmitRequestV2.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/TerminatedResponse.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/TestCaseHiddenGrade.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/TestCaseNonHiddenGrade.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/TestCaseResult.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/TestCaseResultWithStdout.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/TestSubmissionState.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/TestSubmissionStatusV2.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/TestSubmissionUpdate.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/TraceResponse.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/TraceResponseV2.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/TraceResponsesPage.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/TraceResponsesPageV2.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/TracedFile.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/TracedTestCase.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/UnexpectedLanguageError.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/WorkspaceFiles.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/WorkspaceRanResponse.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/WorkspaceRunDetails.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/WorkspaceStarterFilesResponse.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/WorkspaceStarterFilesResponseV2.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/WorkspaceSubmissionState.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/WorkspaceSubmissionStatusV2.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/WorkspaceSubmissionUpdate.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/WorkspaceSubmitRequest.php create mode 100644 seed/php-sdk/trace/src/Submission/Types/WorkspaceTracedUpdate.php create mode 100644 seed/php-sdk/trace/src/V2/Problem/Types/BasicCustomFiles.php create mode 100644 seed/php-sdk/trace/src/V2/Problem/Types/BasicTestCaseTemplate.php create mode 100644 seed/php-sdk/trace/src/V2/Problem/Types/CreateProblemRequestV2.php create mode 100644 seed/php-sdk/trace/src/V2/Problem/Types/DeepEqualityCorrectnessCheck.php create mode 100644 seed/php-sdk/trace/src/V2/Problem/Types/DefaultProvidedFile.php create mode 100644 seed/php-sdk/trace/src/V2/Problem/Types/FileInfoV2.php create mode 100644 seed/php-sdk/trace/src/V2/Problem/Types/Files.php create mode 100644 seed/php-sdk/trace/src/V2/Problem/Types/FunctionImplementation.php create mode 100644 seed/php-sdk/trace/src/V2/Problem/Types/FunctionImplementationForMultipleLanguages.php create mode 100644 seed/php-sdk/trace/src/V2/Problem/Types/GeneratedFiles.php create mode 100644 seed/php-sdk/trace/src/V2/Problem/Types/GetBasicSolutionFileRequest.php create mode 100644 seed/php-sdk/trace/src/V2/Problem/Types/GetBasicSolutionFileResponse.php create mode 100644 seed/php-sdk/trace/src/V2/Problem/Types/GetFunctionSignatureRequest.php create mode 100644 seed/php-sdk/trace/src/V2/Problem/Types/GetFunctionSignatureResponse.php create mode 100644 seed/php-sdk/trace/src/V2/Problem/Types/GetGeneratedTestCaseFileRequest.php create mode 100644 seed/php-sdk/trace/src/V2/Problem/Types/GetGeneratedTestCaseTemplateFileRequest.php create mode 100644 seed/php-sdk/trace/src/V2/Problem/Types/LightweightProblemInfoV2.php create mode 100644 seed/php-sdk/trace/src/V2/Problem/Types/NonVoidFunctionDefinition.php create mode 100644 seed/php-sdk/trace/src/V2/Problem/Types/NonVoidFunctionSignature.php create mode 100644 seed/php-sdk/trace/src/V2/Problem/Types/Parameter.php create mode 100644 seed/php-sdk/trace/src/V2/Problem/Types/ProblemInfoV2.php create mode 100644 seed/php-sdk/trace/src/V2/Problem/Types/TestCaseExpects.php create mode 100644 seed/php-sdk/trace/src/V2/Problem/Types/TestCaseImplementation.php create mode 100644 seed/php-sdk/trace/src/V2/Problem/Types/TestCaseImplementationDescription.php create mode 100644 seed/php-sdk/trace/src/V2/Problem/Types/TestCaseMetadata.php create mode 100644 seed/php-sdk/trace/src/V2/Problem/Types/TestCaseTemplate.php create mode 100644 seed/php-sdk/trace/src/V2/Problem/Types/TestCaseV2.php create mode 100644 seed/php-sdk/trace/src/V2/Problem/Types/TestCaseWithActualResultImplementation.php create mode 100644 seed/php-sdk/trace/src/V2/Problem/Types/VoidFunctionDefinition.php create mode 100644 seed/php-sdk/trace/src/V2/Problem/Types/VoidFunctionDefinitionThatTakesActualResult.php create mode 100644 seed/php-sdk/trace/src/V2/Problem/Types/VoidFunctionSignature.php create mode 100644 seed/php-sdk/trace/src/V2/Problem/Types/VoidFunctionSignatureThatTakesActualResult.php create mode 100644 seed/php-sdk/trace/src/V2/V3/Problem/Types/BasicCustomFiles.php create mode 100644 seed/php-sdk/trace/src/V2/V3/Problem/Types/BasicTestCaseTemplate.php create mode 100644 seed/php-sdk/trace/src/V2/V3/Problem/Types/CreateProblemRequestV2.php create mode 100644 seed/php-sdk/trace/src/V2/V3/Problem/Types/DeepEqualityCorrectnessCheck.php create mode 100644 seed/php-sdk/trace/src/V2/V3/Problem/Types/DefaultProvidedFile.php create mode 100644 seed/php-sdk/trace/src/V2/V3/Problem/Types/FileInfoV2.php create mode 100644 seed/php-sdk/trace/src/V2/V3/Problem/Types/Files.php create mode 100644 seed/php-sdk/trace/src/V2/V3/Problem/Types/FunctionImplementation.php create mode 100644 seed/php-sdk/trace/src/V2/V3/Problem/Types/FunctionImplementationForMultipleLanguages.php create mode 100644 seed/php-sdk/trace/src/V2/V3/Problem/Types/GeneratedFiles.php create mode 100644 seed/php-sdk/trace/src/V2/V3/Problem/Types/GetBasicSolutionFileRequest.php create mode 100644 seed/php-sdk/trace/src/V2/V3/Problem/Types/GetBasicSolutionFileResponse.php create mode 100644 seed/php-sdk/trace/src/V2/V3/Problem/Types/GetFunctionSignatureRequest.php create mode 100644 seed/php-sdk/trace/src/V2/V3/Problem/Types/GetFunctionSignatureResponse.php create mode 100644 seed/php-sdk/trace/src/V2/V3/Problem/Types/GetGeneratedTestCaseFileRequest.php create mode 100644 seed/php-sdk/trace/src/V2/V3/Problem/Types/GetGeneratedTestCaseTemplateFileRequest.php create mode 100644 seed/php-sdk/trace/src/V2/V3/Problem/Types/LightweightProblemInfoV2.php create mode 100644 seed/php-sdk/trace/src/V2/V3/Problem/Types/NonVoidFunctionDefinition.php create mode 100644 seed/php-sdk/trace/src/V2/V3/Problem/Types/NonVoidFunctionSignature.php create mode 100644 seed/php-sdk/trace/src/V2/V3/Problem/Types/Parameter.php create mode 100644 seed/php-sdk/trace/src/V2/V3/Problem/Types/ProblemInfoV2.php create mode 100644 seed/php-sdk/trace/src/V2/V3/Problem/Types/TestCaseExpects.php create mode 100644 seed/php-sdk/trace/src/V2/V3/Problem/Types/TestCaseImplementation.php create mode 100644 seed/php-sdk/trace/src/V2/V3/Problem/Types/TestCaseImplementationDescription.php create mode 100644 seed/php-sdk/trace/src/V2/V3/Problem/Types/TestCaseMetadata.php create mode 100644 seed/php-sdk/trace/src/V2/V3/Problem/Types/TestCaseTemplate.php create mode 100644 seed/php-sdk/trace/src/V2/V3/Problem/Types/TestCaseV2.php create mode 100644 seed/php-sdk/trace/src/V2/V3/Problem/Types/TestCaseWithActualResultImplementation.php create mode 100644 seed/php-sdk/trace/src/V2/V3/Problem/Types/VoidFunctionDefinition.php create mode 100644 seed/php-sdk/trace/src/V2/V3/Problem/Types/VoidFunctionDefinitionThatTakesActualResult.php create mode 100644 seed/php-sdk/trace/src/V2/V3/Problem/Types/VoidFunctionSignature.php create mode 100644 seed/php-sdk/trace/src/V2/V3/Problem/Types/VoidFunctionSignatureThatTakesActualResult.php delete mode 100644 seed/php-sdk/undiscriminated-unions/src/Placeholder/Placeholder.php create mode 100644 seed/php-sdk/undiscriminated-unions/src/Union/Types/KeyType.php delete mode 100644 seed/php-sdk/unions/src/Placeholder/Placeholder.php create mode 100644 seed/php-sdk/unions/src/Types/Types/Bar.php create mode 100644 seed/php-sdk/unions/src/Types/Types/Foo.php create mode 100644 seed/php-sdk/unions/src/Union/Types/Circle.php create mode 100644 seed/php-sdk/unions/src/Union/Types/GetShapeRequest.php create mode 100644 seed/php-sdk/unions/src/Union/Types/Square.php delete mode 100644 seed/php-sdk/unknown/src/Placeholder/Placeholder.php create mode 100644 seed/php-sdk/unknown/src/Unknown/Types/MyObject.php delete mode 100644 seed/php-sdk/validation/src/Placeholder/Placeholder.php create mode 100644 seed/php-sdk/validation/src/Types/Shape.php create mode 100644 seed/php-sdk/validation/src/Types/Type.php delete mode 100644 seed/php-sdk/variables/src/Placeholder/Placeholder.php delete mode 100644 seed/php-sdk/version-no-default/src/Placeholder/Placeholder.php create mode 100644 seed/php-sdk/version-no-default/src/User/Types/User.php delete mode 100644 seed/php-sdk/version/src/Placeholder/Placeholder.php create mode 100644 seed/php-sdk/version/src/User/Types/User.php delete mode 100644 seed/php-sdk/websocket/src/Placeholder/Placeholder.php diff --git a/generators/csharp/model/src/object/ObjectGenerator.ts b/generators/csharp/model/src/object/ObjectGenerator.ts index ed731d293f1..4a8e8b7bcdf 100644 --- a/generators/csharp/model/src/object/ObjectGenerator.ts +++ b/generators/csharp/model/src/object/ObjectGenerator.ts @@ -10,7 +10,6 @@ import { import { ModelCustomConfigSchema } from "../ModelCustomConfig"; import { ModelGeneratorContext } from "../ModelGeneratorContext"; import { ExampleGenerator } from "../snippets/ExampleGenerator"; -import { getUndiscriminatedUnionSerializerAnnotation } from "../undiscriminated-union/getUndiscriminatedUnionSerializerAnnotation"; export class ObjectGenerator extends FileGenerator { private readonly typeDeclaration: TypeDeclaration; diff --git a/generators/php/codegen/src/asIs/SerializableType.Template.php b/generators/php/codegen/src/asIs/SerializableType.Template.php index 7ce3229b33a..5f40a8965e9 100644 --- a/generators/php/codegen/src/asIs/SerializableType.Template.php +++ b/generators/php/codegen/src/asIs/SerializableType.Template.php @@ -14,8 +14,6 @@ abstract class SerializableType { /** * Serializes the object to a JSON string. - * - * @throws JsonException */ public function toJson(): string { @@ -35,6 +33,9 @@ public function toArray(): array foreach ($reflectionClass->getProperties() as $property) { $jsonKey = self::getJsonKey($property); + if ($jsonKey == null) { + continue; + } $value = $property->getValue($this); // Handle DateTime properties @@ -121,6 +122,10 @@ private static function serializeSingleValue(mixed $data, string $type): mixed return $type === 'date' ? $data->format(Constant::DateFormat) : $data->format(Constant::DateTimeFormat); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && $data instanceof $type) { if (method_exists($data, 'toArray')) { return $data->toArray(); @@ -171,19 +176,19 @@ private static function serializeMap(array $data, array $type): array private static function serializeList(array $data, array $type): array { $valueType = $type[0]; - return array_map(fn($item) => self::serializeValue($item, $valueType), $data); + return array_map(fn ($item) => self::serializeValue($item, $valueType), $data); } /** * Helper function to retrieve the JSON key for a property. * * @param ReflectionProperty $property - * @return string + * @return string|null */ - private static function getJsonKey(ReflectionProperty $property): string + private static function getJsonKey(ReflectionProperty $property): ?string { $jsonPropertyAttr = $property->getAttributes(JsonProperty::class)[0] ?? null; - return $jsonPropertyAttr ? $jsonPropertyAttr->newInstance()->name : $property->getName(); + return $jsonPropertyAttr?->newInstance()?->name; } /** @@ -261,7 +266,7 @@ public static function fromArray(array $data): static continue; } - $jsonKey = self::getJsonKey($property); + $jsonKey = self::getJsonKey($property) ?? $property->getName(); if (array_key_exists($jsonKey, $data)) { $value = $data[$jsonKey]; @@ -358,6 +363,10 @@ private static function deserializeSingleValue(mixed $data, string $type): mixed return new DateTime($data); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && is_array($data)) { return $type::fromArray($data); } @@ -400,6 +409,6 @@ private static function deserializeMap(array $data, array $type): array private static function deserializeList(array $data, array $type): array { $valueType = $type[0]; - return array_map(fn($item) => self::deserializeValue($item, $valueType), $data); + return array_map(fn ($item) => self::deserializeValue($item, $valueType), $data); } } \ No newline at end of file diff --git a/generators/php/codegen/src/ast/Array.ts b/generators/php/codegen/src/ast/Array.ts new file mode 100644 index 00000000000..a1a89489a4a --- /dev/null +++ b/generators/php/codegen/src/ast/Array.ts @@ -0,0 +1,28 @@ +import { AstNode } from "./core/AstNode"; +import { Writer } from "./core/Writer"; + +export declare namespace Array { + interface Args { + entries: AstNode[] | undefined; + } +} + +export class Array extends AstNode { + private entries: AstNode[]; + + constructor({ entries }: Array.Args) { + super(); + this.entries = entries ?? []; + } + + public write(writer: Writer): void { + writer.write("["); + this.entries.forEach((entry, index) => { + if (index > 0) { + writer.write(", "); + } + entry.write(writer); + }); + writer.write("]"); + } +} diff --git a/generators/php/codegen/src/ast/Attribute.ts b/generators/php/codegen/src/ast/Attribute.ts new file mode 100644 index 00000000000..aa51618d93c --- /dev/null +++ b/generators/php/codegen/src/ast/Attribute.ts @@ -0,0 +1,39 @@ +import { AstNode } from "./core/AstNode"; +import { ClassReference } from "./ClassReference"; +import { Writer } from "./core/Writer"; + +export declare namespace Attribute { + interface Args { + /* Reference to the Attribute */ + reference: ClassReference; + + arguments?: (string | AstNode)[]; + } +} + +export class Attribute extends AstNode { + private reference: ClassReference; + private arguments: (string | AstNode)[]; + + constructor(args: Attribute.Args) { + super(); + this.reference = args.reference; + this.arguments = args.arguments ?? []; + } + + public write(writer: Writer): void { + writer.addReference(this.reference); + writer.write(`${this.reference.name}`); + if (this.arguments.length > 0) { + writer.write("("); + for (const argument of this.arguments) { + if (typeof argument === "string") { + writer.write(argument); + } else { + argument.write(writer); + } + } + writer.write(")"); + } + } +} diff --git a/generators/php/codegen/src/ast/Class.ts b/generators/php/codegen/src/ast/Class.ts index 5af2e146072..d93fe6a2214 100644 --- a/generators/php/codegen/src/ast/Class.ts +++ b/generators/php/codegen/src/ast/Class.ts @@ -16,6 +16,8 @@ export declare namespace Class { abstract?: boolean; /* Docs associated with the class */ docs?: string; + /* The class to inherit from if any */ + parentClassReference?: AstNode; } interface Constructor { @@ -33,16 +35,18 @@ export class Class extends AstNode { public readonly namespace: string; public readonly abstract: boolean; public readonly docs: string | undefined; + public readonly parentClassReference: AstNode | undefined; private fields: Field[] = []; private constructor_: Class.Constructor | undefined; - constructor({ name, namespace, abstract, docs }: Class.Args) { + constructor({ name, namespace, abstract, docs, parentClassReference }: Class.Args) { super(); this.name = name; this.namespace = namespace; this.abstract = abstract ?? false; this.docs = docs; + this.parentClassReference = parentClassReference; } public addField(field: Field): void { @@ -59,7 +63,11 @@ export class Class extends AstNode { } this.writeComment(writer); writer.writeLine(`class ${this.name}`); - writer.writeLine("{"); + if (this.parentClassReference != null) { + writer.write(" extends "); + this.parentClassReference.write(writer); + } + writer.writeLine(" {"); writer.indent(); for (const field of this.fields) { field.write(writer); diff --git a/generators/php/codegen/src/ast/Enum.ts b/generators/php/codegen/src/ast/Enum.ts new file mode 100644 index 00000000000..4b12e53f769 --- /dev/null +++ b/generators/php/codegen/src/ast/Enum.ts @@ -0,0 +1,77 @@ +import { Comment } from "./Comment"; +import { AstNode } from "./core/AstNode"; +import { Writer } from "./core/Writer"; + +export declare namespace Enum { + interface Args { + /* The name of the PHP enum */ + name: string; + /* The namespace of the PHP enum*/ + namespace: string; + /* If present, specified that the enum is backed by this type */ + backing?: "string" | "int"; + /* Docs associated with the class */ + docs?: string; + } + + interface Member { + /* The name of the enum field */ + name: string; + /* The value of the enum field */ + value?: string | number; + } +} + +export class Enum extends AstNode { + public readonly name: string; + public readonly namespace: string; + public readonly backing: "string" | "int" | undefined; + public readonly docs: string | undefined; + public readonly members: Enum.Member[] = []; + + constructor({ name, namespace, backing, docs }: Enum.Args) { + super(); + this.name = name; + this.namespace = namespace; + this.backing = backing; + this.docs = docs; + } + + public addMember(member: Enum.Member): void { + this.members.push(member); + } + + public write(writer: Writer): void { + this.writeComment(writer); + writer.write("enum "); + writer.writeLine(`${this.name}`); + if (this.backing != null) { + writer.write(` : ${this.backing}`); + } + writer.writeLine(" {"); + + writer.indent(); + for (const member of this.members) { + writer.write(`case ${member.name}`); + if (member.value != null) { + if (typeof member.value === "string") { + writer.write(` = "${member.value}"`); + } else { + writer.write(` = ${member.value}`); + } + } + writer.writeTextStatement(""); + } + writer.writeNewLineIfLastLineNot(); + writer.dedent(); + writer.writeLine("}"); + } + + public writeComment(writer: Writer): void { + if (this.docs == null) { + return undefined; + } + const comment = new Comment({ docs: this.docs }); + comment.write(writer); + } +} diff --git a/generators/php/codegen/src/ast/Field.ts b/generators/php/codegen/src/ast/Field.ts index e44922ec151..86d69730a46 100644 --- a/generators/php/codegen/src/ast/Field.ts +++ b/generators/php/codegen/src/ast/Field.ts @@ -4,6 +4,7 @@ import { AstNode } from "./core/AstNode"; import { Writer } from "./core/Writer"; import { Type } from "./Type"; import { Comment } from "./Comment"; +import { Attribute } from "./Attribute"; export declare namespace Field { interface Args { @@ -21,6 +22,8 @@ export declare namespace Field { docs?: string; /* Docs included in-line */ inlineDocs?: string; + /* Field attributes */ + attributes?: Attribute[]; } } @@ -32,8 +35,9 @@ export class Field extends AstNode { private initializer: CodeBlock | undefined; private docs: string | undefined; private inlineDocs: string | undefined; + private attributes: Attribute[]; - constructor({ name, type, access, readonly_, initializer, docs, inlineDocs }: Field.Args) { + constructor({ name, type, access, readonly_, initializer, docs, inlineDocs, attributes }: Field.Args) { super(); this.name = name; this.type = type; @@ -42,9 +46,11 @@ export class Field extends AstNode { this.initializer = initializer; this.docs = docs; this.inlineDocs = inlineDocs; + this.attributes = attributes ?? []; } public write(writer: Writer): void { + this.writeAttributesIfPresent(writer); this.writeComment(writer); writer.write(`${this.access} `); @@ -77,4 +83,17 @@ export class Field extends AstNode { }); comment.write(writer); } + + private writeAttributesIfPresent(writer: Writer): void { + if (this.attributes.length > 0) { + writer.write("#["); + this.attributes.forEach((attribute, index) => { + if (index > 0) { + writer.write(", "); + } + attribute.write(writer); + }); + writer.writeLine("]"); + } + } } diff --git a/generators/php/codegen/src/ast/Map.ts b/generators/php/codegen/src/ast/Map.ts index ec51c4fd229..eefbdafbf31 100644 --- a/generators/php/codegen/src/ast/Map.ts +++ b/generators/php/codegen/src/ast/Map.ts @@ -13,28 +13,23 @@ export declare namespace Map { } export class Map extends AstNode { - private entries: Map.Entry[] | undefined; + private entries: Map.Entry[]; constructor({ entries }: Map.Args) { super(); - this.entries = entries; + this.entries = entries ?? []; } public write(writer: Writer): void { - if (this.entries == null) { - writer.write("[]"); - return; - } - - writer.writeLine("["); - writer.indent(); - for (const { key, value } of this.entries) { + writer.write("["); + for (const [index, { key, value }] of this.entries.entries()) { + if (index > 0) { + writer.write(","); + } key.write(writer); writer.write(" => "); value.write(writer); - writer.writeLine(", "); } - writer.dedent(); writer.write("]"); } } diff --git a/generators/php/codegen/src/ast/Type.ts b/generators/php/codegen/src/ast/Type.ts index 9f36ffe597c..271a2b366fb 100644 --- a/generators/php/codegen/src/ast/Type.ts +++ b/generators/php/codegen/src/ast/Type.ts @@ -88,7 +88,7 @@ export class Type extends AstNode { super(); } - public write(writer: Writer, { parentType, comment }: { parentType?: Type; comment?: boolean } = {}): void { + public write(writer: Writer, { comment }: { comment?: boolean } = {}): void { switch (this.internalType.type) { case "int": writer.write("int"); @@ -122,7 +122,7 @@ export class Type extends AstNode { break; } writer.write("array<"); - this.internalType.value.write(writer, { parentType: this, comment }); + this.internalType.value.write(writer, { comment }); writer.write(">"); break; case "map": { @@ -131,9 +131,9 @@ export class Type extends AstNode { break; } writer.write("array<"); - this.internalType.keyType.write(writer, { parentType: this, comment }); + this.internalType.keyType.write(writer, { comment }); writer.write(", "); - this.internalType.valueType.write(writer, { parentType: this, comment }); + this.internalType.valueType.write(writer, { comment }); writer.write(">"); break; } @@ -152,17 +152,14 @@ export class Type extends AstNode { writer.write("?"); } writer.write(": "); - entry.valueType.write(writer, { parentType: this, comment }); + entry.valueType.write(writer, { comment }); }); writer.write("}"); break; } case "optional": - if (this.needsOptionalToken({ parentType, value: this.internalType.value })) { - // Avoids double optional. - writer.write("?"); - } - this.internalType.value.write(writer, { parentType: this, comment }); + writer.write("?"); + this.internalType.value.write(writer, { comment }); break; case "reference": writer.writeNode(this.internalType.value); @@ -186,12 +183,12 @@ export class Type extends AstNode { return undefined; } - public isOptional(): boolean { - return this.internalType.type === "optional"; + public underlyingType(): Type { + return this.underlyingTypeIfOptional() ?? this; } - private needsOptionalToken({ parentType, value }: { parentType: Type | undefined; value: Type }): boolean { - return value.internalType.type !== "mixed" && parentType?.internalType?.type !== "optional"; + public isOptional(): boolean { + return this.internalType.type === "optional"; } /* Static factory methods for creating a Type */ @@ -266,6 +263,10 @@ export class Type extends AstNode { } public static optional(value: Type): Type { + // Avoids double optional. + if (this.isAlreadyOptional(value)) { + return value; + } return new this({ type: "optional", value @@ -278,6 +279,10 @@ export class Type extends AstNode { value }); } + + private static isAlreadyOptional(value: Type) { + return value.internalType.type === "optional" || value.internalType.type === "mixed"; + } } export const DateTimeClassReference = new ClassReference({ diff --git a/generators/php/codegen/src/ast/index.ts b/generators/php/codegen/src/ast/index.ts index 20d1e2c6fd6..8b2fb7ab17a 100644 --- a/generators/php/codegen/src/ast/index.ts +++ b/generators/php/codegen/src/ast/index.ts @@ -5,5 +5,8 @@ export { CodeBlock } from "./CodeBlock"; export { Writer } from "./core/Writer"; export { Field } from "./Field"; export { Map } from "./Map"; +export { Array } from "./Array"; export { Parameter } from "./Parameter"; export { Type } from "./Type"; +export { Attribute } from "./Attribute"; +export { Enum } from "./Enum"; diff --git a/generators/php/codegen/src/context/AbstractPhpGeneratorContext.ts b/generators/php/codegen/src/context/AbstractPhpGeneratorContext.ts index fbf831d803b..950a4e77ba4 100644 --- a/generators/php/codegen/src/context/AbstractPhpGeneratorContext.ts +++ b/generators/php/codegen/src/context/AbstractPhpGeneratorContext.ts @@ -8,7 +8,8 @@ import { TypeDeclaration, Subpackage, SubpackageId, - FernFilepath + FernFilepath, + PrimitiveType } from "@fern-fern/ir-sdk/api"; import { BasePhpCustomConfigSchema } from "../custom-config/BasePhpCustomConfigSchema"; import { PhpProject } from "../project"; @@ -16,6 +17,7 @@ import { camelCase, upperFirst } from "lodash-es"; import { PhpTypeMapper } from "./PhpTypeMapper"; import { AsIsFiles } from "../AsIs"; import { RelativeFilePath } from "@fern-api/fs-utils"; +import { php } from ".."; export interface FileLocation { namespace: string; @@ -76,6 +78,37 @@ export abstract class AbstractPhpGeneratorContext< return literal.type === "string" ? `"${literal.string}"` : literal.boolean ? '"true"' : '"false"'; } + public getDateTypeAttributeClassReference(): php.ClassReference { + return this.getCoreClassReference("DateType"); + } + + public getConstantClassReference(): php.ClassReference { + return this.getCoreClassReference("Constant"); + } + + public getJsonPropertyAttributeClassReference(): php.ClassReference { + return this.getCoreClassReference("JsonProperty"); + } + + public getSerializableTypeClassReference(): php.ClassReference { + return this.getCoreClassReference("SerializableType"); + } + + public getUnionClassReference(): php.ClassReference { + return this.getCoreClassReference("Union"); + } + + public getArrayTypeClassReference(): php.ClassReference { + return this.getCoreClassReference("ArrayType"); + } + + private getCoreClassReference(name: string): php.ClassReference { + return php.classReference({ + name, + namespace: this.getCoreNamespace() + }); + } + public isOptional(typeReference: TypeReference): boolean { switch (typeReference.type) { case "container": @@ -148,11 +181,11 @@ export abstract class AbstractPhpGeneratorContext< public abstract getLocationForTypeId(typeId: TypeId): FileLocation; protected getFileLocation(filepath: FernFilepath, suffix?: string): FileLocation { - let parts = [this.getRootNamespace(), ...filepath.allParts.map((path) => path.pascalCase.safeName)]; + let parts = filepath.allParts.map((path) => path.pascalCase.safeName); parts = suffix != null ? [...parts, suffix] : parts; return { - namespace: parts.join("\\"), - directory: RelativeFilePath.of(parts.slice(1).join("/")) + namespace: [this.getRootNamespace(), ...parts].join("\\"), + directory: RelativeFilePath.of(parts.join("/")) }; } } diff --git a/generators/php/codegen/src/context/PhpTypeMapper.ts b/generators/php/codegen/src/context/PhpTypeMapper.ts index a33bc87bf3a..d2c3702d698 100644 --- a/generators/php/codegen/src/context/PhpTypeMapper.ts +++ b/generators/php/codegen/src/context/PhpTypeMapper.ts @@ -86,7 +86,7 @@ export class PhpTypeMapper { uuid: () => php.Type.string(), base64: () => php.Type.string(), bigInteger: () => php.Type.string(), - _other: () => php.Type.object() + _other: () => php.Type.mixed() }); } diff --git a/generators/php/codegen/src/php.ts b/generators/php/codegen/src/php.ts index d77f2d3eb19..fa68acefeeb 100644 --- a/generators/php/codegen/src/php.ts +++ b/generators/php/codegen/src/php.ts @@ -1,4 +1,5 @@ -import { Class, ClassInstantiation, ClassReference, CodeBlock, Field, Map, Parameter } from "./ast"; +import { Class, ClassInstantiation, ClassReference, CodeBlock, Field, Map, Parameter, Array, Enum } from "./ast"; +import { Attribute } from "./ast/Attribute"; export function class_(args: Class.Args): Class { return new Class(args); @@ -8,6 +9,10 @@ export function classReference(args: ClassReference.Args): ClassReference { return new ClassReference(args); } +export function attribute(args: Attribute.Args): Attribute { + return new Attribute(args); +} + export function codeblock(arg: CodeBlock.Arg): CodeBlock { return new CodeBlock(arg); } @@ -24,9 +29,30 @@ export function map(args: Map.Args): Map { return new Map(args); } +export function array(args: Array.Args): Array { + return new Array(args); +} + export function parameter(args: Parameter.Args): Parameter { return new Parameter(args); } +export function enum_(args: Enum.Args): Enum { + return new Enum(args); +} + export { AstNode } from "./ast/core/AstNode"; -export { Class, ClassInstantiation, ClassReference, CodeBlock, Field, Map, Parameter, Type, Writer } from "./ast"; +export { + Class, + ClassInstantiation, + ClassReference, + CodeBlock, + Field, + Map, + Parameter, + Type, + Writer, + Attribute, + Array, + Enum +} from "./ast"; diff --git a/generators/php/codegen/src/project/PhpFile.ts b/generators/php/codegen/src/project/PhpFile.ts index 3140b43e1ab..a0dc85f6194 100644 --- a/generators/php/codegen/src/project/PhpFile.ts +++ b/generators/php/codegen/src/project/PhpFile.ts @@ -4,13 +4,14 @@ import path from "path"; import { BasePhpCustomConfigSchema } from "../custom-config/BasePhpCustomConfigSchema"; import { File } from "@fern-api/generator-commons"; import { Class } from "../ast/Class"; +import { Enum } from "../ast"; export type Namespace = string; export declare namespace PhpFile { interface Args { /* The class to be written to the PHP File */ - clazz: Class; + clazz: Class | Enum; /* Directory of the filepath */ directory: RelativeFilePath; /* The root namespace of the project. Can be pulled directly from context. */ @@ -47,7 +48,7 @@ function phpFileContent({ rootNamespace, customConfig }: { - clazz: Class; + clazz: Class | Enum; rootNamespace: string; customConfig: BasePhpCustomConfigSchema; }): string { diff --git a/generators/php/model/src/enum/EnumGenerator.ts b/generators/php/model/src/enum/EnumGenerator.ts new file mode 100644 index 00000000000..5d986b2ba9f --- /dev/null +++ b/generators/php/model/src/enum/EnumGenerator.ts @@ -0,0 +1,40 @@ +import { RelativeFilePath } from "@fern-api/fs-utils"; +import { FileGenerator, php, PhpFile } from "@fern-api/php-codegen"; +import { EnumTypeDeclaration, TypeDeclaration } from "@fern-fern/ir-sdk/api"; +import { ModelCustomConfigSchema } from "../ModelCustomConfig"; +import { ModelGeneratorContext } from "../ModelGeneratorContext"; + +export class EnumGenerator extends FileGenerator { + private readonly classReference: php.ClassReference; + + constructor( + context: ModelGeneratorContext, + private readonly typeDeclaration: TypeDeclaration, + private readonly enumDeclaration: EnumTypeDeclaration + ) { + super(context); + this.classReference = this.context.phpTypeMapper.convertToClassReference(this.typeDeclaration.name); + } + + protected doGenerate(): PhpFile { + const enum_ = php.enum_({ + ...this.classReference, + backing: "string" + }); + + this.enumDeclaration.values.forEach((member) => + enum_.addMember({ name: member.name.name.pascalCase.safeName, value: member.name.wireValue }) + ); + + return new PhpFile({ + clazz: enum_, + rootNamespace: this.context.getRootNamespace(), + directory: this.context.getLocationForTypeId(this.typeDeclaration.name.typeId).directory, + customConfig: this.context.customConfig + }); + } + + protected getFilepath(): RelativeFilePath { + return this.context.getLocationForTypeId(this.typeDeclaration.name.typeId).directory; + } +} diff --git a/generators/php/model/src/generateModels.ts b/generators/php/model/src/generateModels.ts index 535ac4d668c..98dcb464543 100644 --- a/generators/php/model/src/generateModels.ts +++ b/generators/php/model/src/generateModels.ts @@ -1,5 +1,6 @@ import { PhpFile } from "@fern-api/php-codegen"; import { EnumTypeDeclaration } from "@fern-fern/ir-sdk/api"; +import { EnumGenerator } from "./enum/EnumGenerator"; import { ModelGeneratorContext } from "./ModelGeneratorContext"; import { ObjectGenerator } from "./object/ObjectGenerator"; @@ -9,8 +10,7 @@ export function generateModels({ context }: { context: ModelGeneratorContext }): const file = typeDeclaration.shape._visit({ alias: () => undefined, enum: (etd: EnumTypeDeclaration) => { - return undefined; - // return new EnumGenerator(context, typeDeclaration, etd).generate(); + return new EnumGenerator(context, typeDeclaration, etd).generate(); }, object: (otd) => { return new ObjectGenerator(context, typeDeclaration, otd).generate(); diff --git a/generators/php/model/src/object/ObjectGenerator.ts b/generators/php/model/src/object/ObjectGenerator.ts index 225da11e900..c858ddd7f84 100644 --- a/generators/php/model/src/object/ObjectGenerator.ts +++ b/generators/php/model/src/object/ObjectGenerator.ts @@ -7,8 +7,10 @@ import { NameAndWireValue, ObjectProperty, ObjectTypeDeclaration, + Type, TypeDeclaration } from "@fern-fern/ir-sdk/api"; +import { assertNever } from "../../../codegen/node_modules/@fern-api/core-utils/src"; import { ModelCustomConfigSchema } from "../ModelCustomConfig"; import { ModelGeneratorContext } from "../ModelGeneratorContext"; @@ -28,7 +30,8 @@ export class ObjectGenerator extends FileGenerator { + const type = this.context.phpTypeMapper.convert({ reference: property.valueType }); + const attributes: php.Attribute[] = []; + attributes.push( + php.attribute({ + reference: this.context.getJsonPropertyAttributeClassReference(), + arguments: [`"${property.name.wireValue}"`] + }) + ); + const underlyingInternalType = type.underlyingType().internalType; + if (underlyingInternalType.type === "date" || underlyingInternalType.type === "dateTime") { + attributes.push( + php.attribute({ + reference: this.context.getDateTypeAttributeClassReference(), + arguments: [`DateType::TYPE_${underlyingInternalType.type.toUpperCase()}`] + }) + ); + } + if (underlyingInternalType.type === "array" || underlyingInternalType.type === "map") { + attributes.push( + php.attribute({ + reference: this.context.getArrayTypeClassReference(), + arguments: [this.getArrayTypeAttributeArgument(type.underlyingType())] + }) + ); + } + clazz.addField( php.field({ name: property.name.name.camelCase.safeName, - type: this.context.phpTypeMapper.convert({ reference: property.valueType }), + type, access: "public", docs: property.docs, - readonly_: true + attributes // jsonPropertyName: property.name.wireValue }) ); @@ -78,4 +107,59 @@ export class ObjectGenerator extends FileGeneratorchild = $child; + } +} diff --git a/seed/php-model/alias-extends/src/Core/SerializableType.php b/seed/php-model/alias-extends/src/Core/SerializableType.php index 4bc3eda7bec..27c45fb74a1 100644 --- a/seed/php-model/alias-extends/src/Core/SerializableType.php +++ b/seed/php-model/alias-extends/src/Core/SerializableType.php @@ -14,8 +14,6 @@ abstract class SerializableType { /** * Serializes the object to a JSON string. - * - * @throws JsonException */ public function toJson(): string { @@ -35,6 +33,9 @@ public function toArray(): array foreach ($reflectionClass->getProperties() as $property) { $jsonKey = self::getJsonKey($property); + if ($jsonKey == null) { + continue; + } $value = $property->getValue($this); // Handle DateTime properties @@ -121,6 +122,10 @@ private static function serializeSingleValue(mixed $data, string $type): mixed return $type === 'date' ? $data->format(Constant::DateFormat) : $data->format(Constant::DateTimeFormat); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && $data instanceof $type) { if (method_exists($data, 'toArray')) { return $data->toArray(); @@ -178,12 +183,12 @@ private static function serializeList(array $data, array $type): array * Helper function to retrieve the JSON key for a property. * * @param ReflectionProperty $property - * @return string + * @return string|null */ - private static function getJsonKey(ReflectionProperty $property): string + private static function getJsonKey(ReflectionProperty $property): ?string { $jsonPropertyAttr = $property->getAttributes(JsonProperty::class)[0] ?? null; - return $jsonPropertyAttr ? $jsonPropertyAttr->newInstance()->name : $property->getName(); + return $jsonPropertyAttr?->newInstance()?->name; } /** @@ -261,7 +266,7 @@ public static function fromArray(array $data): static continue; } - $jsonKey = self::getJsonKey($property); + $jsonKey = self::getJsonKey($property) ?? $property->getName(); if (array_key_exists($jsonKey, $data)) { $value = $data[$jsonKey]; @@ -358,6 +363,10 @@ private static function deserializeSingleValue(mixed $data, string $type): mixed return new DateTime($data); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && is_array($data)) { return $type::fromArray($data); } diff --git a/seed/php-model/alias-extends/src/Parent.php b/seed/php-model/alias-extends/src/Parent.php new file mode 100644 index 00000000000..85ee6f19a13 --- /dev/null +++ b/seed/php-model/alias-extends/src/Parent.php @@ -0,0 +1,24 @@ +parent = $parent; + } +} diff --git a/seed/php-model/alias-extends/src/Placeholder/Placeholder.php b/seed/php-model/alias-extends/src/Placeholder/Placeholder.php deleted file mode 100644 index a0eb33a6b60..00000000000 --- a/seed/php-model/alias-extends/src/Placeholder/Placeholder.php +++ /dev/null @@ -1,11 +0,0 @@ -getProperties() as $property) { $jsonKey = self::getJsonKey($property); + if ($jsonKey == null) { + continue; + } $value = $property->getValue($this); // Handle DateTime properties @@ -121,6 +122,10 @@ private static function serializeSingleValue(mixed $data, string $type): mixed return $type === 'date' ? $data->format(Constant::DateFormat) : $data->format(Constant::DateTimeFormat); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && $data instanceof $type) { if (method_exists($data, 'toArray')) { return $data->toArray(); @@ -178,12 +183,12 @@ private static function serializeList(array $data, array $type): array * Helper function to retrieve the JSON key for a property. * * @param ReflectionProperty $property - * @return string + * @return string|null */ - private static function getJsonKey(ReflectionProperty $property): string + private static function getJsonKey(ReflectionProperty $property): ?string { $jsonPropertyAttr = $property->getAttributes(JsonProperty::class)[0] ?? null; - return $jsonPropertyAttr ? $jsonPropertyAttr->newInstance()->name : $property->getName(); + return $jsonPropertyAttr?->newInstance()?->name; } /** @@ -261,7 +266,7 @@ public static function fromArray(array $data): static continue; } - $jsonKey = self::getJsonKey($property); + $jsonKey = self::getJsonKey($property) ?? $property->getName(); if (array_key_exists($jsonKey, $data)) { $value = $data[$jsonKey]; @@ -358,6 +363,10 @@ private static function deserializeSingleValue(mixed $data, string $type): mixed return new DateTime($data); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && is_array($data)) { return $type::fromArray($data); } diff --git a/seed/php-model/alias/src/Placeholder/Placeholder.php b/seed/php-model/alias/src/Placeholder/Placeholder.php deleted file mode 100644 index a0eb33a6b60..00000000000 --- a/seed/php-model/alias/src/Placeholder/Placeholder.php +++ /dev/null @@ -1,11 +0,0 @@ -id = $id; + $this->name = $name; + } +} diff --git a/seed/php-model/any-auth/src/Auth/TokenResponse.php b/seed/php-model/any-auth/src/Auth/TokenResponse.php new file mode 100644 index 00000000000..7ef240ee673 --- /dev/null +++ b/seed/php-model/any-auth/src/Auth/TokenResponse.php @@ -0,0 +1,45 @@ +accessToken = $accessToken; + $this->expiresIn = $expiresIn; + $this->refreshToken = $refreshToken; + } +} diff --git a/seed/php-model/any-auth/src/Core/SerializableType.php b/seed/php-model/any-auth/src/Core/SerializableType.php index 4bc3eda7bec..27c45fb74a1 100644 --- a/seed/php-model/any-auth/src/Core/SerializableType.php +++ b/seed/php-model/any-auth/src/Core/SerializableType.php @@ -14,8 +14,6 @@ abstract class SerializableType { /** * Serializes the object to a JSON string. - * - * @throws JsonException */ public function toJson(): string { @@ -35,6 +33,9 @@ public function toArray(): array foreach ($reflectionClass->getProperties() as $property) { $jsonKey = self::getJsonKey($property); + if ($jsonKey == null) { + continue; + } $value = $property->getValue($this); // Handle DateTime properties @@ -121,6 +122,10 @@ private static function serializeSingleValue(mixed $data, string $type): mixed return $type === 'date' ? $data->format(Constant::DateFormat) : $data->format(Constant::DateTimeFormat); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && $data instanceof $type) { if (method_exists($data, 'toArray')) { return $data->toArray(); @@ -178,12 +183,12 @@ private static function serializeList(array $data, array $type): array * Helper function to retrieve the JSON key for a property. * * @param ReflectionProperty $property - * @return string + * @return string|null */ - private static function getJsonKey(ReflectionProperty $property): string + private static function getJsonKey(ReflectionProperty $property): ?string { $jsonPropertyAttr = $property->getAttributes(JsonProperty::class)[0] ?? null; - return $jsonPropertyAttr ? $jsonPropertyAttr->newInstance()->name : $property->getName(); + return $jsonPropertyAttr?->newInstance()?->name; } /** @@ -261,7 +266,7 @@ public static function fromArray(array $data): static continue; } - $jsonKey = self::getJsonKey($property); + $jsonKey = self::getJsonKey($property) ?? $property->getName(); if (array_key_exists($jsonKey, $data)) { $value = $data[$jsonKey]; @@ -358,6 +363,10 @@ private static function deserializeSingleValue(mixed $data, string $type): mixed return new DateTime($data); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && is_array($data)) { return $type::fromArray($data); } diff --git a/seed/php-model/any-auth/src/Placeholder/Placeholder.php b/seed/php-model/any-auth/src/Placeholder/Placeholder.php deleted file mode 100644 index a0eb33a6b60..00000000000 --- a/seed/php-model/any-auth/src/Placeholder/Placeholder.php +++ /dev/null @@ -1,11 +0,0 @@ -id = $id; + $this->name = $name; + } +} diff --git a/seed/php-model/api-wide-base-path/src/Core/SerializableType.php b/seed/php-model/api-wide-base-path/src/Core/SerializableType.php index 4bc3eda7bec..27c45fb74a1 100644 --- a/seed/php-model/api-wide-base-path/src/Core/SerializableType.php +++ b/seed/php-model/api-wide-base-path/src/Core/SerializableType.php @@ -14,8 +14,6 @@ abstract class SerializableType { /** * Serializes the object to a JSON string. - * - * @throws JsonException */ public function toJson(): string { @@ -35,6 +33,9 @@ public function toArray(): array foreach ($reflectionClass->getProperties() as $property) { $jsonKey = self::getJsonKey($property); + if ($jsonKey == null) { + continue; + } $value = $property->getValue($this); // Handle DateTime properties @@ -121,6 +122,10 @@ private static function serializeSingleValue(mixed $data, string $type): mixed return $type === 'date' ? $data->format(Constant::DateFormat) : $data->format(Constant::DateTimeFormat); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && $data instanceof $type) { if (method_exists($data, 'toArray')) { return $data->toArray(); @@ -178,12 +183,12 @@ private static function serializeList(array $data, array $type): array * Helper function to retrieve the JSON key for a property. * * @param ReflectionProperty $property - * @return string + * @return string|null */ - private static function getJsonKey(ReflectionProperty $property): string + private static function getJsonKey(ReflectionProperty $property): ?string { $jsonPropertyAttr = $property->getAttributes(JsonProperty::class)[0] ?? null; - return $jsonPropertyAttr ? $jsonPropertyAttr->newInstance()->name : $property->getName(); + return $jsonPropertyAttr?->newInstance()?->name; } /** @@ -261,7 +266,7 @@ public static function fromArray(array $data): static continue; } - $jsonKey = self::getJsonKey($property); + $jsonKey = self::getJsonKey($property) ?? $property->getName(); if (array_key_exists($jsonKey, $data)) { $value = $data[$jsonKey]; @@ -358,6 +363,10 @@ private static function deserializeSingleValue(mixed $data, string $type): mixed return new DateTime($data); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && is_array($data)) { return $type::fromArray($data); } diff --git a/seed/php-model/api-wide-base-path/src/Placeholder/Placeholder.php b/seed/php-model/api-wide-base-path/src/Placeholder/Placeholder.php deleted file mode 100644 index a0eb33a6b60..00000000000 --- a/seed/php-model/api-wide-base-path/src/Placeholder/Placeholder.php +++ /dev/null @@ -1,11 +0,0 @@ -getProperties() as $property) { $jsonKey = self::getJsonKey($property); + if ($jsonKey == null) { + continue; + } $value = $property->getValue($this); // Handle DateTime properties @@ -121,6 +122,10 @@ private static function serializeSingleValue(mixed $data, string $type): mixed return $type === 'date' ? $data->format(Constant::DateFormat) : $data->format(Constant::DateTimeFormat); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && $data instanceof $type) { if (method_exists($data, 'toArray')) { return $data->toArray(); @@ -178,12 +183,12 @@ private static function serializeList(array $data, array $type): array * Helper function to retrieve the JSON key for a property. * * @param ReflectionProperty $property - * @return string + * @return string|null */ - private static function getJsonKey(ReflectionProperty $property): string + private static function getJsonKey(ReflectionProperty $property): ?string { $jsonPropertyAttr = $property->getAttributes(JsonProperty::class)[0] ?? null; - return $jsonPropertyAttr ? $jsonPropertyAttr->newInstance()->name : $property->getName(); + return $jsonPropertyAttr?->newInstance()?->name; } /** @@ -261,7 +266,7 @@ public static function fromArray(array $data): static continue; } - $jsonKey = self::getJsonKey($property); + $jsonKey = self::getJsonKey($property) ?? $property->getName(); if (array_key_exists($jsonKey, $data)) { $value = $data[$jsonKey]; @@ -358,6 +363,10 @@ private static function deserializeSingleValue(mixed $data, string $type): mixed return new DateTime($data); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && is_array($data)) { return $type::fromArray($data); } diff --git a/seed/php-model/audiences/src/FolderA/Service/Response.php b/seed/php-model/audiences/src/FolderA/Service/Response.php new file mode 100644 index 00000000000..bec4495ad1d --- /dev/null +++ b/seed/php-model/audiences/src/FolderA/Service/Response.php @@ -0,0 +1,25 @@ +foo = $foo; + } +} diff --git a/seed/php-model/audiences/src/FolderB/Common/Foo.php b/seed/php-model/audiences/src/FolderB/Common/Foo.php new file mode 100644 index 00000000000..45cd98edae6 --- /dev/null +++ b/seed/php-model/audiences/src/FolderB/Common/Foo.php @@ -0,0 +1,25 @@ +foo = $foo; + } +} diff --git a/seed/php-model/audiences/src/FolderC/Common/FolderCFoo.php b/seed/php-model/audiences/src/FolderC/Common/FolderCFoo.php new file mode 100644 index 00000000000..22aa33cba8b --- /dev/null +++ b/seed/php-model/audiences/src/FolderC/Common/FolderCFoo.php @@ -0,0 +1,24 @@ +barProperty = $barProperty; + } +} diff --git a/seed/php-model/audiences/src/FolderD/Service/Response.php b/seed/php-model/audiences/src/FolderD/Service/Response.php new file mode 100644 index 00000000000..13fa0a4536c --- /dev/null +++ b/seed/php-model/audiences/src/FolderD/Service/Response.php @@ -0,0 +1,24 @@ +foo = $foo; + } +} diff --git a/seed/php-model/audiences/src/Foo/FilteredType.php b/seed/php-model/audiences/src/Foo/FilteredType.php new file mode 100644 index 00000000000..5b7885c9443 --- /dev/null +++ b/seed/php-model/audiences/src/Foo/FilteredType.php @@ -0,0 +1,33 @@ +privateProperty = $privateProperty; + $this->publicProperty = $publicProperty; + } +} diff --git a/seed/php-model/audiences/src/Foo/ImportingType.php b/seed/php-model/audiences/src/Foo/ImportingType.php new file mode 100644 index 00000000000..eb53f62ea95 --- /dev/null +++ b/seed/php-model/audiences/src/Foo/ImportingType.php @@ -0,0 +1,24 @@ +imported = $imported; + } +} diff --git a/seed/php-model/audiences/src/Placeholder/Placeholder.php b/seed/php-model/audiences/src/Placeholder/Placeholder.php deleted file mode 100644 index a0eb33a6b60..00000000000 --- a/seed/php-model/audiences/src/Placeholder/Placeholder.php +++ /dev/null @@ -1,11 +0,0 @@ -getProperties() as $property) { $jsonKey = self::getJsonKey($property); + if ($jsonKey == null) { + continue; + } $value = $property->getValue($this); // Handle DateTime properties @@ -121,6 +122,10 @@ private static function serializeSingleValue(mixed $data, string $type): mixed return $type === 'date' ? $data->format(Constant::DateFormat) : $data->format(Constant::DateTimeFormat); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && $data instanceof $type) { if (method_exists($data, 'toArray')) { return $data->toArray(); @@ -178,12 +183,12 @@ private static function serializeList(array $data, array $type): array * Helper function to retrieve the JSON key for a property. * * @param ReflectionProperty $property - * @return string + * @return string|null */ - private static function getJsonKey(ReflectionProperty $property): string + private static function getJsonKey(ReflectionProperty $property): ?string { $jsonPropertyAttr = $property->getAttributes(JsonProperty::class)[0] ?? null; - return $jsonPropertyAttr ? $jsonPropertyAttr->newInstance()->name : $property->getName(); + return $jsonPropertyAttr?->newInstance()?->name; } /** @@ -261,7 +266,7 @@ public static function fromArray(array $data): static continue; } - $jsonKey = self::getJsonKey($property); + $jsonKey = self::getJsonKey($property) ?? $property->getName(); if (array_key_exists($jsonKey, $data)) { $value = $data[$jsonKey]; @@ -358,6 +363,10 @@ private static function deserializeSingleValue(mixed $data, string $type): mixed return new DateTime($data); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && is_array($data)) { return $type::fromArray($data); } diff --git a/seed/php-model/auth-environment-variables/src/Placeholder/Placeholder.php b/seed/php-model/auth-environment-variables/src/Placeholder/Placeholder.php deleted file mode 100644 index a0eb33a6b60..00000000000 --- a/seed/php-model/auth-environment-variables/src/Placeholder/Placeholder.php +++ /dev/null @@ -1,11 +0,0 @@ -getProperties() as $property) { $jsonKey = self::getJsonKey($property); + if ($jsonKey == null) { + continue; + } $value = $property->getValue($this); // Handle DateTime properties @@ -121,6 +122,10 @@ private static function serializeSingleValue(mixed $data, string $type): mixed return $type === 'date' ? $data->format(Constant::DateFormat) : $data->format(Constant::DateTimeFormat); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && $data instanceof $type) { if (method_exists($data, 'toArray')) { return $data->toArray(); @@ -178,12 +183,12 @@ private static function serializeList(array $data, array $type): array * Helper function to retrieve the JSON key for a property. * * @param ReflectionProperty $property - * @return string + * @return string|null */ - private static function getJsonKey(ReflectionProperty $property): string + private static function getJsonKey(ReflectionProperty $property): ?string { $jsonPropertyAttr = $property->getAttributes(JsonProperty::class)[0] ?? null; - return $jsonPropertyAttr ? $jsonPropertyAttr->newInstance()->name : $property->getName(); + return $jsonPropertyAttr?->newInstance()?->name; } /** @@ -261,7 +266,7 @@ public static function fromArray(array $data): static continue; } - $jsonKey = self::getJsonKey($property); + $jsonKey = self::getJsonKey($property) ?? $property->getName(); if (array_key_exists($jsonKey, $data)) { $value = $data[$jsonKey]; @@ -358,6 +363,10 @@ private static function deserializeSingleValue(mixed $data, string $type): mixed return new DateTime($data); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && is_array($data)) { return $type::fromArray($data); } diff --git a/seed/php-model/basic-auth-environment-variables/src/Errors/UnauthorizedRequestErrorBody.php b/seed/php-model/basic-auth-environment-variables/src/Errors/UnauthorizedRequestErrorBody.php new file mode 100644 index 00000000000..aa7c78db7dc --- /dev/null +++ b/seed/php-model/basic-auth-environment-variables/src/Errors/UnauthorizedRequestErrorBody.php @@ -0,0 +1,24 @@ +message = $message; + } +} diff --git a/seed/php-model/basic-auth-environment-variables/src/Placeholder/Placeholder.php b/seed/php-model/basic-auth-environment-variables/src/Placeholder/Placeholder.php deleted file mode 100644 index a0eb33a6b60..00000000000 --- a/seed/php-model/basic-auth-environment-variables/src/Placeholder/Placeholder.php +++ /dev/null @@ -1,11 +0,0 @@ -getProperties() as $property) { $jsonKey = self::getJsonKey($property); + if ($jsonKey == null) { + continue; + } $value = $property->getValue($this); // Handle DateTime properties @@ -121,6 +122,10 @@ private static function serializeSingleValue(mixed $data, string $type): mixed return $type === 'date' ? $data->format(Constant::DateFormat) : $data->format(Constant::DateTimeFormat); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && $data instanceof $type) { if (method_exists($data, 'toArray')) { return $data->toArray(); @@ -178,12 +183,12 @@ private static function serializeList(array $data, array $type): array * Helper function to retrieve the JSON key for a property. * * @param ReflectionProperty $property - * @return string + * @return string|null */ - private static function getJsonKey(ReflectionProperty $property): string + private static function getJsonKey(ReflectionProperty $property): ?string { $jsonPropertyAttr = $property->getAttributes(JsonProperty::class)[0] ?? null; - return $jsonPropertyAttr ? $jsonPropertyAttr->newInstance()->name : $property->getName(); + return $jsonPropertyAttr?->newInstance()?->name; } /** @@ -261,7 +266,7 @@ public static function fromArray(array $data): static continue; } - $jsonKey = self::getJsonKey($property); + $jsonKey = self::getJsonKey($property) ?? $property->getName(); if (array_key_exists($jsonKey, $data)) { $value = $data[$jsonKey]; @@ -358,6 +363,10 @@ private static function deserializeSingleValue(mixed $data, string $type): mixed return new DateTime($data); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && is_array($data)) { return $type::fromArray($data); } diff --git a/seed/php-model/basic-auth/src/Errors/UnauthorizedRequestErrorBody.php b/seed/php-model/basic-auth/src/Errors/UnauthorizedRequestErrorBody.php new file mode 100644 index 00000000000..aa7c78db7dc --- /dev/null +++ b/seed/php-model/basic-auth/src/Errors/UnauthorizedRequestErrorBody.php @@ -0,0 +1,24 @@ +message = $message; + } +} diff --git a/seed/php-model/basic-auth/src/Placeholder/Placeholder.php b/seed/php-model/basic-auth/src/Placeholder/Placeholder.php deleted file mode 100644 index a0eb33a6b60..00000000000 --- a/seed/php-model/basic-auth/src/Placeholder/Placeholder.php +++ /dev/null @@ -1,11 +0,0 @@ -getProperties() as $property) { $jsonKey = self::getJsonKey($property); + if ($jsonKey == null) { + continue; + } $value = $property->getValue($this); // Handle DateTime properties @@ -121,6 +122,10 @@ private static function serializeSingleValue(mixed $data, string $type): mixed return $type === 'date' ? $data->format(Constant::DateFormat) : $data->format(Constant::DateTimeFormat); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && $data instanceof $type) { if (method_exists($data, 'toArray')) { return $data->toArray(); @@ -178,12 +183,12 @@ private static function serializeList(array $data, array $type): array * Helper function to retrieve the JSON key for a property. * * @param ReflectionProperty $property - * @return string + * @return string|null */ - private static function getJsonKey(ReflectionProperty $property): string + private static function getJsonKey(ReflectionProperty $property): ?string { $jsonPropertyAttr = $property->getAttributes(JsonProperty::class)[0] ?? null; - return $jsonPropertyAttr ? $jsonPropertyAttr->newInstance()->name : $property->getName(); + return $jsonPropertyAttr?->newInstance()?->name; } /** @@ -261,7 +266,7 @@ public static function fromArray(array $data): static continue; } - $jsonKey = self::getJsonKey($property); + $jsonKey = self::getJsonKey($property) ?? $property->getName(); if (array_key_exists($jsonKey, $data)) { $value = $data[$jsonKey]; @@ -358,6 +363,10 @@ private static function deserializeSingleValue(mixed $data, string $type): mixed return new DateTime($data); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && is_array($data)) { return $type::fromArray($data); } diff --git a/seed/php-model/bearer-token-environment-variable/src/Placeholder/Placeholder.php b/seed/php-model/bearer-token-environment-variable/src/Placeholder/Placeholder.php deleted file mode 100644 index a0eb33a6b60..00000000000 --- a/seed/php-model/bearer-token-environment-variable/src/Placeholder/Placeholder.php +++ /dev/null @@ -1,11 +0,0 @@ -getProperties() as $property) { $jsonKey = self::getJsonKey($property); + if ($jsonKey == null) { + continue; + } $value = $property->getValue($this); // Handle DateTime properties @@ -121,6 +122,10 @@ private static function serializeSingleValue(mixed $data, string $type): mixed return $type === 'date' ? $data->format(Constant::DateFormat) : $data->format(Constant::DateTimeFormat); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && $data instanceof $type) { if (method_exists($data, 'toArray')) { return $data->toArray(); @@ -178,12 +183,12 @@ private static function serializeList(array $data, array $type): array * Helper function to retrieve the JSON key for a property. * * @param ReflectionProperty $property - * @return string + * @return string|null */ - private static function getJsonKey(ReflectionProperty $property): string + private static function getJsonKey(ReflectionProperty $property): ?string { $jsonPropertyAttr = $property->getAttributes(JsonProperty::class)[0] ?? null; - return $jsonPropertyAttr ? $jsonPropertyAttr->newInstance()->name : $property->getName(); + return $jsonPropertyAttr?->newInstance()?->name; } /** @@ -261,7 +266,7 @@ public static function fromArray(array $data): static continue; } - $jsonKey = self::getJsonKey($property); + $jsonKey = self::getJsonKey($property) ?? $property->getName(); if (array_key_exists($jsonKey, $data)) { $value = $data[$jsonKey]; @@ -358,6 +363,10 @@ private static function deserializeSingleValue(mixed $data, string $type): mixed return new DateTime($data); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && is_array($data)) { return $type::fromArray($data); } diff --git a/seed/php-model/bytes/src/Placeholder/Placeholder.php b/seed/php-model/bytes/src/Placeholder/Placeholder.php deleted file mode 100644 index a0eb33a6b60..00000000000 --- a/seed/php-model/bytes/src/Placeholder/Placeholder.php +++ /dev/null @@ -1,11 +0,0 @@ -name = $name; + $this->value = $value; + } +} diff --git a/seed/php-model/circular-references-advanced/src/Ast/ObjectValue.php b/seed/php-model/circular-references-advanced/src/Ast/ObjectValue.php new file mode 100644 index 00000000000..50f09445f23 --- /dev/null +++ b/seed/php-model/circular-references-advanced/src/Ast/ObjectValue.php @@ -0,0 +1,12 @@ +getProperties() as $property) { $jsonKey = self::getJsonKey($property); + if ($jsonKey == null) { + continue; + } $value = $property->getValue($this); // Handle DateTime properties @@ -121,6 +122,10 @@ private static function serializeSingleValue(mixed $data, string $type): mixed return $type === 'date' ? $data->format(Constant::DateFormat) : $data->format(Constant::DateTimeFormat); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && $data instanceof $type) { if (method_exists($data, 'toArray')) { return $data->toArray(); @@ -178,12 +183,12 @@ private static function serializeList(array $data, array $type): array * Helper function to retrieve the JSON key for a property. * * @param ReflectionProperty $property - * @return string + * @return string|null */ - private static function getJsonKey(ReflectionProperty $property): string + private static function getJsonKey(ReflectionProperty $property): ?string { $jsonPropertyAttr = $property->getAttributes(JsonProperty::class)[0] ?? null; - return $jsonPropertyAttr ? $jsonPropertyAttr->newInstance()->name : $property->getName(); + return $jsonPropertyAttr?->newInstance()?->name; } /** @@ -261,7 +266,7 @@ public static function fromArray(array $data): static continue; } - $jsonKey = self::getJsonKey($property); + $jsonKey = self::getJsonKey($property) ?? $property->getName(); if (array_key_exists($jsonKey, $data)) { $value = $data[$jsonKey]; @@ -358,6 +363,10 @@ private static function deserializeSingleValue(mixed $data, string $type): mixed return new DateTime($data); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && is_array($data)) { return $type::fromArray($data); } diff --git a/seed/php-model/circular-references-advanced/src/ImportingA.php b/seed/php-model/circular-references-advanced/src/ImportingA.php new file mode 100644 index 00000000000..c8de0895882 --- /dev/null +++ b/seed/php-model/circular-references-advanced/src/ImportingA.php @@ -0,0 +1,25 @@ +a = $a; + } +} diff --git a/seed/php-model/circular-references-advanced/src/Placeholder/Placeholder.php b/seed/php-model/circular-references-advanced/src/Placeholder/Placeholder.php deleted file mode 100644 index a0eb33a6b60..00000000000 --- a/seed/php-model/circular-references-advanced/src/Placeholder/Placeholder.php +++ /dev/null @@ -1,11 +0,0 @@ -s = $s; + } +} diff --git a/seed/php-model/circular-references/src/A/A.php b/seed/php-model/circular-references/src/A/A.php new file mode 100644 index 00000000000..d8b13fcadac --- /dev/null +++ b/seed/php-model/circular-references/src/A/A.php @@ -0,0 +1,12 @@ +getProperties() as $property) { $jsonKey = self::getJsonKey($property); + if ($jsonKey == null) { + continue; + } $value = $property->getValue($this); // Handle DateTime properties @@ -121,6 +122,10 @@ private static function serializeSingleValue(mixed $data, string $type): mixed return $type === 'date' ? $data->format(Constant::DateFormat) : $data->format(Constant::DateTimeFormat); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && $data instanceof $type) { if (method_exists($data, 'toArray')) { return $data->toArray(); @@ -178,12 +183,12 @@ private static function serializeList(array $data, array $type): array * Helper function to retrieve the JSON key for a property. * * @param ReflectionProperty $property - * @return string + * @return string|null */ - private static function getJsonKey(ReflectionProperty $property): string + private static function getJsonKey(ReflectionProperty $property): ?string { $jsonPropertyAttr = $property->getAttributes(JsonProperty::class)[0] ?? null; - return $jsonPropertyAttr ? $jsonPropertyAttr->newInstance()->name : $property->getName(); + return $jsonPropertyAttr?->newInstance()?->name; } /** @@ -261,7 +266,7 @@ public static function fromArray(array $data): static continue; } - $jsonKey = self::getJsonKey($property); + $jsonKey = self::getJsonKey($property) ?? $property->getName(); if (array_key_exists($jsonKey, $data)) { $value = $data[$jsonKey]; @@ -358,6 +363,10 @@ private static function deserializeSingleValue(mixed $data, string $type): mixed return new DateTime($data); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && is_array($data)) { return $type::fromArray($data); } diff --git a/seed/php-model/circular-references/src/ImportingA.php b/seed/php-model/circular-references/src/ImportingA.php new file mode 100644 index 00000000000..c8de0895882 --- /dev/null +++ b/seed/php-model/circular-references/src/ImportingA.php @@ -0,0 +1,25 @@ +a = $a; + } +} diff --git a/seed/php-model/circular-references/src/Placeholder/Placeholder.php b/seed/php-model/circular-references/src/Placeholder/Placeholder.php deleted file mode 100644 index a0eb33a6b60..00000000000 --- a/seed/php-model/circular-references/src/Placeholder/Placeholder.php +++ /dev/null @@ -1,11 +0,0 @@ -s = $s; + } +} diff --git a/seed/php-model/cross-package-type-names/src/Core/SerializableType.php b/seed/php-model/cross-package-type-names/src/Core/SerializableType.php index 4bc3eda7bec..27c45fb74a1 100644 --- a/seed/php-model/cross-package-type-names/src/Core/SerializableType.php +++ b/seed/php-model/cross-package-type-names/src/Core/SerializableType.php @@ -14,8 +14,6 @@ abstract class SerializableType { /** * Serializes the object to a JSON string. - * - * @throws JsonException */ public function toJson(): string { @@ -35,6 +33,9 @@ public function toArray(): array foreach ($reflectionClass->getProperties() as $property) { $jsonKey = self::getJsonKey($property); + if ($jsonKey == null) { + continue; + } $value = $property->getValue($this); // Handle DateTime properties @@ -121,6 +122,10 @@ private static function serializeSingleValue(mixed $data, string $type): mixed return $type === 'date' ? $data->format(Constant::DateFormat) : $data->format(Constant::DateTimeFormat); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && $data instanceof $type) { if (method_exists($data, 'toArray')) { return $data->toArray(); @@ -178,12 +183,12 @@ private static function serializeList(array $data, array $type): array * Helper function to retrieve the JSON key for a property. * * @param ReflectionProperty $property - * @return string + * @return string|null */ - private static function getJsonKey(ReflectionProperty $property): string + private static function getJsonKey(ReflectionProperty $property): ?string { $jsonPropertyAttr = $property->getAttributes(JsonProperty::class)[0] ?? null; - return $jsonPropertyAttr ? $jsonPropertyAttr->newInstance()->name : $property->getName(); + return $jsonPropertyAttr?->newInstance()?->name; } /** @@ -261,7 +266,7 @@ public static function fromArray(array $data): static continue; } - $jsonKey = self::getJsonKey($property); + $jsonKey = self::getJsonKey($property) ?? $property->getName(); if (array_key_exists($jsonKey, $data)) { $value = $data[$jsonKey]; @@ -358,6 +363,10 @@ private static function deserializeSingleValue(mixed $data, string $type): mixed return new DateTime($data); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && is_array($data)) { return $type::fromArray($data); } diff --git a/seed/php-model/cross-package-type-names/src/FolderA/Service/Response.php b/seed/php-model/cross-package-type-names/src/FolderA/Service/Response.php new file mode 100644 index 00000000000..bec4495ad1d --- /dev/null +++ b/seed/php-model/cross-package-type-names/src/FolderA/Service/Response.php @@ -0,0 +1,25 @@ +foo = $foo; + } +} diff --git a/seed/php-model/cross-package-type-names/src/FolderB/Common/Foo.php b/seed/php-model/cross-package-type-names/src/FolderB/Common/Foo.php new file mode 100644 index 00000000000..be26b6f60ac --- /dev/null +++ b/seed/php-model/cross-package-type-names/src/FolderB/Common/Foo.php @@ -0,0 +1,25 @@ +foo = $foo; + } +} diff --git a/seed/php-model/cross-package-type-names/src/FolderC/Common/Foo.php b/seed/php-model/cross-package-type-names/src/FolderC/Common/Foo.php new file mode 100644 index 00000000000..ff1e8373b7e --- /dev/null +++ b/seed/php-model/cross-package-type-names/src/FolderC/Common/Foo.php @@ -0,0 +1,24 @@ +barProperty = $barProperty; + } +} diff --git a/seed/php-model/cross-package-type-names/src/FolderD/Service/Response.php b/seed/php-model/cross-package-type-names/src/FolderD/Service/Response.php new file mode 100644 index 00000000000..ea8b176a05d --- /dev/null +++ b/seed/php-model/cross-package-type-names/src/FolderD/Service/Response.php @@ -0,0 +1,25 @@ +foo = $foo; + } +} diff --git a/seed/php-model/cross-package-type-names/src/Foo/ImportingType.php b/seed/php-model/cross-package-type-names/src/Foo/ImportingType.php new file mode 100644 index 00000000000..eb53f62ea95 --- /dev/null +++ b/seed/php-model/cross-package-type-names/src/Foo/ImportingType.php @@ -0,0 +1,24 @@ +imported = $imported; + } +} diff --git a/seed/php-model/cross-package-type-names/src/Placeholder/Placeholder.php b/seed/php-model/cross-package-type-names/src/Placeholder/Placeholder.php deleted file mode 100644 index a0eb33a6b60..00000000000 --- a/seed/php-model/cross-package-type-names/src/Placeholder/Placeholder.php +++ /dev/null @@ -1,11 +0,0 @@ -getProperties() as $property) { $jsonKey = self::getJsonKey($property); + if ($jsonKey == null) { + continue; + } $value = $property->getValue($this); // Handle DateTime properties @@ -121,6 +122,10 @@ private static function serializeSingleValue(mixed $data, string $type): mixed return $type === 'date' ? $data->format(Constant::DateFormat) : $data->format(Constant::DateTimeFormat); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && $data instanceof $type) { if (method_exists($data, 'toArray')) { return $data->toArray(); @@ -178,12 +183,12 @@ private static function serializeList(array $data, array $type): array * Helper function to retrieve the JSON key for a property. * * @param ReflectionProperty $property - * @return string + * @return string|null */ - private static function getJsonKey(ReflectionProperty $property): string + private static function getJsonKey(ReflectionProperty $property): ?string { $jsonPropertyAttr = $property->getAttributes(JsonProperty::class)[0] ?? null; - return $jsonPropertyAttr ? $jsonPropertyAttr->newInstance()->name : $property->getName(); + return $jsonPropertyAttr?->newInstance()?->name; } /** @@ -261,7 +266,7 @@ public static function fromArray(array $data): static continue; } - $jsonKey = self::getJsonKey($property); + $jsonKey = self::getJsonKey($property) ?? $property->getName(); if (array_key_exists($jsonKey, $data)) { $value = $data[$jsonKey]; @@ -358,6 +363,10 @@ private static function deserializeSingleValue(mixed $data, string $type): mixed return new DateTime($data); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && is_array($data)) { return $type::fromArray($data); } diff --git a/seed/php-model/custom-auth/src/Errors/UnauthorizedRequestErrorBody.php b/seed/php-model/custom-auth/src/Errors/UnauthorizedRequestErrorBody.php new file mode 100644 index 00000000000..aa7c78db7dc --- /dev/null +++ b/seed/php-model/custom-auth/src/Errors/UnauthorizedRequestErrorBody.php @@ -0,0 +1,24 @@ +message = $message; + } +} diff --git a/seed/php-model/custom-auth/src/Placeholder/Placeholder.php b/seed/php-model/custom-auth/src/Placeholder/Placeholder.php deleted file mode 100644 index a0eb33a6b60..00000000000 --- a/seed/php-model/custom-auth/src/Placeholder/Placeholder.php +++ /dev/null @@ -1,11 +0,0 @@ -getProperties() as $property) { $jsonKey = self::getJsonKey($property); + if ($jsonKey == null) { + continue; + } $value = $property->getValue($this); // Handle DateTime properties @@ -121,6 +122,10 @@ private static function serializeSingleValue(mixed $data, string $type): mixed return $type === 'date' ? $data->format(Constant::DateFormat) : $data->format(Constant::DateTimeFormat); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && $data instanceof $type) { if (method_exists($data, 'toArray')) { return $data->toArray(); @@ -178,12 +183,12 @@ private static function serializeList(array $data, array $type): array * Helper function to retrieve the JSON key for a property. * * @param ReflectionProperty $property - * @return string + * @return string|null */ - private static function getJsonKey(ReflectionProperty $property): string + private static function getJsonKey(ReflectionProperty $property): ?string { $jsonPropertyAttr = $property->getAttributes(JsonProperty::class)[0] ?? null; - return $jsonPropertyAttr ? $jsonPropertyAttr->newInstance()->name : $property->getName(); + return $jsonPropertyAttr?->newInstance()?->name; } /** @@ -261,7 +266,7 @@ public static function fromArray(array $data): static continue; } - $jsonKey = self::getJsonKey($property); + $jsonKey = self::getJsonKey($property) ?? $property->getName(); if (array_key_exists($jsonKey, $data)) { $value = $data[$jsonKey]; @@ -358,6 +363,10 @@ private static function deserializeSingleValue(mixed $data, string $type): mixed return new DateTime($data); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && is_array($data)) { return $type::fromArray($data); } diff --git a/seed/php-model/enum/src/Operand.php b/seed/php-model/enum/src/Operand.php new file mode 100644 index 00000000000..f312669e799 --- /dev/null +++ b/seed/php-model/enum/src/Operand.php @@ -0,0 +1,10 @@ +"; + case EqualTo = "="; + case LessThan = "less_than"; +} diff --git a/seed/php-model/enum/src/Placeholder/Placeholder.php b/seed/php-model/enum/src/Placeholder/Placeholder.php deleted file mode 100644 index a0eb33a6b60..00000000000 --- a/seed/php-model/enum/src/Placeholder/Placeholder.php +++ /dev/null @@ -1,11 +0,0 @@ -getProperties() as $property) { $jsonKey = self::getJsonKey($property); + if ($jsonKey == null) { + continue; + } $value = $property->getValue($this); // Handle DateTime properties @@ -121,6 +122,10 @@ private static function serializeSingleValue(mixed $data, string $type): mixed return $type === 'date' ? $data->format(Constant::DateFormat) : $data->format(Constant::DateTimeFormat); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && $data instanceof $type) { if (method_exists($data, 'toArray')) { return $data->toArray(); @@ -178,12 +183,12 @@ private static function serializeList(array $data, array $type): array * Helper function to retrieve the JSON key for a property. * * @param ReflectionProperty $property - * @return string + * @return string|null */ - private static function getJsonKey(ReflectionProperty $property): string + private static function getJsonKey(ReflectionProperty $property): ?string { $jsonPropertyAttr = $property->getAttributes(JsonProperty::class)[0] ?? null; - return $jsonPropertyAttr ? $jsonPropertyAttr->newInstance()->name : $property->getName(); + return $jsonPropertyAttr?->newInstance()?->name; } /** @@ -261,7 +266,7 @@ public static function fromArray(array $data): static continue; } - $jsonKey = self::getJsonKey($property); + $jsonKey = self::getJsonKey($property) ?? $property->getName(); if (array_key_exists($jsonKey, $data)) { $value = $data[$jsonKey]; @@ -358,6 +363,10 @@ private static function deserializeSingleValue(mixed $data, string $type): mixed return new DateTime($data); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && is_array($data)) { return $type::fromArray($data); } diff --git a/seed/php-model/error-property/src/Errors/PropertyBasedErrorTestBody.php b/seed/php-model/error-property/src/Errors/PropertyBasedErrorTestBody.php new file mode 100644 index 00000000000..76baa41e601 --- /dev/null +++ b/seed/php-model/error-property/src/Errors/PropertyBasedErrorTestBody.php @@ -0,0 +1,24 @@ +message = $message; + } +} diff --git a/seed/php-model/error-property/src/Placeholder/Placeholder.php b/seed/php-model/error-property/src/Placeholder/Placeholder.php deleted file mode 100644 index a0eb33a6b60..00000000000 --- a/seed/php-model/error-property/src/Placeholder/Placeholder.php +++ /dev/null @@ -1,11 +0,0 @@ - "string"])] + /** + * @var ?array $data + */ + public ?array $data; + + #[JsonProperty("jsonString")] + /** + * @var ?string $jsonString + */ + public ?string $jsonString; + + /** + * @param string $id + * @param ?array $data + * @param ?string $jsonString + */ + public function __construct( + string $id, + ?array $data = null, + ?string $jsonString = null, + ) { + $this->id = $id; + $this->data = $data; + $this->jsonString = $jsonString; + } +} diff --git a/seed/php-model/examples/src/ComplexType.php b/seed/php-model/examples/src/ComplexType.php new file mode 100644 index 00000000000..496c3e20dca --- /dev/null +++ b/seed/php-model/examples/src/ComplexType.php @@ -0,0 +1,10 @@ +getProperties() as $property) { $jsonKey = self::getJsonKey($property); + if ($jsonKey == null) { + continue; + } $value = $property->getValue($this); // Handle DateTime properties @@ -121,6 +122,10 @@ private static function serializeSingleValue(mixed $data, string $type): mixed return $type === 'date' ? $data->format(Constant::DateFormat) : $data->format(Constant::DateTimeFormat); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && $data instanceof $type) { if (method_exists($data, 'toArray')) { return $data->toArray(); @@ -178,12 +183,12 @@ private static function serializeList(array $data, array $type): array * Helper function to retrieve the JSON key for a property. * * @param ReflectionProperty $property - * @return string + * @return string|null */ - private static function getJsonKey(ReflectionProperty $property): string + private static function getJsonKey(ReflectionProperty $property): ?string { $jsonPropertyAttr = $property->getAttributes(JsonProperty::class)[0] ?? null; - return $jsonPropertyAttr ? $jsonPropertyAttr->newInstance()->name : $property->getName(); + return $jsonPropertyAttr?->newInstance()?->name; } /** @@ -261,7 +266,7 @@ public static function fromArray(array $data): static continue; } - $jsonKey = self::getJsonKey($property); + $jsonKey = self::getJsonKey($property) ?? $property->getName(); if (array_key_exists($jsonKey, $data)) { $value = $data[$jsonKey]; @@ -358,6 +363,10 @@ private static function deserializeSingleValue(mixed $data, string $type): mixed return new DateTime($data); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && is_array($data)) { return $type::fromArray($data); } diff --git a/seed/php-model/examples/src/Identifier.php b/seed/php-model/examples/src/Identifier.php new file mode 100644 index 00000000000..354f1958847 --- /dev/null +++ b/seed/php-model/examples/src/Identifier.php @@ -0,0 +1,42 @@ +type = $type; + $this->value = $value; + $this->label = $label; + } +} diff --git a/seed/php-model/examples/src/Placeholder/Placeholder.php b/seed/php-model/examples/src/Placeholder/Placeholder.php deleted file mode 100644 index a0eb33a6b60..00000000000 --- a/seed/php-model/examples/src/Placeholder/Placeholder.php +++ /dev/null @@ -1,11 +0,0 @@ -name = $name; + $this->id = $id; + } +} diff --git a/seed/php-model/examples/src/Types/Actress.php b/seed/php-model/examples/src/Types/Actress.php new file mode 100644 index 00000000000..e45c06de25c --- /dev/null +++ b/seed/php-model/examples/src/Types/Actress.php @@ -0,0 +1,33 @@ +name = $name; + $this->id = $id; + } +} diff --git a/seed/php-model/examples/src/Types/Directory.php b/seed/php-model/examples/src/Types/Directory.php new file mode 100644 index 00000000000..188d78145c5 --- /dev/null +++ b/seed/php-model/examples/src/Types/Directory.php @@ -0,0 +1,45 @@ + $files + */ + public ?array $files; + + #[JsonProperty("directories"), ArrayType([Directory])] + /** + * @var ?array $directories + */ + public ?array $directories; + + /** + * @param string $name + * @param ?array $files + * @param ?array $directories + */ + public function __construct( + string $name, + ?array $files = null, + ?array $directories = null, + ) { + $this->name = $name; + $this->files = $files; + $this->directories = $directories; + } +} diff --git a/seed/php-model/examples/src/Types/Entity.php b/seed/php-model/examples/src/Types/Entity.php new file mode 100644 index 00000000000..cbe48ed3696 --- /dev/null +++ b/seed/php-model/examples/src/Types/Entity.php @@ -0,0 +1,33 @@ +type = $type; + $this->name = $name; + } +} diff --git a/seed/php-model/examples/src/Types/ExceptionInfo.php b/seed/php-model/examples/src/Types/ExceptionInfo.php new file mode 100644 index 00000000000..5227be39c92 --- /dev/null +++ b/seed/php-model/examples/src/Types/ExceptionInfo.php @@ -0,0 +1,42 @@ +exceptionType = $exceptionType; + $this->exceptionMessage = $exceptionMessage; + $this->exceptionStacktrace = $exceptionStacktrace; + } +} diff --git a/seed/php-model/examples/src/Types/ExtendedMovie.php b/seed/php-model/examples/src/Types/ExtendedMovie.php new file mode 100644 index 00000000000..98a666b8702 --- /dev/null +++ b/seed/php-model/examples/src/Types/ExtendedMovie.php @@ -0,0 +1,25 @@ + $cast + */ + public array $cast; + + /** + * @param array $cast + */ + public function __construct( + array $cast, + ) { + $this->cast = $cast; + } +} diff --git a/seed/php-model/examples/src/Types/File.php b/seed/php-model/examples/src/Types/File.php new file mode 100644 index 00000000000..23288175217 --- /dev/null +++ b/seed/php-model/examples/src/Types/File.php @@ -0,0 +1,33 @@ +name = $name; + $this->contents = $contents; + } +} diff --git a/seed/php-model/examples/src/Types/Migration.php b/seed/php-model/examples/src/Types/Migration.php new file mode 100644 index 00000000000..b771cb485d6 --- /dev/null +++ b/seed/php-model/examples/src/Types/Migration.php @@ -0,0 +1,34 @@ +name = $name; + $this->status = $status; + } +} diff --git a/seed/php-model/examples/src/Types/MigrationStatus.php b/seed/php-model/examples/src/Types/MigrationStatus.php new file mode 100644 index 00000000000..fa9c470de8a --- /dev/null +++ b/seed/php-model/examples/src/Types/MigrationStatus.php @@ -0,0 +1,10 @@ +id = $id; + $this->date = $date; + $this->datetime = $datetime; + } +} diff --git a/seed/php-model/examples/src/Types/Movie.php b/seed/php-model/examples/src/Types/Movie.php new file mode 100644 index 00000000000..5478c7049e8 --- /dev/null +++ b/seed/php-model/examples/src/Types/Movie.php @@ -0,0 +1,106 @@ + "mixed"])] + /** + * @var array $metadata + */ + public array $metadata; + + #[JsonProperty("revenue")] + /** + * @var int $revenue + */ + public int $revenue; + + #[JsonProperty("prequel")] + /** + * @var ?string $prequel + */ + public ?string $prequel; + + #[JsonProperty("book")] + /** + * @var ?string $book + */ + public ?string $book; + + /** + * @param string $id + * @param string $title + * @param string $from + * @param float $rating The rating scale is one to five stars + * @param string $type + * @param string $tag + * @param array $metadata + * @param int $revenue + * @param ?string $prequel + * @param ?string $book + */ + public function __construct( + string $id, + string $title, + string $from, + float $rating, + string $type, + string $tag, + array $metadata, + int $revenue, + ?string $prequel = null, + ?string $book = null, + ) { + $this->id = $id; + $this->title = $title; + $this->from = $from; + $this->rating = $rating; + $this->type = $type; + $this->tag = $tag; + $this->metadata = $metadata; + $this->revenue = $revenue; + $this->prequel = $prequel; + $this->book = $book; + } +} diff --git a/seed/php-model/examples/src/Types/Node.php b/seed/php-model/examples/src/Types/Node.php new file mode 100644 index 00000000000..f1fade16245 --- /dev/null +++ b/seed/php-model/examples/src/Types/Node.php @@ -0,0 +1,45 @@ + $nodes + */ + public ?array $nodes; + + #[JsonProperty("trees"), ArrayType([Tree])] + /** + * @var ?array $trees + */ + public ?array $trees; + + /** + * @param string $name + * @param ?array $nodes + * @param ?array $trees + */ + public function __construct( + string $name, + ?array $nodes = null, + ?array $trees = null, + ) { + $this->name = $name; + $this->nodes = $nodes; + $this->trees = $trees; + } +} diff --git a/seed/php-model/examples/src/Types/Request.php b/seed/php-model/examples/src/Types/Request.php new file mode 100644 index 00000000000..f7553278267 --- /dev/null +++ b/seed/php-model/examples/src/Types/Request.php @@ -0,0 +1,24 @@ +request = $request; + } +} diff --git a/seed/php-model/examples/src/Types/Response.php b/seed/php-model/examples/src/Types/Response.php new file mode 100644 index 00000000000..afe9ad4eb73 --- /dev/null +++ b/seed/php-model/examples/src/Types/Response.php @@ -0,0 +1,35 @@ + $identifiers + */ + public array $identifiers; + + /** + * @param mixed $response + * @param array $identifiers + */ + public function __construct( + mixed $response, + array $identifiers, + ) { + $this->response = $response; + $this->identifiers = $identifiers; + } +} diff --git a/seed/php-model/examples/src/Types/ResponseType.php b/seed/php-model/examples/src/Types/ResponseType.php new file mode 100644 index 00000000000..7740069aae7 --- /dev/null +++ b/seed/php-model/examples/src/Types/ResponseType.php @@ -0,0 +1,24 @@ +type = $type; + } +} diff --git a/seed/php-model/examples/src/Types/StuntDouble.php b/seed/php-model/examples/src/Types/StuntDouble.php new file mode 100644 index 00000000000..58d32427f2f --- /dev/null +++ b/seed/php-model/examples/src/Types/StuntDouble.php @@ -0,0 +1,33 @@ +name = $name; + $this->actorOrActressId = $actorOrActressId; + } +} diff --git a/seed/php-model/examples/src/Types/Tree.php b/seed/php-model/examples/src/Types/Tree.php new file mode 100644 index 00000000000..e79ad53a763 --- /dev/null +++ b/seed/php-model/examples/src/Types/Tree.php @@ -0,0 +1,26 @@ + $nodes + */ + public ?array $nodes; + + /** + * @param ?array $nodes + */ + public function __construct( + ?array $nodes = null, + ) { + $this->nodes = $nodes; + } +} diff --git a/seed/php-model/exhaustive/src/Core/SerializableType.php b/seed/php-model/exhaustive/src/Core/SerializableType.php index 4bc3eda7bec..27c45fb74a1 100644 --- a/seed/php-model/exhaustive/src/Core/SerializableType.php +++ b/seed/php-model/exhaustive/src/Core/SerializableType.php @@ -14,8 +14,6 @@ abstract class SerializableType { /** * Serializes the object to a JSON string. - * - * @throws JsonException */ public function toJson(): string { @@ -35,6 +33,9 @@ public function toArray(): array foreach ($reflectionClass->getProperties() as $property) { $jsonKey = self::getJsonKey($property); + if ($jsonKey == null) { + continue; + } $value = $property->getValue($this); // Handle DateTime properties @@ -121,6 +122,10 @@ private static function serializeSingleValue(mixed $data, string $type): mixed return $type === 'date' ? $data->format(Constant::DateFormat) : $data->format(Constant::DateTimeFormat); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && $data instanceof $type) { if (method_exists($data, 'toArray')) { return $data->toArray(); @@ -178,12 +183,12 @@ private static function serializeList(array $data, array $type): array * Helper function to retrieve the JSON key for a property. * * @param ReflectionProperty $property - * @return string + * @return string|null */ - private static function getJsonKey(ReflectionProperty $property): string + private static function getJsonKey(ReflectionProperty $property): ?string { $jsonPropertyAttr = $property->getAttributes(JsonProperty::class)[0] ?? null; - return $jsonPropertyAttr ? $jsonPropertyAttr->newInstance()->name : $property->getName(); + return $jsonPropertyAttr?->newInstance()?->name; } /** @@ -261,7 +266,7 @@ public static function fromArray(array $data): static continue; } - $jsonKey = self::getJsonKey($property); + $jsonKey = self::getJsonKey($property) ?? $property->getName(); if (array_key_exists($jsonKey, $data)) { $value = $data[$jsonKey]; @@ -358,6 +363,10 @@ private static function deserializeSingleValue(mixed $data, string $type): mixed return new DateTime($data); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && is_array($data)) { return $type::fromArray($data); } diff --git a/seed/php-model/exhaustive/src/GeneralErrors/BadObjectRequestInfo.php b/seed/php-model/exhaustive/src/GeneralErrors/BadObjectRequestInfo.php new file mode 100644 index 00000000000..e39bd916a01 --- /dev/null +++ b/seed/php-model/exhaustive/src/GeneralErrors/BadObjectRequestInfo.php @@ -0,0 +1,24 @@ +message = $message; + } +} diff --git a/seed/php-model/exhaustive/src/Placeholder/Placeholder.php b/seed/php-model/exhaustive/src/Placeholder/Placeholder.php deleted file mode 100644 index a0eb33a6b60..00000000000 --- a/seed/php-model/exhaustive/src/Placeholder/Placeholder.php +++ /dev/null @@ -1,11 +0,0 @@ -optionalAlias = $optionalAlias; + } +} diff --git a/seed/php-model/exhaustive/src/Types/Object/NestedObjectWithOptionalField.php b/seed/php-model/exhaustive/src/Types/Object/NestedObjectWithOptionalField.php new file mode 100644 index 00000000000..69aa908b11f --- /dev/null +++ b/seed/php-model/exhaustive/src/Types/Object/NestedObjectWithOptionalField.php @@ -0,0 +1,34 @@ +string = $string; + $this->nestedObject = $nestedObject; + } +} diff --git a/seed/php-model/exhaustive/src/Types/Object/NestedObjectWithRequiredField.php b/seed/php-model/exhaustive/src/Types/Object/NestedObjectWithRequiredField.php new file mode 100644 index 00000000000..3eb16e99a5d --- /dev/null +++ b/seed/php-model/exhaustive/src/Types/Object/NestedObjectWithRequiredField.php @@ -0,0 +1,34 @@ +string = $string; + $this->nestedObject = $nestedObject; + } +} diff --git a/seed/php-model/exhaustive/src/Types/Object/ObjectWithMapOfMap.php b/seed/php-model/exhaustive/src/Types/Object/ObjectWithMapOfMap.php new file mode 100644 index 00000000000..4f09fc2cd7c --- /dev/null +++ b/seed/php-model/exhaustive/src/Types/Object/ObjectWithMapOfMap.php @@ -0,0 +1,25 @@ + ["string" => "string"]])] + /** + * @var array> $map + */ + public array $map; + + /** + * @param array> $map + */ + public function __construct( + array $map, + ) { + $this->map = $map; + } +} diff --git a/seed/php-model/exhaustive/src/Types/Object/ObjectWithOptionalField.php b/seed/php-model/exhaustive/src/Types/Object/ObjectWithOptionalField.php new file mode 100644 index 00000000000..1c23973221f --- /dev/null +++ b/seed/php-model/exhaustive/src/Types/Object/ObjectWithOptionalField.php @@ -0,0 +1,135 @@ + $list + */ + public ?array $list; + + #[JsonProperty("set"), ArrayType(["string"])] + /** + * @var ?array $set + */ + public ?array $set; + + #[JsonProperty("map"), ArrayType(["integer" => "string"])] + /** + * @var ?array $map + */ + public ?array $map; + + #[JsonProperty("bigint")] + /** + * @var ?string $bigint + */ + public ?string $bigint; + + /** + * @param ?string $string This is a rather long descriptor of this single field in a more complex type. If you ask me I think this is a pretty good description for this field all things considered. + * @param ?int $integer + * @param ?int $long + * @param ?float $double + * @param ?bool $bool + * @param ?DateTime $datetime + * @param ?DateTime $date + * @param ?string $uuid + * @param ?string $base64 + * @param ?array $list + * @param ?array $set + * @param ?array $map + * @param ?string $bigint + */ + public function __construct( + ?string $string = null, + ?int $integer = null, + ?int $long = null, + ?float $double = null, + ?bool $bool = null, + ?DateTime $datetime = null, + ?DateTime $date = null, + ?string $uuid = null, + ?string $base64 = null, + ?array $list = null, + ?array $set = null, + ?array $map = null, + ?string $bigint = null, + ) { + $this->string = $string; + $this->integer = $integer; + $this->long = $long; + $this->double = $double; + $this->bool = $bool; + $this->datetime = $datetime; + $this->date = $date; + $this->uuid = $uuid; + $this->base64 = $base64; + $this->list = $list; + $this->set = $set; + $this->map = $map; + $this->bigint = $bigint; + } +} diff --git a/seed/php-model/exhaustive/src/Types/Object/ObjectWithRequiredField.php b/seed/php-model/exhaustive/src/Types/Object/ObjectWithRequiredField.php new file mode 100644 index 00000000000..8b5b9edb476 --- /dev/null +++ b/seed/php-model/exhaustive/src/Types/Object/ObjectWithRequiredField.php @@ -0,0 +1,24 @@ +string = $string; + } +} diff --git a/seed/php-model/exhaustive/src/Types/Union/Cat.php b/seed/php-model/exhaustive/src/Types/Union/Cat.php new file mode 100644 index 00000000000..e122393da6b --- /dev/null +++ b/seed/php-model/exhaustive/src/Types/Union/Cat.php @@ -0,0 +1,33 @@ +name = $name; + $this->likesToMeow = $likesToMeow; + } +} diff --git a/seed/php-model/exhaustive/src/Types/Union/Dog.php b/seed/php-model/exhaustive/src/Types/Union/Dog.php new file mode 100644 index 00000000000..fac513d631f --- /dev/null +++ b/seed/php-model/exhaustive/src/Types/Union/Dog.php @@ -0,0 +1,33 @@ +name = $name; + $this->likesToWoof = $likesToWoof; + } +} diff --git a/seed/php-model/extends/src/Core/SerializableType.php b/seed/php-model/extends/src/Core/SerializableType.php index 4bc3eda7bec..27c45fb74a1 100644 --- a/seed/php-model/extends/src/Core/SerializableType.php +++ b/seed/php-model/extends/src/Core/SerializableType.php @@ -14,8 +14,6 @@ abstract class SerializableType { /** * Serializes the object to a JSON string. - * - * @throws JsonException */ public function toJson(): string { @@ -35,6 +33,9 @@ public function toArray(): array foreach ($reflectionClass->getProperties() as $property) { $jsonKey = self::getJsonKey($property); + if ($jsonKey == null) { + continue; + } $value = $property->getValue($this); // Handle DateTime properties @@ -121,6 +122,10 @@ private static function serializeSingleValue(mixed $data, string $type): mixed return $type === 'date' ? $data->format(Constant::DateFormat) : $data->format(Constant::DateTimeFormat); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && $data instanceof $type) { if (method_exists($data, 'toArray')) { return $data->toArray(); @@ -178,12 +183,12 @@ private static function serializeList(array $data, array $type): array * Helper function to retrieve the JSON key for a property. * * @param ReflectionProperty $property - * @return string + * @return string|null */ - private static function getJsonKey(ReflectionProperty $property): string + private static function getJsonKey(ReflectionProperty $property): ?string { $jsonPropertyAttr = $property->getAttributes(JsonProperty::class)[0] ?? null; - return $jsonPropertyAttr ? $jsonPropertyAttr->newInstance()->name : $property->getName(); + return $jsonPropertyAttr?->newInstance()?->name; } /** @@ -261,7 +266,7 @@ public static function fromArray(array $data): static continue; } - $jsonKey = self::getJsonKey($property); + $jsonKey = self::getJsonKey($property) ?? $property->getName(); if (array_key_exists($jsonKey, $data)) { $value = $data[$jsonKey]; @@ -358,6 +363,10 @@ private static function deserializeSingleValue(mixed $data, string $type): mixed return new DateTime($data); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && is_array($data)) { return $type::fromArray($data); } diff --git a/seed/php-model/extends/src/Docs.php b/seed/php-model/extends/src/Docs.php new file mode 100644 index 00000000000..6ea28c53cd0 --- /dev/null +++ b/seed/php-model/extends/src/Docs.php @@ -0,0 +1,24 @@ +docs = $docs; + } +} diff --git a/seed/php-model/extends/src/ExampleType.php b/seed/php-model/extends/src/ExampleType.php new file mode 100644 index 00000000000..6bcd4963984 --- /dev/null +++ b/seed/php-model/extends/src/ExampleType.php @@ -0,0 +1,24 @@ +name = $name; + } +} diff --git a/seed/php-model/extends/src/Json.php b/seed/php-model/extends/src/Json.php new file mode 100644 index 00000000000..72cd39ab859 --- /dev/null +++ b/seed/php-model/extends/src/Json.php @@ -0,0 +1,24 @@ +raw = $raw; + } +} diff --git a/seed/php-model/extends/src/NestedType.php b/seed/php-model/extends/src/NestedType.php new file mode 100644 index 00000000000..b58be5c61b5 --- /dev/null +++ b/seed/php-model/extends/src/NestedType.php @@ -0,0 +1,24 @@ +name = $name; + } +} diff --git a/seed/php-model/extends/src/Placeholder/Placeholder.php b/seed/php-model/extends/src/Placeholder/Placeholder.php deleted file mode 100644 index a0eb33a6b60..00000000000 --- a/seed/php-model/extends/src/Placeholder/Placeholder.php +++ /dev/null @@ -1,11 +0,0 @@ -getProperties() as $property) { $jsonKey = self::getJsonKey($property); + if ($jsonKey == null) { + continue; + } $value = $property->getValue($this); // Handle DateTime properties @@ -121,6 +122,10 @@ private static function serializeSingleValue(mixed $data, string $type): mixed return $type === 'date' ? $data->format(Constant::DateFormat) : $data->format(Constant::DateTimeFormat); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && $data instanceof $type) { if (method_exists($data, 'toArray')) { return $data->toArray(); @@ -178,12 +183,12 @@ private static function serializeList(array $data, array $type): array * Helper function to retrieve the JSON key for a property. * * @param ReflectionProperty $property - * @return string + * @return string|null */ - private static function getJsonKey(ReflectionProperty $property): string + private static function getJsonKey(ReflectionProperty $property): ?string { $jsonPropertyAttr = $property->getAttributes(JsonProperty::class)[0] ?? null; - return $jsonPropertyAttr ? $jsonPropertyAttr->newInstance()->name : $property->getName(); + return $jsonPropertyAttr?->newInstance()?->name; } /** @@ -261,7 +266,7 @@ public static function fromArray(array $data): static continue; } - $jsonKey = self::getJsonKey($property); + $jsonKey = self::getJsonKey($property) ?? $property->getName(); if (array_key_exists($jsonKey, $data)) { $value = $data[$jsonKey]; @@ -358,6 +363,10 @@ private static function deserializeSingleValue(mixed $data, string $type): mixed return new DateTime($data); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && is_array($data)) { return $type::fromArray($data); } diff --git a/seed/php-model/extra-properties/src/Failure.php b/seed/php-model/extra-properties/src/Failure.php new file mode 100644 index 00000000000..8da3db70676 --- /dev/null +++ b/seed/php-model/extra-properties/src/Failure.php @@ -0,0 +1,24 @@ +status = $status; + } +} diff --git a/seed/php-model/extra-properties/src/Placeholder/Placeholder.php b/seed/php-model/extra-properties/src/Placeholder/Placeholder.php deleted file mode 100644 index a0eb33a6b60..00000000000 --- a/seed/php-model/extra-properties/src/Placeholder/Placeholder.php +++ /dev/null @@ -1,11 +0,0 @@ -name = $name; + } +} diff --git a/seed/php-model/file-download/src/Core/SerializableType.php b/seed/php-model/file-download/src/Core/SerializableType.php index 4bc3eda7bec..27c45fb74a1 100644 --- a/seed/php-model/file-download/src/Core/SerializableType.php +++ b/seed/php-model/file-download/src/Core/SerializableType.php @@ -14,8 +14,6 @@ abstract class SerializableType { /** * Serializes the object to a JSON string. - * - * @throws JsonException */ public function toJson(): string { @@ -35,6 +33,9 @@ public function toArray(): array foreach ($reflectionClass->getProperties() as $property) { $jsonKey = self::getJsonKey($property); + if ($jsonKey == null) { + continue; + } $value = $property->getValue($this); // Handle DateTime properties @@ -121,6 +122,10 @@ private static function serializeSingleValue(mixed $data, string $type): mixed return $type === 'date' ? $data->format(Constant::DateFormat) : $data->format(Constant::DateTimeFormat); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && $data instanceof $type) { if (method_exists($data, 'toArray')) { return $data->toArray(); @@ -178,12 +183,12 @@ private static function serializeList(array $data, array $type): array * Helper function to retrieve the JSON key for a property. * * @param ReflectionProperty $property - * @return string + * @return string|null */ - private static function getJsonKey(ReflectionProperty $property): string + private static function getJsonKey(ReflectionProperty $property): ?string { $jsonPropertyAttr = $property->getAttributes(JsonProperty::class)[0] ?? null; - return $jsonPropertyAttr ? $jsonPropertyAttr->newInstance()->name : $property->getName(); + return $jsonPropertyAttr?->newInstance()?->name; } /** @@ -261,7 +266,7 @@ public static function fromArray(array $data): static continue; } - $jsonKey = self::getJsonKey($property); + $jsonKey = self::getJsonKey($property) ?? $property->getName(); if (array_key_exists($jsonKey, $data)) { $value = $data[$jsonKey]; @@ -358,6 +363,10 @@ private static function deserializeSingleValue(mixed $data, string $type): mixed return new DateTime($data); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && is_array($data)) { return $type::fromArray($data); } diff --git a/seed/php-model/file-download/src/Placeholder/Placeholder.php b/seed/php-model/file-download/src/Placeholder/Placeholder.php deleted file mode 100644 index a0eb33a6b60..00000000000 --- a/seed/php-model/file-download/src/Placeholder/Placeholder.php +++ /dev/null @@ -1,11 +0,0 @@ -getProperties() as $property) { $jsonKey = self::getJsonKey($property); + if ($jsonKey == null) { + continue; + } $value = $property->getValue($this); // Handle DateTime properties @@ -121,6 +122,10 @@ private static function serializeSingleValue(mixed $data, string $type): mixed return $type === 'date' ? $data->format(Constant::DateFormat) : $data->format(Constant::DateTimeFormat); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && $data instanceof $type) { if (method_exists($data, 'toArray')) { return $data->toArray(); @@ -178,12 +183,12 @@ private static function serializeList(array $data, array $type): array * Helper function to retrieve the JSON key for a property. * * @param ReflectionProperty $property - * @return string + * @return string|null */ - private static function getJsonKey(ReflectionProperty $property): string + private static function getJsonKey(ReflectionProperty $property): ?string { $jsonPropertyAttr = $property->getAttributes(JsonProperty::class)[0] ?? null; - return $jsonPropertyAttr ? $jsonPropertyAttr->newInstance()->name : $property->getName(); + return $jsonPropertyAttr?->newInstance()?->name; } /** @@ -261,7 +266,7 @@ public static function fromArray(array $data): static continue; } - $jsonKey = self::getJsonKey($property); + $jsonKey = self::getJsonKey($property) ?? $property->getName(); if (array_key_exists($jsonKey, $data)) { $value = $data[$jsonKey]; @@ -358,6 +363,10 @@ private static function deserializeSingleValue(mixed $data, string $type): mixed return new DateTime($data); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && is_array($data)) { return $type::fromArray($data); } diff --git a/seed/php-model/file-upload/src/Placeholder/Placeholder.php b/seed/php-model/file-upload/src/Placeholder/Placeholder.php deleted file mode 100644 index a0eb33a6b60..00000000000 --- a/seed/php-model/file-upload/src/Placeholder/Placeholder.php +++ /dev/null @@ -1,11 +0,0 @@ -foo = $foo; + } +} diff --git a/seed/php-model/file-upload/src/Service/ObjectType.php b/seed/php-model/file-upload/src/Service/ObjectType.php new file mode 100644 index 00000000000..562d9570d7f --- /dev/null +++ b/seed/php-model/file-upload/src/Service/ObjectType.php @@ -0,0 +1,9 @@ +getProperties() as $property) { $jsonKey = self::getJsonKey($property); + if ($jsonKey == null) { + continue; + } $value = $property->getValue($this); // Handle DateTime properties @@ -121,6 +122,10 @@ private static function serializeSingleValue(mixed $data, string $type): mixed return $type === 'date' ? $data->format(Constant::DateFormat) : $data->format(Constant::DateTimeFormat); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && $data instanceof $type) { if (method_exists($data, 'toArray')) { return $data->toArray(); @@ -178,12 +183,12 @@ private static function serializeList(array $data, array $type): array * Helper function to retrieve the JSON key for a property. * * @param ReflectionProperty $property - * @return string + * @return string|null */ - private static function getJsonKey(ReflectionProperty $property): string + private static function getJsonKey(ReflectionProperty $property): ?string { $jsonPropertyAttr = $property->getAttributes(JsonProperty::class)[0] ?? null; - return $jsonPropertyAttr ? $jsonPropertyAttr->newInstance()->name : $property->getName(); + return $jsonPropertyAttr?->newInstance()?->name; } /** @@ -261,7 +266,7 @@ public static function fromArray(array $data): static continue; } - $jsonKey = self::getJsonKey($property); + $jsonKey = self::getJsonKey($property) ?? $property->getName(); if (array_key_exists($jsonKey, $data)) { $value = $data[$jsonKey]; @@ -358,6 +363,10 @@ private static function deserializeSingleValue(mixed $data, string $type): mixed return new DateTime($data); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && is_array($data)) { return $type::fromArray($data); } diff --git a/seed/php-model/folders/src/Placeholder/Placeholder.php b/seed/php-model/folders/src/Placeholder/Placeholder.php deleted file mode 100644 index a0eb33a6b60..00000000000 --- a/seed/php-model/folders/src/Placeholder/Placeholder.php +++ /dev/null @@ -1,11 +0,0 @@ - $values + */ + public array $values; + + #[JsonProperty("metadata")] + /** + * @var mixed $metadata + */ + public mixed $metadata; + + #[JsonProperty("indexedData")] + /** + * @var ?IndexedData $indexedData + */ + public ?IndexedData $indexedData; + + /** + * @param string $id + * @param array $values + * @param mixed $metadata + * @param ?IndexedData $indexedData + */ + public function __construct( + string $id, + array $values, + mixed $metadata, + ?IndexedData $indexedData = null, + ) { + $this->id = $id; + $this->values = $values; + $this->metadata = $metadata; + $this->indexedData = $indexedData; + } +} diff --git a/seed/php-model/grpc-proto-exhaustive/src/Core/SerializableType.php b/seed/php-model/grpc-proto-exhaustive/src/Core/SerializableType.php index 4bc3eda7bec..27c45fb74a1 100644 --- a/seed/php-model/grpc-proto-exhaustive/src/Core/SerializableType.php +++ b/seed/php-model/grpc-proto-exhaustive/src/Core/SerializableType.php @@ -14,8 +14,6 @@ abstract class SerializableType { /** * Serializes the object to a JSON string. - * - * @throws JsonException */ public function toJson(): string { @@ -35,6 +33,9 @@ public function toArray(): array foreach ($reflectionClass->getProperties() as $property) { $jsonKey = self::getJsonKey($property); + if ($jsonKey == null) { + continue; + } $value = $property->getValue($this); // Handle DateTime properties @@ -121,6 +122,10 @@ private static function serializeSingleValue(mixed $data, string $type): mixed return $type === 'date' ? $data->format(Constant::DateFormat) : $data->format(Constant::DateTimeFormat); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && $data instanceof $type) { if (method_exists($data, 'toArray')) { return $data->toArray(); @@ -178,12 +183,12 @@ private static function serializeList(array $data, array $type): array * Helper function to retrieve the JSON key for a property. * * @param ReflectionProperty $property - * @return string + * @return string|null */ - private static function getJsonKey(ReflectionProperty $property): string + private static function getJsonKey(ReflectionProperty $property): ?string { $jsonPropertyAttr = $property->getAttributes(JsonProperty::class)[0] ?? null; - return $jsonPropertyAttr ? $jsonPropertyAttr->newInstance()->name : $property->getName(); + return $jsonPropertyAttr?->newInstance()?->name; } /** @@ -261,7 +266,7 @@ public static function fromArray(array $data): static continue; } - $jsonKey = self::getJsonKey($property); + $jsonKey = self::getJsonKey($property) ?? $property->getName(); if (array_key_exists($jsonKey, $data)) { $value = $data[$jsonKey]; @@ -358,6 +363,10 @@ private static function deserializeSingleValue(mixed $data, string $type): mixed return new DateTime($data); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && is_array($data)) { return $type::fromArray($data); } diff --git a/seed/php-model/grpc-proto-exhaustive/src/DeleteResponse.php b/seed/php-model/grpc-proto-exhaustive/src/DeleteResponse.php new file mode 100644 index 00000000000..e9bef4c8c86 --- /dev/null +++ b/seed/php-model/grpc-proto-exhaustive/src/DeleteResponse.php @@ -0,0 +1,12 @@ + NamespaceSummary])] + /** + * @var ?array $namespaces + */ + public ?array $namespaces; + + #[JsonProperty("dimension")] + /** + * @var ?int $dimension + */ + public ?int $dimension; + + #[JsonProperty("fullness")] + /** + * @var ?float $fullness + */ + public ?float $fullness; + + #[JsonProperty("totalCount")] + /** + * @var ?int $totalCount + */ + public ?int $totalCount; + + /** + * @param ?array $namespaces + * @param ?int $dimension + * @param ?float $fullness + * @param ?int $totalCount + */ + public function __construct( + ?array $namespaces = null, + ?int $dimension = null, + ?float $fullness = null, + ?int $totalCount = null, + ) { + $this->namespaces = $namespaces; + $this->dimension = $dimension; + $this->fullness = $fullness; + $this->totalCount = $totalCount; + } +} diff --git a/seed/php-model/grpc-proto-exhaustive/src/FetchResponse.php b/seed/php-model/grpc-proto-exhaustive/src/FetchResponse.php new file mode 100644 index 00000000000..27e29279e9d --- /dev/null +++ b/seed/php-model/grpc-proto-exhaustive/src/FetchResponse.php @@ -0,0 +1,45 @@ + Column])] + /** + * @var ?array $columns + */ + public ?array $columns; + + #[JsonProperty("namespace")] + /** + * @var ?string $namespace + */ + public ?string $namespace; + + #[JsonProperty("usage")] + /** + * @var ?Usage $usage + */ + public ?Usage $usage; + + /** + * @param ?array $columns + * @param ?string $namespace + * @param ?Usage $usage + */ + public function __construct( + ?array $columns = null, + ?string $namespace = null, + ?Usage $usage = null, + ) { + $this->columns = $columns; + $this->namespace = $namespace; + $this->usage = $usage; + } +} diff --git a/seed/php-model/grpc-proto-exhaustive/src/IndexedData.php b/seed/php-model/grpc-proto-exhaustive/src/IndexedData.php new file mode 100644 index 00000000000..f5144138748 --- /dev/null +++ b/seed/php-model/grpc-proto-exhaustive/src/IndexedData.php @@ -0,0 +1,34 @@ + $indices + */ + public array $indices; + + #[JsonProperty("values"), ArrayType(["float"])] + /** + * @var array $values + */ + public array $values; + + /** + * @param array $indices + * @param array $values + */ + public function __construct( + array $indices, + array $values, + ) { + $this->indices = $indices; + $this->values = $values; + } +} diff --git a/seed/php-model/grpc-proto-exhaustive/src/ListElement.php b/seed/php-model/grpc-proto-exhaustive/src/ListElement.php new file mode 100644 index 00000000000..a9e9f765666 --- /dev/null +++ b/seed/php-model/grpc-proto-exhaustive/src/ListElement.php @@ -0,0 +1,24 @@ +id = $id; + } +} diff --git a/seed/php-model/grpc-proto-exhaustive/src/ListResponse.php b/seed/php-model/grpc-proto-exhaustive/src/ListResponse.php new file mode 100644 index 00000000000..64cdfdd0706 --- /dev/null +++ b/seed/php-model/grpc-proto-exhaustive/src/ListResponse.php @@ -0,0 +1,55 @@ + $columns + */ + public ?array $columns; + + #[JsonProperty("pagination")] + /** + * @var ?Pagination $pagination + */ + public ?Pagination $pagination; + + #[JsonProperty("namespace")] + /** + * @var ?string $namespace + */ + public ?string $namespace; + + #[JsonProperty("usage")] + /** + * @var ?Usage $usage + */ + public ?Usage $usage; + + /** + * @param ?array $columns + * @param ?Pagination $pagination + * @param ?string $namespace + * @param ?Usage $usage + */ + public function __construct( + ?array $columns = null, + ?Pagination $pagination = null, + ?string $namespace = null, + ?Usage $usage = null, + ) { + $this->columns = $columns; + $this->pagination = $pagination; + $this->namespace = $namespace; + $this->usage = $usage; + } +} diff --git a/seed/php-model/grpc-proto-exhaustive/src/NamespaceSummary.php b/seed/php-model/grpc-proto-exhaustive/src/NamespaceSummary.php new file mode 100644 index 00000000000..7160a3e91a7 --- /dev/null +++ b/seed/php-model/grpc-proto-exhaustive/src/NamespaceSummary.php @@ -0,0 +1,24 @@ +count = $count; + } +} diff --git a/seed/php-model/grpc-proto-exhaustive/src/Pagination.php b/seed/php-model/grpc-proto-exhaustive/src/Pagination.php new file mode 100644 index 00000000000..ba829b6ea7b --- /dev/null +++ b/seed/php-model/grpc-proto-exhaustive/src/Pagination.php @@ -0,0 +1,24 @@ +next = $next; + } +} diff --git a/seed/php-model/grpc-proto-exhaustive/src/Placeholder/Placeholder.php b/seed/php-model/grpc-proto-exhaustive/src/Placeholder/Placeholder.php deleted file mode 100644 index a0eb33a6b60..00000000000 --- a/seed/php-model/grpc-proto-exhaustive/src/Placeholder/Placeholder.php +++ /dev/null @@ -1,11 +0,0 @@ - $values + */ + public array $values; + + #[JsonProperty("topK")] + /** + * @var ?int $topK + */ + public ?int $topK; + + #[JsonProperty("namespace")] + /** + * @var ?string $namespace + */ + public ?string $namespace; + + #[JsonProperty("filter")] + /** + * @var mixed $filter + */ + public mixed $filter; + + #[JsonProperty("indexedData")] + /** + * @var ?IndexedData $indexedData + */ + public ?IndexedData $indexedData; + + /** + * @param array $values + * @param ?int $topK + * @param ?string $namespace + * @param mixed $filter + * @param ?IndexedData $indexedData + */ + public function __construct( + array $values, + ?int $topK = null, + ?string $namespace = null, + mixed $filter, + ?IndexedData $indexedData = null, + ) { + $this->values = $values; + $this->topK = $topK; + $this->namespace = $namespace; + $this->filter = $filter; + $this->indexedData = $indexedData; + } +} diff --git a/seed/php-model/grpc-proto-exhaustive/src/QueryResponse.php b/seed/php-model/grpc-proto-exhaustive/src/QueryResponse.php new file mode 100644 index 00000000000..31ffca40b22 --- /dev/null +++ b/seed/php-model/grpc-proto-exhaustive/src/QueryResponse.php @@ -0,0 +1,55 @@ + $results + */ + public ?array $results; + + #[JsonProperty("matches"), ArrayType([ScoredColumn])] + /** + * @var ?array $matches + */ + public ?array $matches; + + #[JsonProperty("namespace")] + /** + * @var ?string $namespace + */ + public ?string $namespace; + + #[JsonProperty("usage")] + /** + * @var ?Usage $usage + */ + public ?Usage $usage; + + /** + * @param ?array $results + * @param ?array $matches + * @param ?string $namespace + * @param ?Usage $usage + */ + public function __construct( + ?array $results = null, + ?array $matches = null, + ?string $namespace = null, + ?Usage $usage = null, + ) { + $this->results = $results; + $this->matches = $matches; + $this->namespace = $namespace; + $this->usage = $usage; + } +} diff --git a/seed/php-model/grpc-proto-exhaustive/src/QueryResult.php b/seed/php-model/grpc-proto-exhaustive/src/QueryResult.php new file mode 100644 index 00000000000..3368ffe6966 --- /dev/null +++ b/seed/php-model/grpc-proto-exhaustive/src/QueryResult.php @@ -0,0 +1,35 @@ + $matches + */ + public ?array $matches; + + #[JsonProperty("namespace")] + /** + * @var ?string $namespace + */ + public ?string $namespace; + + /** + * @param ?array $matches + * @param ?string $namespace + */ + public function __construct( + ?array $matches = null, + ?string $namespace = null, + ) { + $this->matches = $matches; + $this->namespace = $namespace; + } +} diff --git a/seed/php-model/grpc-proto-exhaustive/src/ScoredColumn.php b/seed/php-model/grpc-proto-exhaustive/src/ScoredColumn.php new file mode 100644 index 00000000000..595ade6afec --- /dev/null +++ b/seed/php-model/grpc-proto-exhaustive/src/ScoredColumn.php @@ -0,0 +1,62 @@ + $values + */ + public ?array $values; + + #[JsonProperty("metadata")] + /** + * @var mixed $metadata + */ + public mixed $metadata; + + #[JsonProperty("indexedData")] + /** + * @var ?IndexedData $indexedData + */ + public ?IndexedData $indexedData; + + /** + * @param string $id + * @param ?float $score + * @param ?array $values + * @param mixed $metadata + * @param ?IndexedData $indexedData + */ + public function __construct( + string $id, + ?float $score = null, + ?array $values = null, + mixed $metadata, + ?IndexedData $indexedData = null, + ) { + $this->id = $id; + $this->score = $score; + $this->values = $values; + $this->metadata = $metadata; + $this->indexedData = $indexedData; + } +} diff --git a/seed/php-model/grpc-proto-exhaustive/src/UpdateResponse.php b/seed/php-model/grpc-proto-exhaustive/src/UpdateResponse.php new file mode 100644 index 00000000000..c5c2a0c5ab9 --- /dev/null +++ b/seed/php-model/grpc-proto-exhaustive/src/UpdateResponse.php @@ -0,0 +1,12 @@ +count = $count; + } +} diff --git a/seed/php-model/grpc-proto-exhaustive/src/Usage.php b/seed/php-model/grpc-proto-exhaustive/src/Usage.php new file mode 100644 index 00000000000..3456a5c7dc1 --- /dev/null +++ b/seed/php-model/grpc-proto-exhaustive/src/Usage.php @@ -0,0 +1,24 @@ +units = $units; + } +} diff --git a/seed/php-model/grpc-proto/src/Core/SerializableType.php b/seed/php-model/grpc-proto/src/Core/SerializableType.php index 4bc3eda7bec..27c45fb74a1 100644 --- a/seed/php-model/grpc-proto/src/Core/SerializableType.php +++ b/seed/php-model/grpc-proto/src/Core/SerializableType.php @@ -14,8 +14,6 @@ abstract class SerializableType { /** * Serializes the object to a JSON string. - * - * @throws JsonException */ public function toJson(): string { @@ -35,6 +33,9 @@ public function toArray(): array foreach ($reflectionClass->getProperties() as $property) { $jsonKey = self::getJsonKey($property); + if ($jsonKey == null) { + continue; + } $value = $property->getValue($this); // Handle DateTime properties @@ -121,6 +122,10 @@ private static function serializeSingleValue(mixed $data, string $type): mixed return $type === 'date' ? $data->format(Constant::DateFormat) : $data->format(Constant::DateTimeFormat); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && $data instanceof $type) { if (method_exists($data, 'toArray')) { return $data->toArray(); @@ -178,12 +183,12 @@ private static function serializeList(array $data, array $type): array * Helper function to retrieve the JSON key for a property. * * @param ReflectionProperty $property - * @return string + * @return string|null */ - private static function getJsonKey(ReflectionProperty $property): string + private static function getJsonKey(ReflectionProperty $property): ?string { $jsonPropertyAttr = $property->getAttributes(JsonProperty::class)[0] ?? null; - return $jsonPropertyAttr ? $jsonPropertyAttr->newInstance()->name : $property->getName(); + return $jsonPropertyAttr?->newInstance()?->name; } /** @@ -261,7 +266,7 @@ public static function fromArray(array $data): static continue; } - $jsonKey = self::getJsonKey($property); + $jsonKey = self::getJsonKey($property) ?? $property->getName(); if (array_key_exists($jsonKey, $data)) { $value = $data[$jsonKey]; @@ -358,6 +363,10 @@ private static function deserializeSingleValue(mixed $data, string $type): mixed return new DateTime($data); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && is_array($data)) { return $type::fromArray($data); } diff --git a/seed/php-model/grpc-proto/src/CreateResponse.php b/seed/php-model/grpc-proto/src/CreateResponse.php new file mode 100644 index 00000000000..20b4f753837 --- /dev/null +++ b/seed/php-model/grpc-proto/src/CreateResponse.php @@ -0,0 +1,25 @@ +user = $user; + } +} diff --git a/seed/php-model/grpc-proto/src/Placeholder/Placeholder.php b/seed/php-model/grpc-proto/src/Placeholder/Placeholder.php deleted file mode 100644 index a0eb33a6b60..00000000000 --- a/seed/php-model/grpc-proto/src/Placeholder/Placeholder.php +++ /dev/null @@ -1,11 +0,0 @@ -username = $username; + $this->email = $email; + $this->age = $age; + $this->weight = $weight; + $this->metadata = $metadata; + } +} diff --git a/seed/php-model/idempotency-headers/src/Core/SerializableType.php b/seed/php-model/idempotency-headers/src/Core/SerializableType.php index 4bc3eda7bec..27c45fb74a1 100644 --- a/seed/php-model/idempotency-headers/src/Core/SerializableType.php +++ b/seed/php-model/idempotency-headers/src/Core/SerializableType.php @@ -14,8 +14,6 @@ abstract class SerializableType { /** * Serializes the object to a JSON string. - * - * @throws JsonException */ public function toJson(): string { @@ -35,6 +33,9 @@ public function toArray(): array foreach ($reflectionClass->getProperties() as $property) { $jsonKey = self::getJsonKey($property); + if ($jsonKey == null) { + continue; + } $value = $property->getValue($this); // Handle DateTime properties @@ -121,6 +122,10 @@ private static function serializeSingleValue(mixed $data, string $type): mixed return $type === 'date' ? $data->format(Constant::DateFormat) : $data->format(Constant::DateTimeFormat); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && $data instanceof $type) { if (method_exists($data, 'toArray')) { return $data->toArray(); @@ -178,12 +183,12 @@ private static function serializeList(array $data, array $type): array * Helper function to retrieve the JSON key for a property. * * @param ReflectionProperty $property - * @return string + * @return string|null */ - private static function getJsonKey(ReflectionProperty $property): string + private static function getJsonKey(ReflectionProperty $property): ?string { $jsonPropertyAttr = $property->getAttributes(JsonProperty::class)[0] ?? null; - return $jsonPropertyAttr ? $jsonPropertyAttr->newInstance()->name : $property->getName(); + return $jsonPropertyAttr?->newInstance()?->name; } /** @@ -261,7 +266,7 @@ public static function fromArray(array $data): static continue; } - $jsonKey = self::getJsonKey($property); + $jsonKey = self::getJsonKey($property) ?? $property->getName(); if (array_key_exists($jsonKey, $data)) { $value = $data[$jsonKey]; @@ -358,6 +363,10 @@ private static function deserializeSingleValue(mixed $data, string $type): mixed return new DateTime($data); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && is_array($data)) { return $type::fromArray($data); } diff --git a/seed/php-model/idempotency-headers/src/Payment/Currency.php b/seed/php-model/idempotency-headers/src/Payment/Currency.php new file mode 100644 index 00000000000..efdf732c496 --- /dev/null +++ b/seed/php-model/idempotency-headers/src/Payment/Currency.php @@ -0,0 +1,9 @@ +getProperties() as $property) { $jsonKey = self::getJsonKey($property); + if ($jsonKey == null) { + continue; + } $value = $property->getValue($this); // Handle DateTime properties @@ -121,6 +122,10 @@ private static function serializeSingleValue(mixed $data, string $type): mixed return $type === 'date' ? $data->format(Constant::DateFormat) : $data->format(Constant::DateTimeFormat); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && $data instanceof $type) { if (method_exists($data, 'toArray')) { return $data->toArray(); @@ -178,12 +183,12 @@ private static function serializeList(array $data, array $type): array * Helper function to retrieve the JSON key for a property. * * @param ReflectionProperty $property - * @return string + * @return string|null */ - private static function getJsonKey(ReflectionProperty $property): string + private static function getJsonKey(ReflectionProperty $property): ?string { $jsonPropertyAttr = $property->getAttributes(JsonProperty::class)[0] ?? null; - return $jsonPropertyAttr ? $jsonPropertyAttr->newInstance()->name : $property->getName(); + return $jsonPropertyAttr?->newInstance()?->name; } /** @@ -261,7 +266,7 @@ public static function fromArray(array $data): static continue; } - $jsonKey = self::getJsonKey($property); + $jsonKey = self::getJsonKey($property) ?? $property->getName(); if (array_key_exists($jsonKey, $data)) { $value = $data[$jsonKey]; @@ -358,6 +363,10 @@ private static function deserializeSingleValue(mixed $data, string $type): mixed return new DateTime($data); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && is_array($data)) { return $type::fromArray($data); } diff --git a/seed/php-sdk/imdb/src/Seed/Types/CreateMovieRequest.php b/seed/php-model/imdb/src/Imdb/CreateMovieRequest.php similarity index 57% rename from seed/php-sdk/imdb/src/Seed/Types/CreateMovieRequest.php rename to seed/php-model/imdb/src/Imdb/CreateMovieRequest.php index 3f7f8cd0584..235bc57efd2 100644 --- a/seed/php-sdk/imdb/src/Seed/Types/CreateMovieRequest.php +++ b/seed/php-model/imdb/src/Imdb/CreateMovieRequest.php @@ -1,18 +1,23 @@ getProperties() as $property) { $jsonKey = self::getJsonKey($property); + if ($jsonKey == null) { + continue; + } $value = $property->getValue($this); // Handle DateTime properties @@ -121,6 +122,10 @@ private static function serializeSingleValue(mixed $data, string $type): mixed return $type === 'date' ? $data->format(Constant::DateFormat) : $data->format(Constant::DateTimeFormat); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && $data instanceof $type) { if (method_exists($data, 'toArray')) { return $data->toArray(); @@ -178,12 +183,12 @@ private static function serializeList(array $data, array $type): array * Helper function to retrieve the JSON key for a property. * * @param ReflectionProperty $property - * @return string + * @return string|null */ - private static function getJsonKey(ReflectionProperty $property): string + private static function getJsonKey(ReflectionProperty $property): ?string { $jsonPropertyAttr = $property->getAttributes(JsonProperty::class)[0] ?? null; - return $jsonPropertyAttr ? $jsonPropertyAttr->newInstance()->name : $property->getName(); + return $jsonPropertyAttr?->newInstance()?->name; } /** @@ -261,7 +266,7 @@ public static function fromArray(array $data): static continue; } - $jsonKey = self::getJsonKey($property); + $jsonKey = self::getJsonKey($property) ?? $property->getName(); if (array_key_exists($jsonKey, $data)) { $value = $data[$jsonKey]; @@ -358,6 +363,10 @@ private static function deserializeSingleValue(mixed $data, string $type): mixed return new DateTime($data); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && is_array($data)) { return $type::fromArray($data); } diff --git a/seed/php-model/literal/src/Inlined/ANestedLiteral.php b/seed/php-model/literal/src/Inlined/ANestedLiteral.php new file mode 100644 index 00000000000..a2dba02f47e --- /dev/null +++ b/seed/php-model/literal/src/Inlined/ANestedLiteral.php @@ -0,0 +1,24 @@ +myLiteral = $myLiteral; + } +} diff --git a/seed/php-model/literal/src/Inlined/ATopLevelLiteral.php b/seed/php-model/literal/src/Inlined/ATopLevelLiteral.php new file mode 100644 index 00000000000..4b71ecf5c5c --- /dev/null +++ b/seed/php-model/literal/src/Inlined/ATopLevelLiteral.php @@ -0,0 +1,25 @@ +nestedLiteral = $nestedLiteral; + } +} diff --git a/seed/php-model/literal/src/Placeholder/Placeholder.php b/seed/php-model/literal/src/Placeholder/Placeholder.php deleted file mode 100644 index a0eb33a6b60..00000000000 --- a/seed/php-model/literal/src/Placeholder/Placeholder.php +++ /dev/null @@ -1,11 +0,0 @@ -prompt = $prompt; + $this->query = $query; + $this->stream = $stream; + $this->context = $context; + $this->maybeContext = $maybeContext; + } +} diff --git a/seed/php-model/literal/src/SendResponse.php b/seed/php-model/literal/src/SendResponse.php new file mode 100644 index 00000000000..8bba47a0df4 --- /dev/null +++ b/seed/php-model/literal/src/SendResponse.php @@ -0,0 +1,42 @@ +message = $message; + $this->status = $status; + $this->success = $success; + } +} diff --git a/seed/php-model/mixed-case/src/Core/SerializableType.php b/seed/php-model/mixed-case/src/Core/SerializableType.php index 4bc3eda7bec..27c45fb74a1 100644 --- a/seed/php-model/mixed-case/src/Core/SerializableType.php +++ b/seed/php-model/mixed-case/src/Core/SerializableType.php @@ -14,8 +14,6 @@ abstract class SerializableType { /** * Serializes the object to a JSON string. - * - * @throws JsonException */ public function toJson(): string { @@ -35,6 +33,9 @@ public function toArray(): array foreach ($reflectionClass->getProperties() as $property) { $jsonKey = self::getJsonKey($property); + if ($jsonKey == null) { + continue; + } $value = $property->getValue($this); // Handle DateTime properties @@ -121,6 +122,10 @@ private static function serializeSingleValue(mixed $data, string $type): mixed return $type === 'date' ? $data->format(Constant::DateFormat) : $data->format(Constant::DateTimeFormat); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && $data instanceof $type) { if (method_exists($data, 'toArray')) { return $data->toArray(); @@ -178,12 +183,12 @@ private static function serializeList(array $data, array $type): array * Helper function to retrieve the JSON key for a property. * * @param ReflectionProperty $property - * @return string + * @return string|null */ - private static function getJsonKey(ReflectionProperty $property): string + private static function getJsonKey(ReflectionProperty $property): ?string { $jsonPropertyAttr = $property->getAttributes(JsonProperty::class)[0] ?? null; - return $jsonPropertyAttr ? $jsonPropertyAttr->newInstance()->name : $property->getName(); + return $jsonPropertyAttr?->newInstance()?->name; } /** @@ -261,7 +266,7 @@ public static function fromArray(array $data): static continue; } - $jsonKey = self::getJsonKey($property); + $jsonKey = self::getJsonKey($property) ?? $property->getName(); if (array_key_exists($jsonKey, $data)) { $value = $data[$jsonKey]; @@ -358,6 +363,10 @@ private static function deserializeSingleValue(mixed $data, string $type): mixed return new DateTime($data); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && is_array($data)) { return $type::fromArray($data); } diff --git a/seed/php-model/mixed-case/src/Placeholder/Placeholder.php b/seed/php-model/mixed-case/src/Placeholder/Placeholder.php deleted file mode 100644 index a0eb33a6b60..00000000000 --- a/seed/php-model/mixed-case/src/Placeholder/Placeholder.php +++ /dev/null @@ -1,11 +0,0 @@ -name = $name; + $this->nestedUser = $nestedUser; + } +} diff --git a/seed/php-model/mixed-case/src/Service/Organization.php b/seed/php-model/mixed-case/src/Service/Organization.php new file mode 100644 index 00000000000..d8ec430dacf --- /dev/null +++ b/seed/php-model/mixed-case/src/Service/Organization.php @@ -0,0 +1,24 @@ +name = $name; + } +} diff --git a/seed/php-model/mixed-case/src/Service/ResourceStatus.php b/seed/php-model/mixed-case/src/Service/ResourceStatus.php new file mode 100644 index 00000000000..906f67dd9e0 --- /dev/null +++ b/seed/php-model/mixed-case/src/Service/ResourceStatus.php @@ -0,0 +1,9 @@ + $metadataTags + */ + public array $metadataTags; + + #[JsonProperty("EXTRA_PROPERTIES"), ArrayType(["string" => "string"])] + /** + * @var array $extraProperties + */ + public array $extraProperties; + + /** + * @param string $userName + * @param array $metadataTags + * @param array $extraProperties + */ + public function __construct( + string $userName, + array $metadataTags, + array $extraProperties, + ) { + $this->userName = $userName; + $this->metadataTags = $metadataTags; + $this->extraProperties = $extraProperties; + } +} diff --git a/seed/php-model/mixed-file-directory/src/Core/SerializableType.php b/seed/php-model/mixed-file-directory/src/Core/SerializableType.php index 4bc3eda7bec..27c45fb74a1 100644 --- a/seed/php-model/mixed-file-directory/src/Core/SerializableType.php +++ b/seed/php-model/mixed-file-directory/src/Core/SerializableType.php @@ -14,8 +14,6 @@ abstract class SerializableType { /** * Serializes the object to a JSON string. - * - * @throws JsonException */ public function toJson(): string { @@ -35,6 +33,9 @@ public function toArray(): array foreach ($reflectionClass->getProperties() as $property) { $jsonKey = self::getJsonKey($property); + if ($jsonKey == null) { + continue; + } $value = $property->getValue($this); // Handle DateTime properties @@ -121,6 +122,10 @@ private static function serializeSingleValue(mixed $data, string $type): mixed return $type === 'date' ? $data->format(Constant::DateFormat) : $data->format(Constant::DateTimeFormat); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && $data instanceof $type) { if (method_exists($data, 'toArray')) { return $data->toArray(); @@ -178,12 +183,12 @@ private static function serializeList(array $data, array $type): array * Helper function to retrieve the JSON key for a property. * * @param ReflectionProperty $property - * @return string + * @return string|null */ - private static function getJsonKey(ReflectionProperty $property): string + private static function getJsonKey(ReflectionProperty $property): ?string { $jsonPropertyAttr = $property->getAttributes(JsonProperty::class)[0] ?? null; - return $jsonPropertyAttr ? $jsonPropertyAttr->newInstance()->name : $property->getName(); + return $jsonPropertyAttr?->newInstance()?->name; } /** @@ -261,7 +266,7 @@ public static function fromArray(array $data): static continue; } - $jsonKey = self::getJsonKey($property); + $jsonKey = self::getJsonKey($property) ?? $property->getName(); if (array_key_exists($jsonKey, $data)) { $value = $data[$jsonKey]; @@ -358,6 +363,10 @@ private static function deserializeSingleValue(mixed $data, string $type): mixed return new DateTime($data); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && is_array($data)) { return $type::fromArray($data); } diff --git a/seed/php-model/mixed-file-directory/src/Organization/CreateOrganizationRequest.php b/seed/php-model/mixed-file-directory/src/Organization/CreateOrganizationRequest.php new file mode 100644 index 00000000000..884663b567c --- /dev/null +++ b/seed/php-model/mixed-file-directory/src/Organization/CreateOrganizationRequest.php @@ -0,0 +1,24 @@ +name = $name; + } +} diff --git a/seed/php-model/mixed-file-directory/src/Organization/Organization.php b/seed/php-model/mixed-file-directory/src/Organization/Organization.php new file mode 100644 index 00000000000..601b84197a8 --- /dev/null +++ b/seed/php-model/mixed-file-directory/src/Organization/Organization.php @@ -0,0 +1,44 @@ + $users + */ + public array $users; + + /** + * @param string $id + * @param string $name + * @param array $users + */ + public function __construct( + string $id, + string $name, + array $users, + ) { + $this->id = $id; + $this->name = $name; + $this->users = $users; + } +} diff --git a/seed/php-model/mixed-file-directory/src/Placeholder/Placeholder.php b/seed/php-model/mixed-file-directory/src/Placeholder/Placeholder.php deleted file mode 100644 index a0eb33a6b60..00000000000 --- a/seed/php-model/mixed-file-directory/src/Placeholder/Placeholder.php +++ /dev/null @@ -1,11 +0,0 @@ -id = $id; + $this->name = $name; + } +} diff --git a/seed/php-model/mixed-file-directory/src/User/Events/Metadata/Metadata.php b/seed/php-model/mixed-file-directory/src/User/Events/Metadata/Metadata.php new file mode 100644 index 00000000000..a2f4077952a --- /dev/null +++ b/seed/php-model/mixed-file-directory/src/User/Events/Metadata/Metadata.php @@ -0,0 +1,33 @@ +id = $id; + $this->value = $value; + } +} diff --git a/seed/php-model/mixed-file-directory/src/User/User.php b/seed/php-model/mixed-file-directory/src/User/User.php new file mode 100644 index 00000000000..f51f594d683 --- /dev/null +++ b/seed/php-model/mixed-file-directory/src/User/User.php @@ -0,0 +1,42 @@ +id = $id; + $this->name = $name; + $this->age = $age; + } +} diff --git a/seed/php-model/multi-line-docs/src/Core/SerializableType.php b/seed/php-model/multi-line-docs/src/Core/SerializableType.php index 4bc3eda7bec..27c45fb74a1 100644 --- a/seed/php-model/multi-line-docs/src/Core/SerializableType.php +++ b/seed/php-model/multi-line-docs/src/Core/SerializableType.php @@ -14,8 +14,6 @@ abstract class SerializableType { /** * Serializes the object to a JSON string. - * - * @throws JsonException */ public function toJson(): string { @@ -35,6 +33,9 @@ public function toArray(): array foreach ($reflectionClass->getProperties() as $property) { $jsonKey = self::getJsonKey($property); + if ($jsonKey == null) { + continue; + } $value = $property->getValue($this); // Handle DateTime properties @@ -121,6 +122,10 @@ private static function serializeSingleValue(mixed $data, string $type): mixed return $type === 'date' ? $data->format(Constant::DateFormat) : $data->format(Constant::DateTimeFormat); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && $data instanceof $type) { if (method_exists($data, 'toArray')) { return $data->toArray(); @@ -178,12 +183,12 @@ private static function serializeList(array $data, array $type): array * Helper function to retrieve the JSON key for a property. * * @param ReflectionProperty $property - * @return string + * @return string|null */ - private static function getJsonKey(ReflectionProperty $property): string + private static function getJsonKey(ReflectionProperty $property): ?string { $jsonPropertyAttr = $property->getAttributes(JsonProperty::class)[0] ?? null; - return $jsonPropertyAttr ? $jsonPropertyAttr->newInstance()->name : $property->getName(); + return $jsonPropertyAttr?->newInstance()?->name; } /** @@ -261,7 +266,7 @@ public static function fromArray(array $data): static continue; } - $jsonKey = self::getJsonKey($property); + $jsonKey = self::getJsonKey($property) ?? $property->getName(); if (array_key_exists($jsonKey, $data)) { $value = $data[$jsonKey]; @@ -358,6 +363,10 @@ private static function deserializeSingleValue(mixed $data, string $type): mixed return new DateTime($data); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && is_array($data)) { return $type::fromArray($data); } diff --git a/seed/php-model/multi-line-docs/src/Operand.php b/seed/php-model/multi-line-docs/src/Operand.php new file mode 100644 index 00000000000..f312669e799 --- /dev/null +++ b/seed/php-model/multi-line-docs/src/Operand.php @@ -0,0 +1,10 @@ +"; + case EqualTo = "="; + case LessThan = "less_than"; +} diff --git a/seed/php-model/multi-line-docs/src/Placeholder/Placeholder.php b/seed/php-model/multi-line-docs/src/Placeholder/Placeholder.php deleted file mode 100644 index a0eb33a6b60..00000000000 --- a/seed/php-model/multi-line-docs/src/Placeholder/Placeholder.php +++ /dev/null @@ -1,11 +0,0 @@ -id = $id; + $this->name = $name; + $this->age = $age; + } +} diff --git a/seed/php-model/multi-url-environment-no-default/src/Core/SerializableType.php b/seed/php-model/multi-url-environment-no-default/src/Core/SerializableType.php index 4bc3eda7bec..27c45fb74a1 100644 --- a/seed/php-model/multi-url-environment-no-default/src/Core/SerializableType.php +++ b/seed/php-model/multi-url-environment-no-default/src/Core/SerializableType.php @@ -14,8 +14,6 @@ abstract class SerializableType { /** * Serializes the object to a JSON string. - * - * @throws JsonException */ public function toJson(): string { @@ -35,6 +33,9 @@ public function toArray(): array foreach ($reflectionClass->getProperties() as $property) { $jsonKey = self::getJsonKey($property); + if ($jsonKey == null) { + continue; + } $value = $property->getValue($this); // Handle DateTime properties @@ -121,6 +122,10 @@ private static function serializeSingleValue(mixed $data, string $type): mixed return $type === 'date' ? $data->format(Constant::DateFormat) : $data->format(Constant::DateTimeFormat); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && $data instanceof $type) { if (method_exists($data, 'toArray')) { return $data->toArray(); @@ -178,12 +183,12 @@ private static function serializeList(array $data, array $type): array * Helper function to retrieve the JSON key for a property. * * @param ReflectionProperty $property - * @return string + * @return string|null */ - private static function getJsonKey(ReflectionProperty $property): string + private static function getJsonKey(ReflectionProperty $property): ?string { $jsonPropertyAttr = $property->getAttributes(JsonProperty::class)[0] ?? null; - return $jsonPropertyAttr ? $jsonPropertyAttr->newInstance()->name : $property->getName(); + return $jsonPropertyAttr?->newInstance()?->name; } /** @@ -261,7 +266,7 @@ public static function fromArray(array $data): static continue; } - $jsonKey = self::getJsonKey($property); + $jsonKey = self::getJsonKey($property) ?? $property->getName(); if (array_key_exists($jsonKey, $data)) { $value = $data[$jsonKey]; @@ -358,6 +363,10 @@ private static function deserializeSingleValue(mixed $data, string $type): mixed return new DateTime($data); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && is_array($data)) { return $type::fromArray($data); } diff --git a/seed/php-model/multi-url-environment-no-default/src/Placeholder/Placeholder.php b/seed/php-model/multi-url-environment-no-default/src/Placeholder/Placeholder.php deleted file mode 100644 index a0eb33a6b60..00000000000 --- a/seed/php-model/multi-url-environment-no-default/src/Placeholder/Placeholder.php +++ /dev/null @@ -1,11 +0,0 @@ -getProperties() as $property) { $jsonKey = self::getJsonKey($property); + if ($jsonKey == null) { + continue; + } $value = $property->getValue($this); // Handle DateTime properties @@ -121,6 +122,10 @@ private static function serializeSingleValue(mixed $data, string $type): mixed return $type === 'date' ? $data->format(Constant::DateFormat) : $data->format(Constant::DateTimeFormat); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && $data instanceof $type) { if (method_exists($data, 'toArray')) { return $data->toArray(); @@ -178,12 +183,12 @@ private static function serializeList(array $data, array $type): array * Helper function to retrieve the JSON key for a property. * * @param ReflectionProperty $property - * @return string + * @return string|null */ - private static function getJsonKey(ReflectionProperty $property): string + private static function getJsonKey(ReflectionProperty $property): ?string { $jsonPropertyAttr = $property->getAttributes(JsonProperty::class)[0] ?? null; - return $jsonPropertyAttr ? $jsonPropertyAttr->newInstance()->name : $property->getName(); + return $jsonPropertyAttr?->newInstance()?->name; } /** @@ -261,7 +266,7 @@ public static function fromArray(array $data): static continue; } - $jsonKey = self::getJsonKey($property); + $jsonKey = self::getJsonKey($property) ?? $property->getName(); if (array_key_exists($jsonKey, $data)) { $value = $data[$jsonKey]; @@ -358,6 +363,10 @@ private static function deserializeSingleValue(mixed $data, string $type): mixed return new DateTime($data); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && is_array($data)) { return $type::fromArray($data); } diff --git a/seed/php-model/multi-url-environment/src/Placeholder/Placeholder.php b/seed/php-model/multi-url-environment/src/Placeholder/Placeholder.php deleted file mode 100644 index a0eb33a6b60..00000000000 --- a/seed/php-model/multi-url-environment/src/Placeholder/Placeholder.php +++ /dev/null @@ -1,11 +0,0 @@ -getProperties() as $property) { $jsonKey = self::getJsonKey($property); + if ($jsonKey == null) { + continue; + } $value = $property->getValue($this); // Handle DateTime properties @@ -121,6 +122,10 @@ private static function serializeSingleValue(mixed $data, string $type): mixed return $type === 'date' ? $data->format(Constant::DateFormat) : $data->format(Constant::DateTimeFormat); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && $data instanceof $type) { if (method_exists($data, 'toArray')) { return $data->toArray(); @@ -178,12 +183,12 @@ private static function serializeList(array $data, array $type): array * Helper function to retrieve the JSON key for a property. * * @param ReflectionProperty $property - * @return string + * @return string|null */ - private static function getJsonKey(ReflectionProperty $property): string + private static function getJsonKey(ReflectionProperty $property): ?string { $jsonPropertyAttr = $property->getAttributes(JsonProperty::class)[0] ?? null; - return $jsonPropertyAttr ? $jsonPropertyAttr->newInstance()->name : $property->getName(); + return $jsonPropertyAttr?->newInstance()?->name; } /** @@ -261,7 +266,7 @@ public static function fromArray(array $data): static continue; } - $jsonKey = self::getJsonKey($property); + $jsonKey = self::getJsonKey($property) ?? $property->getName(); if (array_key_exists($jsonKey, $data)) { $value = $data[$jsonKey]; @@ -358,6 +363,10 @@ private static function deserializeSingleValue(mixed $data, string $type): mixed return new DateTime($data); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && is_array($data)) { return $type::fromArray($data); } diff --git a/seed/php-model/no-environment/src/Placeholder/Placeholder.php b/seed/php-model/no-environment/src/Placeholder/Placeholder.php deleted file mode 100644 index a0eb33a6b60..00000000000 --- a/seed/php-model/no-environment/src/Placeholder/Placeholder.php +++ /dev/null @@ -1,11 +0,0 @@ -accessToken = $accessToken; + $this->expiresIn = $expiresIn; + } +} diff --git a/seed/php-model/oauth-client-credentials-default/src/Core/SerializableType.php b/seed/php-model/oauth-client-credentials-default/src/Core/SerializableType.php index 4bc3eda7bec..27c45fb74a1 100644 --- a/seed/php-model/oauth-client-credentials-default/src/Core/SerializableType.php +++ b/seed/php-model/oauth-client-credentials-default/src/Core/SerializableType.php @@ -14,8 +14,6 @@ abstract class SerializableType { /** * Serializes the object to a JSON string. - * - * @throws JsonException */ public function toJson(): string { @@ -35,6 +33,9 @@ public function toArray(): array foreach ($reflectionClass->getProperties() as $property) { $jsonKey = self::getJsonKey($property); + if ($jsonKey == null) { + continue; + } $value = $property->getValue($this); // Handle DateTime properties @@ -121,6 +122,10 @@ private static function serializeSingleValue(mixed $data, string $type): mixed return $type === 'date' ? $data->format(Constant::DateFormat) : $data->format(Constant::DateTimeFormat); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && $data instanceof $type) { if (method_exists($data, 'toArray')) { return $data->toArray(); @@ -178,12 +183,12 @@ private static function serializeList(array $data, array $type): array * Helper function to retrieve the JSON key for a property. * * @param ReflectionProperty $property - * @return string + * @return string|null */ - private static function getJsonKey(ReflectionProperty $property): string + private static function getJsonKey(ReflectionProperty $property): ?string { $jsonPropertyAttr = $property->getAttributes(JsonProperty::class)[0] ?? null; - return $jsonPropertyAttr ? $jsonPropertyAttr->newInstance()->name : $property->getName(); + return $jsonPropertyAttr?->newInstance()?->name; } /** @@ -261,7 +266,7 @@ public static function fromArray(array $data): static continue; } - $jsonKey = self::getJsonKey($property); + $jsonKey = self::getJsonKey($property) ?? $property->getName(); if (array_key_exists($jsonKey, $data)) { $value = $data[$jsonKey]; @@ -358,6 +363,10 @@ private static function deserializeSingleValue(mixed $data, string $type): mixed return new DateTime($data); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && is_array($data)) { return $type::fromArray($data); } diff --git a/seed/php-model/oauth-client-credentials-default/src/Placeholder/Placeholder.php b/seed/php-model/oauth-client-credentials-default/src/Placeholder/Placeholder.php deleted file mode 100644 index a0eb33a6b60..00000000000 --- a/seed/php-model/oauth-client-credentials-default/src/Placeholder/Placeholder.php +++ /dev/null @@ -1,11 +0,0 @@ -accessToken = $accessToken; + $this->expiresIn = $expiresIn; + $this->refreshToken = $refreshToken; + } +} diff --git a/seed/php-model/oauth-client-credentials-environment-variables/src/Core/SerializableType.php b/seed/php-model/oauth-client-credentials-environment-variables/src/Core/SerializableType.php index 4bc3eda7bec..27c45fb74a1 100644 --- a/seed/php-model/oauth-client-credentials-environment-variables/src/Core/SerializableType.php +++ b/seed/php-model/oauth-client-credentials-environment-variables/src/Core/SerializableType.php @@ -14,8 +14,6 @@ abstract class SerializableType { /** * Serializes the object to a JSON string. - * - * @throws JsonException */ public function toJson(): string { @@ -35,6 +33,9 @@ public function toArray(): array foreach ($reflectionClass->getProperties() as $property) { $jsonKey = self::getJsonKey($property); + if ($jsonKey == null) { + continue; + } $value = $property->getValue($this); // Handle DateTime properties @@ -121,6 +122,10 @@ private static function serializeSingleValue(mixed $data, string $type): mixed return $type === 'date' ? $data->format(Constant::DateFormat) : $data->format(Constant::DateTimeFormat); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && $data instanceof $type) { if (method_exists($data, 'toArray')) { return $data->toArray(); @@ -178,12 +183,12 @@ private static function serializeList(array $data, array $type): array * Helper function to retrieve the JSON key for a property. * * @param ReflectionProperty $property - * @return string + * @return string|null */ - private static function getJsonKey(ReflectionProperty $property): string + private static function getJsonKey(ReflectionProperty $property): ?string { $jsonPropertyAttr = $property->getAttributes(JsonProperty::class)[0] ?? null; - return $jsonPropertyAttr ? $jsonPropertyAttr->newInstance()->name : $property->getName(); + return $jsonPropertyAttr?->newInstance()?->name; } /** @@ -261,7 +266,7 @@ public static function fromArray(array $data): static continue; } - $jsonKey = self::getJsonKey($property); + $jsonKey = self::getJsonKey($property) ?? $property->getName(); if (array_key_exists($jsonKey, $data)) { $value = $data[$jsonKey]; @@ -358,6 +363,10 @@ private static function deserializeSingleValue(mixed $data, string $type): mixed return new DateTime($data); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && is_array($data)) { return $type::fromArray($data); } diff --git a/seed/php-model/oauth-client-credentials-environment-variables/src/Placeholder/Placeholder.php b/seed/php-model/oauth-client-credentials-environment-variables/src/Placeholder/Placeholder.php deleted file mode 100644 index a0eb33a6b60..00000000000 --- a/seed/php-model/oauth-client-credentials-environment-variables/src/Placeholder/Placeholder.php +++ /dev/null @@ -1,11 +0,0 @@ -accessToken = $accessToken; + $this->expiresIn = $expiresIn; + $this->refreshToken = $refreshToken; + } +} diff --git a/seed/php-model/oauth-client-credentials-nested-root/src/Core/SerializableType.php b/seed/php-model/oauth-client-credentials-nested-root/src/Core/SerializableType.php index 4bc3eda7bec..27c45fb74a1 100644 --- a/seed/php-model/oauth-client-credentials-nested-root/src/Core/SerializableType.php +++ b/seed/php-model/oauth-client-credentials-nested-root/src/Core/SerializableType.php @@ -14,8 +14,6 @@ abstract class SerializableType { /** * Serializes the object to a JSON string. - * - * @throws JsonException */ public function toJson(): string { @@ -35,6 +33,9 @@ public function toArray(): array foreach ($reflectionClass->getProperties() as $property) { $jsonKey = self::getJsonKey($property); + if ($jsonKey == null) { + continue; + } $value = $property->getValue($this); // Handle DateTime properties @@ -121,6 +122,10 @@ private static function serializeSingleValue(mixed $data, string $type): mixed return $type === 'date' ? $data->format(Constant::DateFormat) : $data->format(Constant::DateTimeFormat); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && $data instanceof $type) { if (method_exists($data, 'toArray')) { return $data->toArray(); @@ -178,12 +183,12 @@ private static function serializeList(array $data, array $type): array * Helper function to retrieve the JSON key for a property. * * @param ReflectionProperty $property - * @return string + * @return string|null */ - private static function getJsonKey(ReflectionProperty $property): string + private static function getJsonKey(ReflectionProperty $property): ?string { $jsonPropertyAttr = $property->getAttributes(JsonProperty::class)[0] ?? null; - return $jsonPropertyAttr ? $jsonPropertyAttr->newInstance()->name : $property->getName(); + return $jsonPropertyAttr?->newInstance()?->name; } /** @@ -261,7 +266,7 @@ public static function fromArray(array $data): static continue; } - $jsonKey = self::getJsonKey($property); + $jsonKey = self::getJsonKey($property) ?? $property->getName(); if (array_key_exists($jsonKey, $data)) { $value = $data[$jsonKey]; @@ -358,6 +363,10 @@ private static function deserializeSingleValue(mixed $data, string $type): mixed return new DateTime($data); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && is_array($data)) { return $type::fromArray($data); } diff --git a/seed/php-model/oauth-client-credentials-nested-root/src/Placeholder/Placeholder.php b/seed/php-model/oauth-client-credentials-nested-root/src/Placeholder/Placeholder.php deleted file mode 100644 index a0eb33a6b60..00000000000 --- a/seed/php-model/oauth-client-credentials-nested-root/src/Placeholder/Placeholder.php +++ /dev/null @@ -1,11 +0,0 @@ -accessToken = $accessToken; + $this->expiresIn = $expiresIn; + $this->refreshToken = $refreshToken; + } +} diff --git a/seed/php-model/oauth-client-credentials/src/Core/SerializableType.php b/seed/php-model/oauth-client-credentials/src/Core/SerializableType.php index 4bc3eda7bec..27c45fb74a1 100644 --- a/seed/php-model/oauth-client-credentials/src/Core/SerializableType.php +++ b/seed/php-model/oauth-client-credentials/src/Core/SerializableType.php @@ -14,8 +14,6 @@ abstract class SerializableType { /** * Serializes the object to a JSON string. - * - * @throws JsonException */ public function toJson(): string { @@ -35,6 +33,9 @@ public function toArray(): array foreach ($reflectionClass->getProperties() as $property) { $jsonKey = self::getJsonKey($property); + if ($jsonKey == null) { + continue; + } $value = $property->getValue($this); // Handle DateTime properties @@ -121,6 +122,10 @@ private static function serializeSingleValue(mixed $data, string $type): mixed return $type === 'date' ? $data->format(Constant::DateFormat) : $data->format(Constant::DateTimeFormat); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && $data instanceof $type) { if (method_exists($data, 'toArray')) { return $data->toArray(); @@ -178,12 +183,12 @@ private static function serializeList(array $data, array $type): array * Helper function to retrieve the JSON key for a property. * * @param ReflectionProperty $property - * @return string + * @return string|null */ - private static function getJsonKey(ReflectionProperty $property): string + private static function getJsonKey(ReflectionProperty $property): ?string { $jsonPropertyAttr = $property->getAttributes(JsonProperty::class)[0] ?? null; - return $jsonPropertyAttr ? $jsonPropertyAttr->newInstance()->name : $property->getName(); + return $jsonPropertyAttr?->newInstance()?->name; } /** @@ -261,7 +266,7 @@ public static function fromArray(array $data): static continue; } - $jsonKey = self::getJsonKey($property); + $jsonKey = self::getJsonKey($property) ?? $property->getName(); if (array_key_exists($jsonKey, $data)) { $value = $data[$jsonKey]; @@ -358,6 +363,10 @@ private static function deserializeSingleValue(mixed $data, string $type): mixed return new DateTime($data); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && is_array($data)) { return $type::fromArray($data); } diff --git a/seed/php-model/oauth-client-credentials/src/Placeholder/Placeholder.php b/seed/php-model/oauth-client-credentials/src/Placeholder/Placeholder.php deleted file mode 100644 index a0eb33a6b60..00000000000 --- a/seed/php-model/oauth-client-credentials/src/Placeholder/Placeholder.php +++ /dev/null @@ -1,11 +0,0 @@ -getProperties() as $property) { $jsonKey = self::getJsonKey($property); + if ($jsonKey == null) { + continue; + } $value = $property->getValue($this); // Handle DateTime properties @@ -121,6 +122,10 @@ private static function serializeSingleValue(mixed $data, string $type): mixed return $type === 'date' ? $data->format(Constant::DateFormat) : $data->format(Constant::DateTimeFormat); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && $data instanceof $type) { if (method_exists($data, 'toArray')) { return $data->toArray(); @@ -178,12 +183,12 @@ private static function serializeList(array $data, array $type): array * Helper function to retrieve the JSON key for a property. * * @param ReflectionProperty $property - * @return string + * @return string|null */ - private static function getJsonKey(ReflectionProperty $property): string + private static function getJsonKey(ReflectionProperty $property): ?string { $jsonPropertyAttr = $property->getAttributes(JsonProperty::class)[0] ?? null; - return $jsonPropertyAttr ? $jsonPropertyAttr->newInstance()->name : $property->getName(); + return $jsonPropertyAttr?->newInstance()?->name; } /** @@ -261,7 +266,7 @@ public static function fromArray(array $data): static continue; } - $jsonKey = self::getJsonKey($property); + $jsonKey = self::getJsonKey($property) ?? $property->getName(); if (array_key_exists($jsonKey, $data)) { $value = $data[$jsonKey]; @@ -358,6 +363,10 @@ private static function deserializeSingleValue(mixed $data, string $type): mixed return new DateTime($data); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && is_array($data)) { return $type::fromArray($data); } diff --git a/seed/php-model/object/src/Name.php b/seed/php-model/object/src/Name.php new file mode 100644 index 00000000000..7b0d1936841 --- /dev/null +++ b/seed/php-model/object/src/Name.php @@ -0,0 +1,33 @@ +id = $id; + $this->value = $value; + } +} diff --git a/seed/php-model/object/src/Placeholder/Placeholder.php b/seed/php-model/object/src/Placeholder/Placeholder.php deleted file mode 100644 index a0eb33a6b60..00000000000 --- a/seed/php-model/object/src/Placeholder/Placeholder.php +++ /dev/null @@ -1,11 +0,0 @@ - $ten + */ + public array $ten; + + #[JsonProperty("eleven"), ArrayType(["float"])] + /** + * @var array $eleven + */ + public array $eleven; + + #[JsonProperty("twelve"), ArrayType(["string" => "bool"])] + /** + * @var array $twelve + */ + public array $twelve; + + #[JsonProperty("fourteen")] + /** + * @var mixed $fourteen + */ + public mixed $fourteen; + + #[JsonProperty("fifteen"), ArrayType([["integer"]])] + /** + * @var array> $fifteen + */ + public array $fifteen; + + #[JsonProperty("sixteen"), ArrayType([["string" => "integer"]])] + /** + * @var array> $sixteen + */ + public array $sixteen; + + #[JsonProperty("seventeen"), ArrayType([new Union("string", "null")])] + /** + * @var array $seventeen + */ + public array $seventeen; + + #[JsonProperty("eighteen")] + /** + * @var string $eighteen + */ + public string $eighteen; + + #[JsonProperty("nineteen")] + /** + * @var Name $nineteen + */ + public Name $nineteen; + + #[JsonProperty("twenty")] + /** + * @var int $twenty + */ + public int $twenty; + + #[JsonProperty("twentyone")] + /** + * @var int $twentyone + */ + public int $twentyone; + + #[JsonProperty("twentytwo")] + /** + * @var float $twentytwo + */ + public float $twentytwo; + + #[JsonProperty("twentythree")] + /** + * @var string $twentythree + */ + public string $twentythree; + + #[JsonProperty("thirteen")] + /** + * @var ?int $thirteen + */ + public ?int $thirteen; + + /** + * @param int $one + * @param float $two + * @param string $three + * @param bool $four + * @param int $five + * @param DateTime $six + * @param DateTime $seven + * @param string $eight + * @param string $nine + * @param array $ten + * @param array $eleven + * @param array $twelve + * @param mixed $fourteen + * @param array> $fifteen + * @param array> $sixteen + * @param array $seventeen + * @param string $eighteen + * @param Name $nineteen + * @param int $twenty + * @param int $twentyone + * @param float $twentytwo + * @param string $twentythree + * @param ?int $thirteen + */ + public function __construct( + int $one, + float $two, + string $three, + bool $four, + int $five, + DateTime $six, + DateTime $seven, + string $eight, + string $nine, + array $ten, + array $eleven, + array $twelve, + mixed $fourteen, + array $fifteen, + array $sixteen, + array $seventeen, + string $eighteen, + Name $nineteen, + int $twenty, + int $twentyone, + float $twentytwo, + string $twentythree, + ?int $thirteen = null, + ) { + $this->one = $one; + $this->two = $two; + $this->three = $three; + $this->four = $four; + $this->five = $five; + $this->six = $six; + $this->seven = $seven; + $this->eight = $eight; + $this->nine = $nine; + $this->ten = $ten; + $this->eleven = $eleven; + $this->twelve = $twelve; + $this->fourteen = $fourteen; + $this->fifteen = $fifteen; + $this->sixteen = $sixteen; + $this->seventeen = $seventeen; + $this->eighteen = $eighteen; + $this->nineteen = $nineteen; + $this->twenty = $twenty; + $this->twentyone = $twentyone; + $this->twentytwo = $twentytwo; + $this->twentythree = $twentythree; + $this->thirteen = $thirteen; + } +} diff --git a/seed/php-model/objects-with-imports/src/Commons/Metadata/Metadata.php b/seed/php-model/objects-with-imports/src/Commons/Metadata/Metadata.php new file mode 100644 index 00000000000..60e6127eac8 --- /dev/null +++ b/seed/php-model/objects-with-imports/src/Commons/Metadata/Metadata.php @@ -0,0 +1,34 @@ + "string"])] + /** + * @var ?array $data + */ + public ?array $data; + + /** + * @param string $id + * @param ?array $data + */ + public function __construct( + string $id, + ?array $data = null, + ) { + $this->id = $id; + $this->data = $data; + } +} diff --git a/seed/php-model/objects-with-imports/src/Core/SerializableType.php b/seed/php-model/objects-with-imports/src/Core/SerializableType.php index 4bc3eda7bec..27c45fb74a1 100644 --- a/seed/php-model/objects-with-imports/src/Core/SerializableType.php +++ b/seed/php-model/objects-with-imports/src/Core/SerializableType.php @@ -14,8 +14,6 @@ abstract class SerializableType { /** * Serializes the object to a JSON string. - * - * @throws JsonException */ public function toJson(): string { @@ -35,6 +33,9 @@ public function toArray(): array foreach ($reflectionClass->getProperties() as $property) { $jsonKey = self::getJsonKey($property); + if ($jsonKey == null) { + continue; + } $value = $property->getValue($this); // Handle DateTime properties @@ -121,6 +122,10 @@ private static function serializeSingleValue(mixed $data, string $type): mixed return $type === 'date' ? $data->format(Constant::DateFormat) : $data->format(Constant::DateTimeFormat); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && $data instanceof $type) { if (method_exists($data, 'toArray')) { return $data->toArray(); @@ -178,12 +183,12 @@ private static function serializeList(array $data, array $type): array * Helper function to retrieve the JSON key for a property. * * @param ReflectionProperty $property - * @return string + * @return string|null */ - private static function getJsonKey(ReflectionProperty $property): string + private static function getJsonKey(ReflectionProperty $property): ?string { $jsonPropertyAttr = $property->getAttributes(JsonProperty::class)[0] ?? null; - return $jsonPropertyAttr ? $jsonPropertyAttr->newInstance()->name : $property->getName(); + return $jsonPropertyAttr?->newInstance()?->name; } /** @@ -261,7 +266,7 @@ public static function fromArray(array $data): static continue; } - $jsonKey = self::getJsonKey($property); + $jsonKey = self::getJsonKey($property) ?? $property->getName(); if (array_key_exists($jsonKey, $data)) { $value = $data[$jsonKey]; @@ -358,6 +363,10 @@ private static function deserializeSingleValue(mixed $data, string $type): mixed return new DateTime($data); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && is_array($data)) { return $type::fromArray($data); } diff --git a/seed/php-model/objects-with-imports/src/File/Directory/Directory.php b/seed/php-model/objects-with-imports/src/File/Directory/Directory.php new file mode 100644 index 00000000000..90ee9d32407 --- /dev/null +++ b/seed/php-model/objects-with-imports/src/File/Directory/Directory.php @@ -0,0 +1,45 @@ + $files + */ + public ?array $files; + + #[JsonProperty("directories"), ArrayType([Directory])] + /** + * @var ?array $directories + */ + public ?array $directories; + + /** + * @param string $name + * @param ?array $files + * @param ?array $directories + */ + public function __construct( + string $name, + ?array $files = null, + ?array $directories = null, + ) { + $this->name = $name; + $this->files = $files; + $this->directories = $directories; + } +} diff --git a/seed/php-model/objects-with-imports/src/File/File.php b/seed/php-model/objects-with-imports/src/File/File.php new file mode 100644 index 00000000000..cc7a4ba72c5 --- /dev/null +++ b/seed/php-model/objects-with-imports/src/File/File.php @@ -0,0 +1,43 @@ +name = $name; + $this->contents = $contents; + $this->info = $info; + } +} diff --git a/seed/php-model/objects-with-imports/src/File/FileInfo.php b/seed/php-model/objects-with-imports/src/File/FileInfo.php new file mode 100644 index 00000000000..3dc2a3b7327 --- /dev/null +++ b/seed/php-model/objects-with-imports/src/File/FileInfo.php @@ -0,0 +1,9 @@ +id = $id; + $this->label = $label; + $this->metadata = $metadata; + } +} diff --git a/seed/php-model/objects-with-imports/src/Placeholder/Placeholder.php b/seed/php-model/objects-with-imports/src/Placeholder/Placeholder.php deleted file mode 100644 index a0eb33a6b60..00000000000 --- a/seed/php-model/objects-with-imports/src/Placeholder/Placeholder.php +++ /dev/null @@ -1,11 +0,0 @@ - $nodes + */ + public ?array $nodes; + + /** + * @param ?array $nodes + */ + public function __construct( + ?array $nodes = null, + ) { + $this->nodes = $nodes; + } +} diff --git a/seed/php-model/optional/src/Core/SerializableType.php b/seed/php-model/optional/src/Core/SerializableType.php index 4bc3eda7bec..27c45fb74a1 100644 --- a/seed/php-model/optional/src/Core/SerializableType.php +++ b/seed/php-model/optional/src/Core/SerializableType.php @@ -14,8 +14,6 @@ abstract class SerializableType { /** * Serializes the object to a JSON string. - * - * @throws JsonException */ public function toJson(): string { @@ -35,6 +33,9 @@ public function toArray(): array foreach ($reflectionClass->getProperties() as $property) { $jsonKey = self::getJsonKey($property); + if ($jsonKey == null) { + continue; + } $value = $property->getValue($this); // Handle DateTime properties @@ -121,6 +122,10 @@ private static function serializeSingleValue(mixed $data, string $type): mixed return $type === 'date' ? $data->format(Constant::DateFormat) : $data->format(Constant::DateTimeFormat); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && $data instanceof $type) { if (method_exists($data, 'toArray')) { return $data->toArray(); @@ -178,12 +183,12 @@ private static function serializeList(array $data, array $type): array * Helper function to retrieve the JSON key for a property. * * @param ReflectionProperty $property - * @return string + * @return string|null */ - private static function getJsonKey(ReflectionProperty $property): string + private static function getJsonKey(ReflectionProperty $property): ?string { $jsonPropertyAttr = $property->getAttributes(JsonProperty::class)[0] ?? null; - return $jsonPropertyAttr ? $jsonPropertyAttr->newInstance()->name : $property->getName(); + return $jsonPropertyAttr?->newInstance()?->name; } /** @@ -261,7 +266,7 @@ public static function fromArray(array $data): static continue; } - $jsonKey = self::getJsonKey($property); + $jsonKey = self::getJsonKey($property) ?? $property->getName(); if (array_key_exists($jsonKey, $data)) { $value = $data[$jsonKey]; @@ -358,6 +363,10 @@ private static function deserializeSingleValue(mixed $data, string $type): mixed return new DateTime($data); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && is_array($data)) { return $type::fromArray($data); } diff --git a/seed/php-model/optional/src/Placeholder/Placeholder.php b/seed/php-model/optional/src/Placeholder/Placeholder.php deleted file mode 100644 index a0eb33a6b60..00000000000 --- a/seed/php-model/optional/src/Placeholder/Placeholder.php +++ /dev/null @@ -1,11 +0,0 @@ -getProperties() as $property) { $jsonKey = self::getJsonKey($property); + if ($jsonKey == null) { + continue; + } $value = $property->getValue($this); // Handle DateTime properties @@ -121,6 +122,10 @@ private static function serializeSingleValue(mixed $data, string $type): mixed return $type === 'date' ? $data->format(Constant::DateFormat) : $data->format(Constant::DateTimeFormat); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && $data instanceof $type) { if (method_exists($data, 'toArray')) { return $data->toArray(); @@ -178,12 +183,12 @@ private static function serializeList(array $data, array $type): array * Helper function to retrieve the JSON key for a property. * * @param ReflectionProperty $property - * @return string + * @return string|null */ - private static function getJsonKey(ReflectionProperty $property): string + private static function getJsonKey(ReflectionProperty $property): ?string { $jsonPropertyAttr = $property->getAttributes(JsonProperty::class)[0] ?? null; - return $jsonPropertyAttr ? $jsonPropertyAttr->newInstance()->name : $property->getName(); + return $jsonPropertyAttr?->newInstance()?->name; } /** @@ -261,7 +266,7 @@ public static function fromArray(array $data): static continue; } - $jsonKey = self::getJsonKey($property); + $jsonKey = self::getJsonKey($property) ?? $property->getName(); if (array_key_exists($jsonKey, $data)) { $value = $data[$jsonKey]; @@ -358,6 +363,10 @@ private static function deserializeSingleValue(mixed $data, string $type): mixed return new DateTime($data); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && is_array($data)) { return $type::fromArray($data); } diff --git a/seed/php-model/package-yml/src/EchoRequest.php b/seed/php-model/package-yml/src/EchoRequest.php new file mode 100644 index 00000000000..bb0c32744b7 --- /dev/null +++ b/seed/php-model/package-yml/src/EchoRequest.php @@ -0,0 +1,33 @@ +name = $name; + $this->size = $size; + } +} diff --git a/seed/php-model/package-yml/src/Placeholder/Placeholder.php b/seed/php-model/package-yml/src/Placeholder/Placeholder.php deleted file mode 100644 index a0eb33a6b60..00000000000 --- a/seed/php-model/package-yml/src/Placeholder/Placeholder.php +++ /dev/null @@ -1,11 +0,0 @@ -getProperties() as $property) { $jsonKey = self::getJsonKey($property); + if ($jsonKey == null) { + continue; + } $value = $property->getValue($this); // Handle DateTime properties @@ -121,6 +122,10 @@ private static function serializeSingleValue(mixed $data, string $type): mixed return $type === 'date' ? $data->format(Constant::DateFormat) : $data->format(Constant::DateTimeFormat); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && $data instanceof $type) { if (method_exists($data, 'toArray')) { return $data->toArray(); @@ -178,12 +183,12 @@ private static function serializeList(array $data, array $type): array * Helper function to retrieve the JSON key for a property. * * @param ReflectionProperty $property - * @return string + * @return string|null */ - private static function getJsonKey(ReflectionProperty $property): string + private static function getJsonKey(ReflectionProperty $property): ?string { $jsonPropertyAttr = $property->getAttributes(JsonProperty::class)[0] ?? null; - return $jsonPropertyAttr ? $jsonPropertyAttr->newInstance()->name : $property->getName(); + return $jsonPropertyAttr?->newInstance()?->name; } /** @@ -261,7 +266,7 @@ public static function fromArray(array $data): static continue; } - $jsonKey = self::getJsonKey($property); + $jsonKey = self::getJsonKey($property) ?? $property->getName(); if (array_key_exists($jsonKey, $data)) { $value = $data[$jsonKey]; @@ -358,6 +363,10 @@ private static function deserializeSingleValue(mixed $data, string $type): mixed return new DateTime($data); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && is_array($data)) { return $type::fromArray($data); } diff --git a/seed/php-model/pagination/src/Placeholder/Placeholder.php b/seed/php-model/pagination/src/Placeholder/Placeholder.php deleted file mode 100644 index a0eb33a6b60..00000000000 --- a/seed/php-model/pagination/src/Placeholder/Placeholder.php +++ /dev/null @@ -1,11 +0,0 @@ -cursor = $cursor; + } +} diff --git a/seed/php-model/pagination/src/UsernamePage.php b/seed/php-model/pagination/src/UsernamePage.php new file mode 100644 index 00000000000..ec806ef457f --- /dev/null +++ b/seed/php-model/pagination/src/UsernamePage.php @@ -0,0 +1,34 @@ + $data + */ + public array $data; + + #[JsonProperty("after")] + /** + * @var ?string $after + */ + public ?string $after; + + /** + * @param array $data + * @param ?string $after + */ + public function __construct( + array $data, + ?string $after = null, + ) { + $this->data = $data; + $this->after = $after; + } +} diff --git a/seed/php-model/pagination/src/Users/ListUsersExtendedOptionalListResponse.php b/seed/php-model/pagination/src/Users/ListUsersExtendedOptionalListResponse.php new file mode 100644 index 00000000000..86c6d8e4a3d --- /dev/null +++ b/seed/php-model/pagination/src/Users/ListUsersExtendedOptionalListResponse.php @@ -0,0 +1,24 @@ +totalCount = $totalCount; + } +} diff --git a/seed/php-model/pagination/src/Users/ListUsersExtendedResponse.php b/seed/php-model/pagination/src/Users/ListUsersExtendedResponse.php new file mode 100644 index 00000000000..c152a4a6d28 --- /dev/null +++ b/seed/php-model/pagination/src/Users/ListUsersExtendedResponse.php @@ -0,0 +1,24 @@ +totalCount = $totalCount; + } +} diff --git a/seed/php-model/pagination/src/Users/ListUsersPaginationResponse.php b/seed/php-model/pagination/src/Users/ListUsersPaginationResponse.php new file mode 100644 index 00000000000..2b74c19f2a6 --- /dev/null +++ b/seed/php-model/pagination/src/Users/ListUsersPaginationResponse.php @@ -0,0 +1,54 @@ + $data + */ + public array $data; + + #[JsonProperty("hasNextPage")] + /** + * @var ?bool $hasNextPage + */ + public ?bool $hasNextPage; + + #[JsonProperty("page")] + /** + * @var ?Page $page + */ + public ?Page $page; + + /** + * @param int $totalCount The totall number of /users + * @param array $data + * @param ?bool $hasNextPage + * @param ?Page $page + */ + public function __construct( + int $totalCount, + array $data, + ?bool $hasNextPage = null, + ?Page $page = null, + ) { + $this->totalCount = $totalCount; + $this->data = $data; + $this->hasNextPage = $hasNextPage; + $this->page = $page; + } +} diff --git a/seed/php-model/pagination/src/Users/NextPage.php b/seed/php-model/pagination/src/Users/NextPage.php new file mode 100644 index 00000000000..bfa5915d24c --- /dev/null +++ b/seed/php-model/pagination/src/Users/NextPage.php @@ -0,0 +1,33 @@ +page = $page; + $this->startingAfter = $startingAfter; + } +} diff --git a/seed/php-model/pagination/src/Users/Order.php b/seed/php-model/pagination/src/Users/Order.php new file mode 100644 index 00000000000..0fb09df75a6 --- /dev/null +++ b/seed/php-model/pagination/src/Users/Order.php @@ -0,0 +1,9 @@ +page = $page; + $this->perPage = $perPage; + $this->totalPage = $totalPage; + $this->next = $next; + } +} diff --git a/seed/php-model/pagination/src/Users/User.php b/seed/php-model/pagination/src/Users/User.php new file mode 100644 index 00000000000..a59a581ed9d --- /dev/null +++ b/seed/php-model/pagination/src/Users/User.php @@ -0,0 +1,33 @@ +name = $name; + $this->id = $id; + } +} diff --git a/seed/php-model/pagination/src/Users/UserListContainer.php b/seed/php-model/pagination/src/Users/UserListContainer.php new file mode 100644 index 00000000000..297f4201b65 --- /dev/null +++ b/seed/php-model/pagination/src/Users/UserListContainer.php @@ -0,0 +1,26 @@ + $users + */ + public array $users; + + /** + * @param array $users + */ + public function __construct( + array $users, + ) { + $this->users = $users; + } +} diff --git a/seed/php-model/pagination/src/Users/UserOptionalListContainer.php b/seed/php-model/pagination/src/Users/UserOptionalListContainer.php new file mode 100644 index 00000000000..861bb765171 --- /dev/null +++ b/seed/php-model/pagination/src/Users/UserOptionalListContainer.php @@ -0,0 +1,26 @@ + $users + */ + public ?array $users; + + /** + * @param ?array $users + */ + public function __construct( + ?array $users = null, + ) { + $this->users = $users; + } +} diff --git a/seed/php-model/pagination/src/Users/UserOptionalListPage.php b/seed/php-model/pagination/src/Users/UserOptionalListPage.php new file mode 100644 index 00000000000..7ea65d9815a --- /dev/null +++ b/seed/php-model/pagination/src/Users/UserOptionalListPage.php @@ -0,0 +1,34 @@ +data = $data; + $this->next = $next; + } +} diff --git a/seed/php-model/pagination/src/Users/UserPage.php b/seed/php-model/pagination/src/Users/UserPage.php new file mode 100644 index 00000000000..cdd5ff0b9c5 --- /dev/null +++ b/seed/php-model/pagination/src/Users/UserPage.php @@ -0,0 +1,34 @@ +data = $data; + $this->next = $next; + } +} diff --git a/seed/php-model/pagination/src/Users/UsernameContainer.php b/seed/php-model/pagination/src/Users/UsernameContainer.php new file mode 100644 index 00000000000..d34c6c1caa1 --- /dev/null +++ b/seed/php-model/pagination/src/Users/UsernameContainer.php @@ -0,0 +1,25 @@ + $results + */ + public array $results; + + /** + * @param array $results + */ + public function __construct( + array $results, + ) { + $this->results = $results; + } +} diff --git a/seed/php-model/pagination/src/Users/WithCursor.php b/seed/php-model/pagination/src/Users/WithCursor.php new file mode 100644 index 00000000000..083ed4bdcf1 --- /dev/null +++ b/seed/php-model/pagination/src/Users/WithCursor.php @@ -0,0 +1,24 @@ +cursor = $cursor; + } +} diff --git a/seed/php-model/pagination/src/Users/WithPage.php b/seed/php-model/pagination/src/Users/WithPage.php new file mode 100644 index 00000000000..7e832abc2b6 --- /dev/null +++ b/seed/php-model/pagination/src/Users/WithPage.php @@ -0,0 +1,24 @@ +page = $page; + } +} diff --git a/seed/php-model/plain-text/src/Core/SerializableType.php b/seed/php-model/plain-text/src/Core/SerializableType.php index 4bc3eda7bec..27c45fb74a1 100644 --- a/seed/php-model/plain-text/src/Core/SerializableType.php +++ b/seed/php-model/plain-text/src/Core/SerializableType.php @@ -14,8 +14,6 @@ abstract class SerializableType { /** * Serializes the object to a JSON string. - * - * @throws JsonException */ public function toJson(): string { @@ -35,6 +33,9 @@ public function toArray(): array foreach ($reflectionClass->getProperties() as $property) { $jsonKey = self::getJsonKey($property); + if ($jsonKey == null) { + continue; + } $value = $property->getValue($this); // Handle DateTime properties @@ -121,6 +122,10 @@ private static function serializeSingleValue(mixed $data, string $type): mixed return $type === 'date' ? $data->format(Constant::DateFormat) : $data->format(Constant::DateTimeFormat); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && $data instanceof $type) { if (method_exists($data, 'toArray')) { return $data->toArray(); @@ -178,12 +183,12 @@ private static function serializeList(array $data, array $type): array * Helper function to retrieve the JSON key for a property. * * @param ReflectionProperty $property - * @return string + * @return string|null */ - private static function getJsonKey(ReflectionProperty $property): string + private static function getJsonKey(ReflectionProperty $property): ?string { $jsonPropertyAttr = $property->getAttributes(JsonProperty::class)[0] ?? null; - return $jsonPropertyAttr ? $jsonPropertyAttr->newInstance()->name : $property->getName(); + return $jsonPropertyAttr?->newInstance()?->name; } /** @@ -261,7 +266,7 @@ public static function fromArray(array $data): static continue; } - $jsonKey = self::getJsonKey($property); + $jsonKey = self::getJsonKey($property) ?? $property->getName(); if (array_key_exists($jsonKey, $data)) { $value = $data[$jsonKey]; @@ -358,6 +363,10 @@ private static function deserializeSingleValue(mixed $data, string $type): mixed return new DateTime($data); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && is_array($data)) { return $type::fromArray($data); } diff --git a/seed/php-model/plain-text/src/Placeholder/Placeholder.php b/seed/php-model/plain-text/src/Placeholder/Placeholder.php deleted file mode 100644 index a0eb33a6b60..00000000000 --- a/seed/php-model/plain-text/src/Placeholder/Placeholder.php +++ /dev/null @@ -1,11 +0,0 @@ -getProperties() as $property) { $jsonKey = self::getJsonKey($property); + if ($jsonKey == null) { + continue; + } $value = $property->getValue($this); // Handle DateTime properties @@ -121,6 +122,10 @@ private static function serializeSingleValue(mixed $data, string $type): mixed return $type === 'date' ? $data->format(Constant::DateFormat) : $data->format(Constant::DateTimeFormat); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && $data instanceof $type) { if (method_exists($data, 'toArray')) { return $data->toArray(); @@ -178,12 +183,12 @@ private static function serializeList(array $data, array $type): array * Helper function to retrieve the JSON key for a property. * * @param ReflectionProperty $property - * @return string + * @return string|null */ - private static function getJsonKey(ReflectionProperty $property): string + private static function getJsonKey(ReflectionProperty $property): ?string { $jsonPropertyAttr = $property->getAttributes(JsonProperty::class)[0] ?? null; - return $jsonPropertyAttr ? $jsonPropertyAttr->newInstance()->name : $property->getName(); + return $jsonPropertyAttr?->newInstance()?->name; } /** @@ -261,7 +266,7 @@ public static function fromArray(array $data): static continue; } - $jsonKey = self::getJsonKey($property); + $jsonKey = self::getJsonKey($property) ?? $property->getName(); if (array_key_exists($jsonKey, $data)) { $value = $data[$jsonKey]; @@ -358,6 +363,10 @@ private static function deserializeSingleValue(mixed $data, string $type): mixed return new DateTime($data); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && is_array($data)) { return $type::fromArray($data); } diff --git a/seed/php-model/query-parameters/src/Placeholder/Placeholder.php b/seed/php-model/query-parameters/src/Placeholder/Placeholder.php deleted file mode 100644 index a0eb33a6b60..00000000000 --- a/seed/php-model/query-parameters/src/Placeholder/Placeholder.php +++ /dev/null @@ -1,11 +0,0 @@ -name = $name; + $this->user = $user; + } +} diff --git a/seed/php-model/query-parameters/src/User/User.php b/seed/php-model/query-parameters/src/User/User.php new file mode 100644 index 00000000000..7b1ee845f40 --- /dev/null +++ b/seed/php-model/query-parameters/src/User/User.php @@ -0,0 +1,34 @@ + $tags + */ + public array $tags; + + /** + * @param string $name + * @param array $tags + */ + public function __construct( + string $name, + array $tags, + ) { + $this->name = $name; + $this->tags = $tags; + } +} diff --git a/seed/php-model/reserved-keywords/src/Core/SerializableType.php b/seed/php-model/reserved-keywords/src/Core/SerializableType.php index 4bc3eda7bec..27c45fb74a1 100644 --- a/seed/php-model/reserved-keywords/src/Core/SerializableType.php +++ b/seed/php-model/reserved-keywords/src/Core/SerializableType.php @@ -14,8 +14,6 @@ abstract class SerializableType { /** * Serializes the object to a JSON string. - * - * @throws JsonException */ public function toJson(): string { @@ -35,6 +33,9 @@ public function toArray(): array foreach ($reflectionClass->getProperties() as $property) { $jsonKey = self::getJsonKey($property); + if ($jsonKey == null) { + continue; + } $value = $property->getValue($this); // Handle DateTime properties @@ -121,6 +122,10 @@ private static function serializeSingleValue(mixed $data, string $type): mixed return $type === 'date' ? $data->format(Constant::DateFormat) : $data->format(Constant::DateTimeFormat); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && $data instanceof $type) { if (method_exists($data, 'toArray')) { return $data->toArray(); @@ -178,12 +183,12 @@ private static function serializeList(array $data, array $type): array * Helper function to retrieve the JSON key for a property. * * @param ReflectionProperty $property - * @return string + * @return string|null */ - private static function getJsonKey(ReflectionProperty $property): string + private static function getJsonKey(ReflectionProperty $property): ?string { $jsonPropertyAttr = $property->getAttributes(JsonProperty::class)[0] ?? null; - return $jsonPropertyAttr ? $jsonPropertyAttr->newInstance()->name : $property->getName(); + return $jsonPropertyAttr?->newInstance()?->name; } /** @@ -261,7 +266,7 @@ public static function fromArray(array $data): static continue; } - $jsonKey = self::getJsonKey($property); + $jsonKey = self::getJsonKey($property) ?? $property->getName(); if (array_key_exists($jsonKey, $data)) { $value = $data[$jsonKey]; @@ -358,6 +363,10 @@ private static function deserializeSingleValue(mixed $data, string $type): mixed return new DateTime($data); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && is_array($data)) { return $type::fromArray($data); } diff --git a/seed/php-model/reserved-keywords/src/Package/Package.php b/seed/php-model/reserved-keywords/src/Package/Package.php new file mode 100644 index 00000000000..e1652e4f86c --- /dev/null +++ b/seed/php-model/reserved-keywords/src/Package/Package.php @@ -0,0 +1,24 @@ +name = $name; + } +} diff --git a/seed/php-model/reserved-keywords/src/Package/Record.php b/seed/php-model/reserved-keywords/src/Package/Record.php new file mode 100644 index 00000000000..22be77de1e3 --- /dev/null +++ b/seed/php-model/reserved-keywords/src/Package/Record.php @@ -0,0 +1,34 @@ + "string"])] + /** + * @var array $foo + */ + public array $foo; + + #[JsonProperty("3d")] + /** + * @var int $_3D + */ + public int $_3D; + + /** + * @param array $foo + * @param int $_3D + */ + public function __construct( + array $foo, + int $_3D, + ) { + $this->foo = $foo; + $this->_3D = $_3D; + } +} diff --git a/seed/php-model/reserved-keywords/src/Placeholder/Placeholder.php b/seed/php-model/reserved-keywords/src/Placeholder/Placeholder.php deleted file mode 100644 index a0eb33a6b60..00000000000 --- a/seed/php-model/reserved-keywords/src/Placeholder/Placeholder.php +++ /dev/null @@ -1,11 +0,0 @@ -getProperties() as $property) { $jsonKey = self::getJsonKey($property); + if ($jsonKey == null) { + continue; + } $value = $property->getValue($this); // Handle DateTime properties @@ -121,6 +122,10 @@ private static function serializeSingleValue(mixed $data, string $type): mixed return $type === 'date' ? $data->format(Constant::DateFormat) : $data->format(Constant::DateTimeFormat); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && $data instanceof $type) { if (method_exists($data, 'toArray')) { return $data->toArray(); @@ -178,12 +183,12 @@ private static function serializeList(array $data, array $type): array * Helper function to retrieve the JSON key for a property. * * @param ReflectionProperty $property - * @return string + * @return string|null */ - private static function getJsonKey(ReflectionProperty $property): string + private static function getJsonKey(ReflectionProperty $property): ?string { $jsonPropertyAttr = $property->getAttributes(JsonProperty::class)[0] ?? null; - return $jsonPropertyAttr ? $jsonPropertyAttr->newInstance()->name : $property->getName(); + return $jsonPropertyAttr?->newInstance()?->name; } /** @@ -261,7 +266,7 @@ public static function fromArray(array $data): static continue; } - $jsonKey = self::getJsonKey($property); + $jsonKey = self::getJsonKey($property) ?? $property->getName(); if (array_key_exists($jsonKey, $data)) { $value = $data[$jsonKey]; @@ -358,6 +363,10 @@ private static function deserializeSingleValue(mixed $data, string $type): mixed return new DateTime($data); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && is_array($data)) { return $type::fromArray($data); } diff --git a/seed/php-model/response-property/src/Placeholder/Placeholder.php b/seed/php-model/response-property/src/Placeholder/Placeholder.php deleted file mode 100644 index a0eb33a6b60..00000000000 --- a/seed/php-model/response-property/src/Placeholder/Placeholder.php +++ /dev/null @@ -1,11 +0,0 @@ -id = $id; + $this->name = $name; + } +} diff --git a/seed/php-model/response-property/src/Service/Response.php b/seed/php-model/response-property/src/Service/Response.php new file mode 100644 index 00000000000..be46b641f71 --- /dev/null +++ b/seed/php-model/response-property/src/Service/Response.php @@ -0,0 +1,25 @@ +data = $data; + } +} diff --git a/seed/php-model/response-property/src/Service/WithDocs.php b/seed/php-model/response-property/src/Service/WithDocs.php new file mode 100644 index 00000000000..0a4d9c70290 --- /dev/null +++ b/seed/php-model/response-property/src/Service/WithDocs.php @@ -0,0 +1,24 @@ +docs = $docs; + } +} diff --git a/seed/php-model/response-property/src/StringResponse.php b/seed/php-model/response-property/src/StringResponse.php new file mode 100644 index 00000000000..072378f001e --- /dev/null +++ b/seed/php-model/response-property/src/StringResponse.php @@ -0,0 +1,24 @@ +data = $data; + } +} diff --git a/seed/php-model/response-property/src/WithMetadata.php b/seed/php-model/response-property/src/WithMetadata.php new file mode 100644 index 00000000000..1fbab0d3cc5 --- /dev/null +++ b/seed/php-model/response-property/src/WithMetadata.php @@ -0,0 +1,25 @@ + "string"])] + /** + * @var array $metadata + */ + public array $metadata; + + /** + * @param array $metadata + */ + public function __construct( + array $metadata, + ) { + $this->metadata = $metadata; + } +} diff --git a/seed/php-model/simple-fhir/src/Account.php b/seed/php-model/simple-fhir/src/Account.php new file mode 100644 index 00000000000..567b22bd7e9 --- /dev/null +++ b/seed/php-model/simple-fhir/src/Account.php @@ -0,0 +1,53 @@ +resourceType = $resourceType; + $this->name = $name; + $this->patient = $patient; + $this->practitioner = $practitioner; + } +} diff --git a/seed/php-model/simple-fhir/src/BaseResource.php b/seed/php-model/simple-fhir/src/BaseResource.php new file mode 100644 index 00000000000..aef3b4e85ed --- /dev/null +++ b/seed/php-model/simple-fhir/src/BaseResource.php @@ -0,0 +1,44 @@ + $relatedResources + */ + public array $relatedResources; + + #[JsonProperty("memo")] + /** + * @var Memo $memo + */ + public Memo $memo; + + /** + * @param string $id + * @param array $relatedResources + * @param Memo $memo + */ + public function __construct( + string $id, + array $relatedResources, + Memo $memo, + ) { + $this->id = $id; + $this->relatedResources = $relatedResources; + $this->memo = $memo; + } +} diff --git a/seed/php-model/simple-fhir/src/Core/SerializableType.php b/seed/php-model/simple-fhir/src/Core/SerializableType.php index 4bc3eda7bec..27c45fb74a1 100644 --- a/seed/php-model/simple-fhir/src/Core/SerializableType.php +++ b/seed/php-model/simple-fhir/src/Core/SerializableType.php @@ -14,8 +14,6 @@ abstract class SerializableType { /** * Serializes the object to a JSON string. - * - * @throws JsonException */ public function toJson(): string { @@ -35,6 +33,9 @@ public function toArray(): array foreach ($reflectionClass->getProperties() as $property) { $jsonKey = self::getJsonKey($property); + if ($jsonKey == null) { + continue; + } $value = $property->getValue($this); // Handle DateTime properties @@ -121,6 +122,10 @@ private static function serializeSingleValue(mixed $data, string $type): mixed return $type === 'date' ? $data->format(Constant::DateFormat) : $data->format(Constant::DateTimeFormat); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && $data instanceof $type) { if (method_exists($data, 'toArray')) { return $data->toArray(); @@ -178,12 +183,12 @@ private static function serializeList(array $data, array $type): array * Helper function to retrieve the JSON key for a property. * * @param ReflectionProperty $property - * @return string + * @return string|null */ - private static function getJsonKey(ReflectionProperty $property): string + private static function getJsonKey(ReflectionProperty $property): ?string { $jsonPropertyAttr = $property->getAttributes(JsonProperty::class)[0] ?? null; - return $jsonPropertyAttr ? $jsonPropertyAttr->newInstance()->name : $property->getName(); + return $jsonPropertyAttr?->newInstance()?->name; } /** @@ -261,7 +266,7 @@ public static function fromArray(array $data): static continue; } - $jsonKey = self::getJsonKey($property); + $jsonKey = self::getJsonKey($property) ?? $property->getName(); if (array_key_exists($jsonKey, $data)) { $value = $data[$jsonKey]; @@ -358,6 +363,10 @@ private static function deserializeSingleValue(mixed $data, string $type): mixed return new DateTime($data); } + if ($type === 'mixed') { + return $data; + } + if (class_exists($type) && is_array($data)) { return $type::fromArray($data); } diff --git a/seed/php-model/simple-fhir/src/Memo.php b/seed/php-model/simple-fhir/src/Memo.php new file mode 100644 index 00000000000..11a93a356cb --- /dev/null +++ b/seed/php-model/simple-fhir/src/Memo.php @@ -0,0 +1,34 @@ +description = $description; + $this->account = $account; + } +} diff --git a/seed/php-model/simple-fhir/src/Patient.php b/seed/php-model/simple-fhir/src/Patient.php new file mode 100644 index 00000000000..71ea82facaf --- /dev/null +++ b/seed/php-model/simple-fhir/src/Patient.php @@ -0,0 +1,44 @@ + $scripts + */ + public array $scripts; + + /** + * @param string $resourceType + * @param string $name + * @param array