[ 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       * 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  }


Generated : Sun Nov 1 08:20:35 2026 Cross-referenced by PHPXref