[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

/wp-includes/php-ai-client/src/Common/ -> AbstractDataTransferObject.php (source)

   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       * @since 0.1.0
  55       */
  56      public static function isArrayShape(array $array): bool
  57      {
  58          try {
  59              /** @var TArrayShape $array */
  60              static::fromArray($array);
  61              return \true;
  62          } catch (InvalidArgumentException $e) {
  63              return \false;
  64          }
  65      }
  66      /**
  67       * Converts the object to a JSON-serializable format.
  68       *
  69       * This method uses the toArray() method and then processes the result
  70       * based on the JSON schema to ensure proper object representation for
  71       * empty arrays.
  72       *
  73       * @since 0.1.0
  74       *
  75       * @return mixed The JSON-serializable representation.
  76       */
  77      #[\ReturnTypeWillChange]
  78      public function jsonSerialize()
  79      {
  80          $data = $this->toArray();
  81          $schema = static::getJsonSchema();
  82          return $this->convertEmptyArraysToObjects($data, $schema);
  83      }
  84      /**
  85       * Recursively converts empty arrays to stdClass objects where the schema expects objects.
  86       *
  87       * @since 0.1.0
  88       *
  89       * @param mixed $data The data to process.
  90       * @param array<mixed, mixed> $schema The JSON schema for the data.
  91       * @return mixed The processed data.
  92       */
  93      private function convertEmptyArraysToObjects($data, array $schema)
  94      {
  95          // If data is an empty array and schema expects object, convert to stdClass
  96          if (is_array($data) && empty($data) && isset($schema['type']) && $schema['type'] === 'object') {
  97              return new stdClass();
  98          }
  99          // If data is an array with content, recursively process nested structures
 100          if (is_array($data)) {
 101              // Handle object properties
 102              if (isset($schema['properties']) && is_array($schema['properties'])) {
 103                  foreach ($data as $key => $value) {
 104                      if (isset($schema['properties'][$key]) && is_array($schema['properties'][$key])) {
 105                          $data[$key] = $this->convertEmptyArraysToObjects($value, $schema['properties'][$key]);
 106                      }
 107                  }
 108              }
 109              // Handle array items
 110              if (isset($schema['items']) && is_array($schema['items'])) {
 111                  foreach ($data as $index => $item) {
 112                      $data[$index] = $this->convertEmptyArraysToObjects($item, $schema['items']);
 113                  }
 114              }
 115              // Handle oneOf/anyOf schemas - just use the first one
 116              foreach (['oneOf', 'anyOf'] as $keyword) {
 117                  if (isset($schema[$keyword]) && is_array($schema[$keyword])) {
 118                      foreach ($schema[$keyword] as $possibleSchema) {
 119                          if (is_array($possibleSchema)) {
 120                              return $this->convertEmptyArraysToObjects($data, $possibleSchema);
 121                          }
 122                      }
 123                  }
 124              }
 125          }
 126          return $data;
 127      }
 128  }


Generated : Sat Jun 13 09:38:55 2026 Cross-referenced by PHPXref