diff --git a/core/modules/rest/src/Tests/NodeTest.php b/core/modules/rest/src/Tests/NodeTest.php index 2c8de1e..ccbee60 100644 --- a/core/modules/rest/src/Tests/NodeTest.php +++ b/core/modules/rest/src/Tests/NodeTest.php @@ -8,7 +8,7 @@ namespace Drupal\rest\Tests; use Drupal\Core\Url; -use Drupal\rest\Tests\RESTTestBase; +use Drupal\node\Entity\Node; /** * Tests special cases for node entities. @@ -90,4 +90,40 @@ public function testNodes() { // Make sure that the UUID of the node has not changed. $this->assertEqual($node->get('uuid')->getValue(), $updated_node->get('uuid')->getValue(), 'UUID was not changed.'); } + + /** + * Test creating a node using json serialization. + */ + public function testCreate() { + $this->enableNodeConfiguration('POST', 'create'); + $this->enableService('entity:node', 'POST', 'json'); + + // Create a title. + $title = $this->randomString(); + + // Data to be used for serialization. + $data = [ + 'type' => [['target_id' => 'resttest']], + 'title' => [['value' => $title ]], + ]; + + // Create a JSON version of a simple node with the title. + $serialized = $this->container->get('serializer')->serialize($data, 'json'); + + // Post to the REST service to create the node. + $this->httpRequest('/entity/node', 'POST', $serialized, 'application/json'); + + // Make sure the response is "CREATED". + $this->assertResponse(201); + + /** @var \Drupal\node\Entity\Node $node */ + // Load the newly created node. + $node = Node::load(1); + + // Test that the title is the same as what we posted. + $this->assertEqual($node->title->value, $title); + + // Make sure the request returned a redirect header to view the node. + $this->assertHeader('Location', $node->url('canonical', ['absolute' => TRUE])); + } } diff --git a/core/modules/serialization/src/Normalizer/EntityNormalizer.php b/core/modules/serialization/src/Normalizer/EntityNormalizer.php index 5e81b5a..dfea028 100644 --- a/core/modules/serialization/src/Normalizer/EntityNormalizer.php +++ b/core/modules/serialization/src/Normalizer/EntityNormalizer.php @@ -43,22 +43,45 @@ public function __construct(EntityManagerInterface $entity_manager) { /** * {@inheritdoc} */ - public function denormalize($data, $class, $format = NULL, array $context = array()) { - if (empty($context['entity_type'])) { - throw new UnexpectedValueException('Entity type parameter must be included in context.'); - } + public function denormalize($data, $class, $format = NULL, array $context = []) { + // Get the entity type ID letting the context definition override the $class. + $entity_type_id = !empty($context['entity_type']) ? $context['entity_type'] + : $this->entityManager->getEntityTypeFromClass($class); + + /** @var \Drupal\Core\Entity\EntityTypeInterface $entity_type */ + // Get the entity type definition. + $entity_type = $this->entityManager->getDefinition($entity_type_id, FALSE); - $entity_type = $this->entityManager->getDefinition($context['entity_type']); + // Don't try to create an entity without an entity type id. + if (!$entity_type) { + throw new UnexpectedValueException('A valid entity type is required for denormalization.'); + } - // The bundle property behaves differently from other entity properties. - // i.e. the nested structure with a 'value' key does not work. + // The bundle property will be required to denormalize a bundleable entity. if ($entity_type->hasKey('bundle')) { $bundle_key = $entity_type->getKey('bundle'); - $type = $data[$bundle_key][0]['value']; - $data[$bundle_key] = $type; + // Get the base field definitions for this entity type. + $base_field_definitions = $this->entityManager + ->getBaseFieldDefinitions($entity_type_id); + // Get the ID key from the base field definition for the bundle key. + $key_id = $base_field_definitions[$bundle_key] + ? $base_field_definitions[$bundle_key]->getFieldStorageDefinition()->getMainPropertyName() + : 'value'; + // Normalize the bundle if it is not explicitly set. + $data[$bundle_key] = $data[$bundle_key][0][$key_id] ?: $data[$bundle_key]; + // Make sure the bundle is a simple string. + if (!is_string($data[$bundle_key])) { + throw new UnexpectedValueException('A valid bundle is required for denormalization.'); + } } - return $this->entityManager->getStorage($context['entity_type'])->create($data); - } + // Create the entity from data. + $entity = $this->entityManager->getStorage($entity_type_id)->create($data); + + // Pass the names of the fields whose values can be merged. + // @todo https://www.drupal.org/node/2456257 remove this. + $entity->_restSubmittedFields = array_keys($data); + return $entity; + } }