View source
<?php
namespace Drupal\og_menu\Form;
use Drupal\Component\Datetime\TimeInterface;
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Entity\ContentEntityForm;
use Drupal\Core\Entity\EntityRepositoryInterface;
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Link;
use Drupal\Core\Menu\MenuLinkManagerInterface;
use Drupal\Core\Menu\MenuLinkTreeElement;
use Drupal\Core\Menu\MenuLinkTreeInterface;
use Drupal\Core\Menu\MenuTreeParameters;
use Drupal\Core\Render\Element;
use Drupal\Core\Routing\UrlGeneratorInterface;
use Drupal\Core\Url;
use Drupal\Core\Utility\LinkGeneratorInterface;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\og\OgAccessInterface;
use Drupal\og\OgGroupAudienceHelperInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
class OgMenuInstanceForm extends ContentEntityForm {
protected $menuLinkManager;
protected $menuTree;
protected $linkGenerator;
protected $ogAccess;
protected $overviewTreeForm = array(
'#tree' => TRUE,
);
protected $entity;
protected $urlGenerator;
public function __construct(EntityRepositoryInterface $entity_repository, MenuLinkManagerInterface $menu_link_manager, MenuLinkTreeInterface $menu_tree, LinkGeneratorInterface $link_generator, OgAccessInterface $og_access, UrlGeneratorInterface $url_generator, ?EntityTypeBundleInfoInterface $entity_type_bundle_info = NULL, ?TimeInterface $time = NULL) {
parent::__construct($entity_repository, $entity_type_bundle_info, $time);
$this->menuLinkManager = $menu_link_manager;
$this->menuTree = $menu_tree;
$this->linkGenerator = $link_generator;
$this->ogAccess = $og_access;
$this->urlGenerator = $url_generator;
}
public static function create(ContainerInterface $container) {
return new static($container
->get('entity.repository'), $container
->get('plugin.manager.menu.link'), $container
->get('menu.link_tree'), $container
->get('link_generator'), $container
->get('og.access'), $container
->get('url_generator'), $container
->get('entity_type.bundle.info'), $container
->get('datetime.time'));
}
public function buildForm(array $form, FormStateInterface $form_state) {
$form = parent::buildForm($form, $form_state);
if ($this->entity
->isNew()) {
return $form;
}
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('ogmenu-' . $this->entity
->id(), new MenuTreeParameters());
$this
->getRequest()->attributes
->set('_menu_admin', TRUE);
$manipulators = array(
array(
'callable' => 'menu.default_tree_manipulators:checkAccess',
),
array(
'callable' => 'menu.default_tree_manipulators:generateIndexAndSort',
),
);
$tree = $this->menuTree
->transform($tree, $manipulators);
$this
->getRequest()->attributes
->set('_menu_admin', FALSE);
$count = function (array $tree) {
$sum = function ($carry, MenuLinkTreeElement $item) {
return $carry + $item
->count();
};
return array_reduce($tree, $sum);
};
$delta = max($count($tree), 50);
$form['links'] = array(
'#type' => 'table',
'#theme' => 'table__menu_overview',
'#header' => array(
$this
->t('Menu link'),
array(
'data' => $this
->t('Enabled'),
'class' => array(
'checkbox',
),
),
$this
->t('Weight'),
array(
'data' => $this
->t('Operations'),
'colspan' => 3,
),
),
'#attributes' => array(
'id' => 'menu-overview',
),
'#tabledrag' => array(
array(
'action' => 'match',
'relationship' => 'parent',
'group' => 'menu-parent',
'subgroup' => 'menu-parent',
'source' => 'menu-id',
'hidden' => TRUE,
'limit' => \Drupal::menuTree()
->maxDepth() - 1,
),
array(
'action' => 'order',
'relationship' => 'sibling',
'group' => 'menu-weight',
),
),
);
$permission = 'add new links to og menu instance entities';
$has_permission = $this
->currentUser()
->hasPermission($permission) || $this->ogAccess
->userAccess($this->entity
->getGroup(), $permission, $this
->currentUser(), FALSE, TRUE)
->isAllowed();
if ($has_permission) {
$form['links']['#empty'] = $this
->t('There are no menu links yet. <a href=":url">Add link</a>.', [
':url' => $this->urlGenerator
->generateFromRoute('entity.ogmenu_instance.add_link', [
'ogmenu_instance' => $this->entity
->id(),
], [
'query' => [
'destination' => $this->entity
->toUrl('edit-form')
->toString(),
],
]),
]);
}
else {
$form['links']['#empty'] = $this
->t('There are no menu links yet.');
}
$links = $this
->buildOverviewTreeForm($tree, $delta);
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'] = array(
'menu-parent',
);
$element['weight']['#attributes']['class'] = array(
'menu-weight',
);
$element['id']['#attributes']['class'] = array(
'menu-id',
);
$form['links'][$id]['title'] = array(
array(
'#theme' => 'indentation',
'#size' => $element['#item']->depth - 1,
),
$element['title'],
);
$form['links'][$id]['enabled'] = $element['enabled'];
$form['links'][$id]['enabled']['#wrapper_attributes']['class'] = array(
'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) {
$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() ? array(
'class' => array(
'menu-enabled',
),
) : array(
'class' => array(
'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'] = array(
'#type' => 'checkbox',
'#title' => $this
->t('Enable @title menu link', array(
'@title' => $link
->getTitle(),
)),
'#title_display' => 'invisible',
'#default_value' => $link
->isEnabled(),
);
$form[$id]['weight'] = array(
'#type' => 'weight',
'#delta' => $delta,
'#default_value' => $link
->getWeight(),
'#title' => $this
->t('Weight for @title', array(
'@title' => $link
->getTitle(),
)),
'#title_display' => 'invisible',
);
$form[$id]['id'] = array(
'#type' => 'hidden',
'#value' => $link
->getPluginId(),
);
$form[$id]['parent'] = array(
'#type' => 'hidden',
'#default_value' => $link
->getParent(),
);
$operations = array();
$operations['edit'] = array(
'title' => $this
->t('Edit'),
);
$edit_route = $link
->getEditRoute();
if ($edit_route) {
$operations['edit']['url'] = $edit_route;
$operations['edit']['query'] = $this
->getDestinationArray();
}
else {
$operations['edit'] += array(
'url' => Url::fromRoute('menu_ui.link_edit', [
'menu_link_plugin' => $link
->getPluginId(),
]),
);
}
if ($link
->isResettable()) {
$operations['reset'] = array(
'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
->getDestinationArray();
$operations['delete']['title'] = $this
->t('Delete');
}
if ($link
->isTranslatable()) {
$operations['translate'] = array(
'title' => $this
->t('Translate'),
'url' => $link
->getTranslateRoute(),
);
}
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);
}
}
$tree_access_cacheability
->merge(CacheableMetadata::createFromRenderArray($form))
->applyTo($form);
return $form;
}
public function save(array $form, FormStateInterface $form_state) {
$menu = $this->entity;
if (!$menu
->isNew() || $menu
->isLocked()) {
$this
->submitOverviewForm($form, $form_state);
}
$status = $menu
->save();
switch ($status) {
case SAVED_NEW:
$this
->messenger()
->addMessage($this
->t('Created the %label menu.', [
'%label' => $menu
->label(),
]));
break;
default:
$this
->messenger()
->addMessage($this
->t('Saved the %label menu.', [
'%label' => $menu
->label(),
]));
}
$field_storage = FieldStorageConfig::loadByName($this->entity
->getEntityTypeId(), OgGroupAudienceHelperInterface::DEFAULT_FIELD);
$target_type = $field_storage
->getSetting('target_type');
$group_entity = $this->entity
->getGroup();
if ($target_type && $group_entity) {
$form_state
->setRedirect('entity.' . $target_type . '.canonical', [
$target_type => $group_entity
->id(),
]);
}
else {
$form_state
->setRedirect('entity.ogmenu_instance.edit_form', [
'ogmenu_instance' => $menu
->id(),
]);
}
}
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)) : array();
$form = array_intersect_key(array_merge($order, $form), $form);
$fields = array(
'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 = array();
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);
}
}
}
}
}