Skip to content
Snippets Groups Projects
Commit dcafd41f authored by catch's avatar catch
Browse files

Issue #3037970 by Berdir, Baysaa: Custom serialized field's data should be...

Issue #3037970 by Berdir, Baysaa: Custom serialized field's data should be normalized even if it's empty
parent 5cbcd4b5
Branches
Tags
No related merge requests found
Showing
with 289 additions and 4 deletions
......@@ -83,7 +83,7 @@ protected function constructValue($data, $context) {
// being automatically serialized, manually managed serialized properties
// expect to receive serialized input.
foreach ($serialized_property_names as $serialized_property_name) {
if (!empty($data[$serialized_property_name])) {
if (is_array($data) && array_key_exists($serialized_property_name, $data)) {
$data[$serialized_property_name] = serialize($data[$serialized_property_name]);
}
}
......
......@@ -3,6 +3,7 @@
namespace Drupal\Tests\hal\Kernel;
use Drupal\Core\Url;
use Drupal\entity_test\Entity\EntitySerializedField;
use Drupal\field\Entity\FieldConfig;
use Symfony\Component\Serializer\Exception\UnexpectedValueException;
......@@ -139,4 +140,52 @@ public function testMarkFieldForDeletion() {
$this->assertEqual($entity->field_test_text->count(), 0);
}
/**
* Tests normalizing/denormalizing serialized columns.
*/
public function testDenormalizeSerializedItem() {
$entity = EntitySerializedField::create(['serialized' => 'boo']);
$normalized = $this->serializer->normalize($entity, $this->format);
$this->setExpectedException(\LogicException::class, 'The generic FieldItemNormalizer cannot denormalize string values for "value" properties of the "serialized" field (field item class: Drupal\entity_test\Plugin\Field\FieldType\SerializedItem).');
$this->serializer->denormalize($normalized, EntitySerializedField::class, $this->format);
}
/**
* Tests normalizing/denormalizing invalid custom serialized fields.
*/
public function testDenormalizeInvalidCustomSerializedField() {
$entity = EntitySerializedField::create(['serialized_long' => serialize(['Hello world!'])]);
$normalized = $this->serializer->normalize($entity);
$this->assertEquals($normalized['serialized_long'][0]['value'], ['Hello world!']);
$normalized['serialized_long'][0]['value'] = 'boo';
$this->setExpectedException(\LogicException::class, 'The generic FieldItemNormalizer cannot denormalize string values for "value" properties of the "serialized_long" field (field item class: Drupal\Core\Field\Plugin\Field\FieldType\StringLongItem).');
$this->serializer->denormalize($normalized, EntitySerializedField::class);
}
/**
* Tests normalizing/denormalizing empty custom serialized fields.
*/
public function testDenormalizeEmptyCustomSerializedField() {
$entity = EntitySerializedField::create(['serialized_long' => serialize([])]);
$normalized = $this->serializer->normalize($entity);
$this->assertEquals([], $normalized['serialized_long'][0]['value']);
$entity = $this->serializer->denormalize($normalized, EntitySerializedField::class);
$this->assertEquals(serialize([]), $entity->get('serialized_long')->value);
}
/**
* Tests normalizing/denormalizing valid custom serialized fields.
*/
public function testDenormalizeValidCustomSerializedField() {
$entity = EntitySerializedField::create(['serialized_long' => serialize(['key' => 'value'])]);
$normalized = $this->serializer->normalize($entity);
$this->assertEquals(['key' => 'value'], $normalized['serialized_long'][0]['value']);
$entity = $this->serializer->denormalize($normalized, EntitySerializedField::class);
$this->assertEquals(serialize(['key' => 'value']), $entity->get('serialized_long')->value);
}
}
......@@ -62,7 +62,7 @@ protected function constructValue($data, $context) {
// being automatically serialized, manually managed serialized properties
// expect to receive serialized input.
foreach ($serialized_property_names as $serialized_property_name) {
if (!empty($data[$serialized_property_name])) {
if (is_array($data) && array_key_exists($serialized_property_name, $data)) {
$data[$serialized_property_name] = serialize($data[$serialized_property_name]);
}
}
......
......@@ -4,6 +4,7 @@
use Drupal\Component\Serialization\Json;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\entity_test\Entity\EntitySerializedField;
use Drupal\entity_test\Entity\EntityTestMulRev;
use Drupal\filter\Entity\FilterFormat;
use Drupal\Tests\rest\Functional\BcTimestampNormalizerUnixTestTrait;
......@@ -260,4 +261,92 @@ public function testDenormalize() {
}
}
/**
* Tests denormalizing serialized columns.
*/
public function testDenormalizeSerializedItem() {
$this->setExpectedException(\LogicException::class, 'The generic FieldItemNormalizer cannot denormalize string values for "value" properties of the "serialized" field (field item class: Drupal\entity_test\Plugin\Field\FieldType\SerializedItem).');
$this->serializer->denormalize([
'serialized' => [
[
'value' => 'boo',
],
],
'type' => 'entity_test_serialized_field',
], EntitySerializedField::class);
}
/**
* Tests normalizing/denormalizing custom serialized columns.
*/
public function testDenormalizeCustomSerializedItem() {
$entity = EntitySerializedField::create(['serialized_text' => serialize(['Hello world!'])]);
$normalized = $this->serializer->normalize($entity);
$this->assertEquals($normalized['serialized_text'][0]['value'], ['Hello world!']);
$this->setExpectedException(\LogicException::class, 'The generic FieldItemNormalizer cannot denormalize string values for "value" properties of the "serialized_text" field (field item class: Drupal\entity_test\Plugin\Field\FieldType\SerializedPropertyItem).');
$this->serializer->denormalize([
'serialized_text' => [
[
'value' => 'boo',
],
],
'type' => 'entity_test_serialized_field',
], EntitySerializedField::class);
}
/**
* Tests normalizing/denormalizing invalid custom serialized fields.
*/
public function testDenormalizeInvalidCustomSerializedField() {
$entity = EntitySerializedField::create(['serialized_long' => serialize(['Hello world!'])]);
$normalized = $this->serializer->normalize($entity);
$this->assertEquals($normalized['serialized_long'][0]['value'], ['Hello world!']);
$this->setExpectedException(\LogicException::class, 'The generic FieldItemNormalizer cannot denormalize string values for "value" properties of the "serialized_long" field (field item class: Drupal\Core\Field\Plugin\Field\FieldType\StringLongItem).');
$this->serializer->denormalize([
'serialized_long' => [
[
'value' => 'boo',
],
],
'type' => 'entity_test_serialized_field',
], EntitySerializedField::class);
}
/**
* Tests normalizing/denormalizing empty custom serialized fields.
*/
public function testDenormalizeEmptyCustomSerializedField() {
$entity = EntitySerializedField::create(['serialized_long' => serialize([])]);
$normalized = $this->serializer->normalize($entity);
$this->assertEquals([], $normalized['serialized_long'][0]['value']);
$entity = $this->serializer->denormalize($normalized, EntitySerializedField::class);
$this->assertEquals(serialize([]), $entity->get('serialized_long')->value);
}
/**
* Tests normalizing/denormalizing valid custom serialized fields.
*/
public function testDenormalizeValidCustomSerializedField() {
$entity = EntitySerializedField::create(['serialized_long' => serialize(['key' => 'value'])]);
$normalized = $this->serializer->normalize($entity);
$this->assertEquals(['key' => 'value'], $normalized['serialized_long'][0]['value']);
$entity = $this->serializer->denormalize($normalized, EntitySerializedField::class);
$this->assertEquals(serialize(['key' => 'value']), $entity->get('serialized_long')->value);
}
/**
* Tests normalizing/denormalizing using string values.
*/
public function testDenormalizeStringValue() {
$this->setExpectedException(\LogicException::class, 'The generic FieldItemNormalizer cannot denormalize string values for "value" properties of the "serialized_long" field (field item class: Drupal\Core\Field\Plugin\Field\FieldType\StringLongItem).');
$this->serializer->denormalize([
'serialized_long' => ['boo'],
'type' => 'entity_test_serialized_field',
], EntitySerializedField::class);
}
}
......@@ -303,7 +303,7 @@ protected function assertDenormalize(array $data) {
->shouldBeCalled();
}
// Avoid a static method call by returning dummy property data.
// Avoid a static method call by returning dummy serialized property data.
$this->fieldDefinition
->getFieldStorageDefinition()
->willReturn()
......
......@@ -113,7 +113,7 @@ public function testDenormalizeValidFormats($value, $expected) {
$timestamp_item->setValue(['value' => $expected])
->shouldBeCalled();
// Avoid a static method call by returning dummy property data.
// Avoid a static method call by returning dummy serialized property data.
$field_definition = $this->prophesize(FieldDefinitionInterface::class);
$timestamp_item
->getFieldDefinition()
......
<?php
namespace Drupal\entity_test\Entity;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Field\BaseFieldDefinition;
/**
* Defines a test class for testing fields with a serialized column.
*
* @ContentEntityType(
* id = "entity_test_serialized_field",
* label = @Translation("Test serialized fields"),
* entity_keys = {
* "id" = "id",
* "uuid" = "uuid",
* "bundle" = "type",
* "label" = "name"
* },
* base_table = "entity_test_serialized_fields",
* persistent_cache = FALSE,
* serialized_field_property_names = {
* "serialized_long" = {
* "value"
* }
* }
* )
*/
class EntitySerializedField extends EntityTest {
/**
* {@inheritdoc}
*/
public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
$fields = parent::baseFieldDefinitions($entity_type);
$fields['serialized'] = BaseFieldDefinition::create('serialized_item_test')
->setLabel(t('Serialized'));
$fields['serialized_text'] = BaseFieldDefinition::create('serialized_property_item_test')
->setLabel(t('Serialized text'));
$fields['serialized_long'] = BaseFieldDefinition::create('string_long')
->setLabel(t('Serialized long string'));
return $fields;
}
}
<?php
namespace Drupal\entity_test\Plugin\Field\FieldType;
use Drupal\Core\Field\FieldItemBase;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\Core\TypedData\DataDefinition;
/**
* Defines the 'serialized_item' entity field type.
*
* @FieldType(
* id = "serialized_item_test",
* label = @Translation("Test serialized field item"),
* description = @Translation("A field containing a serialized string value."),
* category = @Translation("Field"),
* )
*/
class SerializedItem extends FieldItemBase {
/**
* {@inheritdoc}
*/
public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
$properties['value'] = DataDefinition::create('string')
->setLabel(new TranslatableMarkup('Test serialized value'))
->setRequired(TRUE);
return $properties;
}
/**
* {@inheritdoc}
*/
public static function schema(FieldStorageDefinitionInterface $field_definition) {
return [
'columns' => [
'value' => [
'type' => 'blob',
'size' => 'big',
'serialize' => TRUE,
],
],
];
}
}
<?php
namespace Drupal\entity_test\Plugin\Field\FieldType;
use Drupal\Core\Field\FieldItemBase;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\Core\TypedData\DataDefinition;
/**
* Defines the 'serialized_property_item_test' entity field type.
*
* @FieldType(
* id = "serialized_property_item_test",
* label = @Translation("Test serialized property field item"),
* description = @Translation("A field containing a string representing serialized data."),
* category = @Translation("Field"),
* serialized_property_names = {
* "value"
* }
* )
*/
class SerializedPropertyItem extends FieldItemBase {
/**
* {@inheritdoc}
*/
public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
$properties['value'] = DataDefinition::create('string')
->setLabel(new TranslatableMarkup('Test serialized value'))
->setRequired(TRUE);
return $properties;
}
/**
* {@inheritdoc}
*/
public static function schema(FieldStorageDefinitionInterface $field_definition) {
return [
'columns' => [
'value' => [
'type' => 'text',
'size' => 'big',
],
],
];
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment