Skip to content
Snippets Groups Projects

Issue #2960620: Support for translations of menu items

2 files
+ 197
146
Compare changes
  • Side-by-side
  • Inline
Files
2
@@ -12,6 +12,11 @@ use Drupal\menu_link_content\Entity\MenuLinkContent;
*/
class MenuLinksController extends ControllerBase {
/**
* Structure sync config.
*
* @var \Drupal\Core\Config\Config
*/
private $config;
/**
@@ -36,6 +41,8 @@ class MenuLinksController extends ControllerBase {
*/
public function exportMenuLinks(array $form = NULL, FormStateInterface $form_state = NULL) {
StructureSyncHelper::logMessage('Menu links export started');
$languages_enabled = \Drupal::languageManager()->getLanguages();
$languagesPriority = [];
if (is_object($form_state) && $form_state->hasValue('export_menu_list')) {
$menu_list = $form_state->getValue('export_menu_list');
@@ -60,24 +67,39 @@ class MenuLinksController extends ControllerBase {
$customMenuLinks = [];
foreach ($menuLinks as $menuLink) {
$customMenuLinks[] = [
'menu_name' => $menuLink->menu_name->value,
'title' => $menuLink->title->value,
'parent' => $menuLink->parent->value,
'uri' => $menuLink->link->uri,
'link_title' => $menuLink->link->title,
'description' => $menuLink->description->value,
'enabled' => $menuLink->enabled->value,
'expanded' => $menuLink->expanded->value,
'weight' => $menuLink->weight->value,
'langcode' => $menuLink->langcode->value,
'uuid' => $menuLink->uuid(),
];
if (array_key_exists('drush', $form) && $form['drush'] === TRUE) {
drush_log('Exported "' . $menuLink->title->getValue()[0]['value'] . '" of menu "' . $menuLink->menu_name->getValue()[0]['value'] . '"', 'ok');
$customMenuLink = [];
$field_defs = $menuLink->getFieldDefinitions();
$mid = $menuLink->id();
// Sort the languages to be exported by priority.
$default_language = $menuLink->get('langcode')->value;
$languagesPriority = $languages_enabled;
unset($languagesPriority[$default_language]);
array_unshift($languagesPriority, $languages_enabled[$default_language]);
foreach ($languagesPriority as $language) {
$language_id = $language->getId();
if ($menuLink->hasTranslation($language_id)) {
$customMenuLink[$mid][$language_id]['id'] = $menuLink->id();
foreach ($field_defs as $field_name => $value) {
if (!array_key_exists($field_name, $customMenuLink[$mid][$language_id])) {
if ($field_name == 'link' || $field_name == 'link_override') {
// For link we export all its properties.
// Also adding support for translatable_menu_link_uri module through link_override field.
$customMenuLink[$mid][$language_id][$field_name] = $menuLink->getTranslation($language_id)->{$field_name}->getValue()[0];
}
elseif ($field_name == 'bundle') {
$customMenuLink[$mid][$language_id][$field_name] = $menuLink->bundle();
}
else {
$customMenuLink[$mid][$language_id][$field_name] = $menuLink->getTranslation($language_id)->{$field_name}->value;
}
}
}
StructureSyncHelper::logMessage('Exported "' . $customMenuLink[$mid][$language_id]['title'] . '" of menu "' . $customMenuLink[$mid][$language_id]['menu_name'] . '" (' . $language_id . ')');
}
}
StructureSyncHelper::logMessage('Exported "' . $menuLink->title->value . '" of menu "' . $menuLink->menu_name->value . '"');
$customMenuLinks[] = $customMenuLink[$mid];
}
$this->config->set('menus', $customMenuLinks)->save();
@@ -217,23 +239,67 @@ class MenuLinksController extends ControllerBase {
*/
public static function deleteDeletedMenuLinks($menus, &$context) {
$uuidsInConfig = [];
$midLangConfig = [];
$midLangDb = [];
$midLangToDelete = [];
foreach ($menus as $menuLink) {
$uuidsInConfig[] = $menuLink['uuid'];
foreach ($menuLink as $language_id => $link) {
$midLangConfig[] = $link['id'] . '.' . $language_id;
$uuidsInConfig[] = $link['uuid'];
}
}
if (!empty($uuidsInConfig)) {
$query = StructureSyncHelper::getEntityQuery('menu_link_content');
$query->condition('uuid', $uuidsInConfig, 'NOT IN');
$ids = $query->execute();
$controller = StructureSyncHelper::getEntityManager()
->getStorage('menu_link_content');
$entities = $controller->loadMultiple($ids);
$controller->delete($entities);
// Remove duplicates.
$uuidsInConfig = array_unique($uuidsInConfig);
// Completely delete terms that are not in the exported configuration.
if (!empty($uuidsInConfig) && count($uuidsInConfig) > 0) {
$query = StructureSyncHelper::getEntityQuery('menu_link_content');
$query->condition('uuid', $uuidsInConfig, 'NOT IN');
$ids = $query->execute();
$controller = StructureSyncHelper::getEntityManager()
->getStorage('menu_link_content');
$entities = $controller->loadMultiple($ids);
$controller->delete($entities);
$query = \Drupal::database()->select('menu_link_content_data', 'mlcd');
$query->fields('mlcd', ['id', 'langcode']);
$result = $query->execute();
while ($record = $result->fetchAssoc()) {
$midLangDb[] = $record['id'] . '.' . $record['langcode'];
}
$midLangToDelete = array_diff($midLangDb, $midLangConfig);
// Delete translations of the term.
if (count($midLangToDelete) > 0) {
foreach ($midLangToDelete as $value) {
$divkey = explode('.', $value);
$mid = $divkey[0];
$language_id = $divkey[1];
$link_loaded = \Drupal::entityTypeManager()
->getStorage('menu_link_content')
->load($mid);
if ($link_loaded->hasTranslation($language_id)) {
if ($link_loaded->getUntranslated()->content_translation_source->value == $link_loaded->getTranslation($language_id)->content_translation_source->value) {
if (array_key_exists('drush', $context) && $context['drush'] === TRUE) {
Drush::logger()
->notice('You can not delete the origin "' . $language_id . '" and keep the translation from link id "' . $mid . '"', 'warning');
}
}
else {
$link_loaded->removeTranslation($language_id);
$link_loaded->save();
}
}
}
}
}
if (array_key_exists('drush', $context) && $context['drush'] === TRUE) {
drush_log('Deleted menu links that were not in config', 'ok');
}
else {
self::deleteMenuLinks($context);
}
StructureSyncHelper::logMessage('Deleted menu links that were not in config');
}
@@ -246,16 +312,18 @@ class MenuLinksController extends ControllerBase {
public static function importMenuLinksFull($menus, &$context) {
$uuidsInConfig = [];
foreach ($menus as $menuLink) {
$uuidsInConfig[] = $menuLink['uuid'];
foreach ($menuLink as $language_id => $link) {
$uuidsInConfig[] = $link['uuid'];
}
}
$entities = [];
if (!empty($uuidsInConfig)) {
$query = StructureSyncHelper::getEntityQuery('menu_link_content');
$query->condition('uuid', $uuidsInConfig, 'IN');
$ids = $query->execute();
$controller = StructureSyncHelper::getEntityManager()
->getStorage('menu_link_content');
$entities = $controller->loadMultiple($ids);
$query = StructureSyncHelper::getEntityQuery('menu_link_content');
$query->condition('uuid', $uuidsInConfig, 'IN');
$ids = $query->execute();
$controller = StructureSyncHelper::getEntityManager()
->getStorage('menu_link_content');
$entities = $controller->loadMultiple($ids);
}
$parents = array_column($menus, 'parent');
@@ -277,81 +345,78 @@ class MenuLinksController extends ControllerBase {
$context['sandbox']['progress'] = 0;
while ($firstRun || count($idsLeft) > 0) {
foreach ($menus as $menuLink) {
$query = StructureSyncHelper::getEntityQuery('menu_link_content');
$query->condition('uuid', $menuLink['uuid']);
$ids = $query->execute();
$currentParent = $menuLink['parent'];
if (!is_null($currentParent)) {
if (($pos = strpos($currentParent, ":")) !== FALSE) {
$currentParent = substr($currentParent, $pos + 1);
}
}
if (!in_array($menuLink['uuid'], $idsDone)
&& ($menuLink['parent'] === NULL
|| !in_array($menuLink['parent'], $parents)
|| in_array($currentParent, $idsDone))
) {
if (count($ids) <= 0) {
MenuLinkContent::create([
'title' => $menuLink['title'],
'link' => [
'uri' => $menuLink['uri'],
'title' => $menuLink['link_title'],
],
'menu_name' => $menuLink['menu_name'],
'expanded' => $menuLink['expanded'] === '1' ? TRUE : FALSE,
'enabled' => $menuLink['enabled'] === '1' ? TRUE : FALSE,
'parent' => $menuLink['parent'],
'description' => $menuLink['description'],
'weight' => $menuLink['weight'],
'langcode' => $menuLink['langcode'],
'uuid' => $menuLink['uuid'],
])->save();
foreach ($menuLink as $language_id => $link) {
$query = StructureSyncHelper::getEntityQuery('menu_link_content');
$query->condition('uuid', $link['uuid']);
$query->condition('langcode', $language_id);
$ids = $query->execute();
$currentParent = $link['parent'];
if (!is_null($currentParent)) {
if (($pos = strpos($currentParent, ":")) !== FALSE) {
$currentParent = substr($currentParent, $pos + 1);
}
}
else {
foreach ($entities as $entity) {
if ($menuLink['uuid'] === $entity->uuid()) {
$customMenuLink = MenuLinkContent::load($entity->id());
if (!empty($customMenuLink)) {
$customMenuLink
->set('title', $menuLink['title'])
->set('link', [
'uri' => $menuLink['uri'],
'title' => $menuLink['link_title'],
])
->set('expanded', $menuLink['expanded'] === '1' ? TRUE : FALSE)
->set('enabled', $menuLink['enabled'] === '1' ? TRUE : FALSE)
->set('parent', $menuLink['parent'])
->set('description', $menuLink['description'])
->set('weight', $menuLink['weight'])
->save();
if (!in_array($link['uuid'], $idsDone)
&& ($link['parent'] === NULL
|| !in_array($link['parent'], $parents)
|| in_array($currentParent, $idsDone))
) {
if (count($ids) <= 0) {
$query = StructureSyncHelper::getEntityQuery('menu_link_content');
$query->condition('uuid', $link['uuid']);
// Add translation.
if (count($query->execute()) >= 1) {
MenuLinkContent::load($link['id'])->addTranslation($language_id, $link)->save();
StructureSyncHelper::logMessage('Imported link translation (' . $language_id . ') "' . $link['title'] . '" into "' . $link['menu_name'] . '"');
}
// Create a new menu link.
else {
MenuLinkContent::create($link)->save();
StructureSyncHelper::logMessage('Imported link "' . $link['title'] . '" into "' . $link['menu_name'] . '"');
}
}
// Update links.
else {
foreach ($entities as $entity) {
if ($link['uuid'] === $entity->uuid()) {
$link_loaded = MenuLinkContent::load($entity->id());
foreach ($link as $field_name => $field_value) {
if ($link_loaded->get($field_name)->getFieldDefinition()->isTranslatable()) {
// Update link field translation.
$link_loaded->getTranslation($language_id)->{$field_name}->setValue($field_value);
}
else {
// Update link field.
$link_loaded->{$field_name}->setValue($field_value);
}
}
// Save link.
$link_loaded->save();
StructureSyncHelper::logMessage('Updated link (' . $language_id . ') "' . $link['title'] . '" into "' . $link['menu_name'] . '"');
}
break;
}
}
}
$idsDone[] = $menuLink['uuid'];
if (in_array($menuLink['uuid'], $idsLeft)) {
unset($idsLeft[$menuLink['uuid']]);
else {
$idsLeft[$link['uuid']] = $link['uuid'];
}
}
if (array_key_exists('drush', $context) && $context['drush'] === TRUE) {
drush_log('Imported "' . $menuLink['title'] . '" into ' . $menuLink['menu_name'], 'ok');
}
StructureSyncHelper::logMessage('Imported "' . $menuLink['title'] . '" into ' . $menuLink['menu_name']);
$idsDone[] = $link['uuid'];
if (in_array($link['uuid'], $idsLeft)) {
unset($idsLeft[$link['uuid']]);
}
$context['sandbox']['progress']++;
if ($context['sandbox']['progress'] != $context['sandbox']['max']) {
$context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
}
$context['sandbox']['progress']++;
if ($context['sandbox']['progress'] != $context['sandbox']['max']) {
$context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
}
else {
$idsLeft[$menuLink['uuid']] = $menuLink['uuid'];
if (array_key_exists('drush', $context) && $context['drush'] === TRUE) {
drush_log('Imported "' . $menuLink['title'] . '" into ' . $menuLink['menu_name'], 'ok');
}
}
@@ -371,35 +436,27 @@ class MenuLinksController extends ControllerBase {
->getStorage('menu_link_content')
->loadMultiple();
foreach ($entities as $entity) {
for ($i = 0; $i < count($menus); $i++) {
if ($entity->uuid() === $menus[$i]['uuid']) {
unset($menusFiltered[$i]);
foreach ($entities as $key => $entity) {
foreach ($menusFiltered as $key => $menuLink) {
foreach ($menuLink as $language_id => $link) {
if ($entity->uuid() === $link['uuid']) {
if ($entity->hasTranslation($language_id)) {
unset($menusFiltered[$key][$language_id]);
}
}
}
if (isset($menusFiltered[$key]) && empty($menusFiltered[$key])) {
unset($menusFiltered[$key]);
}
}
}
foreach ($menusFiltered as $menuLink) {
MenuLinkContent::create([
'title' => $menuLink['title'],
'link' => [
'uri' => $menuLink['uri'],
'title' => $menuLink['link_title'],
],
'menu_name' => $menuLink['menu_name'],
'expanded' => $menuLink['expanded'] === '1' ? TRUE : FALSE,
'enabled' => $menuLink['enabled'] === '1' ? TRUE : FALSE,
'parent' => $menuLink['parent'],
'description' => $menuLink['description'],
'weight' => $menuLink['weight'],
'langcode' => $menuLink['langcode'],
'uuid' => $menuLink['uuid'],
])->save();
if (array_key_exists('drush', $context) && $context['drush'] === TRUE) {
drush_log('Imported "' . $menuLink['title'] . '" into "' . $menuLink['menu_name'] . '" menu', 'ok');
}
StructureSyncHelper::logMessage('Imported "' . $menuLink['title'] . '" into "' . $menuLink['menu_name'] . '" menu');
// Import new links and translation links.
if (count($menusFiltered) > 0) {
self::importMenuLinksFull($menusFiltered, $context);
}
else {
StructureSyncHelper::logMessage('Not found new links to import');
}
}
@@ -424,27 +481,19 @@ class MenuLinksController extends ControllerBase {
* Function to import (create) all menu links that need to be imported.
*/
public static function importMenuLinksForce($menus, &$context) {
foreach ($menus as $menuLink) {
MenuLinkContent::create([
'title' => $menuLink['title'],
'link' => [
'uri' => $menuLink['uri'],
'title' => $menuLink['link_title'],
],
'menu_name' => $menuLink['menu_name'],
'expanded' => $menuLink['expanded'] === '1' ? TRUE : FALSE,
'enabled' => $menuLink['enabled'] === '1' ? TRUE : FALSE,
'parent' => $menuLink['parent'],
'description' => $menuLink['description'],
'weight' => $menuLink['weight'],
'langcode' => $menuLink['langcode'],
'uuid' => $menuLink['uuid'],
])->save();
if (array_key_exists('drush', $context) && $context['drush'] === TRUE) {
drush_log('Imported "' . $menuLink['title'] . '" into "' . $menuLink['menu_name'] . '" menu', 'ok');
foreach ($menuLink as $language_id => $link) {
if ($link['content_translation_source'] === 'und') {
MenuLinkContent::create($link)->save();
StructureSyncHelper::logMessage('Imported link "' . $link['title'] . '" into "' . $link['menu_name'] . '" menu');
}
else {
MenuLinkContent::load($link['id'])->addTranslation($language_id, $link)->save();
if (array_key_exists('drush', $context) && $context['drush'] === TRUE) {
drush_log('Imported "' . $menuLink['title'] . '" into "' . $menuLink['menu_name'] . '" menu', 'ok');
}
StructureSyncHelper::logMessage('Imported link translation (' . $language_id . ') "' . $link['title'] . '" into "' . $link['menu_name'] . '" menu');
}
StructureSyncHelper::logMessage('Imported "' . $menuLink['title'] . '" into "' . $menuLink['menu_name'] . '" menu');
}
}
Loading