Skip to content
Snippets Groups Projects
Commit 5a0a0d29 authored by florisg's avatar florisg Committed by mandclu
Browse files

reroll for #3247537 Serialization issue in Rest

parent fa0557b7
No related branches found
Tags 3.5.0-beta2
No related merge requests found
<?php
namespace Drupal\smart_date\Normalizer;
use Drupal\serialization\Normalizer\TimestampItemNormalizer;
use Drupal\smart_date\Plugin\Field\FieldType\SmartDateItem;
use Drupal\smart_date\TypedData\Plugin\DataType\SmartDate;
/**
* Converts values for TimestampItem to and from common formats.
*
* Overrides FieldItemNormalizer to use \Drupal\serialization\Normalizer\TimestampNormalizer
*
* Overrides FieldItemNormalizer to
* - during normalization, add the 'format' key to assist consumers
* - during denormalization, use \Drupal\serialization\Normalizer\TimestampNormalizer
*/
class SmartDateItemNormalizer extends TimestampItemNormalizer {
/**
* {@inheritdoc}
*/
protected $supportedInterfaceOrClass = SmartDateItem::class;
/**
* {@inheritdoc}
*/
public function normalize($object, $format = NULL, array $context = []) {
return parent::normalize($object, $format, $context) + [
// 'format' is not a property on Timestamp objects. This is present to
// assist consumers of this data.
'format' => \DateTime::RFC3339,
];
}
/**
* {@inheritdoc}
*/
protected function constructValue($data, $context) {
if (!empty($data['format'])) {
$context['datetime_allowed_formats'] = [$data['format']];
}
return $this->serializer->denormalize($data, SmartDate::class, NULL, $context);
}
}
......@@ -2,35 +2,52 @@
namespace Drupal\smart_date\Normalizer;
use Drupal\hal\Normalizer\TimestampItemNormalizer;
use Drupal\smart_date\Plugin\Field\FieldType\SmartDateItem;
use DateTimeZone;
use DateTime;
use Drupal\serialization\Normalizer\TimestampNormalizer;
use Drupal\smart_date\TypedData\Plugin\DataType\SmartDate;
use Drupal\Core\TypedData\Plugin\DataType\StringData;
use Drupal\Core\TypedData\Plugin\DataType\IntegerData;
/**
* Enhances the smart date field so it can be denormalized.
*/
class SmartDateNormalizer extends TimestampItemNormalizer {
class SmartDateNormalizer extends TimestampNormalizer {
/**
* The interface or class that this Normalizer supports.
*
* @var string
*/
protected $supportedInterfaceOrClass = SmartDateItem::class;
protected $supportedInterfaceOrClass = SmartDate::class;
/**
* {@inheritdoc}
*/
public function denormalize($data, $class, $format = NULL, array $context = []) {
$field = parent::denormalize($data, $class, $format, $context);
// Repeat the denormalization of date string for end_value.
$timezone = new DateTimeZone('UTC');
$date = DateTime::createFromFormat($data['format'], $data['end_value'], $timezone);
$field->get('end_value')->setValue($date->getTimestamp());
return $field;
if(!empty($data['format'])) {
//REST request sender may provide own data format, try deploy it
//parent classes override $format anyway
$context['datetime_allowed_formats'] =
empty($context['datetime_allowed_formats']) ? [] : $context['datetime_allowed_formats'] + ['user_format' => $data['format']];
}
/*
@todo check this suggestion
not sure if this needed, seems properties should go from
\TypedData\Plugin\DataType\SmartData and fall down to existing
serializers may be via
TypedDataInternalPropertiesHelper::getNonInternalProperties()
but most inheritance done from Timestamps
*/
$res = [
'value' => parent::denormalize($data['value'], $class, $format, $context),
'end_value' => parent::denormalize($data['end_value'], $class, $format, $context),
//StringData and IntegerData do not have normalizers
'duration' => @$data['duration'],
'rrule' => @$data['rrule'],
'rrule_index' => @$data['rrule_index'],
'timezone' => @$data['timezone'],
];
return $res;
}
}
......@@ -5,7 +5,9 @@ namespace Drupal\smart_date;
use Drupal\Core\DependencyInjection\ContainerBuilder;
use Drupal\Core\DependencyInjection\ServiceProviderBase;
use Drupal\smart_date\Normalizer\SmartDateNormalizer;
use Drupal\smart_date\Normalizer\SmartDateItemNormalizer;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
/**
* Service Provider for Smart Date.
......@@ -17,13 +19,27 @@ class SmartDateServiceProvider extends ServiceProviderBase {
*/
public function alter(ContainerBuilder $container) {
$modules = $container->getParameter('container.modules');
if (isset($modules['serialization'])) {
// Serialization module is enabled, add our Smart Date normalizer.
// Priority of the normalizer must be higher than other
// general-purpose typed data and field item normalizers.
$smart_date = new Definition(SmartDateNormalizer::class);
$smart_date->addTag('normalizer', ['priority' => 30]);
$smart_date->addArgument(new Reference('config.factory'));
$container->setDefinition('smart_date.normalizer.smartdate', $smart_date);
$smart_date = new Definition(SmartDateItemNormalizer::class);
$smart_date->addTag('normalizer', ['priority' => 9]);
$container->setDefinition('smart_date.normalizer.smartdate_item', $smart_date);
}
if (isset($modules['hal'])) {
// HAL module is enabled, add our Smart Date normalizer.
// Priority of the normalizer must be higher than other
// general-purpose typed data and field item normalizers.
$smart_date = new Definition(SmartDateNormalizer::class);
$smart_date = new Definition(SmartDateItemNormalizer::class);
$smart_date->addTag('normalizer', ['priority' => 30]);
$container->setDefinition('smart_date.normalizer.smartdate.hal', $smart_date);
$container->setDefinition('smart_date.normalizer.smartdate_item.hal', $smart_date);
}
}
......
<?php
namespace Drupal\smart_date\TypedData\Plugin\DataType;
use Drupal\Core\Datetime\DrupalDateTime;
use Drupal\Core\TypedData\Type\DateTimeInterface;
use Drupal\Core\TypedData\Plugin\DataType\Timestamp;
/**
* The SmartDate data type.
*
* @DataType(
* id = "smart_date",
* label = @Translation("Smart Date")
* )
*/
class SmartDate extends Timestamp implements DateTimeInterface {
/**
* The data value as a UNIX timestamp.
*
* @var int
*/
protected $value;
protected $end_value;
protected $duration;
protected $rrule;
protected $rrule_index;
protected $timezone;
/**
* {@inheritdoc}
*/
public function getDateTime() {
if (isset($this->value)) {
return DrupalDateTime::createFromTimestamp($this->value);
}
}
/**
* {@inheritdoc}
*/
public function setDateTime(DrupalDateTime $dateTime, $notify = TRUE) {
$this->value = $dateTime->getTimestamp();
// Notify the parent of any changes.
if ($notify && isset($this->parent)) {
$this->parent->onChange($this->name);
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment