diff --git a/core/modules/hal/tests/src/Functional/EntityResource/Node/NodeHalJsonCookieTranslationsTest.php b/core/modules/hal/tests/src/Functional/EntityResource/Node/NodeHalJsonCookieTranslationsTest.php new file mode 100644 index 0000000..9d10dd5 --- /dev/null +++ b/core/modules/hal/tests/src/Functional/EntityResource/Node/NodeHalJsonCookieTranslationsTest.php @@ -0,0 +1,198 @@ +grantPermissionsToTestedRole(['translate any entity', 'administer nodes']); + } + + /** + * {@inheritdoc} + */ + protected function createEntity() { + if (!ConfigurableLanguage::load('de')) { + ConfigurableLanguage::createFromLangcode('de')->save(); + } + + /** @var \Drupal\node\NodeInterface $node */ + $node = parent::createEntity(); + + ContentLanguageSettings::loadByEntityTypeBundle('node', 'camelids') + ->setLanguageAlterable(TRUE) + ->setDefaultLangcode('en') + ->save(); + + $translation = $node->addTranslation('de', $node->toArray()); + $translation->get('title')->value = 'Lama'; + $node->save(); + return $node; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedNormalizedEntity() { + $normalization = parent::getExpectedNormalizedEntity(); + + foreach ($this->entity->getFieldDefinitions() as $field_name => $field_definition) { + // @todo It seems that currently two items exist if the *storage* is + // translatable, should be when the field is? + if ($field_definition->getFieldStorageDefinition()->isTranslatable() && isset($normalization[$field_name])) { + $normalization[$field_name][1] = [ + 'lang' => 'de', + ] + $normalization[$field_name][0]; + } + } + + $normalization['title'][1]['value'] = 'Lama'; + $normalization['langcode'][1]['value'] = 'de'; + $normalization['default_langcode'][1]['value'] = '0'; + + $author = User::load($this->entity->getOwnerId()); + $normalization['_links'][$this->baseUrl . '/rest/relation/node/camelids/uid'][1] = [ + 'href' => $this->baseUrl . '/user/' . $author->id() . '?_format=hal_json', + 'lang' => 'de', + ]; + $normalization['_embedded'][$this->baseUrl . '/rest/relation/node/camelids/uid'][1] = [ + '_links' => [ + 'self' => [ + 'href' => $this->baseUrl . '/user/' . $author->id() . '?_format=hal_json', + ], + 'type' => [ + 'href' => $this->baseUrl . '/rest/type/user/user', + ], + ], + 'uuid' => [ + ['value' => $author->uuid()] + ], + 'lang' => 'de', + ]; + + return $normalization; + } + + /** + * {@inheritdoc} + */ + public function testPost() { + parent::testPost(); + + // Create an entity with a translation. + $normalized_entity = $this->getExpectedNormalizedEntity(); + unset($normalized_entity['nid']); + unset($normalized_entity['vid']); + unset($normalized_entity['uuid']); + unset($normalized_entity['changed']); + unset($normalized_entity['revision_timestamp']); + unset($normalized_entity['_embedded'][$this->baseUrl . '/rest/relation/node/camelids/revision_uid']); + $entity_body_with_a_translations = $this->serializer->encode($normalized_entity, static::$format); + + $request_options = []; + $request_options[RequestOptions::HEADERS]['Content-Type'] = static::$mimeType; + $request_options[RequestOptions::BODY] = $entity_body_with_a_translations; + $request_options = NestedArray::mergeDeep($request_options, $this->getAuthenticationRequestOptions('POST')); + + $url = $this->getPostUrl(); + $url->setOption('query', ['_format' => static::$format]); + + // 201 for well-formed request. + $response = $this->request('POST', $url, $request_options); + $this->assertResourceResponse(201, FALSE, $response); + /** @var \Drupal\node\NodeInterface $created_node */ + $created_node = $this->serializer->deserialize((string) $response->getBody(), get_class($this->entity), static::$format); + $this->assertSame([$created_node->toUrl('canonical')->setAbsolute(TRUE)->toString()], $response->getHeader('Location')); + $this->assertFalse($response->hasHeader('X-Drupal-Cache')); + + $this->assertSame('Llama', $created_node->getTitle()); + $this->assertSame('Lama', $created_node->getTranslation('de')->getTitle()); + } + + /** + * {@inheritdoc} + */ + public function testPatch() { + parent::testPatch(); + + $title_with_translation = $this->getNormalizedPatchEntity(); + $title_with_translation['title'][0]['lang'] = 'en'; + $title_with_translation['title'][1] = [ + 'value' => 'Drama-Lama', + 'lang' => 'de', + ]; + + $entity_body_title_with_translation = $this->serializer->encode($title_with_translation, static::$format); + + $request_options = []; + $request_options[RequestOptions::HEADERS]['Content-Type'] = static::$mimeType; + $request_options[RequestOptions::BODY] = $entity_body_title_with_translation; + $request_options = NestedArray::mergeDeep($request_options, $this->getAuthenticationRequestOptions('POST')); + + $url = $this->getUrl(); + $url->setOption('query', ['_format' => static::$format]); + + $response = $this->request('PATCH', $url, $request_options); + $this->assertResourceResponse(200, FALSE, $response); + $this->assertFalse($response->hasHeader('X-Drupal-Cache')); + + $storage = \Drupal::entityTypeManager()->getStorage('node'); + $storage->resetCache(); + + $patched_node = $storage->load($this->entity->id()); + $this->assertSame('Dramallama', $patched_node->getTitle()); + $this->assertSame('Drama-Lama', $patched_node->getTranslation('de')->getTitle()); + } + +} diff --git a/core/modules/rest/src/Plugin/rest/resource/EntityResource.php b/core/modules/rest/src/Plugin/rest/resource/EntityResource.php index 3e35f83..d60e423 100644 --- a/core/modules/rest/src/Plugin/rest/resource/EntityResource.php +++ b/core/modules/rest/src/Plugin/rest/resource/EntityResource.php @@ -180,19 +180,14 @@ public function post(EntityInterface $entity = NULL) { // Validate the received data before saving. $this->validate($entity); - try { - $entity->save(); - $this->logger->notice('Created entity %type with ID %id.', array('%type' => $entity->getEntityTypeId(), '%id' => $entity->id())); + $entity->save(); + $this->logger->notice('Created entity %type with ID %id.', array('%type' => $entity->getEntityTypeId(), '%id' => $entity->id())); - // 201 Created responses return the newly created entity in the response - // body. These responses are not cacheable, so we add no cacheability - // metadata here. - $url = $entity->urlInfo('canonical', ['absolute' => TRUE])->toString(TRUE); - return new ModifiedResourceResponse($entity, 201, ['Location' => $url->getGeneratedUrl()]); - } - catch (EntityStorageException $e) { - throw new HttpException(500, 'Internal Server Error', $e); - } + // 201 Created responses return the newly created entity in the response + // body. These responses are not cacheable, so we add no cacheability + // metadata here. + $url = $entity->urlInfo('canonical', ['absolute' => TRUE])->toString(TRUE); + return new ModifiedResourceResponse($entity, 201, ['Location' => $url->getGeneratedUrl()]); } /** diff --git a/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php b/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php index 73dfc62..42f99b6 100644 --- a/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php +++ b/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php @@ -435,12 +435,16 @@ public function testGet() { // Finally, assert that the expected 'Link' headers are present. $this->assertArrayHasKey('Link', $response->getHeaders()); $link_relation_type_manager = $this->container->get('plugin.manager.link_relation_type'); - $expected_link_relation_headers = array_map(function ($rel) use ($link_relation_type_manager) { + $expected_link_relation_headers = array_filter(array_map(function ($rel) use ($link_relation_type_manager) { + // @todo What to do about content_translation link relationships? + if (strpos($rel, 'drupal:content-translation') !== FALSE) { + return FALSE; + } $definition = $link_relation_type_manager->getDefinition($rel, FALSE); return (!empty($definition['uri'])) ? $definition['uri'] : $rel; - }, array_keys($this->entity->getEntityType()->getLinkTemplates())); + }, array_keys($this->entity->getEntityType()->getLinkTemplates()))); $parse_rel_from_link_header = function ($value) use ($link_relation_type_manager) { $matches = []; if (preg_match('/rel="([^"]+)"/', $value, $matches) === 1) {