DateTimeIso8601Normalizer.php

Same filename and directory in other branches
  1. 11.x core/modules/serialization/src/Normalizer/DateTimeIso8601Normalizer.php
  2. 10 core/modules/serialization/src/Normalizer/DateTimeIso8601Normalizer.php
  3. 9 core/modules/serialization/src/Normalizer/DateTimeIso8601Normalizer.php
  4. 8.9.x core/modules/serialization/src/Normalizer/DateTimeIso8601Normalizer.php

Namespace

Drupal\serialization\Normalizer

File

core/modules/serialization/src/Normalizer/DateTimeIso8601Normalizer.php

View source
<?php

namespace Drupal\serialization\Normalizer;

use Drupal\Core\Serialization\Attribute\JsonSchema;
use Drupal\Core\TypedData\Plugin\DataType\DateTimeIso8601;
use Drupal\datetime\Plugin\Field\FieldType\DateTimeItem;
use Drupal\datetime\Plugin\Field\FieldType\DateTimeItemInterface;
use Symfony\Component\Serializer\Exception\InvalidArgumentException;

/**
 * Converts values for the DateTimeIso8601 data type to RFC3339.
 *
 * @internal
 */
class DateTimeIso8601Normalizer extends DateTimeNormalizer {
  use SchematicNormalizerHelperTrait;
  
  /**
   * {@inheritdoc}
   */
  protected $allowedFormats = [
    'RFC 3339' => \DateTime::RFC3339,
    'ISO 8601' => \DateTime::ISO8601,
    // @todo Remove this in https://www.drupal.org/project/drupal/issues/2958416.
    // RFC3339 only covers combined date and time representations. For date-only
    // representations, we need to use ISO 8601. There isn't a constant on the
    // \DateTime class that we can use, so we have to hardcode the format.
    // @see https://en.wikipedia.org/wiki/ISO_8601#Calendar_dates
    // @see \Drupal\datetime\Plugin\Field\FieldType\DateTimeItemInterface::DATE_STORAGE_FORMAT
'date-only' => 'Y-m-d',
  ];
  
  /**
   * Normalizes data into a set of arrays/scalars.
   *
   * @param \Drupal\Core\TypedData\Plugin\DataType\DateTimeIso8601 $object
   *   Data to normalize.
   * @param string|null $format
   *   Format the normalization result will be encoded as.
   * @param array<string, mixed> $context
   *   Context options for the normalizer.
   *
   * @return array|string|int|float|bool|\ArrayObject<mixed, mixed>|null
   *   \ArrayObject is used to make sure an empty object is encoded as an
   *   object not an array.
   */
  public function normalize($object, $format = NULL, array $context = []) : array|string|int|float|bool|\ArrayObject|null {
    if ($format === 'json_schema') {
      return $this->getNormalizationSchema($object, $context);
    }
    assert($object instanceof DateTimeIso8601);
    $field_item = $object->getParent();
    // @todo Remove this in https://www.drupal.org/project/drupal/issues/2958416.
    if ($field_item instanceof DateTimeItem && $field_item->getFieldDefinition()
      ->getFieldStorageDefinition()
      ->getSetting('datetime_type') === DateTimeItem::DATETIME_TYPE_DATE) {
      $drupal_date_time = $object->getDateTime();
      if ($drupal_date_time === NULL) {
        return $drupal_date_time;
      }
      return $drupal_date_time->format($this->allowedFormats['date-only']);
    }
    return parent::normalize($object, $format, $context);
  }
  
  /**
   * {@inheritdoc}
   */
  public function denormalize($data, $class, $format = NULL, array $context = []) : mixed {
    // @todo Move the date-only handling out of here in https://www.drupal.org/project/drupal/issues/2958416.
    if (isset($context['target_instance'])) {
      $field_definition = $context['target_instance']->getFieldDefinition();
    }
    elseif (isset($context['field_definition'])) {
      $field_definition = $context['field_definition'];
    }
    else {
      throw new InvalidArgumentException('$context[\'target_instance\'] or $context[\'field_definition\'] must be set to denormalize with the DateTimeIso8601Normalizer');
    }
    $datetime_type = $field_definition->getSetting('datetime_type');
    $is_date_only = $datetime_type === DateTimeItem::DATETIME_TYPE_DATE;
    if ($is_date_only) {
      $context['datetime_allowed_formats'] = array_intersect_key($this->allowedFormats, [
        'date-only' => TRUE,
      ]);
      $datetime = parent::denormalize($data, $class, $format, $context);
      if (!$datetime instanceof \DateTime) {
        return $datetime;
      }
      return $datetime->format(DateTimeItemInterface::DATE_STORAGE_FORMAT);
    }
    $context['datetime_allowed_formats'] = array_diff_key($this->allowedFormats, [
      'date-only' => TRUE,
    ]);
    $datetime = parent::denormalize($data, $class, $format, $context);
    if (!$datetime instanceof \DateTime) {
      return $datetime;
    }
    $datetime->setTimezone(new \DateTimeZone(DateTimeItemInterface::STORAGE_TIMEZONE));
    return $datetime->format(DateTimeItemInterface::DATETIME_STORAGE_FORMAT);
  }
  
  /**
   * {@inheritdoc}
   */
  public function getSupportedTypes(?string $format) : array {
    return [
      DateTimeIso8601::class => TRUE,
    ];
  }

}

Classes

Title Deprecated Summary
DateTimeIso8601Normalizer Converts values for the DateTimeIso8601 data type to RFC3339.

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.