View source
<?php
namespace Drupal\lingotek;
use Drupal\cohesion\LayoutCanvas\ElementModel;
use Drupal\cohesion\LayoutCanvas\LayoutCanvas;
use Drupal\cohesion_elements\Entity\Component;
use Drupal\Component\Render\FormattableMarkup;
use Drupal\Component\Utility\Html;
use Drupal\Component\Utility\NestedArray;
use Drupal\Component\Utility\SortArray;
use Drupal\Component\Utility\UrlHelper;
use Drupal\Core\Config\Entity\ConfigEntityInterface;
use Drupal\Core\Database\Connection;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\ContentEntityTypeInterface;
use Drupal\Core\Entity\EntityChangedInterface;
use Drupal\Core\Entity\EntityFieldManagerInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Entity\EntityStorageException;
use Drupal\Core\Entity\RevisionableEntityBundleInterface;
use Drupal\Core\Entity\RevisionLogInterface;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\language\Entity\ConfigurableLanguage;
use Drupal\lingotek\Entity\LingotekContentMetadata;
use Drupal\lingotek\Exception\LingotekApiException;
use Drupal\lingotek\Exception\LingotekContentEntityStorageException;
use Drupal\lingotek\Exception\LingotekDocumentArchivedException;
use Drupal\lingotek\Exception\LingotekDocumentLockedException;
use Drupal\lingotek\Exception\LingotekPaymentRequiredException;
use Drupal\node\NodeInterface;
use Drupal\user\UserInterface;
class LingotekContentTranslationService implements LingotekContentTranslationServiceInterface {
use StringTranslationTrait;
protected $lingotek;
protected $languageLocaleMapper;
protected $lingotekConfiguration;
protected $lingotekConfigTranslation;
protected $entityTypeManager;
protected $entityFieldManager;
protected $languageManager;
protected $connection;
public function __construct(LingotekInterface $lingotek, LanguageLocaleMapperInterface $language_locale_mapper, LingotekConfigurationServiceInterface $lingotek_configuration, LingotekConfigTranslationServiceInterface $lingotek_config_translation, EntityTypeManagerInterface $entity_type_manager, LanguageManagerInterface $language_manager, EntityFieldManagerInterface $entity_field_manager, Connection $connection) {
$this->lingotek = $lingotek;
$this->languageLocaleMapper = $language_locale_mapper;
$this->lingotekConfiguration = $lingotek_configuration;
$this->lingotekConfigTranslation = $lingotek_config_translation;
$this->entityTypeManager = $entity_type_manager;
$this->languageManager = $language_manager;
$this->entityFieldManager = $entity_field_manager;
$this->connection = $connection;
}
public function checkSourceStatus(ContentEntityInterface &$entity) {
$profile = $this->lingotekConfiguration
->getEntityProfile($entity);
if ($profile
->id() === Lingotek::PROFILE_DISABLED || $this
->getSourceStatus($entity) === Lingotek::STATUS_CANCELLED) {
return FALSE;
}
$document_id = $this
->getDocumentId($entity);
$maxImportTime = 3600;
$source_status = $this
->getSourceStatus($entity);
if ($document_id) {
if ($this->lingotek
->getDocumentStatus($document_id)) {
$this
->setSourceStatus($entity, Lingotek::STATUS_CURRENT);
return TRUE;
}
else {
if ($entity
->getEntityType()
->entityClassImplements(EntityChangedInterface::class)) {
$last_uploaded_time = $entity
->getChangedTime();
if (\Drupal::time()
->getRequestTime() - $last_uploaded_time > $maxImportTime) {
$this
->setSourceStatus($entity, Lingotek::STATUS_ERROR);
}
else {
}
}
return FALSE;
}
}
if ($this
->getSourceStatus($entity) == Lingotek::STATUS_DISABLED) {
$this
->setTargetStatuses($entity, Lingotek::STATUS_DISABLED);
}
return FALSE;
}
public function getSourceStatus(ContentEntityInterface &$entity) {
$source_language = LanguageInterface::LANGCODE_NOT_SPECIFIED;
$metadata = $entity->lingotek_metadata ? $entity->lingotek_metadata->entity : NULL;
if ($metadata !== NULL && $metadata->translation_source && $metadata->translation_source->value !== NULL) {
$source_language = $metadata->translation_source->value;
}
if ($source_language == LanguageInterface::LANGCODE_NOT_SPECIFIED) {
$source_language = $entity
->getUntranslated()
->language()
->getId();
}
return $this
->getTargetStatus($entity, $source_language);
}
public function setSourceStatus(ContentEntityInterface &$entity, $status) {
$metadata = $entity->lingotek_metadata->entity;
$source_language = $metadata->translation_source->value;
if ($source_language == LanguageInterface::LANGCODE_NOT_SPECIFIED || $source_language == NULL) {
$source_language = $entity
->getUntranslated()
->language()
->getId();
}
return $this
->setTargetStatus($entity, $source_language, $status);
}
protected function clearTargetStatuses(ContentEntityInterface &$entity) {
$profile = $this->lingotekConfiguration
->getEntityProfile($entity);
if ($profile
->id() === Lingotek::PROFILE_DISABLED || $this
->getSourceStatus($entity) === Lingotek::STATUS_CANCELLED) {
return FALSE;
}
$source_status = $this
->getSourceStatus($entity);
$metadata =& $entity->lingotek_metadata->entity;
if ($metadata
->hasField('translation_status') && count($metadata->translation_status) > 0) {
$metadata->translation_status = NULL;
}
$this
->setTargetStatus($entity, $entity
->getUntranslated()
->language()
->getId(), $source_status);
}
public function checkTargetStatuses(ContentEntityInterface &$entity) {
$profile = $this->lingotekConfiguration
->getEntityProfile($entity);
if ($profile
->id() === Lingotek::PROFILE_DISABLED || $this
->getSourceStatus($entity) === Lingotek::STATUS_CANCELLED) {
return FALSE;
}
$document_id = $this
->getDocumentId($entity);
$translation_statuses = $this->lingotek
->getDocumentTranslationStatuses($document_id);
$source_status = $this
->getSourceStatus($entity);
$statuses = [];
$languages = $this->languageManager
->getLanguages();
foreach ($languages as $language) {
$statuses[$language
->getId()] = $this
->getTargetStatus($entity, $language
->getId());
}
$this
->clearTargetStatuses($entity);
foreach ($translation_statuses as $lingotek_locale => $progress) {
$drupal_language = $this->languageLocaleMapper
->getConfigurableLanguageForLocale($lingotek_locale);
if ($drupal_language == NULL) {
continue;
}
$langcode = $drupal_language
->id();
$current_target_status = $statuses[$langcode];
if (in_array($current_target_status, [
Lingotek::STATUS_UNTRACKED,
Lingotek::STATUS_DISABLED,
Lingotek::STATUS_EDITED,
Lingotek::STATUS_REQUEST,
Lingotek::STATUS_NONE,
Lingotek::STATUS_READY,
Lingotek::STATUS_PENDING,
Lingotek::STATUS_CANCELLED,
NULL,
])) {
if ($progress === Lingotek::STATUS_CANCELLED) {
$this
->setTargetStatus($entity, $langcode, Lingotek::STATUS_CANCELLED);
}
elseif ($progress === Lingotek::PROGRESS_COMPLETE) {
$this
->setTargetStatus($entity, $langcode, Lingotek::STATUS_READY);
}
else {
$this
->setTargetStatus($entity, $langcode, Lingotek::STATUS_PENDING);
}
}
if ($source_status !== Lingotek::STATUS_CURRENT && $statuses[$langcode] === Lingotek::STATUS_EDITED && $langcode !== $entity
->getUntranslated()
->language()
->getId()) {
$this
->setTargetStatus($entity, $langcode, Lingotek::STATUS_EDITED);
}
if ($source_status === Lingotek::STATUS_CURRENT && $statuses[$langcode] === Lingotek::STATUS_CURRENT && $langcode !== $entity
->getUntranslated()
->language()
->getId()) {
$this
->setTargetStatus($entity, $langcode, Lingotek::STATUS_CURRENT);
}
}
if ($this
->getSourceStatus($entity) == Lingotek::STATUS_DISABLED) {
$this
->setTargetStatuses($entity, Lingotek::STATUS_DISABLED);
}
}
public function checkTargetStatus(ContentEntityInterface &$entity, $langcode) {
$profile = $this->lingotekConfiguration
->getEntityProfile($entity);
if ($profile
->id() === Lingotek::PROFILE_DISABLED || $this
->getSourceStatus($entity) === Lingotek::STATUS_CANCELLED) {
return FALSE;
}
$current_status = $this
->getTargetStatus($entity, $langcode);
$locale = $this->languageLocaleMapper
->getLocaleForLangcode($langcode);
$source_status = $this
->getSourceStatus($entity);
$document_id = $this
->getDocumentId($entity);
if ($langcode !== $entity
->getUntranslated()
->language()
->getId()) {
if (($current_status == Lingotek::STATUS_PENDING || $current_status == Lingotek::STATUS_EDITED) && $source_status !== Lingotek::STATUS_EDITED) {
$translation_status = $this->lingotek
->getDocumentTranslationStatus($document_id, $locale);
if ($translation_status === Lingotek::STATUS_CANCELLED) {
$this
->setTargetStatus($entity, $langcode, Lingotek::STATUS_CANCELLED);
}
elseif ($translation_status === TRUE) {
$current_status = Lingotek::STATUS_READY;
$this
->setTargetStatus($entity, $langcode, $current_status);
}
elseif ($this->lingotek
->downloadDocument($document_id, $locale)) {
}
}
elseif ($current_status == Lingotek::STATUS_REQUEST || $current_status == Lingotek::STATUS_UNTRACKED) {
$translation_status = $this->lingotek
->getDocumentTranslationStatus($document_id, $locale);
if ($translation_status === TRUE) {
$current_status = Lingotek::STATUS_READY;
$this
->setTargetStatus($entity, $langcode, $current_status);
}
elseif ($translation_status !== FALSE) {
$current_status = Lingotek::STATUS_PENDING;
$this
->setTargetStatus($entity, $langcode, $current_status);
}
}
}
if ($this
->getSourceStatus($entity) == Lingotek::STATUS_DISABLED) {
$this
->setTargetStatuses($entity, Lingotek::STATUS_DISABLED);
}
return $current_status;
}
public function getTargetStatus(ContentEntityInterface &$entity, $langcode) {
$status = Lingotek::STATUS_UNTRACKED;
$statuses = $this
->getTargetStatuses($entity);
if (isset($statuses[$langcode])) {
$status = $statuses[$langcode];
}
return $status;
}
public function getTargetStatuses(ContentEntityInterface &$entity) {
$statuses = [];
$metadata = $entity->lingotek_metadata ? $entity->lingotek_metadata->entity : NULL;
if ($metadata !== NULL && count($metadata->translation_status) > 0) {
foreach ($metadata->translation_status
->getIterator() as $delta => $value) {
$statuses[$value->language] = $value->value;
}
}
return $statuses;
}
public function setTargetStatus(ContentEntityInterface &$entity, $langcode, $status, $save = TRUE) {
$set = FALSE;
if (!$entity->lingotek_metadata->entity) {
$entity->lingotek_metadata->entity = LingotekContentMetadata::loadByTargetId($entity
->getEntityTypeId(), $entity
->id());
}
$metadata =& $entity->lingotek_metadata->entity;
if ($metadata
->hasField('translation_status') && count($metadata->translation_status) > 0) {
foreach ($metadata->translation_status
->getIterator() as $delta => $value) {
if ($value->language == $langcode) {
$value->value = $status;
$set = TRUE;
}
}
}
if (!$set && $metadata
->hasField('translation_status')) {
$metadata->translation_status
->appendItem([
'language' => $langcode,
'value' => $status,
]);
$set = TRUE;
}
if ($set) {
$entity->lingotek_processed = TRUE;
$metadata
->save();
}
return $entity;
}
public function setTargetStatuses(ContentEntityInterface &$entity, $status) {
$target_languages = $this->languageManager
->getLanguages();
$entity_langcode = $entity
->getUntranslated()
->language()
->getId();
foreach ($target_languages as $langcode => $language) {
if ($langcode != $entity_langcode && ($current_status = $this
->getTargetStatus($entity, $langcode))) {
if ($current_status === Lingotek::STATUS_PENDING && $status === Lingotek::STATUS_REQUEST) {
continue;
}
if (in_array($current_status, [
Lingotek::STATUS_UNTRACKED,
Lingotek::STATUS_REQUEST,
Lingotek::STATUS_DISABLED,
NULL,
]) && $status === Lingotek::STATUS_PENDING) {
continue;
}
if ($current_status == $status) {
continue;
}
if ($current_status != Lingotek::STATUS_EDITED && $current_status !== Lingotek::STATUS_CURRENT) {
$this
->setTargetStatus($entity, $langcode, $status);
}
elseif ($current_status == Lingotek::STATUS_EDITED && in_array($status, [
Lingotek::STATUS_CURRENT,
Lingotek::STATUS_PENDING,
])) {
$this
->setTargetStatus($entity, $langcode, $status);
}
if ($status === Lingotek::STATUS_CANCELLED) {
$this
->setTargetStatus($entity, $langcode, $status);
}
if ($status === Lingotek::STATUS_DISABLED) {
$this
->setTargetStatus($entity, $langcode, $status);
}
}
}
}
public function markTranslationsAsDirty(ContentEntityInterface &$entity) {
$profile = $this->lingotekConfiguration
->getEntityProfile($entity);
if ($profile
->id() === Lingotek::PROFILE_DISABLED || $this
->getSourceStatus($entity) === Lingotek::STATUS_CANCELLED) {
return FALSE;
}
$target_languages = $this->languageManager
->getLanguages();
$entity_langcode = $entity
->getUntranslated()
->language()
->getId();
$to_change = [
Lingotek::STATUS_CURRENT,
];
foreach ($target_languages as $langcode => $language) {
if ($langcode != $entity_langcode && ($current_status = $this
->getTargetStatus($entity, $langcode))) {
if (in_array($current_status, $to_change)) {
$this
->setTargetStatus($entity, $langcode, Lingotek::STATUS_PENDING);
}
}
}
}
public function getDocumentId(ContentEntityInterface &$entity) {
$doc_id = NULL;
$metadata = $entity
->hasField('lingotek_metadata') ? $entity->lingotek_metadata->entity : NULL;
if ($metadata !== NULL && $metadata->document_id) {
$doc_id = $metadata->document_id->value;
}
return $doc_id;
}
public function setDocumentId(ContentEntityInterface &$entity, $doc_id) {
if ($entity->lingotek_metadata->entity === NULL) {
$entity->lingotek_metadata->entity = LingotekContentMetadata::loadByTargetId($entity
->getEntityTypeId(), $entity
->id());
}
$entity->lingotek_processed = TRUE;
$entity->lingotek_metadata->entity
->setDocumentId($doc_id);
$entity->lingotek_metadata->entity
->save();
return $entity;
}
public function getSourceLocale(ContentEntityInterface &$entity) {
$source_language = $entity
->getUntranslated()
->language()
->getId();
return $this->languageLocaleMapper
->getLocaleForLangcode($source_language);
}
public function getSourceData(ContentEntityInterface &$entity, &$visited = []) {
$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 = [];
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 = [];
$source_entity = $entity
->getUntranslated();
foreach ($translatable_fields as $k => $definition) {
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 (!$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 ($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 ($entity->{$k} as $field_item) {
$pluginId = $field_item
->get('plugin_id')
->getValue();
$block_instance = $field_item
->getBlock();
$lingotekConfigTranslation = \Drupal::service('lingotek.config_translation');
$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 === 'entity_reference' || $field_type === 'er_viewmode' || $field_type === 'bricks') {
$target_entity_type_id = $field_definitions[$k]
->getFieldStorageDefinition()
->getSetting('target_type');
foreach ($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);
if ($embedded_entity !== NULL) {
if ($embedded_entity instanceof ContentEntityInterface) {
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 {
$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 {
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 ($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);
if (!empty($embedded_entity)) {
$embedded_data = $this
->getSourceData($embedded_entity, $visited);
$data[$k][$field_item
->getName()] = $embedded_data;
}
else {
unset($data[$k]);
}
}
}
elseif ($field_type === 'tablefield') {
foreach ($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 = $entity->{$k}->value;
$layout_canvas = new LayoutCanvas($value);
foreach ($layout_canvas
->iterateCanvas() as $element) {
$data_layout = [];
if ($element
->isComponent() && ($component = Component::load($element
->getComponentID()))) {
$component_model = $component
->getLayoutCanvasInstance()
->iterateModels('component_form');
if ($element
->getModel()) {
$data_layout = array_merge($data_layout, $this
->processCohesionComponentsValues($element
->getModel()
->getValues(), $component_model));
}
}
$data[$k][$element
->getModelUUID()] = $data_layout;
}
unset($data[$k][0]);
}
elseif ($field_type === 'metatag') {
foreach ($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 ($entity
->id()) {
$source = '/' . $entity
->toUrl()
->getInternalPath();
$alias_storage = $this->entityTypeManager
->getStorage('path_alias');
$paths = $alias_storage
->loadByProperties([
'path' => $source,
'langcode' => $entity
->language()
->getId(),
]);
if (count($paths) > 0) {
$path = reset($paths);
$alias = $path
->getAlias();
if ($alias !== NULL) {
$data[$k][0]['alias'] = $alias;
}
}
}
}
}
$this
->includeMetadata($entity, $data, $isParentEntity);
return $data;
}
private function processCohesionComponentsValues($values, $component_model, $model_key = []) {
$data_layout = [];
foreach ($values as $key => $value) {
if (preg_match(ElementModel::MATCH_UUID, $key)) {
if (is_array($value)) {
foreach ($value as $index => $inner_value) {
$data_layout = array_merge($data_layout, $this
->processCohesionComponentsValues($inner_value, $component_model, array_merge($model_key, [
$key,
$index,
])));
}
}
elseif (isset($component_model[$key]) && $component_model[$key]
->getProperty([
'settings',
'translate',
]) !== FALSE) {
$form_elements = \Drupal::keyValue('cohesion.assets.form_elements');
$field_uid = $component_model[$key]
->getElement()
->getProperty('uid');
$form_field = $form_elements
->get($field_uid);
$model = $component = $component_model[$key]
->getElement()
->getProperty('uuid');
$componentType = isset($form_field['model']['settings']['type']) ? $form_field['model']['settings']['type'] : 'notDiscardedType';
$protectedComponentTypes = [
'cohTypeahead',
'cohEntityBrowser',
'cohFileBrowser',
];
if (!in_array($componentType, $protectedComponentTypes)) {
if (isset($form_field['translate']) && $form_field['translate'] === TRUE) {
if (is_string($value) && !empty($value)) {
$data_layout[$key] = $value;
}
elseif (is_object($value) && property_exists($value, 'text') && property_exists($value, 'textFormat')) {
$data_layout[$key] = Html::escape($value->text);
}
}
}
}
}
}
return $data_layout;
}
public function updateEntityHash(ContentEntityInterface $entity) {
$source_data = json_encode($this
->getSourceData($entity));
if ($entity->lingotek_metadata->entity) {
$entity->lingotek_metadata->entity->lingotek_hash = md5($source_data);
$entity->lingotek_metadata->entity
->save();
}
}
public function hasEntityChanged(ContentEntityInterface &$entity) {
if (isset($entity->original)) {
if ($entity
->getRevisionId() !== $entity->original
->getRevisionId()) {
return TRUE;
}
$source_data = $this
->getSourceData($entity);
if (isset($source_data['_lingotek_metadata'])) {
unset($source_data['_lingotek_metadata']['_entity_revision']);
}
$source_data = json_encode($source_data);
$hash = md5($source_data);
$old_source_data = $this
->getSourceData($entity->original);
if (isset($old_source_data['_lingotek_metadata'])) {
unset($old_source_data['_lingotek_metadata']['_entity_revision']);
}
$old_source_data = json_encode($old_source_data);
$old_hash = md5($old_source_data);
return (bool) strcmp($hash, $old_hash);
}
else {
return TRUE;
}
}
public function addTarget(ContentEntityInterface &$entity, $locale) {
$profile = $this->lingotekConfiguration
->getEntityProfile($entity);
if ($profile
->id() === Lingotek::PROFILE_DISABLED || $this
->getSourceStatus($entity) === Lingotek::STATUS_CANCELLED) {
return FALSE;
}
$source_langcode = $entity
->getUntranslated()
->language()
->getId();
$source_locale = $this->languageLocaleMapper
->getLocaleForLangcode($source_langcode);
if ($locale == $source_locale) {
return FALSE;
}
if ($document_id = $this
->getDocumentId($entity)) {
$drupal_language = $this->languageLocaleMapper
->getConfigurableLanguageForLocale($locale);
$source_status = $this
->getSourceStatus($entity);
$current_status = $this
->getTargetStatus($entity, $drupal_language
->id());
$pristine_statuses = [
Lingotek::STATUS_REQUEST,
Lingotek::STATUS_UNTRACKED,
Lingotek::STATUS_EDITED,
];
if (in_array($current_status, $pristine_statuses)) {
try {
$result = $this->lingotek
->addTarget($document_id, $locale, $this->lingotekConfiguration
->getEntityProfile($entity));
} catch (LingotekDocumentLockedException $exception) {
$this
->setDocumentId($entity, $exception
->getNewDocumentId());
throw $exception;
} catch (LingotekDocumentArchivedException $exception) {
$this
->setDocumentId($entity, NULL);
$this
->deleteMetadata($entity);
throw $exception;
} catch (LingotekPaymentRequiredException $exception) {
throw $exception;
} catch (LingotekApiException $exception) {
throw $exception;
}
if ($result) {
$this
->setTargetStatus($entity, $drupal_language
->id(), Lingotek::STATUS_PENDING);
if ($source_status == Lingotek::STATUS_IMPORTING) {
$this
->setSourceStatus($entity, Lingotek::STATUS_CURRENT);
}
return TRUE;
}
}
}
if ($this
->getSourceStatus($entity) == Lingotek::STATUS_DISABLED) {
$this
->setTargetStatuses($entity, Lingotek::STATUS_DISABLED);
}
return FALSE;
}
public function requestTranslations(ContentEntityInterface &$entity) {
$profile = $this->lingotekConfiguration
->getEntityProfile($entity);
if ($profile
->id() === Lingotek::PROFILE_DISABLED || $this
->getSourceStatus($entity) === Lingotek::STATUS_CANCELLED) {
return FALSE;
}
$languages = [];
if ($document_id = $this
->getDocumentId($entity)) {
$target_languages = $this->languageManager
->getLanguages();
$target_languages = array_filter($target_languages, function (LanguageInterface $language) {
$configLanguage = ConfigurableLanguage::load($language
->getId());
return $this->lingotekConfiguration
->isLanguageEnabled($configLanguage);
});
$entity_langcode = $entity
->getUntranslated()
->language()
->getId();
foreach ($target_languages as $langcode => $language) {
$locale = $this->languageLocaleMapper
->getLocaleForLangcode($langcode);
if ($langcode !== $entity_langcode) {
$source_status = $this
->getSourceStatus($entity);
$current_status = $this
->getTargetStatus($entity, $langcode);
if ($current_status !== Lingotek::STATUS_PENDING && $current_status !== Lingotek::STATUS_CURRENT && $current_status !== Lingotek::STATUS_EDITED && $current_status !== Lingotek::STATUS_READY) {
try {
$result = $this->lingotek
->addTarget($document_id, $locale, $this->lingotekConfiguration
->getEntityProfile($entity));
} catch (LingotekDocumentLockedException $exception) {
$this
->setDocumentId($entity, $exception
->getNewDocumentId());
throw $exception;
} catch (LingotekDocumentArchivedException $exception) {
$this
->setDocumentId($entity, NULL);
$this
->deleteMetadata($entity);
throw $exception;
} catch (LingotekPaymentRequiredException $exception) {
throw $exception;
} catch (LingotekApiException $exception) {
throw $exception;
}
if ($result) {
$languages[] = $langcode;
$this
->setTargetStatus($entity, $langcode, Lingotek::STATUS_PENDING);
if ($source_status == Lingotek::STATUS_IMPORTING) {
$this
->setSourceStatus($entity, Lingotek::STATUS_CURRENT);
}
}
}
}
}
}
if ($this
->getSourceStatus($entity) == Lingotek::STATUS_DISABLED) {
$this
->setTargetStatuses($entity, Lingotek::STATUS_DISABLED);
}
return $languages;
}
public function uploadDocument(ContentEntityInterface $entity, $job_id = NULL) {
$profile = $this->lingotekConfiguration
->getEntityProfile($entity);
if (!$this->lingotekConfiguration
->isEnabled($entity
->getEntityTypeId(), $entity
->bundle())) {
return FALSE;
}
if ($profile
->id() === Lingotek::PROFILE_DISABLED) {
return FALSE;
}
if ($job_id === NULL) {
$job_id = $this
->getJobId($entity) ?: NULL;
}
if ($document_id = $this
->getDocumentId($entity)) {
return $this
->updateDocument($entity, $job_id);
}
$source_data = $this
->getSourceData($entity);
$extended_name = $entity
->bundle() . ' (' . $entity
->getEntityTypeId() . '): ' . $entity
->label();
$profile_preference = $profile
->getAppendContentTypeToTitle();
$global_preference = $this->lingotekConfiguration
->getPreference('append_type_to_title');
switch ($profile_preference) {
case 'yes':
$document_name = $extended_name;
break;
case 'no':
$document_name = $entity
->label();
break;
case 'global_setting':
$document_name = $global_preference ? $extended_name : $entity
->label();
break;
default:
$document_name = $extended_name;
}
$url = $entity
->hasLinkTemplate('canonical') ? $entity
->toUrl()
->setAbsolute(TRUE)
->toString() : NULL;
\Drupal::moduleHandler()
->invokeAll('lingotek_content_entity_document_upload', [
&$source_data,
&$entity,
&$url,
]);
try {
$document_id = $this->lingotek
->uploadDocument($document_name, $source_data, $this
->getSourceLocale($entity), $url, $profile, $job_id);
} catch (LingotekPaymentRequiredException $exception) {
$this
->setSourceStatus($entity, Lingotek::STATUS_ERROR);
throw $exception;
} catch (LingotekApiException $exception) {
$this
->setSourceStatus($entity, Lingotek::STATUS_ERROR);
throw $exception;
}
if ($document_id) {
$this->lingotekConfiguration
->setProfile($entity, $profile
->id());
$this
->setDocumentId($entity, $document_id);
$this
->setSourceStatus($entity, Lingotek::STATUS_IMPORTING);
$this
->setTargetStatuses($entity, Lingotek::STATUS_REQUEST);
$this
->setJobId($entity, $job_id);
return $document_id;
}
if ($this
->getSourceStatus($entity) == Lingotek::STATUS_DISABLED) {
$this
->setTargetStatuses($entity, Lingotek::STATUS_DISABLED);
}
return FALSE;
}
public function downloadDocument(ContentEntityInterface &$entity, $locale) {
$profile = $this->lingotekConfiguration
->getEntityProfile($entity);
if ($profile
->id() === Lingotek::PROFILE_DISABLED || $this
->getSourceStatus($entity) === Lingotek::STATUS_CANCELLED) {
\Drupal::logger('lingotek')
->warning($this
->t('Avoided download for (%entity_id,%revision_id): Source status is %source_status.', [
'%entity_id' => $entity
->id(),
'%revision_id' => $entity
->getRevisionId(),
'%source_status' => $this
->getSourceStatus($entity),
]));
return FALSE;
}
if ($document_id = $this
->getDocumentId($entity)) {
$source_status = $this
->getSourceStatus($entity);
$drupal_language = $this->languageLocaleMapper
->getConfigurableLanguageForLocale($locale);
$langcode = $drupal_language
->id();
$data = [];
try {
if ($this->lingotek
->getDocumentTranslationStatus($document_id, $locale) !== FALSE) {
$data = $this->lingotek
->downloadDocument($document_id, $locale);
}
else {
\Drupal::logger('lingotek')
->warning($this
->t('Avoided download for (%entity_id,%revision_id): Source status is %source_status.', [
'%entity_id' => $entity
->id(),
'%revision_id' => $entity
->getRevisionId(),
'%source_status' => $this
->getSourceStatus($entity),
]));
return NULL;
}
} catch (LingotekApiException $exception) {
\Drupal::logger('lingotek')
->error($this
->t('Error happened downloading %document_id %locale: %message', [
'%document_id' => $document_id,
'%locale' => $locale,
'%message' => $exception
->getMessage(),
]));
$this
->setTargetStatus($entity, $langcode, Lingotek::STATUS_ERROR);
throw $exception;
}
if ($data) {
$status = $this->lingotek
->getDocumentTranslationStatus($document_id, $locale);
$transaction = $this->connection
->startTransaction();
try {
$saved = $this
->saveTargetData($entity, $langcode, $data);
if ($saved) {
if ($source_status == Lingotek::STATUS_IMPORTING) {
$this
->setSourceStatus($entity, Lingotek::STATUS_CURRENT);
}
if ($source_status == Lingotek::STATUS_EDITED) {
$this
->setTargetStatus($entity, $langcode, Lingotek::STATUS_EDITED);
}
elseif ($status === TRUE) {
$this
->setTargetStatus($entity, $langcode, Lingotek::STATUS_CURRENT);
}
else {
$this
->setTargetStatus($entity, $langcode, Lingotek::STATUS_INTERMEDIATE);
}
}
} catch (LingotekContentEntityStorageException $storageException) {
$this
->setTargetStatus($entity, $langcode, Lingotek::STATUS_ERROR);
\Drupal::logger('lingotek')
->error($this
->t('Error happened (storage) saving %document_id %locale: %message', [
'%document_id' => $document_id,
'%locale' => $locale,
'%message' => $storageException
->getMessage(),
]));
throw $storageException;
} catch (\Exception $exception) {
\Drupal::logger('lingotek')
->error($this
->t('Error happened (unknown) saving %document_id %locale: %message', [
'%document_id' => $document_id,
'%locale' => $locale,
'%message' => $exception
->getMessage(),
]));
$this
->setTargetStatus($entity, $langcode, Lingotek::STATUS_ERROR);
$transaction
->rollBack();
return FALSE;
}
return TRUE;
}
}
if ($this
->getSourceStatus($entity) == Lingotek::STATUS_DISABLED) {
$this
->setTargetStatuses($entity, Lingotek::STATUS_DISABLED);
}
\Drupal::logger('lingotek')
->warning($this
->t('Error happened trying to download (%entity_id,%revision_id): no document id found.', [
'%entity_id' => $entity
->id(),
'%revision_id' => $entity
->getRevisionId(),
]));
return FALSE;
}
public function updateDocument(ContentEntityInterface &$entity, $job_id = NULL) {
$profile = $this->lingotekConfiguration
->getEntityProfile($entity);
if ($profile
->id() === Lingotek::PROFILE_DISABLED || $this
->getSourceStatus($entity) === Lingotek::STATUS_CANCELLED) {
return FALSE;
}
if ($job_id === NULL) {
$job_id = $this
->getJobId($entity) ?: NULL;
}
$source_data = $this
->getSourceData($entity);
$document_id = $this
->getDocumentId($entity);
$url = $entity
->hasLinkTemplate('canonical') ? $entity
->toUrl()
->setAbsolute(TRUE)
->toString() : NULL;
$extended_name = $entity
->bundle() . ' (' . $entity
->getEntityTypeId() . '): ' . $entity
->label();
$profile_preference = $profile
->getAppendContentTypeToTitle();
$global_preference = $this->lingotekConfiguration
->getPreference('append_type_to_title');
switch ($profile_preference) {
case 'yes':
$document_name = $extended_name;
break;
case 'no':
$document_name = $entity
->label();
break;
case 'global_setting':
$document_name = $global_preference ? $extended_name : $entity
->label();
break;
default:
$document_name = $extended_name;
}
\Drupal::moduleHandler()
->invokeAll('lingotek_content_entity_document_upload', [
&$source_data,
&$entity,
&$url,
]);
try {
$newDocumentID = $this->lingotek
->updateDocument($document_id, $source_data, $url, $document_name, $profile, $job_id);
} catch (LingotekDocumentLockedException $exception) {
$this
->setDocumentId($entity, $exception
->getNewDocumentId());
throw $exception;
} catch (LingotekDocumentArchivedException $exception) {
$this
->setDocumentId($entity, NULL);
$this
->deleteMetadata($entity);
throw $exception;
} catch (LingotekPaymentRequiredException $exception) {
$this
->setSourceStatus($entity, Lingotek::STATUS_ERROR);
throw $exception;
} catch (LingotekApiException $exception) {
$this
->setSourceStatus($entity, Lingotek::STATUS_ERROR);
throw $exception;
}
if ($newDocumentID) {
if (is_string($newDocumentID)) {
$document_id = $newDocumentID;
$this
->setDocumentId($entity, $newDocumentID);
}
$this
->setSourceStatus($entity, Lingotek::STATUS_IMPORTING);
$this
->setTargetStatuses($entity, Lingotek::STATUS_PENDING);
$this
->setJobId($entity, $job_id);
return $document_id;
}
if ($this
->getSourceStatus($entity) == Lingotek::STATUS_DISABLED) {
$this
->setTargetStatuses($entity, Lingotek::STATUS_DISABLED);
}
return FALSE;
}
public function downloadDocuments(ContentEntityInterface &$entity) {
$profile = $this->lingotekConfiguration
->getEntityProfile($entity);
if ($profile
->id() === Lingotek::PROFILE_DISABLED || $this
->getSourceStatus($entity) === Lingotek::STATUS_CANCELLED) {
return FALSE;
}
if ($document_id = $this
->getDocumentId($entity)) {
$source_status = $this
->getSourceStatus($entity);
$target_languages = $this->languageManager
->getLanguages();
$target_languages = array_filter($target_languages, function (LanguageInterface $language) {
$configLanguage = ConfigurableLanguage::load($language
->getId());
return $this->lingotekConfiguration
->isLanguageEnabled($configLanguage);
});
$entity_langcode = $entity
->getUntranslated()
->language()
->getId();
foreach ($target_languages as $langcode => $language) {
$locale = $this->languageLocaleMapper
->getLocaleForLangcode($langcode);
if ($langcode !== $entity_langcode) {
try {
if ($this->lingotek
->getDocumentTranslationStatus($document_id, $locale) !== FALSE) {
$data = $this->lingotek
->downloadDocument($document_id, $locale);
if ($data) {
$status = $this->lingotek
->getDocumentTranslationStatus($document_id, $locale);
$transaction = $this->connection
->startTransaction();
try {
$saved = $this
->saveTargetData($entity, $langcode, $data);
if ($saved) {
if ($source_status == Lingotek::STATUS_IMPORTING) {
$this
->setSourceStatus($entity, Lingotek::STATUS_CURRENT);
}
if ($source_status == Lingotek::STATUS_EDITED) {
$this
->setTargetStatus($entity, $langcode, Lingotek::STATUS_EDITED);
}
elseif ($status === TRUE) {
$this
->setTargetStatus($entity, $langcode, Lingotek::STATUS_CURRENT);
}
else {
$this
->setTargetStatus($entity, $langcode, Lingotek::STATUS_INTERMEDIATE);
}
}
} catch (LingotekApiException $exception) {
$this
->setTargetStatus($entity, $langcode, Lingotek::STATUS_ERROR);
throw $exception;
} catch (LingotekContentEntityStorageException $storageException) {
$this
->setTargetStatus($entity, $langcode, Lingotek::STATUS_ERROR);
throw $storageException;
} catch (\Exception $exception) {
$this
->setTargetStatus($entity, $langcode, Lingotek::STATUS_ERROR);
$transaction
->rollBack();
}
}
else {
return NULL;
}
}
} catch (LingotekApiException $exception) {
$this
->setTargetStatus($entity, $langcode, Lingotek::STATUS_ERROR);
throw $exception;
}
}
}
}
if ($this
->getSourceStatus($entity) == Lingotek::STATUS_DISABLED) {
$this
->setTargetStatuses($entity, Lingotek::STATUS_DISABLED);
}
return FALSE;
}
public function cancelDocument(ContentEntityInterface &$entity) {
$result = FALSE;
$doc_id = $this
->getDocumentId($entity);
if ($doc_id) {
$result = $this->lingotek
->cancelDocument($doc_id);
$this->lingotekConfiguration
->setProfile($entity, NULL);
$this
->setDocumentId($entity, NULL);
}
$this
->setSourceStatus($entity, Lingotek::STATUS_CANCELLED);
$this
->setTargetStatuses($entity, Lingotek::STATUS_CANCELLED);
return $result;
}
public function cancelDocumentTarget(ContentEntityInterface &$entity, $locale) {
$profile = $this->lingotekConfiguration
->getEntityProfile($entity);
if ($profile
->id() === Lingotek::PROFILE_DISABLED || $this
->getSourceStatus($entity) === Lingotek::STATUS_CANCELLED) {
return FALSE;
}
$source_langcode = $entity
->getUntranslated()
->language()
->getId();
$source_locale = $this->languageLocaleMapper
->getLocaleForLangcode($source_langcode);
if ($locale == $source_locale) {
return FALSE;
}
if ($document_id = $this
->getDocumentId($entity)) {
$drupal_language = $this->languageLocaleMapper
->getConfigurableLanguageForLocale($locale);
if ($this->lingotek
->cancelDocumentTarget($document_id, $locale)) {
$this
->setTargetStatus($entity, $drupal_language
->id(), Lingotek::STATUS_CANCELLED);
return TRUE;
}
}
if ($this
->getSourceStatus($entity) == Lingotek::STATUS_DISABLED) {
$this
->setTargetStatuses($entity, Lingotek::STATUS_DISABLED);
}
return FALSE;
}
public function deleteMetadata(ContentEntityInterface &$entity) {
$doc_id = $this
->getDocumentId($entity);
if ($doc_id) {
$this
->cancelDocument($entity);
}
$metadata = $entity->lingotek_metadata->entity;
if ($metadata !== NULL) {
$metadata
->delete();
}
}
public function loadByDocumentId($document_id) {
$entity = NULL;
$metadata = LingotekContentMetadata::loadByDocumentID($document_id);
if ($metadata && $metadata
->getContentEntityTypeId() && $metadata
->getContentEntityId()) {
$entity = $this->entityTypeManager
->getStorage($metadata
->getContentEntityTypeId())
->load($metadata
->getContentEntityId());
}
return $entity;
}
public function getAllLocalDocumentIds() {
return LingotekContentMetadata::getAllLocalDocumentIds();
}
protected function loadUploadedRevision(ContentEntityInterface $entity, $revision = NULL) {
$the_revision = NULL;
$entity_type = $entity
->getEntityType();
$entity_type_id = $entity
->getEntityTypeId();
$entity_storage = $this->entityTypeManager
->getStorage($entity_type_id);
if ($entity_type
->isRevisionable()) {
if ($revision !== NULL) {
$the_revision = $entity_storage
->loadRevision($revision);
}
elseif ($revision === NULL && $entity
->hasField('revision_timestamp')) {
$timestamp = $this->lingotek
->getUploadedTimestamp($this
->getDocumentId($entity));
$revision = $this
->getClosestRevisionToTimestamp($entity, $timestamp);
if ($revision !== NULL) {
$the_revision = $entity_storage
->loadRevision($revision);
}
}
if ($the_revision === NULL) {
$the_revision = $entity_storage
->loadRevision($entity
->getRevisionId());
}
}
else {
$entity_storage
->resetCache([
$entity
->id(),
]);
$the_revision = $entity_storage
->load($entity
->id());
}
return $the_revision;
}
protected function getClosestRevisionToTimestamp(ContentEntityInterface &$entity, $timestamp) {
$entity_id = $entity
->id();
$query = \Drupal::database()
->select($entity
->getEntityType()
->getRevisionDataTable(), 'nfr');
$query
->fields('nfr', [
$entity
->getEntityType()
->getKey('revision'),
]);
$query
->addJoin('INNER', $entity
->getEntityType()
->getRevisionTable(), 'nr', 'nfr.vid = nr.vid and nfr.nid = nr.nid and nfr.langcode = nr.langcode');
$query
->condition('nfr.' . $entity
->getEntityType()
->getKey('id'), $entity_id);
$query
->condition('nfr.' . $entity
->getEntityType()
->getKey('langcode'), $entity
->language()
->getId());
$query
->condition('nr.revision_timestamp', $timestamp, '<');
$query
->orderBy('nfr.changed', 'DESC');
$query
->range(0, 1);
$value = $query
->execute();
$vids = $value
->fetchAssoc();
return $vids !== FALSE && count($vids) === 1 ? $vids['vid'] : NULL;
}
public function saveTargetData(ContentEntityInterface &$entity, $langcode, $data) {
if (!$langcode) {
return FALSE;
}
$storage_definitions = $this->entityFieldManager
->getFieldStorageDefinitions($entity
->getEntityTypeId());
try {
$revision = isset($data['_lingotek_metadata']) && isset($data['_lingotek_metadata']['_entity_revision']) ? $data['_lingotek_metadata']['_entity_revision'] : NULL;
$revision = $this
->loadUploadedRevision($entity, $revision);
if ($entity
->id() && !$entity
->hasTranslationChanges()) {
$entity = $this->entityTypeManager
->getStorage($entity
->getEntityTypeId())
->load($entity
->id());
}
if (!$entity
->hasTranslation($langcode)) {
$entity
->addTranslation($langcode, $revision
->toArray());
}
$translation = $entity
->getTranslation($langcode);
foreach ($data as $name => $field_data) {
if (strpos($name, '_') === 0) {
break;
}
$field_definition = $entity
->getFieldDefinition($name);
if ($field_definition && ($field_definition
->isTranslatable() || $field_definition
->getType() === 'cohesion_entity_reference_revisions' || $field_definition
->getType() === 'entity_reference_revisions') && $this->lingotekConfiguration
->isFieldLingotekEnabled($entity
->getEntityTypeId(), $entity
->bundle(), $name)) {
$field_type = $field_definition
->getType();
if ($field_type === 'entity_reference' || $field_type === 'er_viewmode' || $field_type === 'bricks') {
$target_entity_type_id = $field_definition
->getFieldStorageDefinition()
->getSetting('target_type');
$translation->{$name} = NULL;
$delta = 0;
foreach ($field_data as $index => $field_item) {
if (isset($field_item['_lingotek_metadata'])) {
$target_entity_type_id = $field_item['_lingotek_metadata']['_entity_type_id'];
$embedded_entity_id = $field_item['_lingotek_metadata']['_entity_id'];
$embedded_entity_revision_id = $field_item['_lingotek_metadata']['_entity_revision'];
}
else {
$embedded_entity_id = $revision->{$name}
->get($index)
->get('target_id')
->getValue();
}
$embedded_entity = $this->entityTypeManager
->getStorage($target_entity_type_id)
->load($embedded_entity_id);
if ($embedded_entity !== NULL) {
if ($embedded_entity instanceof ContentEntityInterface) {
if ($this->lingotekConfiguration
->isEnabled($embedded_entity
->getEntityTypeId(), $embedded_entity
->bundle())) {
$this
->saveTargetData($embedded_entity, $langcode, $field_item);
}
else {
\Drupal::logger('lingotek')
->warning($this
->t('Field %field not saved as its referenced entity is not translatable by Lingotek', [
'%field' => $name,
]));
}
}
elseif ($embedded_entity instanceof ConfigEntityInterface) {
$this->lingotekConfigTranslation
->saveTargetData($embedded_entity, $langcode, $field_item);
}
$translation->{$name}
->set($delta, $embedded_entity_id);
$delta++;
}
}
}
elseif ($field_type === 'entity_reference_revisions') {
$paragraphTranslatable = $field_definition
->isTranslatable();
$target_entity_type_id = $field_definition
->getFieldStorageDefinition()
->getSetting('target_type');
if ($paragraphTranslatable) {
$translation->{$name} = NULL;
}
$delta = 0;
$fieldValues = [];
foreach ($field_data as $index => $field_item) {
$embedded_entity_id = $revision->{$name}
->get($index)
->get('target_id')
->getValue();
$embedded_entity = $this->entityTypeManager
->getStorage($target_entity_type_id)
->load($embedded_entity_id);
if ($embedded_entity !== NULL) {
if ($paragraphTranslatable && \Drupal::moduleHandler()
->moduleExists('paragraphs_asymmetric_translation_widgets')) {
$duplicate = $embedded_entity
->createDuplicate();
if ($duplicate
->isTranslatable()) {
if ($duplicate
->hasTranslation($langcode)) {
$duplicate
->removeTranslation($langcode);
$duplicate
->save();
}
$duplicate
->set('langcode', $langcode);
foreach ($duplicate
->getTranslationLanguages(FALSE) as $translationLanguage) {
try {
$duplicate
->removeTranslation($translationLanguage
->getId());
} catch (\InvalidArgumentException $e) {
}
}
}
$embedded_entity = $duplicate;
}
$this
->saveTargetData($embedded_entity, $langcode, $field_item);
$fieldValues[$delta] = [
'target_id' => $embedded_entity
->id(),
'target_revision_id' => $embedded_entity
->getRevisionId(),
];
$delta++;
}
}
if ($paragraphTranslatable) {
$translation->{$name} = $fieldValues;
}
}
elseif ($field_type === 'tablefield') {
foreach ($field_data as $delta => $field_item_data) {
$embedded_data = [];
$caption = '';
$table = [];
foreach ($field_item_data as $row_index => $row) {
if ($row_index === 'caption') {
$caption = $row;
}
else {
foreach ($row as $col_index => $cell) {
$table[intval(str_replace('row:', '', $row_index))][intval(str_replace('col:', '', $col_index))] = $cell;
}
}
}
$translation->{$name}
->set($delta, [
'caption' => $caption,
'value' => $table,
]);
}
}
elseif ($field_type === 'cohesion_entity_reference_revisions') {
$cohesionLayoutTranslatable = $field_definition
->isTranslatable();
$target_entity_type_id = $field_definition
->getFieldStorageDefinition()
->getSetting('target_type');
if ($cohesionLayoutTranslatable) {
$translation->{$name} = NULL;
}
$delta = 0;
$fieldValues = [];
foreach ($field_data as $index => $field_item) {
$embedded_entity_id = $revision->{$name}
->get($index)
->get('target_id')
->getValue();
$embedded_entity = $this->entityTypeManager
->getStorage($target_entity_type_id)
->load($embedded_entity_id);
if ($embedded_entity !== NULL) {
$this
->saveTargetData($embedded_entity, $langcode, $field_item);
$fieldValues[$delta] = [
'target_id' => $embedded_entity
->id(),
'target_revision_id' => $embedded_entity
->getRevisionId(),
];
$delta++;
}
}
if ($cohesionLayoutTranslatable) {
$translation->{$name} = $fieldValues;
}
}
elseif ($field_type === 'path') {
$pid = NULL;
$source = '/' . $entity
->toUrl()
->getInternalPath();
$alias_storage = $this->entityTypeManager
->getStorage('path_alias');
$original_paths = $alias_storage
->loadByProperties([
'path' => $source,
'langcode' => $entity
->getUntranslated()
->language()
->getId(),
]);
$original_path = NULL;
$alias = $field_data[0]['alias'];
if (!UrlHelper::isValid($alias)) {
\Drupal::logger('lingotek')
->warning($this
->t('Alias for %type %label in language %langcode not saved, invalid uri "%uri"', [
'%type' => $entity
->getEntityTypeId(),
'%label' => $entity
->label(),
'%langcode' => $langcode,
'%uri' => $alias,
]));
if (count($original_paths) > 0) {
$original_path = reset($original_paths);
$alias = $original_path
->getAlias();
}
else {
$alias = $source;
}
if (\Drupal::moduleHandler()
->moduleExists('pathauto')) {
$alias = '';
$translation
->get($name)
->offsetGet(0)
->set('alias', $alias);
$translation
->get($name)
->offsetGet(0)
->set('pathauto', TRUE);
}
}
if ($alias !== NULL) {
$translation
->get($name)
->offsetGet(0)
->set('alias', $alias);
if (\Drupal::moduleHandler()
->moduleExists('pathauto') && !empty($alias) && $alias !== $original_path) {
$translation
->get($name)
->offsetGet(0)
->set('pathauto', FALSE);
}
}
}
elseif ($field_type === 'metatag') {
$index = 0;
foreach ($field_data as $field_item) {
$metatag_value = serialize($field_item);
$translation->{$name}
->set($index, $metatag_value);
++$index;
}
}
elseif ($field_type === 'string_long' && $field_definition
->getName() === 'json_values' && $field_definition
->getTargetEntityTypeId() === 'cohesion_layout') {
$existingData = $revision
->get($name)
->offsetGet(0)->value;
$layout_canvas = new LayoutCanvas($existingData);
foreach ($layout_canvas
->iterateModels() as $element_uuid => &$model) {
foreach ($model
->getValues() as $key => $value) {
if (isset($field_data[$element_uuid]) && isset($field_data[$element_uuid][$key])) {
if (is_string($value) && !empty($value)) {
$model
->setProperty($key, $field_data[$element_uuid][$key]);
}
elseif (is_object($value) && property_exists($value, 'text') && property_exists($value, 'textFormat')) {
$new_value = $value;
$new_value->text = Html::decodeEntities($field_data[$element_uuid][$key]);
$model
->setProperty($key, $new_value);
}
}
}
}
$translation
->get($name)
->offsetGet(0)
->set('value', json_encode($layout_canvas));
}
elseif ($field_type === 'block_field') {
$translation->{$name} = NULL;
foreach ($field_data as $index => $field_item) {
$block = $revision
->get($name)
->get($index)
->getBlock();
if ($block !== NULL) {
$entityData = NULL;
if (isset($field_item['entity'])) {
$entityData = $field_item['entity'];
unset($field_item['entity']);
}
$configuration = $block
->getConfiguration();
$newConfiguration = $configuration;
foreach ($field_item as $fieldItemProperty => $fieldItemPropertyData) {
$componentDataKeyParts = explode('.', $fieldItemProperty);
NestedArray::setValue($newConfiguration, $componentDataKeyParts, $fieldItemPropertyData);
}
$translation->{$name}
->set($index, [
'plugin_id' => $block
->getPluginId(),
'settings' => $newConfiguration,
]);
if ($entityData !== NULL) {
$embedded_entity_id = NULL;
if (isset($entityData['_lingotek_metadata'])) {
$target_entity_type_id = $entityData['_lingotek_metadata']['_entity_type_id'];
$embedded_entity_id = $entityData['_lingotek_metadata']['_entity_id'];
$embedded_entity_revision_id = $entityData['_lingotek_metadata']['_entity_revision'];
$embedded_entity = $this->entityTypeManager
->getStorage($target_entity_type_id)
->load($embedded_entity_id);
if ($embedded_entity !== NULL) {
if ($embedded_entity instanceof ContentEntityInterface) {
if ($this->lingotekConfiguration
->isEnabled($embedded_entity
->getEntityTypeId(), $embedded_entity
->bundle())) {
$this
->saveTargetData($embedded_entity, $langcode, $entityData);
}
else {
\Drupal::logger('lingotek')
->warning($this
->t('Field %field not saved as its referenced entity is not translatable by Lingotek', [
'%field' => $name,
]));
}
}
}
}
}
}
}
}
else {
$delta = -1;
foreach ($field_data as $delta => $delta_data) {
foreach ($delta_data as $property => $property_data) {
$property_definition = $storage_definitions[$name]
->getPropertyDefinition($property);
$data_type = $property_definition
->getDataType();
if ($data_type === 'uri') {
if (!\Drupal::pathValidator()
->isValid($property_data)) {
\Drupal::logger('lingotek')
->warning($this
->t('Field %field for %type %label in language %langcode not saved, invalid uri "%uri"', [
'%field' => $name,
'%type' => $entity
->getEntityTypeId(),
'%label' => $entity
->label(),
'%langcode' => $langcode,
'%uri' => $property_data,
]));
$property_data = $revision
->get($name)
->offsetGet($delta)->{$property};
}
}
if (method_exists($translation
->get($name)
->offsetGet($delta), "set")) {
$translation
->get($name)
->offsetGet($delta)
->set($property, html_entity_decode($property_data));
}
elseif ($translation
->get($name)) {
$translation
->get($name)
->appendItem()
->set($property, html_entity_decode($property_data));
}
}
}
$continue = TRUE;
while ($continue) {
if ($translation
->get($name)
->offsetExists($delta + 1)) {
$translation
->get($name)
->removeItem($delta + 1);
}
else {
$continue = FALSE;
}
}
}
}
}
$translation
->set('content_translation_source', $entity
->getUntranslated()
->language()
->getId());
$entity->lingotek_processed = TRUE;
\Drupal::moduleHandler()
->invokeAll('lingotek_content_entity_translation_presave', [
&$translation,
$langcode,
$data,
]);
$status_field = $entity
->getEntityType()
->getKey('status');
$status_field_definition = $entity
->getFieldDefinition($status_field);
if ($status_field_definition !== NULL && $status_field_definition
->isTranslatable()) {
$status_setting = $this->lingotekConfiguration
->getPreference('target_download_status');
if ($status_setting !== "same-as-source") {
$status_value = $status_setting === 'published' ? NodeInterface::PUBLISHED : NodeInterface::NOT_PUBLISHED;
$translation
->set($status_field, $status_value);
}
}
$moderation_factory = \Drupal::service('lingotek.moderation_factory');
$moderation_handler = $moderation_factory
->getModerationHandler();
$moderation_handler
->performModerationTransitionIfNeeded($translation);
if ($moderation_handler
->isModerationEnabled($translation) && $translation
->getEntityType()
->isRevisionable()) {
if ($bundle_entity_type = $entity
->getEntityType()
->getBundleEntityType()) {
$bundle_entity = $this->entityTypeManager
->getStorage($bundle_entity_type)
->load($entity
->bundle());
if ($bundle_entity instanceof RevisionableEntityBundleInterface) {
$translation
->setNewRevision($bundle_entity
->shouldCreateNewRevision());
}
}
if ($translation instanceof RevisionLogInterface && $translation
->isNewRevision()) {
$requestTime = \Drupal::time()
->getRequestTime();
$translation
->setRevisionUserId(\Drupal::currentUser()
->id());
$translation
->setRevisionCreationTime($requestTime);
$translation
->setRevisionLogMessage((string) new FormattableMarkup('Document translated into @langcode by Lingotek.', [
'@langcode' => strtoupper($langcode),
]));
}
}
$translation
->save();
return $entity;
} catch (EntityStorageException $storage_exception) {
$this
->setTargetStatus($entity, $langcode, Lingotek::STATUS_ERROR);
throw new LingotekContentEntityStorageException($entity, $storage_exception, $storage_exception
->getMessage());
}
}
public function getJobId(ContentEntityInterface $entity) {
$job_id = NULL;
if (!empty($entity
->get('lingotek_metadata')->target_id)) {
$metadata = $entity->lingotek_metadata->entity;
$job_id = $metadata
->getJobId();
}
return $job_id;
}
public function setJobId(ContentEntityInterface $entity, $job_id, $update_tms = FALSE) {
if (!$entity->lingotek_metadata->entity) {
$entity->lingotek_metadata->entity = LingotekContentMetadata::loadByTargetId($entity
->getEntityTypeId(), $entity
->id());
}
$metadata =& $entity->lingotek_metadata->entity;
$newDocumentID = FALSE;
if ($update_tms && ($document_id = $this
->getDocumentId($entity))) {
try {
$newDocumentID = $this->lingotek
->updateDocument($document_id, NULL, NULL, NULL, NULL, $job_id);
} catch (LingotekDocumentLockedException $exception) {
$this
->setDocumentId($entity, $exception
->getNewDocumentId());
throw $exception;
} catch (LingotekDocumentArchivedException $exception) {
$old_job_id = $this
->getJobId($entity);
$this
->setDocumentId($entity, NULL);
$this
->deleteMetadata($entity);
$metadata = LingotekContentMetadata::create([
'content_entity_type_id' => $entity
->getEntityTypeId(),
'content_entity_id' => $entity
->id(),
]);
$metadata
->setJobId($old_job_id);
$metadata
->save();
throw $exception;
} catch (LingotekPaymentRequiredException $exception) {
throw $exception;
} catch (LingotekApiException $exception) {
throw $exception;
}
}
if (is_string($newDocumentID)) {
$metadata
->setDocumentId($newDocumentID);
}
$metadata
->setJobId($job_id);
$metadata
->save();
return $entity;
}
protected function includeMetadata(ContentEntityInterface &$entity, &$data, $includeIntelligenceMetadata = TRUE) {
$data['_lingotek_metadata']['_entity_type_id'] = $entity
->getEntityTypeId();
$data['_lingotek_metadata']['_entity_id'] = $entity
->id();
$data['_lingotek_metadata']['_entity_revision'] = $entity
->getRevisionId();
if ($includeIntelligenceMetadata) {
$intelligenceService = \Drupal::service('lingotek.intelligence');
if ($entity
->id()) {
if ($entity->lingotek_metadata && $entity->lingotek_metadata->entity) {
$profile = $this->lingotekConfiguration
->getEntityProfile($entity);
}
else {
$profile = NULL;
}
$domain = \Drupal::request()
->getSchemeAndHttpHost();
$author_name = '';
$author_email = '';
if (method_exists($entity, 'getOwner')) {
$user = $entity
->getOwner();
if ($user !== NULL && $user instanceof UserInterface) {
$author_name = $user
->getDisplayName();
$author_email = $user
->getEmail();
}
}
$intelligenceService
->setProfile($profile);
$data['_lingotek_metadata']['_intelligence']['external_document_id'] = $entity
->id();
$data['_lingotek_metadata']['_intelligence']['content_type'] = $entity
->getEntityTypeId() . ' - ' . $entity
->bundle();
if ($intelligenceService
->getBaseDomainPermission()) {
$data['_lingotek_metadata']['_intelligence']['domain'] = $domain;
}
if ($intelligenceService
->getReferenceUrlPermission()) {
$data['_lingotek_metadata']['_intelligence']['reference_url'] = $entity
->hasLinkTemplate('canonical') ? $entity
->toUrl()
->setAbsolute(TRUE)
->toString() : NULL;
}
if ($intelligenceService
->getAuthorPermission()) {
$data['_lingotek_metadata']['_intelligence']['author_name'] = $author_name;
}
if ($intelligenceService
->getAuthorPermission() && $intelligenceService
->getAuthorEmailPermission() && $intelligenceService
->getContactEmailForAuthorPermission() && $intelligenceService
->getContactEmailPermission()) {
$data['_lingotek_metadata']['_intelligence']['author_email'] = $intelligenceService
->getContactEmail();
}
if ($intelligenceService
->getAuthorPermission() && $intelligenceService
->getAuthorEmailPermission() && (!$intelligenceService
->getContactEmailForAuthorPermission() || !$intelligenceService
->getContactEmailPermission())) {
$data['_lingotek_metadata']['_intelligence']['author_email'] = $author_email;
}
if ($intelligenceService
->getBusinessUnitPermission()) {
$data['_lingotek_metadata']['_intelligence']['business_unit'] = $intelligenceService
->getBusinessUnit();
}
if ($intelligenceService
->getBusinessDivisionPermission()) {
$data['_lingotek_metadata']['_intelligence']['business_division'] = $intelligenceService
->getBusinessDivision();
}
if ($intelligenceService
->getCampaignIdPermission()) {
$data['_lingotek_metadata']['_intelligence']['campaign_id'] = $intelligenceService
->getCampaignId();
}
if ($intelligenceService
->getCampaignRatingPermission()) {
$data['_lingotek_metadata']['_intelligence']['campaign_rating'] = $intelligenceService
->getCampaignRating();
}
if ($intelligenceService
->getChannelPermission()) {
$data['_lingotek_metadata']['_intelligence']['channel'] = $intelligenceService
->getChannel();
}
if ($intelligenceService
->getContactNamePermission()) {
$data['_lingotek_metadata']['_intelligence']['contact_name'] = $intelligenceService
->getContactName();
}
if ($intelligenceService
->getContactEmailPermission()) {
$data['_lingotek_metadata']['_intelligence']['contact_email'] = $intelligenceService
->getContactEmail();
}
if ($intelligenceService
->getContentDescriptionPermission()) {
$data['_lingotek_metadata']['_intelligence']['content_description'] = $intelligenceService
->getContentDescription();
}
if ($intelligenceService
->getExternalStyleIdPermission()) {
$data['_lingotek_metadata']['_intelligence']['external_style_id'] = $intelligenceService
->getExternalStyleId();
}
if ($intelligenceService
->getPurchaseOrderPermission()) {
$data['_lingotek_metadata']['_intelligence']['purchase_order'] = $intelligenceService
->getPurchaseOrder();
}
if ($intelligenceService
->getRegionPermission()) {
$data['_lingotek_metadata']['_intelligence']['region'] = $intelligenceService
->getRegion();
}
}
}
}
}