public function LingotekContentTranslationService::getSourceData in Lingotek Translation 3.7.x
Same name and namespace in other branches
- 8 src/LingotekContentTranslationService.php \Drupal\lingotek\LingotekContentTranslationService::getSourceData()
- 8.2 src/LingotekContentTranslationService.php \Drupal\lingotek\LingotekContentTranslationService::getSourceData()
- 4.0.x src/LingotekContentTranslationService.php \Drupal\lingotek\LingotekContentTranslationService::getSourceData()
- 3.0.x src/LingotekContentTranslationService.php \Drupal\lingotek\LingotekContentTranslationService::getSourceData()
- 3.1.x src/LingotekContentTranslationService.php \Drupal\lingotek\LingotekContentTranslationService::getSourceData()
- 3.2.x src/LingotekContentTranslationService.php \Drupal\lingotek\LingotekContentTranslationService::getSourceData()
- 3.3.x src/LingotekContentTranslationService.php \Drupal\lingotek\LingotekContentTranslationService::getSourceData()
- 3.4.x src/LingotekContentTranslationService.php \Drupal\lingotek\LingotekContentTranslationService::getSourceData()
- 3.5.x src/LingotekContentTranslationService.php \Drupal\lingotek\LingotekContentTranslationService::getSourceData()
- 3.6.x src/LingotekContentTranslationService.php \Drupal\lingotek\LingotekContentTranslationService::getSourceData()
- 3.8.x src/LingotekContentTranslationService.php \Drupal\lingotek\LingotekContentTranslationService::getSourceData()
Returns the source data that will be uploaded to the Lingotek service.
Only those fields that have actual translatable text, and have marked for upload will be included.
Parameters
\Drupal\Core\Entity\ContentEntityInterface &$entity: The entity which we want the source data.
Return value
mixed
Overrides LingotekContentTranslationServiceInterface::getSourceData
4 calls to LingotekContentTranslationService::getSourceData()
- LingotekContentTranslationService::hasEntityChanged in src/
LingotekContentTranslationService.php - Checks if the source entity data has changed from last time we uploaded it.
- LingotekContentTranslationService::updateDocument in src/
LingotekContentTranslationService.php - Resends a document to the translation service.
- LingotekContentTranslationService::updateEntityHash in src/
LingotekContentTranslationService.php - Updates the entity hash.
- LingotekContentTranslationService::uploadDocument in src/
LingotekContentTranslationService.php - Uploads a document to the Lingotek service.
File
- src/
LingotekContentTranslationService.php, line 578
Class
- LingotekContentTranslationService
- Service for managing Lingotek content translations.
Namespace
Drupal\lingotekCode
public function getSourceData(ContentEntityInterface &$entity, &$visited = []) {
// Logic adapted from Content Translation core module and TMGMT contrib
// module for pulling translatable field info from content entities.
$source_entity = NULL;
if ($entity instanceof RevisionableInterface) {
$storage = $this->entityTypeManager
->getStorage($entity
->getEntityTypeId());
if ($revision_id = $storage
->getLatestTranslationAffectedRevisionId($entity
->id(), $entity
->getUntranslated()
->language()
->getId())) {
$source_entity = $storage
->loadRevision($revision_id);
}
else {
$source_entity = $entity
->getUntranslated();
}
}
$isParentEntity = count($visited) === 0;
$visited[$entity
->bundle()][] = $entity
->id();
$entity_type = $entity
->getEntityType();
$field_definitions = $this->entityFieldManager
->getFieldDefinitions($entity
->getEntityTypeId(), $entity
->bundle());
$storage_definitions = $entity_type instanceof ContentEntityTypeInterface ? $this->entityFieldManager
->getFieldStorageDefinitions($entity_type
->id()) : [];
$translatable_fields = [];
// We need to include computed fields, as we may have a URL alias.
foreach ($entity
->getFields(TRUE) as $field_name => $definition) {
if ($this->lingotekConfiguration
->isFieldLingotekEnabled($entity
->getEntityTypeId(), $entity
->bundle(), $field_name) && $field_name != $entity_type
->getKey('langcode') && $field_name != $entity_type
->getKey('default_langcode')) {
$translatable_fields[$field_name] = $definition;
}
}
$default_display = $this->entityTypeManager
->getStorage('entity_view_display')
->load($entity_type
->id() . '.' . $entity
->bundle() . '.' . 'default');
if ($default_display !== NULL) {
uksort($translatable_fields, function ($a, $b) use ($default_display) {
return SortArray::sortByKeyString($default_display
->getComponent($a), $default_display
->getComponent($b), 'weight');
});
}
$data = [];
foreach ($translatable_fields as $k => $definition) {
// If there is only one relevant attribute, upload it.
// Get the column translatability configuration.
module_load_include('inc', 'content_translation', 'content_translation.admin');
$column_element = content_translation_field_sync_widget($field_definitions[$k]);
$field = $source_entity
->get($k);
$field_type = $field_definitions[$k]
->getType();
if ($field
->isEmpty()) {
$data[$k] = [];
}
foreach ($field as $fkey => $fval) {
// If we have only one relevant column, upload that. If not, check our
// settings.
if (!$column_element) {
$properties = $fval
->getProperties();
foreach ($properties as $property_name => $property_value) {
if (isset($storage_definitions[$k])) {
$property_definition = $storage_definitions[$k]
->getPropertyDefinition($property_name);
$data_type = $property_definition
->getDataType();
if (($data_type === 'string' || $data_type === 'uri') && !$property_definition
->isComputed()) {
if (isset($fval->{$property_name}) && !empty($fval->{$property_name})) {
$data[$k][$fkey][$property_name] = $fval
->get($property_name)
->getValue();
}
// If there is a path item, we need to handle that the pid is a
// string but we don't want to upload it. See
// https://www.drupal.org/node/2689253.
if ($field_type === 'path') {
unset($data[$k][$fkey]['pid']);
}
}
}
}
}
else {
$configured_properties = $this->lingotekConfiguration
->getFieldPropertiesLingotekEnabled($entity
->getEntityTypeId(), $entity
->bundle(), $k);
$properties = $fval
->getProperties();
foreach ($properties as $pkey => $pval) {
if (isset($configured_properties[$pkey]) && $configured_properties[$pkey]) {
$data[$k][$fkey][$pkey] = $pval
->getValue();
}
}
}
}
if ($field_type === 'block_field') {
foreach ($source_entity->{$k} as $field_item) {
$pluginId = $field_item
->get('plugin_id')
->getValue();
$block_instance = $field_item
->getBlock();
$lingotekConfigTranslation = \Drupal::service('lingotek.config_translation');
/** @var \Drupal\Core\Config\TypedConfigManagerInterface $typedConfigManager */
$typedConfigManager = \Drupal::service('config.typed');
$pluginIDName = $block_instance
->getPluginDefinition()['id'];
$blockConfig = $block_instance
->getConfiguration();
$definition = $typedConfigManager
->getDefinition('block.settings.' . $pluginIDName);
if ($definition['type'] == 'undefined') {
$definition = $typedConfigManager
->getDefinition('block_settings');
}
$dataDefinition = $typedConfigManager
->buildDataDefinition($definition, $blockConfig);
$schema = $typedConfigManager
->create($dataDefinition, $blockConfig);
$properties = $lingotekConfigTranslation
->getTranslatableProperties($schema, NULL);
$embedded_data = [];
foreach ($properties as $property) {
$propertyParts = explode('.', $property);
$embedded_data[$property] = NestedArray::getValue($blockConfig, $propertyParts);
}
if (strpos($pluginId, 'block_content') === 0) {
$uuid = $block_instance
->getDerivativeId();
if ($block = \Drupal::service('entity.repository')
->loadEntityByUuid('block_content', $uuid)) {
$embedded_data['entity'] = $this
->getSourceData($block, $visited);
}
}
$data[$k][$field_item
->getName()] = $embedded_data;
}
}
if ($field_type === 'layout_section') {
// This means that we are using layout:builder_at. We verify it anyway.
$layoutBuilderAT = \Drupal::moduleHandler()
->moduleExists('layout_builder_at');
if ($layoutBuilderAT) {
$block_manager = \Drupal::service('plugin.manager.block');
$lingotekConfigTranslation = \Drupal::service('lingotek.config_translation');
/** @var \Drupal\Core\Config\TypedConfigManagerInterface $typedConfigManager */
$typedConfigManager = \Drupal::service('config.typed');
$data[$k] = [
'components' => [],
];
foreach ($source_entity->{$k} as $field_item) {
$sectionObject = $field_item
->getValue()['section'];
$components = $sectionObject
->getComponents();
/** @var \Drupal\layout_builder\SectionComponent $component */
foreach ($components as $componentUuid => $component) {
/** @var \Drupal\Core\Block\BlockPluginInterface $block_instance */
// TODO: Change this to getConfiguration() when is safe to do so.
// See https://www.drupal.org/project/drupal/issues/3180555.
$block_instance = $block_manager
->createInstance($component
->getPluginId(), $component
->get('configuration'));
$pluginIDName = $block_instance
->getPluginDefinition()['id'];
$blockConfig = $block_instance
->getConfiguration();
$definition = $typedConfigManager
->getDefinition('block.settings.' . $pluginIDName);
if ($definition['type'] == 'undefined') {
$definition = $typedConfigManager
->getDefinition('block_settings');
}
$dataDefinition = $typedConfigManager
->buildDataDefinition($definition, $blockConfig);
$schema = $typedConfigManager
->create($dataDefinition, $blockConfig);
$properties = $lingotekConfigTranslation
->getTranslatableProperties($schema, NULL);
$embedded_data = [];
foreach ($properties as $property) {
// The data definition will return nested keys as dot separated.
$propertyParts = explode('.', $property);
$embedded_data[$property] = NestedArray::getValue($blockConfig, $propertyParts);
}
$data[$k]['components'][$componentUuid] = $embedded_data;
if (strpos($pluginIDName, 'inline_block') === 0) {
$blockRevisionId = $blockConfig['block_revision_id'];
if ($block = $this->entityTypeManager
->getStorage('block_content')
->loadRevision($blockRevisionId)) {
$data[$k]['entities']['block_content'][$blockRevisionId] = $this
->getSourceData($block, $visited);
}
}
}
}
}
}
if ($field_type === 'layout_translation') {
// We need to get the original data from the layout.
$layoutBuilderST = \Drupal::moduleHandler()
->moduleExists('layout_builder_st');
if ($layoutBuilderST) {
$data[$k] = [
'components' => [],
];
$layoutField = $source_entity->{OverridesSectionStorage::FIELD_NAME};
$block_manager = \Drupal::service('plugin.manager.block');
$lingotekConfigTranslation = \Drupal::service('lingotek.config_translation');
/** @var \Drupal\Core\Config\TypedConfigManagerInterface $typedConfigManager */
$typedConfigManager = \Drupal::service('config.typed');
$layout = $layoutField
->getValue();
/** @var \Drupal\layout_builder\Section $sectionObject */
foreach ($layout as $sectionIndex => $section) {
$sectionObject = $section['section'];
$components = $sectionObject
->getComponents();
/** @var \Drupal\layout_builder\SectionComponent $component */
foreach ($components as $componentUuid => $component) {
/** @var \Drupal\Core\Block\BlockPluginInterface $block_instance */
// TODO: Change this to getConfiguration() when is safe to do so.
// See https://www.drupal.org/project/drupal/issues/3180555.
$block_instance = $block_manager
->createInstance($component
->getPluginId(), $component
->get('configuration'));
$pluginIDName = $block_instance
->getPluginDefinition()['id'];
$blockConfig = $block_instance
->getConfiguration();
$definition = $typedConfigManager
->getDefinition('block.settings.' . $pluginIDName);
if ($definition['type'] == 'undefined') {
$definition = $typedConfigManager
->getDefinition('block_settings');
}
$dataDefinition = $typedConfigManager
->buildDataDefinition($definition, $blockConfig);
$schema = $typedConfigManager
->create($dataDefinition, $blockConfig);
$properties = $lingotekConfigTranslation
->getTranslatableProperties($schema, NULL);
$embedded_data = [];
foreach ($properties as $property) {
// The data definition will return nested keys as dot separated.
$propertyParts = explode('.', $property);
$embedded_data[$property] = NestedArray::getValue($blockConfig, $propertyParts);
}
$data[$k]['components'][$componentUuid] = $embedded_data;
if (strpos($pluginIDName, 'inline_block') === 0) {
$blockRevisionId = $blockConfig['block_revision_id'];
if ($block = $this->entityTypeManager
->getStorage('block_content')
->loadRevision($blockRevisionId)) {
$data[$k]['entities']['block_content'][$blockRevisionId] = $this
->getSourceData($block, $visited);
}
}
}
}
}
}
// If we have an entity reference, we may want to embed it.
if ($field_type === 'entity_reference' || $field_type === 'er_viewmode' || $field_type === 'bricks') {
$target_entity_type_id = $field_definitions[$k]
->getFieldStorageDefinition()
->getSetting('target_type');
foreach ($source_entity->{$k} as $field_item) {
$embedded_entity_id = $field_item
->get('target_id')
->getValue();
$embedded_entity = $this->entityTypeManager
->getStorage($target_entity_type_id)
->load($embedded_entity_id);
// We may have orphan references, so ensure that they exist before
// continuing.
if ($embedded_entity !== NULL) {
if ($embedded_entity instanceof ContentEntityInterface) {
// We need to avoid cycles if we have several entity references
// referencing each other.
if (!isset($visited[$embedded_entity
->bundle()]) || !in_array($embedded_entity
->id(), $visited[$embedded_entity
->bundle()])) {
$embedded_data = $this
->getSourceData($embedded_entity, $visited);
$data[$k][$field_item
->getName()] = $embedded_data;
}
else {
// We don't want to embed the data, but still will need the
// references, so let's include the metadata.
$metadata = [];
$this
->includeMetadata($embedded_entity, $metadata, FALSE);
$data[$k][$field_item
->getName()] = $metadata;
}
}
elseif ($embedded_entity instanceof ConfigEntityInterface) {
$embedded_data = $this->lingotekConfigTranslation
->getSourceData($embedded_entity);
$data[$k][$field_item
->getName()] = $embedded_data;
}
}
else {
// If the referenced entity doesn't exist, remove the target_id
// that may be already set.
unset($data[$k]);
}
}
}
elseif ($field_type === 'entity_reference_revisions' || $field_type === 'cohesion_entity_reference_revisions') {
$target_entity_type_id = $field_definitions[$k]
->getFieldStorageDefinition()
->getSetting('target_type');
foreach ($source_entity->{$k} as $field_item) {
$embedded_entity_id = $field_item
->get('target_id')
->getValue();
$embedded_entity_revision_id = $field_item
->get('target_revision_id')
->getValue();
$embedded_entity = $this->entityTypeManager
->getStorage($target_entity_type_id)
->loadRevision($embedded_entity_revision_id);
// Handle the unlikely case where a paragraph has lost its parent.
if (!empty($embedded_entity)) {
$embedded_data = $this
->getSourceData($embedded_entity, $visited);
$data[$k][$field_item
->getName()] = $embedded_data;
}
else {
// If the referenced entity doesn't exist, remove the target_id
// that may be already set.
unset($data[$k]);
}
}
}
elseif ($field_type === 'tablefield') {
foreach ($source_entity->{$k} as $index => $field_item) {
$tableValue = $field_item->value;
$embedded_data = [];
foreach ($tableValue as $row_index => $row) {
if ($row_index === 'caption') {
$embedded_data[$index]['caption'] = $row;
}
else {
foreach ($row as $col_index => $cell) {
$embedded_data[$index]['row:' . $row_index]['col:' . $col_index] = $cell;
}
}
}
$data[$k] = $embedded_data;
}
}
elseif ($field_type === 'string_long' && $field
->getName() === 'json_values' && $field
->getEntity()
->getEntityTypeId() === 'cohesion_layout') {
$value = $source_entity->{$k}->value;
$layout_canvas = new LayoutCanvas($value);
foreach ($layout_canvas
->iterateCanvas() as $element) {
$data_layout = [];
if ($element
->isComponent() && ($component = Component::load($element
->getComponentID()))) {
// Get the models of each form field of the component as an array keyed by their uuid
$component_model = $component
->getLayoutCanvasInstance()
->iterateModels('component_form');
if ($element
->getModel()) {
$data_layout = array_merge($data_layout, $this
->extractCohesionComponentValues($component_model, $element
->getModel()
->getValues()));
}
}
if (!empty($data_layout)) {
$data[$k][$element
->getModelUUID()] = $data_layout;
}
}
unset($data[$k][0]);
}
elseif ($field_type === 'metatag') {
foreach ($source_entity->{$k} as $field_item) {
$metatag_serialized = $field_item
->get('value')
->getValue();
$metatags = unserialize($metatag_serialized);
if ($metatags) {
$data[$k][$field_item
->getName()] = $metatags;
}
}
}
elseif ($field_type === 'path') {
if ($source_entity
->id()) {
$source = '/' . $source_entity
->toUrl()
->getInternalPath();
/** @var \Drupal\Core\Entity\EntityStorageInterface $aliasStorage */
$alias_storage = $this->entityTypeManager
->getStorage('path_alias');
/** @var \Drupal\path_alias\PathAliasInterface[] $paths */
$paths = $alias_storage
->loadByProperties([
'path' => $source,
'langcode' => $source_entity
->language()
->getId(),
]);
if (count($paths) > 0) {
$path = reset($paths);
$alias = $path
->getAlias();
if ($alias !== NULL) {
$data[$k][0]['alias'] = $alias;
}
}
}
}
}
// Embed entity metadata. We need to exclude intelligence metadata if it is
// a child entity.
$this
->includeMetadata($source_entity, $data, $isParentEntity);
return $data;
}