Skip to content

Commit

Permalink
EWPP-3399: Dashboard links for new local translations.
Browse files Browse the repository at this point in the history
  • Loading branch information
upchuk committed Apr 18, 2024
1 parent 8b58c80 commit 17454c5
Show file tree
Hide file tree
Showing 5 changed files with 250 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1148,9 +1148,11 @@ public function testMappingOperationsForMultipleVersions(): void {
$french_mapping_operations = $french_row->findAll('xpath', '//td[6]//a');
$this->assertOperationLinks([
'View' => TRUE,
'Add new local translation' => TRUE,
], $french_published_operations);
$this->assertOperationLinks([
'View' => TRUE,
'Add new local translation' => TRUE,
// We cannot delete the validated translation if we have a mapping.
'Delete translation' => FALSE,
'Add mapping' => FALSE,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,13 @@
use Drupal\oe_translation\EntityRevisionInfoInterface;
use Drupal\oe_translation\Event\ContentTranslationDashboardAlterEvent;
use Drupal\oe_translation_corporate_workflow\CorporateWorkflowTranslationTrait;
use Drupal\oe_translation_local\TranslationRequestLocal;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
* Subscribes to the translation dashboard alteration event.
*
* @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
*/
class TranslationDashboardAlterSubscriber implements EventSubscriberInterface {

Expand Down Expand Up @@ -210,6 +213,8 @@ protected function alterExistingTranslationsTable(array &$build, ContentEntityIn
}

$latest_entity_version = $this->getEntityVersion($latest_entity);
$current_entity_started_languages = $this->getStartedLocalTranslationRequestLanguages($entity);
$latest_entity_started_languages = $this->getStartedLocalTranslationRequestLanguages($latest_entity);

// Create an array of languages across both versions, with info related
// to each.
Expand All @@ -233,6 +238,34 @@ protected function alterExistingTranslationsTable(array &$build, ContentEntityIn
'operations' => $this->getTranslationOperations($translation, TRUE),
];

if (!isset($info['operations']['#links'])) {
$info['operations'] = [
'#type' => 'operations',
'#links' => [],
];
}

// Add the operation to create a new local translation to the current
// entity.
if (!in_array($language->getId(), $current_entity_started_languages) && $language->getId() !== $entity->getUntranslated()->language()->getId()) {
$url = Url::fromRoute('oe_translation_local.create_local_translation_request', [
'entity_type' => $entity->getEntityTypeId(),
'entity' => $entity->getRevisionId(),
'source' => $entity->getUntranslated()->language()->getId(),
'target' => $language->getId(),
], ['query' => ['destination' => Url::fromRoute('<current>')->toString()]]);

if ($url->access()) {
$link = [
'title' => $this->t('Add new local translation'),
'weight' => -100,
'url' => $url,
];

$info['operations']['#links']['add'] = $link;
}
}

$languages[$language->getId()][$published_version] = $info;
if ($translation && $translation->isDefaultTranslation()) {
$languages[$language->getId()]['default_language'] = TRUE;
Expand Down Expand Up @@ -278,6 +311,36 @@ protected function alterExistingTranslationsTable(array &$build, ContentEntityIn
$row['class'][] = 'color-success';
}

// Add the operation to create a new local translation to the latest
// version.
if (!in_array($langcode, $latest_entity_started_languages) && $langcode !== $entity->getUntranslated()->language()->getId()) {
$url = Url::fromRoute('oe_translation_local.create_local_translation_request', [
'entity_type' => $entity->getEntityTypeId(),
'entity' => $latest_entity->getRevisionId(),
'source' => $latest_entity->getUntranslated()->language()->getId(),
'target' => $langcode,
], ['query' => ['destination' => Url::fromRoute('<current>')->toString()]]);

if ($url->access()) {
$link = [
'title' => $this->t('Add new local translation'),
'weight' => -100,
'url' => $url,
];

if (is_string($row['data']['operations_validated'])) {
// It means it's empty and set to N/A.
$row['data']['operations_validated'] = [
'data' => [
'#type' => 'operations',
'#links' => [],
],
];
}
$row['data']['operations_validated']['data']['#links']['add'] = $link;
}
}

$rows[] = $row;
}

Expand Down Expand Up @@ -372,4 +435,32 @@ protected function getTranslationOperations(ContentEntityInterface $translation
];
}

/**
* Gets the started local translation requests.
*
* @param \Drupal\Core\Entity\ContentEntityInterface $entity
* The entity.
*
* @return array
* The requests.
*/
protected function getStartedLocalTranslationRequestLanguages(ContentEntityInterface $entity): array {
/** @var \Drupal\oe_translation\TranslationRequestStorageInterface $storage */
$storage = $this->entityTypeManager->getStorage('oe_translation_request');

$languages = [];

/** @var \Drupal\oe_translation_local\TranslationRequestLocal[] $translation_requests */
$translation_requests = $storage->getTranslationRequestsForEntityRevision($entity, 'local');
$translation_requests = array_filter($translation_requests, function (TranslationRequestLocal $translation_request) {
return $translation_request->getTargetLanguageWithStatus()->getStatus() !== TranslationRequestLocal::STATUS_LANGUAGE_SYNCHRONISED;
});

foreach ($translation_requests as $request) {
$languages[] = $request->getTargetLanguageWithStatus()->getLangcode();
}

return $languages;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use Drupal\Core\Url;
use Drupal\language\Entity\ConfigurableLanguage;
use Drupal\node\Entity\Node;
use Drupal\node\NodeInterface;
use Drupal\oe_translation\Entity\TranslationRequest;
use Drupal\oe_translation\Entity\TranslationRequestInterface;
use Drupal\oe_translation_corporate_workflow\CorporateWorkflowTranslationTrait;
Expand All @@ -35,6 +36,7 @@
* versions.
*
* @group batch1
* @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
*/
class CorporateWorkflowTranslationTest extends BrowserTestBase {

Expand Down Expand Up @@ -278,6 +280,8 @@ public function testTranslationDashboardExistingTranslations(): void {
],
], ['1.0.0 / published', '2.0.0 / validated']);

$this->assertNewLocalTranslationLinks($node, ['en'], ['en']);

// Create a translation in IT for the published version.
$this->clickLink('Local translations');
$this->getSession()->getPage()->find('css', 'tr[hreflang="it"] td[data-version="1.0.0"] a')->click();
Expand All @@ -286,8 +290,6 @@ public function testTranslationDashboardExistingTranslations(): void {
'Translation' => 'My node IT',
];
$this->submitForm($values, 'Save and synchronise');

// Go back to the dashboard and assert our table got this new language.
$this->drupalGet($node->toUrl('drupal:content-translation-overview'));
$this->assertExtendedDashboardExistingTranslations([
'en' => [
Expand All @@ -305,6 +307,34 @@ public function testTranslationDashboardExistingTranslations(): void {
'validated_title' => 'No translation',
],
], ['1.0.0 / published', '2.0.0 / validated']);

// Start another translation and save as draft.
$this->clickLink('Local translations');
$this->getSession()->getPage()->find('css', 'tr[hreflang="it"] td[data-version="1.0.0"] a')->click();
$this->assertSession()->elementTextEquals('css', 'h1', 'Translate My node in Italian (version 1.0.0)');
$values = [
'Translation' => 'My node IT',
];
$this->submitForm($values, 'Save as draft');
// Go back to the dashboard and assert the "add local translation" links
// are reflecting this change.
$this->drupalGet($node->toUrl('drupal:content-translation-overview'));
$this->assertNewLocalTranslationLinks($node, ['en', 'it'], ['en']);
// Sync the translation and create one for the validated version.
$this->clickLink('Edit draft translation');
$this->submitForm($values, 'Save and synchronise');
$this->assertNewLocalTranslationLinks($node, ['en'], ['en']);
$this->clickLink('Local translations');
$this->getSession()->getPage()->find('css', 'tr[hreflang="it"] td[data-version="2.0.0"] a')->click();
$this->assertSession()->elementTextEquals('css', 'h1', 'Translate My node 2 in Italian (version 2.0.0)');
$values = [
'Translation' => 'My node IT 2',
];
$this->submitForm($values, 'Save as draft');
$this->assertNewLocalTranslationLinks($node, ['en'], ['en', 'it']);
// Synchronise it.
$this->clickLink('Edit draft translation');
$this->submitForm($values, 'Save and synchronise');
}

/**
Expand Down Expand Up @@ -1210,4 +1240,44 @@ protected function assertLocalOngoingRequests(array $expected): void {
}
}

/**
* Asserts that on the dashboard, we have an operation to add new local trans.
*
* @param \Drupal\node\NodeInterface $node
* The node.
* @param array $current_excluded_languages
* The languages for which we don't have (current entity).
* @param array $latest_excluded_languages
* The languages for which we don't have (current version).
*/
protected function assertNewLocalTranslationLinks(NodeInterface $node, array $current_excluded_languages = [], array $latest_excluded_languages = []): void {
foreach ($this->getSession()->getPage()->findAll('css', 'table.existing-translations-table tbody tr') as $row) {
$langcode = $row->getAttribute('hreflang');
$col_current = $row->find('xpath', '//td[3]');
$col_latest = $row->find('xpath', '//td[5]');
// Current entity.
$current_entity_link = $col_current->findLink('Add new local translation');
$latest_version_link = $col_latest->findLink('Add new local translation');
$continue = FALSE;
if (in_array($langcode, $current_excluded_languages)) {
$this->assertNull($current_entity_link);
$continue = TRUE;
}
if (in_array($langcode, $latest_excluded_languages)) {
$this->assertNull($latest_version_link);
$continue = TRUE;
}

if ($continue) {
continue;
}

$node_storage = \Drupal::entityTypeManager()->getStorage('node');
$current_node = $node_storage->load($node->id());
$latest_node = $node_storage->loadRevision($node_storage->getLatestRevisionId($node->id()));
$this->assertEquals('/build/admin/oe_translation/translate-local/node/' . $current_node->getRevisionId() . '/en/' . $langcode . '?destination=/build/node/' . $current_node->id() . '/translations', $current_entity_link->getAttribute('href'));
$this->assertEquals('/build/admin/oe_translation/translate-local/node/' . $latest_node->getRevisionId() . '/en/' . $langcode . '?destination=/build/node/' . $latest_node->id() . '/translations', $latest_version_link->getAttribute('href'));
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
namespace Drupal\oe_translation_local\EventSubscriber;

use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\Url;
use Drupal\oe_translation\Event\ContentTranslationDashboardAlterEvent;
use Drupal\oe_translation_local\TranslationRequestLocal;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
Expand Down Expand Up @@ -83,6 +85,8 @@ public function alterDashboard(ContentTranslationDashboardAlterEvent $event) {
return $translation_request->getTargetLanguageWithStatus()->getStatus() !== TranslationRequestLocal::STATUS_LANGUAGE_SYNCHRONISED;
});

$this->addLocalTranslationOperation($build, $translation_requests, $current_entity);

$cache->addCacheTags(['oe_translation_request_list']);
if (!$translation_requests) {
$element[] = [
Expand Down Expand Up @@ -131,4 +135,58 @@ public function alterDashboard(ContentTranslationDashboardAlterEvent $event) {
$event->setBuild($build);
}

/**
* Adds the link to create a new local translation.
*
* @param array $build
* The page build.
* @param array $translation_requests
* The existing translation requests.
* @param \Drupal\Core\Entity\ContentEntityInterface $entity
* The current entity.
*/
protected function addLocalTranslationOperation(array &$build, array $translation_requests, ContentEntityInterface $entity) {
$started_local_requests = [];
foreach ($translation_requests as $request) {
$started_local_requests[] = $request->getTargetLanguageWithStatus()->getLangcode();
}
foreach ($build['existing_translations']['table']['#rows'] as $index => &$row) {
$langcode = $row['hreflang'];
if (in_array($langcode, $started_local_requests) || $langcode === $entity->getUntranslated()->language()->getId()) {
// If there is already a started translation request, we don't add any
// operation.
continue;
}

$url = Url::fromRoute('oe_translation_local.create_local_translation_request', [
'entity_type' => $entity->getEntityTypeId(),
'entity' => $entity->getRevisionId(),
'source' => $entity->getUntranslated()->language()->getId(),
'target' => $langcode,
], ['query' => ['destination' => Url::fromRoute('<current>')->toString()]]);

if (!$url->access()) {
continue;
}
$link = [
'title' => $this->t('Add new local translation'),
'weight' => -100,
'url' => $url,
];
if (isset($row['data']['operations']['data']['#links'])) {
// It means we have already the operations.
$row['data']['operations']['data']['#links']['add'] = $link;
continue;
}

// Otherwise, start the operations.
$row['data']['operations']['data'] = [
'#type' => 'operations',
'#links' => [
'add' => $link,
],
];
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Drupal\Core\Url;
use Drupal\language\Entity\ConfigurableLanguage;
use Drupal\menu_link_content\Entity\MenuLinkContent;
use Drupal\node\NodeInterface;
use Drupal\Tests\oe_translation\Functional\TranslationTestBase;
use Drupal\user\Entity\Role;

Expand Down Expand Up @@ -538,12 +539,16 @@ public function testLocalTranslationDashboard(): void {
$first_node->save();
$this->drupalGet($first_node->toUrl());
$this->clickLink('Translate');
$this->assertAddLocalTranslationOperation($first_node, ['en']);
$this->clickLink('Local translations');
$this->getSession()->getPage()->find('css', 'table tbody tr[hreflang="fr"] a')->click();
$element = $this->getSession()->getPage()->find('xpath', "//textarea[contains(@name,'[translation]')]");
$element->setValue('First node FR');
$this->getSession()->getPage()->pressButton('Save as draft');
$this->assertSession()->pageTextContains('The translation has been saved.');
$this->drupalGet($first_node->toUrl());
$this->clickLink('Translate');
$this->assertAddLocalTranslationOperation($first_node, ['fr', 'en']);

$second_node = $this->createBasicTestNode();
$second_node->set('title', 'Second node');
Expand Down Expand Up @@ -756,4 +761,26 @@ protected function assertLocalLanguagesTable(array $with_edit = []): void {
}
}

/**
* Asserts that on the dashboard, we have an operation to add new local trans.
*
* @param \Drupal\node\NodeInterface $node
* The node.
* @param array $excluded_languages
* The languages for which we don't have.
*/
protected function assertAddLocalTranslationOperation(NodeInterface $node, array $excluded_languages = []): void {
foreach ($this->getSession()->getPage()->findAll('css', 'table.existing-translations-table tbody tr') as $row) {
$langcode = $row->getAttribute('hreflang');
$col = $row->find('xpath', '//td[3]');
$link = $col->findLink('Add new local translation');
if (in_array($langcode, $excluded_languages)) {
$this->assertNull($link);
continue;
}

$this->assertEquals('/build/en/admin/oe_translation/translate-local/node/' . $node->getRevisionId() . '/en/' . $langcode . '?destination=/build/en/node/' . $node->id() . '/translations', $link->getAttribute('href'));
}
}

}

0 comments on commit 17454c5

Please sign in to comment.