Issue #2365319 by damiankloip, larowlan: Entity normalization should check field access to avoid leaking data
parent
6414318293
commit
689797a6bd
|
@ -63,6 +63,11 @@ class ContentEntityNormalizer extends NormalizerBase {
|
||||||
* Implements \Symfony\Component\Serializer\Normalizer\NormalizerInterface::normalize()
|
* Implements \Symfony\Component\Serializer\Normalizer\NormalizerInterface::normalize()
|
||||||
*/
|
*/
|
||||||
public function normalize($entity, $format = NULL, array $context = array()) {
|
public function normalize($entity, $format = NULL, array $context = array()) {
|
||||||
|
$context += array(
|
||||||
|
'account' => NULL,
|
||||||
|
'included_fields' => NULL,
|
||||||
|
);
|
||||||
|
|
||||||
// Create the array of normalized fields, starting with the URI.
|
// Create the array of normalized fields, starting with the URI.
|
||||||
/** @var $entity \Drupal\Core\Entity\ContentEntityInterface */
|
/** @var $entity \Drupal\Core\Entity\ContentEntityInterface */
|
||||||
$normalized = array(
|
$normalized = array(
|
||||||
|
@ -90,9 +95,12 @@ class ContentEntityNormalizer extends NormalizerBase {
|
||||||
// Ignore the entity ID and revision ID.
|
// Ignore the entity ID and revision ID.
|
||||||
$exclude = array($entity->getEntityType()->getKey('id'), $entity->getEntityType()->getKey('revision'));
|
$exclude = array($entity->getEntityType()->getKey('id'), $entity->getEntityType()->getKey('revision'));
|
||||||
foreach ($fields as $field) {
|
foreach ($fields as $field) {
|
||||||
if (in_array($field->getFieldDefinition()->getName(), $exclude)) {
|
// Continue if this is an excluded field or the current user does not have
|
||||||
|
// access to view it.
|
||||||
|
if (in_array($field->getFieldDefinition()->getName(), $exclude) || !$field->access('view', $context['account'])) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$normalized_property = $this->serializer->normalize($field, $format, $context);
|
$normalized_property = $this->serializer->normalize($field, $format, $context);
|
||||||
$normalized = NestedArray::mergeDeep($normalized, $normalized_property);
|
$normalized = NestedArray::mergeDeep($normalized, $normalized_property);
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,6 +92,9 @@ class EntityTest extends NormalizerTestBase {
|
||||||
$vocabulary = entity_create('taxonomy_vocabulary', array('vid' => 'example_vocabulary'));
|
$vocabulary = entity_create('taxonomy_vocabulary', array('vid' => 'example_vocabulary'));
|
||||||
$vocabulary->save();
|
$vocabulary->save();
|
||||||
|
|
||||||
|
$account = entity_create('user', array('name' => $this->randomMachineName()));
|
||||||
|
$account->save();
|
||||||
|
|
||||||
// @todo Until https://www.drupal.org/node/2327935 is fixed, if no parent is
|
// @todo Until https://www.drupal.org/node/2327935 is fixed, if no parent is
|
||||||
// set, the test fails because target_id => 0 is reserialized to NULL.
|
// set, the test fails because target_id => 0 is reserialized to NULL.
|
||||||
$term_parent = entity_create('taxonomy_term', array(
|
$term_parent = entity_create('taxonomy_term', array(
|
||||||
|
@ -113,9 +116,9 @@ class EntityTest extends NormalizerTestBase {
|
||||||
$original_values = $term->toArray();
|
$original_values = $term->toArray();
|
||||||
unset($original_values['tid']);
|
unset($original_values['tid']);
|
||||||
|
|
||||||
$normalized = $this->serializer->normalize($term, $this->format);
|
$normalized = $this->serializer->normalize($term, $this->format, ['account' => $account]);
|
||||||
|
|
||||||
$denormalized_term = $this->serializer->denormalize($normalized, 'Drupal\taxonomy\Entity\Term', $this->format);
|
$denormalized_term = $this->serializer->denormalize($normalized, 'Drupal\taxonomy\Entity\Term', $this->format, ['account' => $account]);
|
||||||
|
|
||||||
// Verify that the ID and revision ID were skipped by the normalizer.
|
// Verify that the ID and revision ID were skipped by the normalizer.
|
||||||
$this->assertEqual(NULL, $denormalized_term->id());
|
$this->assertEqual(NULL, $denormalized_term->id());
|
||||||
|
@ -133,8 +136,8 @@ class EntityTest extends NormalizerTestBase {
|
||||||
$node_type = entity_create('node_type', array('type' => 'example_type'));
|
$node_type = entity_create('node_type', array('type' => 'example_type'));
|
||||||
$node_type->save();
|
$node_type->save();
|
||||||
|
|
||||||
$user = entity_create('user', array('name' => $this->randomMachineName()));
|
$account = entity_create('user', array('name' => $this->randomMachineName()));
|
||||||
$user->save();
|
$account->save();
|
||||||
|
|
||||||
// Add comment type.
|
// Add comment type.
|
||||||
$this->container->get('entity.manager')->getStorage('comment_type')->create(array(
|
$this->container->get('entity.manager')->getStorage('comment_type')->create(array(
|
||||||
|
@ -147,7 +150,7 @@ class EntityTest extends NormalizerTestBase {
|
||||||
|
|
||||||
$node = entity_create('node', array(
|
$node = entity_create('node', array(
|
||||||
'title' => $this->randomMachineName(),
|
'title' => $this->randomMachineName(),
|
||||||
'uid' => $user->id(),
|
'uid' => $account->id(),
|
||||||
'type' => $node_type->id(),
|
'type' => $node_type->id(),
|
||||||
'status' => NODE_PUBLISHED,
|
'status' => NODE_PUBLISHED,
|
||||||
'promote' => 1,
|
'promote' => 1,
|
||||||
|
@ -160,7 +163,7 @@ class EntityTest extends NormalizerTestBase {
|
||||||
$node->save();
|
$node->save();
|
||||||
|
|
||||||
$parent_comment = entity_create('comment', array(
|
$parent_comment = entity_create('comment', array(
|
||||||
'uid' => $user->id(),
|
'uid' => $account->id(),
|
||||||
'subject' => $this->randomMachineName(),
|
'subject' => $this->randomMachineName(),
|
||||||
'comment_body' => [
|
'comment_body' => [
|
||||||
'value' => $this->randomMachineName(),
|
'value' => $this->randomMachineName(),
|
||||||
|
@ -173,7 +176,7 @@ class EntityTest extends NormalizerTestBase {
|
||||||
$parent_comment->save();
|
$parent_comment->save();
|
||||||
|
|
||||||
$comment = entity_create('comment', array(
|
$comment = entity_create('comment', array(
|
||||||
'uid' => $user->id(),
|
'uid' => $account->id(),
|
||||||
'subject' => $this->randomMachineName(),
|
'subject' => $this->randomMachineName(),
|
||||||
'comment_body' => [
|
'comment_body' => [
|
||||||
'value' => $this->randomMachineName(),
|
'value' => $this->randomMachineName(),
|
||||||
|
@ -189,10 +192,16 @@ class EntityTest extends NormalizerTestBase {
|
||||||
$comment->save();
|
$comment->save();
|
||||||
|
|
||||||
$original_values = $comment->toArray();
|
$original_values = $comment->toArray();
|
||||||
unset($original_values['cid']);
|
// cid will not exist and hostname will always be denied view access.
|
||||||
|
unset($original_values['cid'], $original_values['hostname']);
|
||||||
|
|
||||||
$normalized = $this->serializer->normalize($comment, $this->format);
|
$normalized = $this->serializer->normalize($comment, $this->format, ['account' => $account]);
|
||||||
$denormalized_comment = $this->serializer->denormalize($normalized, 'Drupal\comment\Entity\Comment', $this->format);
|
|
||||||
|
// Assert that the hostname field does not appear at all in the normalized
|
||||||
|
// data.
|
||||||
|
$this->assertFalse(array_key_exists('hostname', $normalized), 'Hostname was not found in normalized comment data.');
|
||||||
|
|
||||||
|
$denormalized_comment = $this->serializer->denormalize($normalized, 'Drupal\comment\Entity\Comment', $this->format, ['account' => $account]);
|
||||||
|
|
||||||
// Verify that the ID and revision ID were skipped by the normalizer.
|
// Verify that the ID and revision ID were skipped by the normalizer.
|
||||||
$this->assertEqual(NULL, $denormalized_comment->id());
|
$this->assertEqual(NULL, $denormalized_comment->id());
|
||||||
|
|
|
@ -41,7 +41,7 @@ class CreateTest extends RESTTestBase {
|
||||||
|
|
||||||
$entity_values = $this->entityValues($entity_type);
|
$entity_values = $this->entityValues($entity_type);
|
||||||
$entity = entity_create($entity_type, $entity_values);
|
$entity = entity_create($entity_type, $entity_values);
|
||||||
$serialized = $serializer->serialize($entity, $this->defaultFormat);
|
$serialized = $serializer->serialize($entity, $this->defaultFormat, ['account' => $account]);
|
||||||
// Create the entity over the REST API.
|
// Create the entity over the REST API.
|
||||||
$this->httpRequest('entity/' . $entity_type, 'POST', $serialized, $this->defaultMimeType);
|
$this->httpRequest('entity/' . $entity_type, 'POST', $serialized, $this->defaultMimeType);
|
||||||
$this->assertResponse(201);
|
$this->assertResponse(201);
|
||||||
|
@ -68,23 +68,24 @@ class CreateTest extends RESTTestBase {
|
||||||
// Try to create an entity with an access protected field.
|
// Try to create an entity with an access protected field.
|
||||||
// @see entity_test_entity_field_access()
|
// @see entity_test_entity_field_access()
|
||||||
if ($entity_type == 'entity_test') {
|
if ($entity_type == 'entity_test') {
|
||||||
$entity->field_test_text->value = 'no access value';
|
$context = ['account' => $account];
|
||||||
$serialized = $serializer->serialize($entity, $this->defaultFormat);
|
$normalized = $serializer->normalize($entity, $this->defaultFormat, $context);
|
||||||
$this->httpRequest('entity/' . $entity_type, 'POST', $serialized, $this->defaultMimeType);
|
$normalized['field_test_text'][0]['value'] = 'no access value';
|
||||||
|
$this->httpRequest('entity/' . $entity_type, 'POST', $serializer->serialize($normalized, $this->defaultFormat, $context), $this->defaultMimeType);
|
||||||
$this->assertResponse(403);
|
$this->assertResponse(403);
|
||||||
$this->assertFalse(entity_load_multiple($entity_type, NULL, TRUE), 'No entity has been created in the database.');
|
$this->assertFalse(entity_load_multiple($entity_type, NULL, TRUE), 'No entity has been created in the database.');
|
||||||
|
|
||||||
// Try to create a field with a text format this user has no access to.
|
// Try to create a field with a text format this user has no access to.
|
||||||
$entity->field_test_text->value = $entity_values['field_test_text'][0]['value'];
|
$entity->field_test_text->value = $entity_values['field_test_text'][0]['value'];
|
||||||
$entity->field_test_text->format = 'full_html';
|
$entity->field_test_text->format = 'full_html';
|
||||||
$serialized = $serializer->serialize($entity, $this->defaultFormat);
|
$serialized = $serializer->serialize($entity, $this->defaultFormat, $context);
|
||||||
$this->httpRequest('entity/' . $entity_type, 'POST', $serialized, $this->defaultMimeType);
|
$this->httpRequest('entity/' . $entity_type, 'POST', $serialized, $this->defaultMimeType);
|
||||||
$this->assertResponse(422);
|
$this->assertResponse(422);
|
||||||
$this->assertFalse(entity_load_multiple($entity_type, NULL, TRUE), 'No entity has been created in the database.');
|
$this->assertFalse(entity_load_multiple($entity_type, NULL, TRUE), 'No entity has been created in the database.');
|
||||||
|
|
||||||
// Restore the valid test value.
|
// Restore the valid test value.
|
||||||
$entity->field_test_text->format = 'plain_text';
|
$entity->field_test_text->format = 'plain_text';
|
||||||
$serialized = $serializer->serialize($entity, $this->defaultFormat);
|
$serialized = $serializer->serialize($entity, $this->defaultFormat, $context);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to send invalid data that cannot be correctly deserialized.
|
// Try to send invalid data that cannot be correctly deserialized.
|
||||||
|
@ -98,7 +99,7 @@ class CreateTest extends RESTTestBase {
|
||||||
// Try to send invalid data to trigger the entity validation constraints.
|
// Try to send invalid data to trigger the entity validation constraints.
|
||||||
// Send a UUID that is too long.
|
// Send a UUID that is too long.
|
||||||
$entity->set('uuid', $this->randomMachineName(129));
|
$entity->set('uuid', $this->randomMachineName(129));
|
||||||
$invalid_serialized = $serializer->serialize($entity, $this->defaultFormat);
|
$invalid_serialized = $serializer->serialize($entity, $this->defaultFormat, $context);
|
||||||
$response = $this->httpRequest('entity/' . $entity_type, 'POST', $invalid_serialized, $this->defaultMimeType);
|
$response = $this->httpRequest('entity/' . $entity_type, 'POST', $invalid_serialized, $this->defaultMimeType);
|
||||||
$this->assertResponse(422);
|
$this->assertResponse(422);
|
||||||
$error = Json::decode($response);
|
$error = Json::decode($response);
|
||||||
|
|
|
@ -40,6 +40,8 @@ class UpdateTest extends RESTTestBase {
|
||||||
$account = $this->drupalCreateUser($permissions);
|
$account = $this->drupalCreateUser($permissions);
|
||||||
$this->drupalLogin($account);
|
$this->drupalLogin($account);
|
||||||
|
|
||||||
|
$context = ['account' => $account];
|
||||||
|
|
||||||
// Create an entity and save it to the database.
|
// Create an entity and save it to the database.
|
||||||
$entity = $this->entityCreate($entity_type);
|
$entity = $this->entityCreate($entity_type);
|
||||||
$entity->save();
|
$entity->save();
|
||||||
|
@ -52,7 +54,7 @@ class UpdateTest extends RESTTestBase {
|
||||||
$patch_entity = entity_create($entity_type, $patch_values);
|
$patch_entity = entity_create($entity_type, $patch_values);
|
||||||
// We don't want to overwrite the UUID.
|
// We don't want to overwrite the UUID.
|
||||||
unset($patch_entity->uuid);
|
unset($patch_entity->uuid);
|
||||||
$serialized = $serializer->serialize($patch_entity, $this->defaultFormat);
|
$serialized = $serializer->serialize($patch_entity, $this->defaultFormat, $context);
|
||||||
|
|
||||||
// Update the entity over the REST API.
|
// Update the entity over the REST API.
|
||||||
$this->httpRequest($entity->getSystemPath(), 'PATCH', $serialized, $this->defaultMimeType);
|
$this->httpRequest($entity->getSystemPath(), 'PATCH', $serialized, $this->defaultMimeType);
|
||||||
|
@ -64,7 +66,7 @@ class UpdateTest extends RESTTestBase {
|
||||||
|
|
||||||
// Make sure that the field does not get deleted if it is not present in the
|
// Make sure that the field does not get deleted if it is not present in the
|
||||||
// PATCH request.
|
// PATCH request.
|
||||||
$normalized = $serializer->normalize($patch_entity, $this->defaultFormat);
|
$normalized = $serializer->normalize($patch_entity, $this->defaultFormat, $context);
|
||||||
unset($normalized['field_test_text']);
|
unset($normalized['field_test_text']);
|
||||||
$serialized = $serializer->encode($normalized, $this->defaultFormat);
|
$serialized = $serializer->encode($normalized, $this->defaultFormat);
|
||||||
$this->httpRequest($entity->getSystemPath(), 'PATCH', $serialized, $this->defaultMimeType);
|
$this->httpRequest($entity->getSystemPath(), 'PATCH', $serialized, $this->defaultMimeType);
|
||||||
|
@ -100,8 +102,9 @@ class UpdateTest extends RESTTestBase {
|
||||||
$this->assertEqual($entity->field_test_text->value, 'no delete access value', 'Text field was not deleted.');
|
$this->assertEqual($entity->field_test_text->value, 'no delete access value', 'Text field was not deleted.');
|
||||||
|
|
||||||
// Try to update an access protected field.
|
// Try to update an access protected field.
|
||||||
$patch_entity->get('field_test_text')->value = 'no access value';
|
$normalized = $serializer->normalize($patch_entity, $this->defaultFormat, $context);
|
||||||
$serialized = $serializer->serialize($patch_entity, $this->defaultFormat);
|
$normalized['field_test_text'][0]['value'] = 'no access value';
|
||||||
|
$serialized = $serializer->serialize($normalized, $this->defaultFormat, $context);
|
||||||
$this->httpRequest($entity->getSystemPath(), 'PATCH', $serialized, $this->defaultMimeType);
|
$this->httpRequest($entity->getSystemPath(), 'PATCH', $serialized, $this->defaultMimeType);
|
||||||
$this->assertResponse(403);
|
$this->assertResponse(403);
|
||||||
|
|
||||||
|
@ -114,7 +117,7 @@ class UpdateTest extends RESTTestBase {
|
||||||
'value' => 'test',
|
'value' => 'test',
|
||||||
'format' => 'full_html',
|
'format' => 'full_html',
|
||||||
));
|
));
|
||||||
$serialized = $serializer->serialize($patch_entity, $this->defaultFormat);
|
$serialized = $serializer->serialize($patch_entity, $this->defaultFormat, $context);
|
||||||
$this->httpRequest($entity->getSystemPath(), 'PATCH', $serialized, $this->defaultMimeType);
|
$this->httpRequest($entity->getSystemPath(), 'PATCH', $serialized, $this->defaultMimeType);
|
||||||
$this->assertResponse(422);
|
$this->assertResponse(422);
|
||||||
|
|
||||||
|
@ -139,7 +142,7 @@ class UpdateTest extends RESTTestBase {
|
||||||
// Try to send invalid data to trigger the entity validation constraints.
|
// Try to send invalid data to trigger the entity validation constraints.
|
||||||
// Send a UUID that is too long.
|
// Send a UUID that is too long.
|
||||||
$entity->set('uuid', $this->randomMachineName(129));
|
$entity->set('uuid', $this->randomMachineName(129));
|
||||||
$invalid_serialized = $serializer->serialize($entity, $this->defaultFormat);
|
$invalid_serialized = $serializer->serialize($entity, $this->defaultFormat, $context);
|
||||||
$response = $this->httpRequest($entity->getSystemPath(), 'PATCH', $invalid_serialized, $this->defaultMimeType);
|
$response = $this->httpRequest($entity->getSystemPath(), 'PATCH', $invalid_serialized, $this->defaultMimeType);
|
||||||
$this->assertResponse(422);
|
$this->assertResponse(422);
|
||||||
$error = Json::decode($response);
|
$error = Json::decode($response);
|
||||||
|
|
|
@ -7,6 +7,11 @@ services:
|
||||||
tags:
|
tags:
|
||||||
- { name: normalizer }
|
- { name: normalizer }
|
||||||
arguments: ['@entity.manager']
|
arguments: ['@entity.manager']
|
||||||
|
serializer.normalizer.content_entity:
|
||||||
|
class: Drupal\serialization\Normalizer\ContentEntityNormalizer
|
||||||
|
tags:
|
||||||
|
- { name: normalizer }
|
||||||
|
arguments: ['@entity.manager']
|
||||||
serializer.normalizer.entity:
|
serializer.normalizer.entity:
|
||||||
class: Drupal\serialization\Normalizer\EntityNormalizer
|
class: Drupal\serialization\Normalizer\EntityNormalizer
|
||||||
tags:
|
tags:
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Contains \Drupal\serialization\Normalizer\ContentEntityNormalizer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Drupal\serialization\Normalizer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normalizes/denormalizes Drupal content entities into an array structure.
|
||||||
|
*/
|
||||||
|
class ContentEntityNormalizer extends EntityNormalizer {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The interface or class that this Normalizer supports.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $supportedInterfaceOrClass = ['Drupal\Core\Entity\ContentEntityInterface'];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function normalize($object, $format = NULL, array $context = array()) {
|
||||||
|
$context += array(
|
||||||
|
'account' => NULL,
|
||||||
|
);
|
||||||
|
|
||||||
|
$attributes = [];
|
||||||
|
foreach ($object as $name => $field) {
|
||||||
|
if ($field->access('view', $context['account'])) {
|
||||||
|
$attributes[$name] = $this->serializer->normalize($field, $format, $context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $attributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -9,6 +9,7 @@ namespace Drupal\serialization\Tests;
|
||||||
|
|
||||||
use Drupal\Core\Language\LanguageInterface;
|
use Drupal\Core\Language\LanguageInterface;
|
||||||
use Drupal\Component\Utility\String;
|
use Drupal\Component\Utility\String;
|
||||||
|
use Drupal\user\Entity\User;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests that entities can be serialized to supported core formats.
|
* Tests that entities can be serialized to supported core formats.
|
||||||
|
@ -48,6 +49,8 @@ class EntitySerializationTest extends NormalizerTestBase {
|
||||||
protected function setUp() {
|
protected function setUp() {
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
|
|
||||||
|
// User create needs sequence table.
|
||||||
|
$this->installSchema('system', array('sequences'));
|
||||||
// Create a test entity to serialize.
|
// Create a test entity to serialize.
|
||||||
$this->values = array(
|
$this->values = array(
|
||||||
'name' => $this->randomMachineName(),
|
'name' => $this->randomMachineName(),
|
||||||
|
@ -105,6 +108,17 @@ class EntitySerializationTest extends NormalizerTestBase {
|
||||||
$this->assertEqual($expected[$fieldName], $normalized[$fieldName], "ComplexDataNormalizer produces expected array for $fieldName.");
|
$this->assertEqual($expected[$fieldName], $normalized[$fieldName], "ComplexDataNormalizer produces expected array for $fieldName.");
|
||||||
}
|
}
|
||||||
$this->assertEqual(array_diff_key($normalized, $expected), array(), 'No unexpected data is added to the normalized array.');
|
$this->assertEqual(array_diff_key($normalized, $expected), array(), 'No unexpected data is added to the normalized array.');
|
||||||
|
|
||||||
|
// Test password isn't available.
|
||||||
|
$account = User::create([
|
||||||
|
'name' => 'foo',
|
||||||
|
'mail' => 'foo@example.com',
|
||||||
|
'pass' => '123456',
|
||||||
|
]);
|
||||||
|
$account->save();
|
||||||
|
$normalized = $this->serializer->normalize($account);
|
||||||
|
$this->assertTrue(empty($normalized['pass']));
|
||||||
|
$this->assertTrue(empty($normalized['mail']));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -0,0 +1,155 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Contains \Drupal\Tests\serialization\Unit\Normalizer\ContentEntityNormalizerTest.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Drupal\Tests\serialization\Unit\Normalizer;
|
||||||
|
|
||||||
|
use Drupal\serialization\Normalizer\ContentEntityNormalizer;
|
||||||
|
use Drupal\Tests\UnitTestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @coversDefaultClass \Drupal\serialization\Normalizer\ContentEntityNormalizer
|
||||||
|
* @group serialization
|
||||||
|
*/
|
||||||
|
class ContentEntityNormalizerTest extends UnitTestCase {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The mock entity manager.
|
||||||
|
*
|
||||||
|
* @var \Drupal\Core\Entity\EntityManagerInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||||
|
*/
|
||||||
|
protected $entityManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The mock serializer.
|
||||||
|
*
|
||||||
|
* @var \Symfony\Component\Serializer\SerializerInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||||
|
*/
|
||||||
|
protected $serializer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The normalizer under test.
|
||||||
|
*
|
||||||
|
* @var \Drupal\serialization\Normalizer\ContentEntityNormalizer
|
||||||
|
*/
|
||||||
|
protected $contentEntityNormalizer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
protected function setUp() {
|
||||||
|
$this->entityManager = $this->getMock('Drupal\Core\Entity\EntityManagerInterface');
|
||||||
|
$this->contentEntityNormalizer = new ContentEntityNormalizer($this->entityManager);
|
||||||
|
$this->serializer = $this->getMockBuilder('Symfony\Component\Serializer\Serializer')
|
||||||
|
->disableOriginalConstructor()
|
||||||
|
->setMethods(array('normalize'))
|
||||||
|
->getMock();
|
||||||
|
$this->contentEntityNormalizer->setSerializer($this->serializer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers ::supportsNormalization
|
||||||
|
*/
|
||||||
|
public function testSupportsNormalization() {
|
||||||
|
$content_mock = $this->getMock('Drupal\Core\Entity\ContentEntityInterface');
|
||||||
|
$config_mock = $this->getMock('Drupal\Core\Entity\ConfigEntityInterface');
|
||||||
|
$this->assertTrue($this->contentEntityNormalizer->supportsNormalization($content_mock));
|
||||||
|
$this->assertFalse($this->contentEntityNormalizer->supportsNormalization($config_mock));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests the normalize() method.
|
||||||
|
*
|
||||||
|
* @covers ::normalize
|
||||||
|
*/
|
||||||
|
public function testNormalize() {
|
||||||
|
$this->serializer->expects($this->any())
|
||||||
|
->method('normalize')
|
||||||
|
->with($this->containsOnlyInstancesOf('Drupal\Core\Field\FieldItemListInterface'), 'test_format', ['account' => NULL])
|
||||||
|
->will($this->returnValue('test'));
|
||||||
|
|
||||||
|
$definitions = array(
|
||||||
|
'field_1' => $this->createMockFieldListItem(),
|
||||||
|
'field_2' => $this->createMockFieldListItem(FALSE),
|
||||||
|
);
|
||||||
|
$content_entity_mock = $this->createMockForContentEntity($definitions);
|
||||||
|
|
||||||
|
$normalized = $this->contentEntityNormalizer->normalize($content_entity_mock, 'test_format');
|
||||||
|
|
||||||
|
$this->assertArrayHasKey('field_1', $normalized);
|
||||||
|
$this->assertEquals('test', $normalized['field_1']);
|
||||||
|
$this->assertArrayNotHasKey('field_2', $normalized);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests the normalize() method with account context passed.
|
||||||
|
*
|
||||||
|
* @covers ::normalize
|
||||||
|
*/
|
||||||
|
public function testNormalizeWithAccountContext() {
|
||||||
|
$mock_account = $this->getMock('Drupal\Core\Session\AccountInterface');
|
||||||
|
|
||||||
|
$context = [
|
||||||
|
'account' => $mock_account,
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->serializer->expects($this->any())
|
||||||
|
->method('normalize')
|
||||||
|
->with($this->containsOnlyInstancesOf('Drupal\Core\Field\FieldItemListInterface'), 'test_format', $context)
|
||||||
|
->will($this->returnValue('test'));
|
||||||
|
|
||||||
|
// The mock account should get passed directly into the access() method on
|
||||||
|
// field items from $context['account'].
|
||||||
|
$definitions = array(
|
||||||
|
'field_1' => $this->createMockFieldListItem(TRUE, $mock_account),
|
||||||
|
'field_2' => $this->createMockFieldListItem(FALSE, $mock_account),
|
||||||
|
);
|
||||||
|
$content_entity_mock = $this->createMockForContentEntity($definitions);
|
||||||
|
|
||||||
|
$normalized = $this->contentEntityNormalizer->normalize($content_entity_mock, 'test_format', $context);
|
||||||
|
|
||||||
|
$this->assertArrayHasKey('field_1', $normalized);
|
||||||
|
$this->assertEquals('test', $normalized['field_1']);
|
||||||
|
$this->assertArrayNotHasKey('field_2', $normalized);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a mock content entity.
|
||||||
|
*
|
||||||
|
* @param $definitions
|
||||||
|
*
|
||||||
|
* @return \PHPUnit_Framework_MockObject_MockObject
|
||||||
|
*/
|
||||||
|
public function createMockForContentEntity($definitions) {
|
||||||
|
$content_entity_mock = $this->getMockBuilder('Drupal\Core\Entity\ContentEntityBase')
|
||||||
|
->disableOriginalConstructor()
|
||||||
|
->setMethods(array('getFields'))
|
||||||
|
->getMockForAbstractClass();
|
||||||
|
$content_entity_mock->expects($this->once())
|
||||||
|
->method('getFields')
|
||||||
|
->will($this->returnValue($definitions));
|
||||||
|
|
||||||
|
return $content_entity_mock;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a mock field list item.
|
||||||
|
*
|
||||||
|
* @param bool $access
|
||||||
|
*
|
||||||
|
* @return \Drupal\Core\Field\FieldItemListInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||||
|
*/
|
||||||
|
protected function createMockFieldListItem($access = TRUE, $user_context = NULL) {
|
||||||
|
$mock = $this->getMock('Drupal\Core\Field\FieldItemListInterface');
|
||||||
|
$mock->expects($this->once())
|
||||||
|
->method('access')
|
||||||
|
->with('view', $user_context)
|
||||||
|
->will($this->returnValue($access));
|
||||||
|
|
||||||
|
return $mock;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue