View source
<?php
namespace Drupal\group_content_menu\Form;
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Entity\ContentEntityForm;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Link;
use Drupal\Core\Menu\MenuLinkTreeElement;
use Drupal\Core\Menu\MenuTreeParameters;
use Drupal\Core\Render\Element;
use Drupal\Core\Url;
use Drupal\group\Entity\GroupInterface;
use Drupal\group_content_menu\GroupContentMenuInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
class GroupContentMenuForm extends ContentEntityForm {
protected $menuLinkManager;
protected $menuTree;
protected $linkGenerator;
protected $overviewTreeForm = [
'#tree' => TRUE,
];
protected $entity;
public static function create(ContainerInterface $container) {
$instance = parent::create($container);
$instance->menuLinkManager = $container
->get('plugin.manager.menu.link');
$instance->menuTree = $container
->get('menu.link_tree');
$instance->linkGenerator = $container
->get('link_generator');
return $instance;
}
public function buildForm(array $form, FormStateInterface $form_state) {
$form = parent::buildForm($form, $form_state);
if ($this->entity
->isNew()) {
return $form;
}
$group = $form_state
->get('group');
if (!$group) {
$group_contents = $this->entityTypeManager
->getStorage('group_content')
->loadByEntity($this->entity);
if (!$group_contents) {
return $form;
}
$group_content = reset($group_contents);
$group = $group_content
->getGroup();
}
$form_state
->set('group', $group);
if (!$form_state
->has('menu_overview_form_parents')) {
$form_state
->set('menu_overview_form_parents', []);
}
$form['#attached']['library'][] = 'menu_ui/drupal.menu_ui.adminforms';
$tree = $this->menuTree
->load(GroupContentMenuInterface::MENU_PREFIX . $this->entity
->id(), new MenuTreeParameters());
$this
->getRequest()->attributes
->set('_menu_admin', TRUE);
$manipulators = [
[
'callable' => 'menu.default_tree_manipulators:checkAccess',
],
[
'callable' => 'menu.default_tree_manipulators:generateIndexAndSort',
],
];
$tree = $this->menuTree
->transform($tree, $manipulators);
$this
->getRequest()->attributes
->set('_menu_admin', FALSE);
$count = static function (array $tree) {
$sum = static function ($carry, MenuLinkTreeElement $item) {
return $carry + $item
->count();
};
return array_reduce($tree, $sum);
};
$delta = max($count($tree), 50);
$form['links'] = [
'#type' => 'table',
'#theme' => 'table__menu_overview',
'#header' => [
$this
->t('Menu link'),
[
'data' => $this
->t('Enabled'),
'class' => [
'checkbox',
],
],
$this
->t('Weight'),
[
'data' => $this
->t('Operations'),
'colspan' => 3,
],
],
'#attributes' => [
'id' => 'menu-overview',
],
'#tabledrag' => [
[
'action' => 'match',
'relationship' => 'parent',
'group' => 'menu-parent',
'subgroup' => 'menu-parent',
'source' => 'menu-id',
'hidden' => TRUE,
'limit' => $this->menuTree
->maxDepth() - 1,
],
[
'action' => 'order',
'relationship' => 'sibling',
'group' => 'menu-weight',
],
],
];
$permission = 'administer group content menu types';
$plugin_id = 'group_content_menu:' . $this->entity
->getEntityTypeId();
$has_permission = $this
->currentUser()
->hasPermission($permission) || $group
->hasPermission("view {$plugin_id} entity", $this
->currentUser());
if ($has_permission) {
$form['links']['#empty'] = $this
->t('There are no menu links yet. <a href=":url">Add link</a>.', [
':url' => Url::fromRoute('entity.group_content_menu.add_link', [
'group' => $group
->id(),
'group_content_menu' => $this->entity
->id(),
], [
'query' => [
'destination' => $this->entity
->toUrl('edit-form')
->toString(),
],
])
->toString(),
]);
}
else {
$form['links']['#empty'] = $this
->t('There are no menu links yet.');
}
$links = $this
->buildOverviewTreeForm($tree, $delta, $group);
foreach (Element::children($links) as $id) {
if (isset($links[$id]['#item'])) {
$element = $links[$id];
$form['links'][$id]['#item'] = $element['#item'];
$form['links'][$id]['#attributes'] = $element['#attributes'];
$form['links'][$id]['#attributes']['class'][] = 'draggable';
$form['links'][$id]['#weight'] = $element['#item']->link
->getWeight();
$element['parent']['#attributes']['class'] = [
'menu-parent',
];
$element['weight']['#attributes']['class'] = [
'menu-weight',
];
$element['id']['#attributes']['class'] = [
'menu-id',
];
$form['links'][$id]['title'] = [
[
'#theme' => 'indentation',
'#size' => $element['#item']->depth - 1,
],
$element['title'],
];
$form['links'][$id]['enabled'] = $element['enabled'];
$form['links'][$id]['enabled']['#wrapper_attributes']['class'] = [
'checkbox',
'menu-enabled',
];
$form['links'][$id]['weight'] = $element['weight'];
$form['links'][$id]['operations'] = $element['operations'];
$form['links'][$id]['id'] = $element['id'];
$form['links'][$id]['parent'] = $element['parent'];
}
}
return $form;
}
protected function buildOverviewTreeForm($tree, $delta, GroupInterface $group) {
$form =& $this->overviewTreeForm;
$tree_access_cacheability = new CacheableMetadata();
foreach ($tree as $element) {
$tree_access_cacheability = $tree_access_cacheability
->merge(CacheableMetadata::createFromObject($element->access));
if (!$element->access
->isAllowed()) {
continue;
}
$link = $element->link;
if ($link) {
$id = 'menu_plugin_id:' . $link
->getPluginId();
$form[$id]['#item'] = $element;
$form[$id]['#attributes'] = $link
->isEnabled() ? [
'class' => [
'menu-enabled',
],
] : [
'class' => [
'menu-disabled',
],
];
$form[$id]['title'] = Link::fromTextAndUrl($link
->getTitle(), $link
->getUrlObject())
->toRenderable();
if (!$link
->isEnabled()) {
$form[$id]['title']['#suffix'] = ' (' . $this
->t('disabled') . ')';
}
elseif ($id === 'menu_plugin_id:user.logout') {
$form[$id]['title']['#suffix'] = ' (' . $this
->t('<q>Log in</q> for anonymous users') . ')';
}
elseif (($url = $link
->getUrlObject()) && $url
->isRouted() && $url
->getRouteName() == 'user.page') {
$form[$id]['title']['#suffix'] = ' (' . $this
->t('logged in users only') . ')';
}
$form[$id]['enabled'] = [
'#type' => 'checkbox',
'#title' => $this
->t('Enable @title menu link', [
'@title' => $link
->getTitle(),
]),
'#title_display' => 'invisible',
'#default_value' => $link
->isEnabled(),
];
$form[$id]['weight'] = [
'#type' => 'weight',
'#delta' => $delta,
'#default_value' => $link
->getWeight(),
'#title' => $this
->t('Weight for @title', [
'@title' => $link
->getTitle(),
]),
'#title_display' => 'invisible',
];
$form[$id]['id'] = [
'#type' => 'hidden',
'#value' => $link
->getPluginId(),
];
$form[$id]['parent'] = [
'#type' => 'hidden',
'#default_value' => $link
->getParent(),
];
$operations = [];
$operations['edit'] = [
'title' => $this
->t('Edit'),
];
$operations['edit']['url'] = Url::fromRoute('entity.group_content_menu.edit_link', [
'group' => $group
->id(),
'group_content_menu' => $this->entity
->id(),
'menu_link_content' => $link
->getMetaData()['entity_id'],
]);
$operations['edit']['query'] = [
'destination' => Url::fromRouteMatch($this
->getRouteMatch())
->toString(),
];
if ($link
->isResettable()) {
$operations['reset'] = [
'title' => $this
->t('Reset'),
'url' => Url::fromRoute('menu_ui.link_reset', [
'menu_link_plugin' => $link
->getPluginId(),
]),
];
}
elseif ($delete_link = $link
->getDeleteRoute()) {
$operations['delete']['url'] = $delete_link;
$operations['delete']['query'] = $this
->getRedirectDestination()
->getAsArray();
$operations['delete']['title'] = $this
->t('Delete');
}
if ($link
->isTranslatable()) {
$operations['translate'] = [
'title' => $this
->t('Translate'),
'url' => $link
->getTranslateRoute(),
];
$operations['translate']['query'] = [
'destination' => Url::fromRouteMatch($this
->getRouteMatch())
->toString(),
];
}
foreach ($operations as $key => $operation) {
if (!$operation['url']
->access()) {
unset($operations[$key]);
}
}
$form[$id]['operations'] = [
'#type' => 'operations',
'#links' => $operations,
];
}
if ($element->subtree) {
$this
->buildOverviewTreeForm($element->subtree, $delta, $group);
}
}
$tree_access_cacheability
->merge(CacheableMetadata::createFromRenderArray($form))
->applyTo($form);
return $form;
}
public function save(array $form, FormStateInterface $form_state) {
$menu = $this
->getEntity();
if (!$menu
->isNew()) {
$this
->submitOverviewForm($form, $form_state);
}
$status = $menu
->save();
$arguments = [
'%label' => $this->entity
->label(),
];
if ($status === SAVED_NEW) {
$this
->messenger()
->addStatus($this
->t('New group menu <em>%label</em> has been created.', $arguments));
$this
->logger('group_content_menu')
->notice('Created new group menu %label', $arguments);
}
else {
$this
->messenger()
->addStatus($this
->t('The group menu <em>%label</em> has been update.', $arguments));
$this
->logger('group_content_menu')
->notice('Updated group menu %label.', $arguments);
}
}
protected function submitOverviewForm(array $complete_form, FormStateInterface $form_state) {
$parents = $form_state
->get('menu_overview_form_parents');
$input = NestedArray::getValue($form_state
->getUserInput(), $parents);
$form =& NestedArray::getValue($complete_form, $parents);
$order = is_array($input) ? array_flip(array_keys($input)) : [];
$form = array_intersect_key(array_merge($order, $form), $form);
$fields = [
'weight',
'parent',
'enabled',
];
$form_links = $form['links'];
foreach (Element::children($form_links) as $id) {
if (isset($form_links[$id]['#item'])) {
$element = $form_links[$id];
$updated_values = [];
foreach ($fields as $field) {
if ($element[$field]['#value'] !== $element[$field]['#default_value']) {
$updated_values[$field] = $element[$field]['#value'];
}
}
if ($updated_values) {
$this->menuLinkManager
->updateDefinition($element['#item']->link
->getPLuginId(), $updated_values);
}
}
}
}
}