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;
@@ -12,6 +12,11 @@ use Drupal\menu_link_content\Entity\MenuLinkContent;
*/
*/
class MenuLinksController extends ControllerBase {
class MenuLinksController extends ControllerBase {
 
/**
 
* Structure sync config.
 
*
 
* @var \Drupal\Core\Config\Config
 
*/
private $config;
private $config;
/**
/**
@@ -36,6 +41,8 @@ class MenuLinksController extends ControllerBase {
@@ -36,6 +41,8 @@ class MenuLinksController extends ControllerBase {
*/
*/
public function exportMenuLinks(array $form = NULL, FormStateInterface $form_state = NULL) {
public function exportMenuLinks(array $form = NULL, FormStateInterface $form_state = NULL) {
StructureSyncHelper::logMessage('Menu links export started');
StructureSyncHelper::logMessage('Menu links export started');
 
$languages_enabled = \Drupal::languageManager()->getLanguages();
 
$languagesPriority = [];
if (is_object($form_state) && $form_state->hasValue('export_menu_list')) {
if (is_object($form_state) && $form_state->hasValue('export_menu_list')) {
$menu_list = $form_state->getValue('export_menu_list');
$menu_list = $form_state->getValue('export_menu_list');
@@ -60,24 +67,39 @@ class MenuLinksController extends ControllerBase {
@@ -60,24 +67,39 @@ class MenuLinksController extends ControllerBase {
$customMenuLinks = [];
$customMenuLinks = [];
foreach ($menuLinks as $menuLink) {
foreach ($menuLinks as $menuLink) {
$customMenuLinks[] = [
$customMenuLink = [];
'menu_name' => $menuLink->menu_name->value,
$field_defs = $menuLink->getFieldDefinitions();
'title' => $menuLink->title->value,
$mid = $menuLink->id();
'parent' => $menuLink->parent->value,
'uri' => $menuLink->link->uri,
// Sort the languages to be exported by priority.
'link_title' => $menuLink->link->title,
$default_language = $menuLink->get('langcode')->value;
'description' => $menuLink->description->value,
$languagesPriority = $languages_enabled;
'enabled' => $menuLink->enabled->value,
unset($languagesPriority[$default_language]);
'expanded' => $menuLink->expanded->value,
array_unshift($languagesPriority, $languages_enabled[$default_language]);
'weight' => $menuLink->weight->value,
'langcode' => $menuLink->langcode->value,
foreach ($languagesPriority as $language) {
'uuid' => $menuLink->uuid(),
$language_id = $language->getId();
];
if ($menuLink->hasTranslation($language_id)) {
$customMenuLink[$mid][$language_id]['id'] = $menuLink->id();
if (array_key_exists('drush', $form) && $form['drush'] === TRUE) {
foreach ($field_defs as $field_name => $value) {
drush_log('Exported "' . $menuLink->title->getValue()[0]['value'] . '" of menu "' . $menuLink->menu_name->getValue()[0]['value'] . '"', 'ok');
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();
$this->config->set('menus', $customMenuLinks)->save();
@@ -217,23 +239,67 @@ class MenuLinksController extends ControllerBase {
@@ -217,23 +239,67 @@ class MenuLinksController extends ControllerBase {
*/
*/
public static function deleteDeletedMenuLinks($menus, &$context) {
public static function deleteDeletedMenuLinks($menus, &$context) {
$uuidsInConfig = [];
$uuidsInConfig = [];
 
$midLangConfig = [];
 
$midLangDb = [];
 
$midLangToDelete = [];
foreach ($menus as $menuLink) {
foreach ($menus as $menuLink) {
$uuidsInConfig[] = $menuLink['uuid'];
foreach ($menuLink as $language_id => $link) {
 
$midLangConfig[] = $link['id'] . '.' . $language_id;
 
$uuidsInConfig[] = $link['uuid'];
 
}
}
}
if (!empty($uuidsInConfig)) {
// Remove duplicates.
$query = StructureSyncHelper::getEntityQuery('menu_link_content');
$uuidsInConfig = array_unique($uuidsInConfig);
$query->condition('uuid', $uuidsInConfig, 'NOT IN');
$ids = $query->execute();
// Completely delete terms that are not in the exported configuration.
$controller = StructureSyncHelper::getEntityManager()
if (!empty($uuidsInConfig) && count($uuidsInConfig) > 0) {
->getStorage('menu_link_content');
$query = StructureSyncHelper::getEntityQuery('menu_link_content');
$entities = $controller->loadMultiple($ids);
$query->condition('uuid', $uuidsInConfig, 'NOT IN');
$controller->delete($entities);
$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) {
if (array_key_exists('drush', $context) && $context['drush'] === TRUE) {
drush_log('Deleted menu links that were not in config', 'ok');
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');
StructureSyncHelper::logMessage('Deleted menu links that were not in config');
}
}
@@ -246,16 +312,18 @@ class MenuLinksController extends ControllerBase {
@@ -246,16 +312,18 @@ class MenuLinksController extends ControllerBase {
public static function importMenuLinksFull($menus, &$context) {
public static function importMenuLinksFull($menus, &$context) {
$uuidsInConfig = [];
$uuidsInConfig = [];
foreach ($menus as $menuLink) {
foreach ($menus as $menuLink) {
$uuidsInConfig[] = $menuLink['uuid'];
foreach ($menuLink as $language_id => $link) {
 
$uuidsInConfig[] = $link['uuid'];
 
}
}
}
$entities = [];
$entities = [];
if (!empty($uuidsInConfig)) {
if (!empty($uuidsInConfig)) {
$query = StructureSyncHelper::getEntityQuery('menu_link_content');
$query = StructureSyncHelper::getEntityQuery('menu_link_content');
$query->condition('uuid', $uuidsInConfig, 'IN');
$query->condition('uuid', $uuidsInConfig, 'IN');
$ids = $query->execute();
$ids = $query->execute();
$controller = StructureSyncHelper::getEntityManager()
$controller = StructureSyncHelper::getEntityManager()
->getStorage('menu_link_content');
->getStorage('menu_link_content');
$entities = $controller->loadMultiple($ids);
$entities = $controller->loadMultiple($ids);
}
}
$parents = array_column($menus, 'parent');
$parents = array_column($menus, 'parent');
@@ -277,81 +345,78 @@ class MenuLinksController extends ControllerBase {
@@ -277,81 +345,78 @@ class MenuLinksController extends ControllerBase {
$context['sandbox']['progress'] = 0;
$context['sandbox']['progress'] = 0;
while ($firstRun || count($idsLeft) > 0) {
while ($firstRun || count($idsLeft) > 0) {
foreach ($menus as $menuLink) {
foreach ($menus as $menuLink) {
$query = StructureSyncHelper::getEntityQuery('menu_link_content');
foreach ($menuLink as $language_id => $link) {
$query->condition('uuid', $menuLink['uuid']);
$query = StructureSyncHelper::getEntityQuery('menu_link_content');
$ids = $query->execute();
$query->condition('uuid', $link['uuid']);
$query->condition('langcode', $language_id);
$currentParent = $menuLink['parent'];
$ids = $query->execute();
if (!is_null($currentParent)) {
if (($pos = strpos($currentParent, ":")) !== FALSE) {
$currentParent = $link['parent'];
$currentParent = substr($currentParent, $pos + 1);
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();
}
}
else {
if (!in_array($link['uuid'], $idsDone)
foreach ($entities as $entity) {
&& ($link['parent'] === NULL
if ($menuLink['uuid'] === $entity->uuid()) {
|| !in_array($link['parent'], $parents)
$customMenuLink = MenuLinkContent::load($entity->id());
|| in_array($currentParent, $idsDone))
if (!empty($customMenuLink)) {
) {
$customMenuLink
if (count($ids) <= 0) {
->set('title', $menuLink['title'])
$query = StructureSyncHelper::getEntityQuery('menu_link_content');
->set('link', [
$query->condition('uuid', $link['uuid']);
'uri' => $menuLink['uri'],
// Add translation.
'title' => $menuLink['link_title'],
if (count($query->execute()) >= 1) {
])
MenuLinkContent::load($link['id'])->addTranslation($language_id, $link)->save();
->set('expanded', $menuLink['expanded'] === '1' ? TRUE : FALSE)
StructureSyncHelper::logMessage('Imported link translation (' . $language_id . ') "' . $link['title'] . '" into "' . $link['menu_name'] . '"');
->set('enabled', $menuLink['enabled'] === '1' ? TRUE : FALSE)
}
->set('parent', $menuLink['parent'])
// Create a new menu link.
->set('description', $menuLink['description'])
else {
->set('weight', $menuLink['weight'])
MenuLinkContent::create($link)->save();
->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;
break;
}
}
}
}
}
}
else {
$idsDone[] = $menuLink['uuid'];
$idsLeft[$link['uuid']] = $link['uuid'];
if (in_array($menuLink['uuid'], $idsLeft)) {
unset($idsLeft[$menuLink['uuid']]);
}
}
 
}
if (array_key_exists('drush', $context) && $context['drush'] === TRUE) {
$idsDone[] = $link['uuid'];
drush_log('Imported "' . $menuLink['title'] . '" into ' . $menuLink['menu_name'], 'ok');
if (in_array($link['uuid'], $idsLeft)) {
}
unset($idsLeft[$link['uuid']]);
StructureSyncHelper::logMessage('Imported "' . $menuLink['title'] . '" into ' . $menuLink['menu_name']);
}
$context['sandbox']['progress']++;
$context['sandbox']['progress']++;
if ($context['sandbox']['progress'] != $context['sandbox']['max']) {
if ($context['sandbox']['progress'] != $context['sandbox']['max']) {
$context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
$context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
}
}
}
else {
if (array_key_exists('drush', $context) && $context['drush'] === TRUE) {
$idsLeft[$menuLink['uuid']] = $menuLink['uuid'];
drush_log('Imported "' . $menuLink['title'] . '" into ' . $menuLink['menu_name'], 'ok');
}
}
}
}
@@ -371,35 +436,27 @@ class MenuLinksController extends ControllerBase {
@@ -371,35 +436,27 @@ class MenuLinksController extends ControllerBase {
->getStorage('menu_link_content')
->getStorage('menu_link_content')
->loadMultiple();
->loadMultiple();
foreach ($entities as $entity) {
foreach ($entities as $key => $entity) {
for ($i = 0; $i < count($menus); $i++) {
foreach ($menusFiltered as $key => $menuLink) {
if ($entity->uuid() === $menus[$i]['uuid']) {
foreach ($menuLink as $language_id => $link) {
unset($menusFiltered[$i]);
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) {
// Import new links and translation links.
MenuLinkContent::create([
if (count($menusFiltered) > 0) {
'title' => $menuLink['title'],
self::importMenuLinksFull($menusFiltered, $context);
'link' => [
}
'uri' => $menuLink['uri'],
else {
'title' => $menuLink['link_title'],
StructureSyncHelper::logMessage('Not found new links to import');
],
'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');
}
}
}
}
@@ -424,27 +481,19 @@ class MenuLinksController extends ControllerBase {
@@ -424,27 +481,19 @@ class MenuLinksController extends ControllerBase {
* Function to import (create) all menu links that need to be imported.
* Function to import (create) all menu links that need to be imported.
*/
*/
public static function importMenuLinksForce($menus, &$context) {
public static function importMenuLinksForce($menus, &$context) {
foreach ($menus as $menuLink) {
foreach ($menuLink as $language_id => $link) {
MenuLinkContent::create([
if ($link['content_translation_source'] === 'und') {
'title' => $menuLink['title'],
MenuLinkContent::create($link)->save();
'link' => [
StructureSyncHelper::logMessage('Imported link "' . $link['title'] . '" into "' . $link['menu_name'] . '" menu');
'uri' => $menuLink['uri'],
}
'title' => $menuLink['link_title'],
else {
],
MenuLinkContent::load($link['id'])->addTranslation($language_id, $link)->save();
'menu_name' => $menuLink['menu_name'],
'expanded' => $menuLink['expanded'] === '1' ? TRUE : FALSE,
if (array_key_exists('drush', $context) && $context['drush'] === TRUE) {
'enabled' => $menuLink['enabled'] === '1' ? TRUE : FALSE,
drush_log('Imported "' . $menuLink['title'] . '" into "' . $menuLink['menu_name'] . '" menu', 'ok');
'parent' => $menuLink['parent'],
}
'description' => $menuLink['description'],
StructureSyncHelper::logMessage('Imported link translation (' . $language_id . ') "' . $link['title'] . '" into "' . $link['menu_name'] . '" menu');
'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');
}
}
}
}
Loading