diff --git a/core/lib/Drupal/Core/TypedData/TypedDataInternalPropertiesHelper.php b/core/lib/Drupal/Core/TypedData/TypedDataInternalPropertiesHelper.php new file mode 100644 index 0000000000..96a240ce81 --- /dev/null +++ b/core/lib/Drupal/Core/TypedData/TypedDataInternalPropertiesHelper.php @@ -0,0 +1,27 @@ +getProperties(TRUE), function (TypedDataInterface $property) use ($context) { + return !$property->getDataDefinition()->isInternal(); + }); + } + +} diff --git a/core/modules/hal/src/Normalizer/ContentEntityNormalizer.php b/core/modules/hal/src/Normalizer/ContentEntityNormalizer.php index 178db1cc6e..22d59aa6cc 100644 --- a/core/modules/hal/src/Normalizer/ContentEntityNormalizer.php +++ b/core/modules/hal/src/Normalizer/ContentEntityNormalizer.php @@ -6,8 +6,8 @@ use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityManagerInterface; use Drupal\Core\Extension\ModuleHandlerInterface; +use Drupal\Core\TypedData\TypedDataInternalPropertiesHelper; use Drupal\hal\LinkManager\LinkManagerInterface; -use Drupal\serialization\Normalizer\ComplexDataPropertiesNormalizerTrait; use Drupal\serialization\Normalizer\FieldableEntityNormalizerTrait; use Symfony\Component\Serializer\Exception\UnexpectedValueException; @@ -18,8 +18,6 @@ class ContentEntityNormalizer extends NormalizerBase { use FieldableEntityNormalizerTrait; - use ComplexDataPropertiesNormalizerTrait; - /** * The interface or class that this Normalizer supports. * @@ -75,12 +73,17 @@ public function normalize($entity, $format = NULL, array $context = []) { ], ]; - $field_items = static::getNonInternalAccessibleProperties($entity->getTypedData(), $context); + $field_items = TypedDataInternalPropertiesHelper::getNonInternalProperties($entity->getTypedData(), $context); // If the fields to use were specified, only output those field values. if (isset($context['included_fields'])) { $field_items = array_intersect_key($field_items, array_flip($context['included_fields'])); } foreach ($field_items as $field) { + // Continue if the current user does not have access to view this field. + if (!$field->access('view', $context['account'])) { + continue; + } + $normalized_property = $this->serializer->normalize($field, $format, $context); $normalized = NestedArray::mergeDeep($normalized, $normalized_property); } diff --git a/core/modules/hal/src/Normalizer/FieldItemNormalizer.php b/core/modules/hal/src/Normalizer/FieldItemNormalizer.php index 4a44b03409..a216029a63 100644 --- a/core/modules/hal/src/Normalizer/FieldItemNormalizer.php +++ b/core/modules/hal/src/Normalizer/FieldItemNormalizer.php @@ -3,7 +3,7 @@ namespace Drupal\hal\Normalizer; use Drupal\Core\Field\FieldItemInterface; -use Drupal\serialization\Normalizer\ComplexDataPropertiesNormalizerTrait; +use Drupal\Core\TypedData\TypedDataInternalPropertiesHelper; use Symfony\Component\Serializer\Exception\InvalidArgumentException; /** @@ -11,8 +11,6 @@ */ class FieldItemNormalizer extends NormalizerBase { - use ComplexDataPropertiesNormalizerTrait; - /** * The interface or class that this Normalizer supports. * @@ -90,7 +88,13 @@ protected function constructValue($data, $context) { * An array of field item values, keyed by property name. */ protected function normalizedFieldValues(FieldItemInterface $field_item, $format, array $context) { - $denormalized = $this->normalizeProperties($field_item, $format, $context); + $denormalized = []; + // We normalize each individual property, so each can do their own casting, + // if needed. + /** @var \Drupal\Core\TypedData\TypedDataInterface $property */ + foreach (TypedDataInternalPropertiesHelper::getNonInternalProperties($field_item, $context) as $property_name => $property) { + $denormalized[$property_name] = $this->serializer->normalize($property, $format, $context); + } if (isset($context['langcode'])) { $denormalized['lang'] = $context['langcode']; diff --git a/core/modules/serialization/src/Normalizer/ComplexDataNormalizer.php b/core/modules/serialization/src/Normalizer/ComplexDataNormalizer.php index 399fcd5679..3478124b40 100644 --- a/core/modules/serialization/src/Normalizer/ComplexDataNormalizer.php +++ b/core/modules/serialization/src/Normalizer/ComplexDataNormalizer.php @@ -3,6 +3,7 @@ namespace Drupal\serialization\Normalizer; use Drupal\Core\TypedData\ComplexDataInterface; +use Drupal\Core\TypedData\TypedDataInternalPropertiesHelper; /** * Converts the Drupal entity object structures to a normalized array. @@ -16,8 +17,6 @@ */ class ComplexDataNormalizer extends NormalizerBase { - use ComplexDataPropertiesNormalizerTrait; - /** * The interface or class that this Normalizer supports. * @@ -29,19 +28,17 @@ class ComplexDataNormalizer extends NormalizerBase { * {@inheritdoc} */ public function normalize($object, $format = NULL, array $context = []) { + $attributes = []; // $object will not always match $supportedInterfaceOrClass. // @see \Drupal\serialization\Normalizer\EntityNormalizer // Other normalizers that extend this class may only provide $object that // implements \Traversable. if ($object instanceof ComplexDataInterface) { - $attributes = $this->normalizeProperties($object, $format, $context); + $object = TypedDataInternalPropertiesHelper::getNonInternalProperties($object, $context); } - else { - $attributes = []; - /** @var \Drupal\Core\TypedData\TypedDataInterface $property */ - foreach ($object as $name => $property) { - $attributes[$name] = $this->serializer->normalize($property, $format, $context); - } + /** @var \Drupal\Core\TypedData\TypedDataInterface $property */ + foreach ($object as $name => $property) { + $attributes[$name] = $this->serializer->normalize($property, $format, $context); } return $attributes; } diff --git a/core/modules/serialization/src/Normalizer/ComplexDataPropertiesNormalizerTrait.php b/core/modules/serialization/src/Normalizer/ComplexDataPropertiesNormalizerTrait.php deleted file mode 100644 index 6252792bf6..0000000000 --- a/core/modules/serialization/src/Normalizer/ComplexDataPropertiesNormalizerTrait.php +++ /dev/null @@ -1,57 +0,0 @@ - $property) { - $attributes[$name] = $this->serializer->normalize($property, $format, $context); - } - return $attributes; - } - - /** - * Gets an array non-internal properties from a complex data object. - * - * @param \Drupal\Core\TypedData\ComplexDataInterface $data - * The complex data object. - * @param array $context - * The context passed into the Normalizer. - * - * @return \Drupal\Core\TypedData\TypedDataInterface[] - * The non-internal properties, keyed by property name. - */ - public static function getNonInternalAccessibleProperties(ComplexDataInterface $data, array $context) { - return array_filter($data->getProperties(TRUE), function (TypedDataInterface $property) use ($context) { - if ($property instanceof AccessibleInterface && !$property->access('view', $context['account'])) { - return FALSE; - } - return !$property->getDataDefinition()->isInternal(); - }); - } - -} diff --git a/core/modules/serialization/src/Normalizer/ContentEntityNormalizer.php b/core/modules/serialization/src/Normalizer/ContentEntityNormalizer.php index d17f3ece11..96ef4040ee 100644 --- a/core/modules/serialization/src/Normalizer/ContentEntityNormalizer.php +++ b/core/modules/serialization/src/Normalizer/ContentEntityNormalizer.php @@ -1,14 +1,13 @@ NULL, ]; - /* @var \Drupal\Core\Entity\ContentEntityInterface $entity */ - return $this->normalizeProperties($entity->getTypedData(), $format, $context); + $attributes = []; + /** @var \Drupal\Core\Entity\Entity $entity */ + foreach (TypedDataInternalPropertiesHelper::getNonInternalProperties($entity->getTypedData(), $context) as $name => $field_items) { + if ($field_items->access('view', $context['account'])) { + $attributes[$name] = $this->serializer->normalize($field_items, $format, $context); + } + } + + return $attributes; } } diff --git a/core/modules/serialization/tests/src/Unit/Normalizer/ContentEntityNormalizerTest.php b/core/modules/serialization/tests/src/Unit/Normalizer/ContentEntityNormalizerTest.php index 674943b0c9..09c97f80a7 100644 --- a/core/modules/serialization/tests/src/Unit/Normalizer/ContentEntityNormalizerTest.php +++ b/core/modules/serialization/tests/src/Unit/Normalizer/ContentEntityNormalizerTest.php @@ -150,15 +150,13 @@ protected function createMockFieldListItem($access = TRUE, $user_context = NULL) ->method('access') ->with('view', $user_context) ->will($this->returnValue($access)); - if ($access) { - $data_definition = $this->prophesize(DataDefinitionInterface::class); - $data_definition->isInternal() - ->willReturn(FALSE) - ->shouldBeCalled(); - $mock->expects($this->once()) - ->method('getDataDefinition') - ->will($this->returnValue($data_definition->reveal())); - } + $data_definition = $this->prophesize(DataDefinitionInterface::class); + $data_definition->isInternal() + ->willReturn(FALSE) + ->shouldBeCalled(); + $mock->expects($this->once()) + ->method('getDataDefinition') + ->will($this->returnValue($data_definition->reveal())); return $mock; }