Issue #2599228 by tstoeckler, Taran2L, poornachandran, catch, vacho, johan.s, Berdir, hchonov, osman, tim.plunkett, GoZ, Voidtek, neetu morwani, psf_, alexpott, dxvargas, nkoporec, plach, andy@andyhawks.com, joey-santiago: Programmatically created translatable content type returns SQL error on content creation
parent
cbef6823ee
commit
46424a89ef
|
|
@ -16,6 +16,7 @@ use Drupal\Core\Form\FormStateInterface;
|
|||
use Drupal\Core\Language\LanguageInterface;
|
||||
use Drupal\Core\Routing\RouteMatchInterface;
|
||||
use Drupal\Core\StringTranslation\TranslatableMarkup;
|
||||
use Drupal\language\ContentLanguageSettingsInterface;
|
||||
|
||||
/**
|
||||
* Implements hook_help().
|
||||
|
|
@ -172,27 +173,72 @@ function content_translation_entity_type_alter(array &$entity_types) {
|
|||
/**
|
||||
* Implements hook_ENTITY_TYPE_insert().
|
||||
*
|
||||
* Clear the bundle information cache so that the bundle's translatability will
|
||||
* be set properly.
|
||||
* Installs Content Translation's field storage definitions for the target
|
||||
* entity type, if required.
|
||||
*
|
||||
* Also clears the bundle information cache so that the bundle's translatability
|
||||
* will be set properly.
|
||||
*
|
||||
* @see content_translation_entity_bundle_info_alter()
|
||||
* @see \Drupal\content_translation\ContentTranslationManager::isEnabled()
|
||||
*/
|
||||
function content_translation_language_content_settings_insert(EntityInterface $entity) {
|
||||
function content_translation_language_content_settings_insert(ContentLanguageSettingsInterface $settings) {
|
||||
if ($settings->getThirdPartySetting('content_translation', 'enabled', FALSE)) {
|
||||
_content_translation_install_field_storage_definitions($settings->getTargetEntityTypeId());
|
||||
}
|
||||
|
||||
\Drupal::service('entity_type.bundle.info')->clearCachedBundles();
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_update().
|
||||
*
|
||||
* Clear the bundle information cache so that the bundle's translatability will
|
||||
* be changed properly.
|
||||
* Installs Content Translation's field storage definitions for the target
|
||||
* entity type, if required.
|
||||
*
|
||||
* Also clears the bundle information cache so that the bundle's translatability
|
||||
* will be changed properly.
|
||||
*
|
||||
* @see content_translation_entity_bundle_info_alter()
|
||||
* @see \Drupal\content_translation\ContentTranslationManager::isEnabled()
|
||||
*/
|
||||
function content_translation_language_content_settings_update(EntityInterface $entity) {
|
||||
function content_translation_language_content_settings_update(ContentLanguageSettingsInterface $settings) {
|
||||
$original_settings = $settings->original;
|
||||
if ($settings->getThirdPartySetting('content_translation', 'enabled', FALSE)
|
||||
&& !$original_settings->getThirdPartySetting('content_translation', 'enabled', FALSE)
|
||||
) {
|
||||
_content_translation_install_field_storage_definitions($settings->getTargetEntityTypeId());
|
||||
}
|
||||
\Drupal::service('entity_type.bundle.info')->clearCachedBundles();
|
||||
}
|
||||
|
||||
/**
|
||||
* Installs Content Translation's fields for a given entity type.
|
||||
*
|
||||
* @param string $entity_type_id
|
||||
* The entity type ID.
|
||||
*
|
||||
* @todo Generalize this code in https://www.drupal.org/node/2346013.
|
||||
*/
|
||||
function _content_translation_install_field_storage_definitions($entity_type_id) {
|
||||
/** @var \Drupal\Core\Entity\EntityFieldManagerInterface $field_manager */
|
||||
$field_manager = \Drupal::service('entity_field.manager');
|
||||
/** @var \Drupal\Core\Entity\EntityLastInstalledSchemaRepositoryInterface $schema_repository */
|
||||
$schema_repository = \Drupal::service('entity.last_installed_schema.repository');
|
||||
$definition_update_manager = \Drupal::entityDefinitionUpdateManager();
|
||||
|
||||
$field_manager->useCaches(FALSE);
|
||||
$storage_definitions = $field_manager->getFieldStorageDefinitions($entity_type_id);
|
||||
$field_manager->useCaches(TRUE);
|
||||
$installed_storage_definitions = $schema_repository->getLastInstalledFieldStorageDefinitions($entity_type_id);
|
||||
foreach (array_diff_key($storage_definitions, $installed_storage_definitions) as $storage_definition) {
|
||||
/** @var \Drupal\Core\Field\FieldStorageDefinitionInterface $storage_definition */
|
||||
if ($storage_definition->getProvider() == 'content_translation') {
|
||||
$definition_update_manager->installFieldStorageDefinition($storage_definition->getName(), $entity_type_id, 'content_translation', $storage_definition);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_entity_bundle_info_alter().
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -29,10 +29,9 @@ services:
|
|||
|
||||
content_translation.manager:
|
||||
class: Drupal\content_translation\ContentTranslationManager
|
||||
arguments: ['@entity_type.manager', '@content_translation.updates_manager', '@entity_type.bundle.info']
|
||||
arguments: ['@entity_type.manager', '@entity_type.bundle.info']
|
||||
|
||||
content_translation.updates_manager:
|
||||
class: Drupal\content_translation\ContentTranslationUpdatesManager
|
||||
arguments: ['@entity_type.manager', '@entity.definition_update_manager', '@entity_field.manager', '@entity.last_installed_schema.repository']
|
||||
tags:
|
||||
- { name: event_subscriber }
|
||||
deprecated: The "%service_id%" service is deprecated. Definitions are updated automatically now so no replacement is needed. See https://www.drupal.org/node/2973222.
|
||||
|
|
|
|||
|
|
@ -25,11 +25,6 @@ process:
|
|||
third_party_settings/content_translation/bundle_settings/untranslatable_fields_hide: untranslatable_fields_hide
|
||||
destination:
|
||||
plugin: entity:language_content_settings
|
||||
content_translation_update_definitions:
|
||||
- comment
|
||||
- node
|
||||
- taxonomy_term
|
||||
- user
|
||||
migration_dependencies:
|
||||
optional:
|
||||
- d7_comment_type
|
||||
|
|
|
|||
|
|
@ -33,8 +33,6 @@ process:
|
|||
destination:
|
||||
plugin: entity:node
|
||||
translations: true
|
||||
content_translation_update_definitions:
|
||||
- node
|
||||
destination_module: content_translation
|
||||
migration_dependencies:
|
||||
required:
|
||||
|
|
|
|||
|
|
@ -17,7 +17,10 @@ class ContentTranslationManager implements ContentTranslationManagerInterface, B
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $deprecatedProperties = ['entityManager' => 'entity.manager'];
|
||||
protected $deprecatedProperties = [
|
||||
'entityManager' => 'entity.manager',
|
||||
'updatesManager' => 'content_translation.updates_manager',
|
||||
];
|
||||
|
||||
/**
|
||||
* The entity type bundle info provider.
|
||||
|
|
@ -33,28 +36,19 @@ class ContentTranslationManager implements ContentTranslationManagerInterface, B
|
|||
*/
|
||||
protected $entityTypeManager;
|
||||
|
||||
/**
|
||||
* The updates manager.
|
||||
*
|
||||
* @var \Drupal\content_translation\ContentTranslationUpdatesManager
|
||||
*/
|
||||
protected $updatesManager;
|
||||
|
||||
/**
|
||||
* Constructs a ContentTranslationManageAccessCheck object.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
|
||||
* The entity type manager.
|
||||
* @param \Drupal\content_translation\ContentTranslationUpdatesManager $updates_manager
|
||||
* The updates manager.
|
||||
* @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $entity_type_bundle_info
|
||||
* The entity type bundle info provider.
|
||||
*/
|
||||
public function __construct(EntityTypeManagerInterface $entity_type_manager, ContentTranslationUpdatesManager $updates_manager, EntityTypeBundleInfoInterface $entity_type_bundle_info = NULL) {
|
||||
public function __construct(EntityTypeManagerInterface $entity_type_manager, $entity_type_bundle_info) {
|
||||
$this->entityTypeManager = $entity_type_manager;
|
||||
$this->updatesManager = $updates_manager;
|
||||
if (!$entity_type_bundle_info) {
|
||||
@trigger_error('The entity_type.bundle.info service must be passed to ContentTranslationManager::__construct(), it is required before Drupal 9.0.0. See https://www.drupal.org/node/2549139.', E_USER_DEPRECATED);
|
||||
|
||||
if (!($entity_type_bundle_info instanceof EntityTypeBundleInfoInterface)) {
|
||||
@trigger_error('The entity_type.bundle.info service should be passed to ContentTranslationManager::__construct() instead of the content_translation.updates_manager service since 8.7.0. This will be required in Drupal 9.0.0. See https://www.drupal.org/node/2549139 and https://www.drupal.org/node/2973222.', E_USER_DEPRECATED);
|
||||
$entity_type_bundle_info = \Drupal::service('entity_type.bundle.info');
|
||||
}
|
||||
$this->entityTypeBundleInfo = $entity_type_bundle_info;
|
||||
|
|
@ -104,8 +98,6 @@ class ContentTranslationManager implements ContentTranslationManagerInterface, B
|
|||
public function setEnabled($entity_type_id, $bundle, $value) {
|
||||
$config = $this->loadContentLanguageSettings($entity_type_id, $bundle);
|
||||
$config->setThirdPartySetting('content_translation', 'enabled', $value)->save();
|
||||
$entity_type = $this->entityTypeManager->getDefinition($entity_type_id);
|
||||
$this->updatesManager->updateDefinitions([$entity_type_id => $entity_type]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -2,28 +2,22 @@
|
|||
|
||||
namespace Drupal\content_translation;
|
||||
|
||||
use Drupal\Component\Utility\NestedArray;
|
||||
use Drupal\Core\Config\ConfigEvents;
|
||||
use Drupal\Core\DependencyInjection\DeprecatedServicePropertyTrait;
|
||||
use Drupal\Core\Entity\EntityDefinitionUpdateManagerInterface;
|
||||
use Drupal\Core\Entity\EntityFieldManagerInterface;
|
||||
use Drupal\Core\Entity\EntityLastInstalledSchemaRepositoryInterface;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Drupal\migrate\Event\MigrateEvents;
|
||||
use Drupal\migrate\Event\MigrateImportEvent;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
@trigger_error('\Drupal\content_translation\ContentTranslationUpdatesManager is scheduled for removal in Drupal 9.0.0. Definitions are updated automatically now so no replacement is needed. See https://www.drupal.org/node/2973222.', E_USER_DEPRECATED);
|
||||
|
||||
/**
|
||||
* Provides the logic needed to update field storage definitions when needed.
|
||||
*
|
||||
* @deprecated in Drupal 8.7.x, to be removed before Drupal 9.0.0.
|
||||
* Definitions are updated automatically now so no replacement is needed.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2973222
|
||||
*/
|
||||
class ContentTranslationUpdatesManager implements EventSubscriberInterface {
|
||||
use DeprecatedServicePropertyTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $deprecatedProperties = ['entityManager' => 'entity.manager'];
|
||||
class ContentTranslationUpdatesManager {
|
||||
|
||||
/**
|
||||
* The entity field manager.
|
||||
|
|
@ -69,12 +63,10 @@ class ContentTranslationUpdatesManager implements EventSubscriberInterface {
|
|||
$this->entityTypeManager = $entity_type_manager;
|
||||
$this->updateManager = $update_manager;
|
||||
if (!$entity_field_manager) {
|
||||
@trigger_error('The entity_field.manager service must be passed to ContentTranslationUpdatesManager::__construct(), it is required before Drupal 9.0.0. See https://www.drupal.org/node/2549139.', E_USER_DEPRECATED);
|
||||
$entity_field_manager = \Drupal::service('entity_field.manager');
|
||||
}
|
||||
$this->entityFieldManager = $entity_field_manager;
|
||||
if (!$entity_last_installed_schema_repository) {
|
||||
@trigger_error('The entity.last_installed_schema.repository service must be passed to ContentTranslationUpdatesManager::__construct(), it is required before Drupal 9.0.0. See https://www.drupal.org/node/2549139.', E_USER_DEPRECATED);
|
||||
$entity_last_installed_schema_repository = \Drupal::service('entity.last_installed_schema.repository');
|
||||
}
|
||||
$this->entityLastInstalledSchemaRepository = $entity_last_installed_schema_repository;
|
||||
|
|
@ -88,8 +80,6 @@ class ContentTranslationUpdatesManager implements EventSubscriberInterface {
|
|||
*/
|
||||
public function updateDefinitions(array $entity_types) {
|
||||
// Handle field storage definition creation, if needed.
|
||||
// @todo Generalize this code in https://www.drupal.org/node/2346013.
|
||||
// @todo Handle initial values in https://www.drupal.org/node/2346019.
|
||||
if ($this->updateManager->needsUpdates()) {
|
||||
foreach ($entity_types as $entity_type_id => $entity_type) {
|
||||
$storage_definitions = $this->entityFieldManager->getFieldStorageDefinitions($entity_type_id);
|
||||
|
|
@ -104,38 +94,4 @@ class ContentTranslationUpdatesManager implements EventSubscriberInterface {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Listener for the ConfigImporter import event.
|
||||
*/
|
||||
public function onConfigImporterImport() {
|
||||
$entity_types = array_filter($this->entityTypeManager->getDefinitions(), function (EntityTypeInterface $entity_type) {
|
||||
return $entity_type->isTranslatable();
|
||||
});
|
||||
$this->updateDefinitions($entity_types);
|
||||
}
|
||||
|
||||
/**
|
||||
* Listener for migration imports.
|
||||
*/
|
||||
public function onMigrateImport(MigrateImportEvent $event) {
|
||||
$migration = $event->getMigration();
|
||||
$configuration = $migration->getDestinationConfiguration();
|
||||
$entity_types = NestedArray::getValue($configuration, ['content_translation_update_definitions']);
|
||||
if ($entity_types) {
|
||||
$entity_types = array_intersect_key($this->entityTypeManager->getDefinitions(), array_flip($entity_types));
|
||||
$this->updateDefinitions($entity_types);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getSubscribedEvents() {
|
||||
$events[ConfigEvents::IMPORT][] = ['onConfigImporterImport', 60];
|
||||
if (class_exists('\Drupal\migrate\Event\MigrateEvents')) {
|
||||
$events[MigrateEvents::POST_IMPORT][] = ['onMigrateImport'];
|
||||
}
|
||||
return $events;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
langcode: en
|
||||
status: true
|
||||
dependencies: { }
|
||||
id: test
|
||||
label: null
|
||||
description: null
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
langcode: en
|
||||
status: true
|
||||
dependencies:
|
||||
config:
|
||||
- entity_test.entity_test_bundle.test
|
||||
module:
|
||||
- content_translation
|
||||
third_party_settings:
|
||||
content_translation:
|
||||
enabled: true
|
||||
bundle_settings:
|
||||
untranslatable_fields_hide: '0'
|
||||
id: entity_test_with_bundle.test
|
||||
target_entity_type_id: entity_test_with_bundle
|
||||
target_bundle: test
|
||||
default_langcode: site_default
|
||||
language_alterable: true
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\content_translation\Kernel;
|
||||
|
||||
use Drupal\entity_test\Entity\EntityTestWithBundle;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
use Drupal\language\Entity\ConfigurableLanguage;
|
||||
|
||||
/**
|
||||
* Tests content translation for modules that provide translatable bundles.
|
||||
*
|
||||
* @group content_translation
|
||||
*/
|
||||
class ContentTranslationModuleInstallTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = [
|
||||
'content_translation',
|
||||
'content_translation_test',
|
||||
'entity_test',
|
||||
'language',
|
||||
'user',
|
||||
];
|
||||
|
||||
/**
|
||||
* The content translation manager.
|
||||
*
|
||||
* @var \Drupal\content_translation\ContentTranslationManagerInterface
|
||||
*/
|
||||
protected $contentTranslationManager;
|
||||
|
||||
/**
|
||||
* The language code of the source language for this test.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $sourceLangcode = 'en';
|
||||
|
||||
/**
|
||||
* The language code of the translation language for this test.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $translationLangcode = 'af';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->installEntitySchema('entity_test_with_bundle');
|
||||
ConfigurableLanguage::createFromLangcode($this->translationLangcode)->save();
|
||||
|
||||
$this->contentTranslationManager = $this->container->get('content_translation.manager');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that content translation fields are created upon module installation.
|
||||
*/
|
||||
public function testFieldUpdates() {
|
||||
// The module ships a translatable bundle of the 'entity_test_with_bundle'
|
||||
// entity type.
|
||||
$this->installConfig(['content_translation_test']);
|
||||
|
||||
$entity = EntityTestWithBundle::create([
|
||||
'type' => 'test',
|
||||
'langcode' => $this->sourceLangcode,
|
||||
]);
|
||||
$entity->save();
|
||||
|
||||
// Add a translation with some translation metadata.
|
||||
$translation = $entity->addTranslation($this->translationLangcode);
|
||||
$translation_metadata = $this->contentTranslationManager->getTranslationMetadata($translation);
|
||||
$translation_metadata->setSource($this->sourceLangcode)->setOutdated(TRUE);
|
||||
$translation->save();
|
||||
|
||||
// Make sure the translation metadata has been saved correctly.
|
||||
$entity = EntityTestWithBundle::load($entity->id());
|
||||
$translation = $entity->getTranslation($this->translationLangcode);
|
||||
$translation_metadata = $this->contentTranslationManager->getTranslationMetadata($translation);
|
||||
$this->assertSame($this->sourceLangcode, $translation_metadata->getSource());
|
||||
$this->assertSame(TRUE, $translation_metadata->isOutdated());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -40,8 +40,6 @@ process:
|
|||
2: true
|
||||
destination:
|
||||
plugin: entity:language_content_settings
|
||||
content_translation_update_definitions:
|
||||
- node
|
||||
migration_dependencies:
|
||||
required:
|
||||
- d6_node_type
|
||||
|
|
|
|||
|
|
@ -46,8 +46,6 @@ process:
|
|||
source: language
|
||||
destination:
|
||||
plugin: entity:language_content_settings
|
||||
content_translation_update_definitions:
|
||||
- taxonomy_term
|
||||
migration_dependencies:
|
||||
required:
|
||||
- d6_taxonomy_vocabulary
|
||||
|
|
|
|||
|
|
@ -43,8 +43,6 @@ process:
|
|||
4: true
|
||||
destination:
|
||||
plugin: entity:language_content_settings
|
||||
content_translation_update_definitions:
|
||||
- node
|
||||
migration_dependencies:
|
||||
required:
|
||||
- d7_node_type
|
||||
|
|
|
|||
|
|
@ -25,8 +25,10 @@ use Drupal\Core\Field\BaseFieldDefinition;
|
|||
* },
|
||||
* },
|
||||
* base_table = "entity_test_with_bundle",
|
||||
* data_table = "entity_test_with_bundle_field_data",
|
||||
* admin_permission = "administer entity_test_with_bundle content",
|
||||
* persistent_cache = FALSE,
|
||||
* translatable = TRUE,
|
||||
* entity_keys = {
|
||||
* "id" = "id",
|
||||
* "uuid" = "uuid",
|
||||
|
|
|
|||
Loading…
Reference in New Issue