| [ Index ] |
PHP Cross Reference of WordPress Trunk (Updated Daily) |
[Summary view] [Print] [Text view]
1 <?php 2 3 declare (strict_types=1); 4 namespace WordPress\AiClient\Common; 5 6 use JsonSerializable; 7 use stdClass; 8 use WordPress\AiClient\Common\Contracts\WithArrayTransformationInterface; 9 use WordPress\AiClient\Common\Contracts\WithJsonSchemaInterface; 10 use WordPress\AiClient\Common\Exception\InvalidArgumentException; 11 /** 12 * Abstract base class for all Data Value Objects in the AI Client. 13 * 14 * This abstract class consolidates the common functionality needed by all 15 * data transfer objects: 16 * - Array transformation for data manipulation 17 * - JSON schema support for validation and documentation 18 * - JSON serialization with proper empty object handling 19 * 20 * All DTOs in the AI Client should extend this class to ensure 21 * consistent behavior across the codebase. 22 * 23 * @since 0.1.0 24 * 25 * @template TArrayShape of array<string, mixed> 26 * @implements WithArrayTransformationInterface<TArrayShape> 27 */ 28 abstract class AbstractDataTransferObject implements WithArrayTransformationInterface, WithJsonSchemaInterface, JsonSerializable 29 { 30 /** 31 * Validates that required keys exist in the array data. 32 * 33 * @since 0.1.0 34 * 35 * @param array<mixed> $data The array data to validate. 36 * @param string[] $requiredKeys The keys that must be present. 37 * @throws InvalidArgumentException If any required key is missing. 38 */ 39 protected static function validateFromArrayData(array $data, array $requiredKeys): void 40 { 41 $missingKeys = []; 42 foreach ($requiredKeys as $key) { 43 if (!array_key_exists($key, $data)) { 44 $missingKeys[] = $key; 45 } 46 } 47 if (!empty($missingKeys)) { 48 throw new InvalidArgumentException(sprintf('%s::fromArray() missing required keys: %s', static::class, implode(', ', $missingKeys))); 49 } 50 } 51 /** 52 * {@inheritDoc} 53 * 54 * The default implementation attempts to construct the object. Subclasses whose fromArray() has side 55 * effects, is expensive, or handles untrusted input should override this with a structural check. 56 * 57 * @since 0.1.0 58 */ 59 public static function isArrayShape(array $array): bool 60 { 61 try { 62 /** @var TArrayShape $array */ 63 static::fromArray($array); 64 return \true; 65 } catch (InvalidArgumentException $e) { 66 return \false; 67 } 68 } 69 /** 70 * Converts the object to a JSON-serializable format. 71 * 72 * This method uses the toArray() method and then processes the result 73 * based on the JSON schema to ensure proper object representation for 74 * empty arrays. 75 * 76 * @since 0.1.0 77 * 78 * @return mixed The JSON-serializable representation. 79 */ 80 #[\ReturnTypeWillChange] 81 public function jsonSerialize() 82 { 83 $data = $this->toArray(); 84 $schema = static::getJsonSchema(); 85 return $this->convertEmptyArraysToObjects($data, $schema); 86 } 87 /** 88 * Recursively converts empty arrays to stdClass objects where the schema expects objects. 89 * 90 * @since 0.1.0 91 * 92 * @param mixed $data The data to process. 93 * @param array<mixed, mixed> $schema The JSON schema for the data. 94 * @return mixed The processed data. 95 */ 96 private function convertEmptyArraysToObjects($data, array $schema) 97 { 98 // If data is an empty array and schema expects object, convert to stdClass 99 if (is_array($data) && empty($data) && isset($schema['type']) && $schema['type'] === 'object') { 100 return new stdClass(); 101 } 102 // If data is an array with content, recursively process nested structures 103 if (is_array($data)) { 104 // Handle object properties 105 if (isset($schema['properties']) && is_array($schema['properties'])) { 106 foreach ($data as $key => $value) { 107 if (isset($schema['properties'][$key]) && is_array($schema['properties'][$key])) { 108 $data[$key] = $this->convertEmptyArraysToObjects($value, $schema['properties'][$key]); 109 } 110 } 111 } 112 // Handle array items 113 if (isset($schema['items']) && is_array($schema['items'])) { 114 foreach ($data as $index => $item) { 115 $data[$index] = $this->convertEmptyArraysToObjects($item, $schema['items']); 116 } 117 } 118 // Handle oneOf/anyOf schemas - just use the first one 119 foreach (['oneOf', 'anyOf'] as $keyword) { 120 if (isset($schema[$keyword]) && is_array($schema[$keyword])) { 121 foreach ($schema[$keyword] as $possibleSchema) { 122 if (is_array($possibleSchema)) { 123 return $this->convertEmptyArraysToObjects($data, $possibleSchema); 124 } 125 } 126 } 127 } 128 } 129 return $data; 130 } 131 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated : Sun Nov 1 08:20:35 2026 | Cross-referenced by PHPXref |