Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
<?php
namespace Drupal\structure_sync\Controller;
use Drupal\Core\Controller\ControllerBase;
use Drupal\structure_sync\StructureSyncHelper;
use Drupal\Core\Form\FormStateInterface;
use Drupal\menu_link_content\Entity\MenuLinkContent;
/**
* Controller for syncing menu links.
*/
class MenuLinksController extends ControllerBase {
private $config;
/**
* Constructor for menu links controller.
*/
public function __construct() {
$this->config = $this->getEditableConfig();
$this->entityTypeManager();
}
/**
* Gets the editable version of the config.
*/
private function getEditableConfig() {
$this->config('structure_sync.data');
return $this->configFactory->getEditable('structure_sync.data');
}
/**
* Function to export menu links.
*/
public function exportMenuLinks(array $form = NULL, FormStateInterface $form_state = NULL) {
StructureSyncHelper::logMessage('Menu links export started');
if (is_object($form_state) && $form_state->hasValue('export_menu_list')) {
$menu_list = $form_state->getValue('export_menu_list');
$menu_list = array_filter($menu_list, 'is_string');
}
$this->config->clear('menus')->save();
if (isset($menu_list)) {
$menuLinks = [];
foreach ($menu_list as $menu_name) {
$menuLinks = array_merge($this->entityTypeManager
->getStorage('menu_link_content')
->loadByProperties(['menu_name' => $menu_name]), $menuLinks);
}
}
else {
$menuLinks = $this->entityTypeManager()->getStorage('menu_link_content')
->loadMultiple();
}
$customMenuLinks = [];
foreach ($menuLinks as $menuLink) {
$customMenuLinks[] = [
'menu_name' => $menuLink->menu_name->getValue()[0]['value'],
'title' => $menuLink->title->getValue()[0]['value'],
'parent' => $menuLink->parent->getValue()[0]['value'],
'uri' => $menuLink->link->getValue()[0]['uri'],
'link_title' => $menuLink->link->getValue()[0]['title'],
'description' => $menuLink->description->getValue()[0]['value'],
'enabled' => $menuLink->enabled->getValue()[0]['value'],
'expanded' => $menuLink->expanded->getValue()[0]['value'],
'weight' => $menuLink->weight->getValue()[0]['value'],
'langcode' => $menuLink->langcode->getValue()[0]['value'],
Tim Kruijsen
committed
'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');
}
StructureSyncHelper::logMessage('Exported "' . $menuLink->title->getValue()[0]['value'] . '" of menu "' . $menuLink->menu_name->getValue()[0]['value'] . '"');
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
}
$this->config->set('menus', $customMenuLinks)->save();
drupal_set_message($this->t('The menu links have been successfully exported.'));
StructureSyncHelper::logMessage('Menu links exported');
}
/**
* Function to import menu links.
*
* When this function is used without the designated form, you should assign
* an array with a key value pair for form with key 'style' and value 'full',
* 'safe' or 'force' to apply that import style.
*/
public function importMenuLinks(array $form, FormStateInterface $form_state = NULL) {
StructureSyncHelper::logMessage('Menu links import started');
// Check if the there is a selection made in a form for what menus need to
// be imported.
if (is_object($form_state) && $form_state->hasValue('import_menu_list')) {
$menusSelected = $form_state->getValue('import_menu_list');
$menusSelected = array_filter($menusSelected, 'is_string');
}
if (array_key_exists('style', $form)) {
$style = $form['style'];
}
else {
StructureSyncHelper::logMessage('No style defined on menu links import', 'error');
return;
}
StructureSyncHelper::logMessage('Using "' . $style . '" style for menu links import');
// Get menu links from config.
$menusConfig = $this->config->get('menus');
$menus = [];
if (isset($menusSelected)) {
foreach ($menusConfig as $menu) {
if (in_array($menu['menu_name'], array_keys($menusSelected))) {
$menus[] = $menu;
}
}
}
else {
$menus = $menusConfig;
}
if (array_key_exists('drush', $form) && $form['drush'] === TRUE) {
$context = [];
$context['drush'] = TRUE;
switch ($style) {
case 'full':
self::deleteDeletedMenuLinks($menus, $context);
self::importMenuLinksFull($menus, $context);
self::menuLinksImportFinishedCallback(NULL, NULL, NULL);
break;
case 'safe':
self::importMenuLinksSafe($menus, $context);
self::menuLinksImportFinishedCallback(NULL, NULL, NULL);
break;
case 'force':
self::deleteMenuLinks($context);
self::importMenuLinksForce($menus, $context);
self::menuLinksImportFinishedCallback(NULL, NULL, NULL);
break;
}
return;
}
// Import the menu links with the chosen style of importing.
switch ($style) {
case 'full':
$batch = [
'title' => $this->t('Importing menu links...'),
'operations' => [
[
'\Drupal\structure_sync\Controller\MenuLinksController::deleteDeletedMenuLinks',
[$menus],
],
[
'\Drupal\structure_sync\Controller\MenuLinksController::importMenuLinksFull',
[$menus],
],
],
'finished' => '\Drupal\structure_sync\Controller\MenuLinksController::menuLinksImportFinishedCallback',
];
batch_set($batch);
break;
case 'safe':
Tim Kruijsen
committed
$batch = [
'title' => $this->t('Importing menu links...'),
'operations' => [
[
'\Drupal\structure_sync\Controller\MenuLinksController::importMenuLinksSafe',
[$menus],
Tim Kruijsen
committed
],
'finished' => '\Drupal\structure_sync\Controller\MenuLinksController::menuLinksImportFinishedCallback',
];
batch_set($batch);
break;
Tim Kruijsen
committed
case 'force':
$batch = [
'title' => $this->t('Importing menu links...'),
'operations' => [
[
'\Drupal\structure_sync\Controller\MenuLinksController::deleteMenuLinks',
[],
],
[
'\Drupal\structure_sync\Controller\MenuLinksController::importMenuLinksForce',
[$menus],
],
],
'finished' => '\Drupal\structure_sync\Controller\MenuLinksController::menuLinksImportFinishedCallback',
];
batch_set($batch);
break;
Tim Kruijsen
committed
default:
StructureSyncHelper::logMessage('Style not recognized', 'error');
break;
}
}
/**
* Function to delete the menu links that should be removed in this import.
*/
public static function deleteDeletedMenuLinks($menus, &$context) {
$uuidsInConfig = [];
foreach ($menus as $menuLink) {
$uuidsInConfig[] = $menuLink['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);
}
if (array_key_exists('drush', $context) && $context['drush'] === TRUE) {
drush_log('Deleted menu links that were not in config', 'ok');
}
StructureSyncHelper::logMessage('Deleted menu links that were not in config');
}
/**
* Function to fully import the menu links.
*
* Basically a safe import with update actions for already existing menu
* links.
*/
public static function importMenuLinksFull($menus, &$context) {
$uuidsInConfig = [];
foreach ($menus as $menuLink) {
$uuidsInConfig[] = $menuLink['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);
}
$parents = array_column($menus, 'parent');
foreach ($parents as &$parent) {
if (!is_null($parent)) {
if (($pos = strpos($parent, ":")) !== FALSE) {
$parent = substr($parent, $pos + 1);
}
else {
$parent = NULL;
}
}
}
$idsDone = [];
$idsLeft = [];
$firstRun = TRUE;
$context['sandbox']['max'] = count($menus);
$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))
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
) {
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 {
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();
}
}
}
}
$idsDone[] = $menuLink['uuid'];
if (in_array($menuLink['uuid'], $idsLeft)) {
unset($idsLeft[$menuLink['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']);
$context['sandbox']['progress']++;
if ($context['sandbox']['progress'] != $context['sandbox']['max']) {
$context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
}
}
else {
$idsLeft[$menuLink['uuid']] = $menuLink['uuid'];
}
}
$firstRun = FALSE;
}
$context['finished'] = 1;
}
Tim Kruijsen
committed
/**
* Function to import menu links safe (only adding what isn't already there).
*/
public static function importMenuLinksSafe($menus, &$context) {
$menusFiltered = $menus;
Tim Kruijsen
committed
$entities = StructureSyncHelper::getEntityManager()
->getStorage('menu_link_content')
->loadMultiple();
Tim Kruijsen
committed
foreach ($entities as $entity) {
for ($i = 0; $i < count($menus); $i++) {
if ($entity->uuid() === $menus[$i]['uuid']) {
unset($menusFiltered[$i]);
Tim Kruijsen
committed
}
}
Tim Kruijsen
committed
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');
}
Tim Kruijsen
committed
StructureSyncHelper::logMessage('Imported "' . $menuLink['title'] . '" into "' . $menuLink['menu_name'] . '" menu');
}
}
Tim Kruijsen
committed
/**
* Function to delete all menu links.
Tim Kruijsen
committed
*/
public static function deleteMenuLinks(&$context) {
$entities = StructureSyncHelper::getEntityManager()
->getStorage('menu_link_content')
->loadMultiple();
StructureSyncHelper::getEntityManager()
->getStorage('menu_link_content')
->delete($entities);
if (array_key_exists('drush', $context) && $context['drush'] === TRUE) {
drush_log('Deleted all (content) menu links', 'ok');
}
Tim Kruijsen
committed
StructureSyncHelper::logMessage('Deleted all (content) menu links');
}
Tim Kruijsen
committed
/**
* 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');
}
Tim Kruijsen
committed
StructureSyncHelper::logMessage('Imported "' . $menuLink['title'] . '" into "' . $menuLink['menu_name'] . '" menu');
}
Tim Kruijsen
committed
/**
* Function that signals that the import of menu links has finished.
*/
public static function menuLinksImportFinishedCallback($success, $results, $operations) {
Tim Kruijsen
committed
StructureSyncHelper::logMessage('Flushing all caches');
drupal_flush_all_caches();
StructureSyncHelper::logMessage('Successfully flushed caches');
Tim Kruijsen
committed
StructureSyncHelper::logMessage('Successfully imported menu links');
drupal_set_message(t('Successfully imported menu links'));