View source
<?php
namespace Drupal\colossal_menu\Form;
use Drupal\Core\Entity\EntityForm;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Link;
use Drupal\Core\Menu\MenuLinkTreeInterface;
use Drupal\Core\Menu\MenuLinkTreeElement;
use Drupal\Core\Menu\MenuTreeParameters;
use Symfony\Component\DependencyInjection\ContainerInterface;
class MenuForm extends EntityForm {
protected $entityTypeManager;
protected $menuLinkTree;
public function __construct(EntityTypeManagerInterface $entity_type_manager, MenuLinkTreeInterface $menu_link_tree) {
$this->entityTypeManager = $entity_type_manager;
$this->menuLinkTree = $menu_link_tree;
}
public static function create(ContainerInterface $container) {
return new static($container
->get('entity_type.manager'), $container
->get('colossal_menu.link_tree'));
}
public function form(array $form, FormStateInterface $form_state) {
$menu = $this->entity;
$form['label'] = [
'#type' => 'textfield',
'#title' => $this
->t('Label'),
'#maxlength' => 255,
'#default_value' => $menu
->label(),
'#description' => $this
->t("Label for the Menu."),
'#required' => TRUE,
];
$form['id'] = [
'#type' => 'machine_name',
'#default_value' => $menu
->id(),
'#machine_name' => [
'exists' => '\\Drupal\\colossal_menu\\Entity\\Menu::load',
],
'#disabled' => !$menu
->isNew(),
];
if (!$menu
->isNew()) {
$form_state
->set('links', [
'links',
]);
$form['links'] = [];
$form['links'] = $this
->buildOverviewForm($form['links'], $form_state);
}
return parent::form($form, $form_state);
}
public function save(array $form, FormStateInterface $form_state) {
$menu = $this->entity;
if (!$menu
->isNew()) {
$this
->submitOverviewForm($form, $form_state);
}
$status = $menu
->save();
switch ($status) {
case SAVED_NEW:
$this
->messenger()
->addStatus($this
->t('Created the %label Menu.', [
'%label' => $menu
->label(),
]));
break;
default:
$this
->messenger()
->addStatus($this
->t('Saved the %label Menu.', [
'%label' => $menu
->label(),
]));
}
$form_state
->setRedirectUrl($menu
->toUrl('collection'));
}
protected function submitOverviewForm(array $complete_form, FormStateInterface $form_state) {
$input = $form_state
->getUserInput();
foreach ($input['links'] as $id => $input) {
$storage = $this->entityTypeManager
->getStorage('colossal_menu_link');
$link = $storage
->load($id);
$diff = FALSE;
if (array_key_exists('parent', $input) && $link
->get('parent')
->access('edit')) {
if (!$link
->getParent() && $input['parent']) {
$diff = TRUE;
$link
->setParent($input['parent']);
}
elseif ($link
->getParent() && $link
->getParent()
->id() != $input['parent']) {
$diff = TRUE;
$link
->setParent($input['parent']);
}
}
if (array_key_exists('weight', $input) && $link
->get('weight')
->access('edit')) {
if ($link
->getWeight() != $input['weight']) {
$diff = TRUE;
$link
->setWeight($input['weight']);
}
}
if (array_key_exists('enabled', $input) && $link
->get('enabled')
->access('edit')) {
$enabled = (bool) $input['enabled'];
if ($link
->isEnabled() != $enabled) {
$diff = TRUE;
$link
->setEnabled($enabled);
}
}
if ($diff) {
$link
->save();
}
}
}
protected function buildOverviewForm(array &$form, FormStateInterface $form_state) {
$menu = $this->entity;
if (!$form_state
->has('menu_overview_form_parents')) {
$form_state
->set('menu_overview_form_parents', []);
}
$form['links'] = [
'#type' => 'table',
'#sorted' => TRUE,
'#header' => [
$this
->t('Title'),
$this
->t('Enabled'),
$this
->t('Weight'),
[
'data' => $this
->t('Operations'),
'colspan' => 3,
],
],
'#tabledrag' => [
[
'action' => 'match',
'relationship' => 'parent',
'group' => 'link-parent',
'subgroup' => 'link-parent',
'source' => 'link-id',
'hidden' => TRUE,
'limit' => $this->menuLinkTree
->maxDepth(),
],
[
'action' => 'order',
'relationship' => 'sibling',
'group' => 'link-weight',
],
],
];
$params = new MenuTreeParameters();
$tree = $this->menuLinkTree
->load($menu
->id(), $params);
$elements = [];
foreach ($tree as $item) {
$this
->buildLinkElement($elements, $item);
}
$form['links'] = $form['links'] + $elements;
return $form;
}
protected function buildLinkElement(array &$elements, MenuLinkTreeElement $item, $depth = 0) {
$link = $item->link;
$id = $link
->id();
$elements[$id] = [
'#weight' => $link
->getWeight(),
];
if ($link
->get('parent')
->access('edit') && $link
->get('weight')
->access('edit')) {
$elements[$id]['#attributes']['class'][] = 'draggable';
}
$text = [];
if (!$link
->isExternal() && $link
->getRouteName() == '<none>') {
$text = [
'#plain_text' => $link
->getTitle(),
];
}
else {
$text = Link::fromTextAndUrl($link
->getTitle(), $link
->getUrlObject())
->toRenderable();
}
$elements[$id]['indent'] = [
[
'#theme' => 'indentation',
'#size' => $depth,
],
[
$text,
],
];
if ($link
->get('enabled')
->access('edit')) {
$elements[$id]['enabled'] = [
'#type' => 'checkbox',
'#default_value' => $link
->isEnabled(),
'#title' => $this
->t('Enabled'),
'#title_display' => 'invisible',
];
}
else {
$elements[$id]['enabled'] = [
'#markup' => $link
->isEnabled() ? $this
->t('Enabled') : $this
->t('Disabled'),
];
}
$elements[$id]['weight'] = [
'#type' => 'weight',
'#delta' => 50,
'#default_value' => $link
->getWeight(),
'#title' => $this
->t('Weight for @title', [
'@title' => $link
->getTitle(),
]),
'#title_display' => 'invisible',
'#attributes' => [
'class' => [
'link-weight',
],
],
'#access' => $link
->get('weight')
->access('edit'),
];
$operations = [];
if ($link
->access('update')) {
$operations['edit'] = [
'title' => $this
->t('Edit'),
'url' => $link
->getEditRoute(),
'query' => $this
->getDestinationArray(),
];
}
if ($link
->access('delete')) {
$operations['delete'] = [
'title' => $this
->t('Delete'),
'url' => $link
->getDeleteRoute(),
'query' => $this
->getDestinationArray(),
];
}
$elements[$id]['operations'] = [
'#type' => 'operations',
'#links' => $operations,
];
$elements[$id]['id'] = [
'#type' => 'hidden',
'#default_value' => $id,
'#attributes' => [
'class' => [
'link-id',
],
],
];
$elements[$id]['parent'] = [
'#type' => 'hidden',
'#default_value' => $link
->getParent() ? $link
->getParent()
->id() : 0,
'#attributes' => [
'class' => [
'link-parent',
],
],
'#access' => $link
->get('parent')
->access('edit'),
];
if (!empty($item->subtree)) {
$subdepth = $depth + 1;
foreach ($item->subtree as $subitem) {
$this
->buildLinkElement($elements, $subitem, $subdepth);
}
}
}
}