From 5699dcb45e1bebb156948959c9d8cf9da652e9bb Mon Sep 17 00:00:00 2001 From: Lee Rowlands <lee.rowlands@previousnext.com.au> Date: Thu, 22 Aug 2019 12:24:11 +1000 Subject: [PATCH] Issue #3043168 by Wim Leers, Niklan, gabesullice, joelstein, plach, mglaman: PATCH 405 for untranslatable content entities with different default language than English --- .../ParamConverter/EntityUuidConverter.php | 5 +- .../JsonApiFunctionalMultilingualTest.php | 20 +++--- .../src/Functional/JsonApiRegressionTest.php | 64 +++++++++++++++++++ 3 files changed, 78 insertions(+), 11 deletions(-) diff --git a/core/modules/jsonapi/src/ParamConverter/EntityUuidConverter.php b/core/modules/jsonapi/src/ParamConverter/EntityUuidConverter.php index aeec4c5d44b5..75f7181796ff 100644 --- a/core/modules/jsonapi/src/ParamConverter/EntityUuidConverter.php +++ b/core/modules/jsonapi/src/ParamConverter/EntityUuidConverter.php @@ -2,11 +2,10 @@ namespace Drupal\jsonapi\ParamConverter; -use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\Entity\TranslatableInterface; use Drupal\Core\Language\LanguageInterface; use Drupal\Core\Language\LanguageManagerInterface; use Drupal\Core\ParamConverter\EntityConverter; -use Drupal\Core\TypedData\TranslatableInterface; use Drupal\jsonapi\Routing\Routes; use Symfony\Cmf\Component\Routing\RouteObjectInterface; use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException; @@ -62,7 +61,7 @@ public function convert($value, $definition, $name, array $defaults) { $entity = reset($entities); // If the entity type is translatable, ensure we return the proper // translation object for the current context. - if ($entity instanceof EntityInterface && $entity instanceof TranslatableInterface) { + if ($entity instanceof TranslatableInterface && $entity->isTranslatable()) { // @see https://www.drupal.org/project/drupal/issues/2624770 $entity_repository = isset($this->entityRepository) ? $this->entityRepository : $this->entityManager; $entity = $entity_repository->getTranslationFromContext($entity, NULL, ['operation' => 'entity_upcast']); diff --git a/core/modules/jsonapi/tests/src/Functional/JsonApiFunctionalMultilingualTest.php b/core/modules/jsonapi/tests/src/Functional/JsonApiFunctionalMultilingualTest.php index 01e01db7dcea..65cdf3c8baff 100644 --- a/core/modules/jsonapi/tests/src/Functional/JsonApiFunctionalMultilingualTest.php +++ b/core/modules/jsonapi/tests/src/Functional/JsonApiFunctionalMultilingualTest.php @@ -25,6 +25,7 @@ class JsonApiFunctionalMultilingualTest extends JsonApiFunctionalTestBase { */ public static $modules = [ 'language', + 'content_translation', ]; /** @@ -45,6 +46,13 @@ protected function setUp() { ->set('url.prefixes.ca-fr', 'ca-fr') ->save(); + ContentLanguageSettings::create([ + 'target_entity_type_id' => 'node', + 'target_bundle' => 'article', + ]) + ->setThirdPartySetting('content_translation', 'enabled', TRUE) + ->save(); + $this->createDefaultContent(5, 5, TRUE, TRUE, static::IS_MULTILINGUAL, FALSE); } @@ -138,10 +146,8 @@ public function testPatchTranslation() { // Specifying a langcode is allowed once configured to be alterable. But // modifying the language of a non-default translation is still not allowed. - ContentLanguageSettings::create([ - 'target_entity_type_id' => 'node', - 'target_bundle' => 'article', - ])->setLanguageAlterable(TRUE) + ContentLanguageSettings::loadByEntityTypeBundle('node', 'article') + ->setLanguageAlterable(TRUE) ->save(); $response = $this->request('PATCH', Url::fromUri('base:/ca/jsonapi/node/article/' . $this->nodes[0]->uuid()), $request_options); $this->assertSame(500, $response->getStatusCode()); @@ -266,10 +272,8 @@ public function testPostTranslation() { // Specifying a langcode is allowed once configured to be alterable. Now an // entity can be created with the specified langcode. - ContentLanguageSettings::create([ - 'target_entity_type_id' => 'node', - 'target_bundle' => 'article', - ])->setLanguageAlterable(TRUE) + ContentLanguageSettings::loadByEntityTypeBundle('node', 'article') + ->setLanguageAlterable(TRUE) ->save(); $request_document['data']['attributes']['langcode'] = 'ca'; $request_options[RequestOptions::BODY] = Json::encode($request_document); diff --git a/core/modules/jsonapi/tests/src/Functional/JsonApiRegressionTest.php b/core/modules/jsonapi/tests/src/Functional/JsonApiRegressionTest.php index bd05177b8c95..636e8d141f33 100644 --- a/core/modules/jsonapi/tests/src/Functional/JsonApiRegressionTest.php +++ b/core/modules/jsonapi/tests/src/Functional/JsonApiRegressionTest.php @@ -6,9 +6,12 @@ use Drupal\comment\Plugin\Field\FieldType\CommentItemInterface; use Drupal\comment\Tests\CommentTestTrait; use Drupal\Component\Serialization\Json; +use Drupal\Core\Entity\TranslatableInterface; use Drupal\Core\Field\FieldStorageDefinitionInterface; +use Drupal\Core\Language\LanguageInterface; use Drupal\Core\Url; use Drupal\datetime\Plugin\Field\FieldType\DateTimeItem; +use Drupal\entity_test\Entity\EntityTest; use Drupal\entity_test\Entity\EntityTestMapField; use Drupal\field\Entity\FieldConfig; use Drupal\field\Entity\FieldStorageConfig; @@ -989,4 +992,65 @@ public function testLeakedCacheMetadataViaRdfFromIssue3053827() { $this->assertSame(200, $response->getStatusCode()); } + /** + * Ensure non-translatable entities can be PATCHed with an alternate language. + * + * @see https://www.drupal.org/project/drupal/issues/3043168 + */ + public function testNonTranslatableEntityUpdatesFromIssue3043168() { + // Enable write-mode. + $this->config('jsonapi.settings')->set('read_only', FALSE)->save(TRUE); + // Set the site language to Russian. + $this->config('system.site')->set('langcode', 'ru')->set('default_langcode', 'ru')->save(TRUE); + // Install a "custom" entity type that is not translatable. + $this->assertTrue($this->container->get('module_installer')->install(['entity_test'], TRUE), 'Installed modules.'); + // Clear and rebuild caches and routes. + $this->rebuildAll(); + // Create a test entity. + // @see \Drupal\language\DefaultLanguageItem + $entity = EntityTest::create([ + 'name' => 'Alexander', + 'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED, + ]); + $entity->save(); + // Ensure it is an instance of TranslatableInterface and that it is *not* + // translatable. + $this->assertInstanceOf(TranslatableInterface::class, $entity); + $this->assertFalse($entity->isTranslatable()); + // Set up a test user with permission to view and update the test entity. + $user = $this->drupalCreateUser(['view test entity', 'administer entity_test content']); + $request_options[RequestOptions::HEADERS]['Accept'] = 'application/vnd.api+json'; + $request_options[RequestOptions::AUTH] = [ + $user->getAccountName(), + $user->pass_raw, + ]; + // GET the test entity via JSON:API. + $entity_url = Url::fromUri('internal:/jsonapi/entity_test/entity_test/' . $entity->uuid()); + $response = $this->request('GET', $entity_url, $request_options); + $this->assertSame(200, $response->getStatusCode()); + $response_document = Json::decode($response->getBody()); + // Ensure that the entity's langcode attribute is 'und'. + $this->assertSame(LanguageInterface::LANGCODE_NOT_SPECIFIED, $response_document['data']['attributes']['langcode']); + // Prepare to PATCH the entity via JSON:API. + $request_options[RequestOptions::HEADERS]['Content-Type'] = 'application/vnd.api+json'; + $request_options[RequestOptions::JSON] = [ + 'data' => [ + 'type' => 'entity_test--entity_test', + 'id' => $entity->uuid(), + 'attributes' => [ + 'name' => 'Constantine', + ], + ], + ]; + // Issue the PATCH request and verify that the test entity was successfully + // updated. + $response = $this->request('PATCH', $entity_url, $request_options); + $this->assertSame(200, $response->getStatusCode(), (string) $response->getBody()); + $response_document = Json::decode($response->getBody()); + // Ensure that the entity's langcode attribute is still 'und' and the name + // was successfully updated. + $this->assertSame(LanguageInterface::LANGCODE_NOT_SPECIFIED, $response_document['data']['attributes']['langcode']); + $this->assertSame('Constantine', $response_document['data']['attributes']['name']); + } + } -- GitLab