diff --git a/core/lib/Drupal/Core/Field/TypedData/FieldItemDataDefinition.php b/core/lib/Drupal/Core/Field/TypedData/FieldItemDataDefinition.php index 7b85e8c..e8dbe48 100644 --- a/core/lib/Drupal/Core/Field/TypedData/FieldItemDataDefinition.php +++ b/core/lib/Drupal/Core/Field/TypedData/FieldItemDataDefinition.php @@ -43,6 +43,13 @@ public static function createFromDataType($data_type) { } /** + * Returns the field definition. + */ + public function getFieldDefinition() { + return $this->fieldDefinition; + } + + /** * Creates a new field item definition. * * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition diff --git a/core/lib/Drupal/Core/Menu/MenuParentFormSelector.php b/core/lib/Drupal/Core/Menu/MenuParentFormSelector.php index e57b7e8..65ac1e6 100644 --- a/core/lib/Drupal/Core/Menu/MenuParentFormSelector.php +++ b/core/lib/Drupal/Core/Menu/MenuParentFormSelector.php @@ -79,8 +79,8 @@ public function getParentSelectOptions($id = '', array $menus = NULL) { /** * {@inheritdoc} */ - public function parentSelectElement($menu_parent, $id = '', array $menus = NULL) { - $options = $this->getParentSelectOptions($id, $menus); + public function parentSelectElement($menu_parent, $exclude_id = '', array $menus = NULL) { + $options = $this->getParentSelectOptions($exclude_id, $menus); // If no options were found, there is nothing to select. if ($options) { if (!isset($options[$menu_parent])) { diff --git a/core/lib/Drupal/Core/Menu/MenuParentFormSelectorInterface.php b/core/lib/Drupal/Core/Menu/MenuParentFormSelectorInterface.php index 33ada87..7e607b3 100644 --- a/core/lib/Drupal/Core/Menu/MenuParentFormSelectorInterface.php +++ b/core/lib/Drupal/Core/Menu/MenuParentFormSelectorInterface.php @@ -38,7 +38,7 @@ public function getParentSelectOptions($id = '', array $menus = NULL); * @param string $menu_parent * A menu name and parent ID concatenated with a ':' character to use as the * default value. - * @param string $id + * @param string $exclude_id * (optional) ID of a link plugin. This will exclude the link and its * children from being selected. * @param array $menus @@ -51,6 +51,6 @@ public function getParentSelectOptions($id = '', array $menus = NULL); * a single string containing the chosen menu name and parent ID separated * by a ':' character. */ - public function parentSelectElement($menu_parent, $id = '', array $menus = NULL); + public function parentSelectElement($menu_parent, $exclude_id = '', array $menus = NULL); } diff --git a/core/modules/menu_link/menu_link.info.yml b/core/modules/menu_link/menu_link.info.yml new file mode 100644 index 0000000..2c90e90 --- /dev/null +++ b/core/modules/menu_link/menu_link.info.yml @@ -0,0 +1,8 @@ +name: Menu link +type: module +description: 'Defines a menu link field type' +package: Field types +version: VERSION +core: 8.x +dependencies: + - field diff --git a/core/modules/menu_link/src/Plugin/Field/FieldType/MenuLinkItem.php b/core/modules/menu_link/src/Plugin/Field/FieldType/MenuLinkItem.php new file mode 100644 index 0000000..5fd1bb3 --- /dev/null +++ b/core/modules/menu_link/src/Plugin/Field/FieldType/MenuLinkItem.php @@ -0,0 +1,213 @@ +menuPluginManager = \Drupal::service('plugin.manager.menu.link'); + } + + /** + * {@inheritdoc} + */ + public static function defaultInstanceSettings() { + $settings = parent::defaultInstanceSettings(); + + $settings['available_menus'] = array('main'); + return $settings; + } + + /** + * {@inheritdoc} + */ + public function instanceSettingsForm(array $form, FormStateInterface $form_state) { + $form = parent::instanceSettingsForm($form, $form_state); + + $menu_options = menu_ui_get_menus(); + $form['available_menus'] = array( + '#type' => 'checkboxes', + '#title' => $this->t('Available menus'), + '#default_value' => $this->getSetting('available_menus'), + '#options' => $menu_options, + '#description' => $this->t('The menus available to place links in for this content type.'), + ); + + return $form; + } + + /** + * {@inheritdoc} + */ + public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) { + $definitions = array(); + + $definitions['menu_name'] = DataDefinition::create('string') + ->setLabel(t('Menu')); + $definitions['parent'] = DataDefinition::create('string') + ->setLabel(t('Parent menu link')); + $definitions['title'] = DataDefinition::create('string') + ->setLabel(t('Menu link title')); + $definitions['description'] = DataDefinition::create('string') + ->setLabel(t('Menu link description')); + $definitions['weight'] = DataDefinition::create('integer') + ->setLabel(t('Menu link weight')); + + return $definitions; + } + + /** + * {@inheritdoc} + */ + public static function schema(FieldStorageDefinitionInterface $field_definition) { + $schema = array(); + + $schema['columns']['title'] = array( + 'description' => 'The link text.', + 'type' => 'varchar', + 'length' => 255, + 'not null' => FALSE, + ); + + $schema['columns']['menu_name'] = array( + 'description' => 'The menu of the link', + 'type' => 'varchar', + 'length' => 255, + 'not null' => FALSE, + ); + $schema['columns']['parent'] = array( + 'description' => 'The parent of the menu link', + 'type' => 'varchar', + 'length' => 255, + 'not null' => FALSE, + ); + + $schema['columns']['weight'] = array( + 'description' => 'The weight of the menu link', + 'type' => 'int', + ); + + $schema['columns']['description'] = array( + 'description' => 'The link description.', + 'type' => 'blob', + 'size' => 'big', + 'not null' => FALSE, + ); + + return $schema; + } + + /** + * {@inheritdoc} + */ + public function insert() { + parent::insert(); + + $this->doSave(); + } + + /** + * {@inheritdoc} + */ + public function update() { + parent::update(); + + $this->doSave(); + } + + /** + * {@inheritdoc} + */ + public function delete() { + parent::delete(); + + $plugin_id = $this->getMenuPluginId(); + if ($this->menuPluginManager->hasDefinition($plugin_id)) { + $this->menuPluginManager->removeDefinition($plugin_id); + } + } + + /** + * @TODO + */ + protected function doSave() { + $plugin_id = $this->getMenuPluginId(); + if (!$this->menuPluginManager->hasDefinition($plugin_id)) { + $this->menuPluginManager->addDefinition($plugin_id, $this->getMenuPluginDefinition()); + } + else { + $this->menuPluginManager->updateDefinition($plugin_id, $this->getMenuPluginDefinition(), FALSE); + } + } + + /** + * Generates the plugin ID for the associated menu link. + * + * @return string + */ + protected function getMenuPluginId() { + $field_name = $this->definition->getFieldDefinition()->getName(); + $entity_type_id = $this->getEntity()->getEntityTypeId(); + return 'menu_link_field:' . "{$entity_type_id}_{$field_name}_{$this->getEntity()->uuid()}"; + } + + /** + * Generates the plugin definition of the associated menu link. + * + * @return array + */ + protected function getMenuPluginDefinition() { + $menu_definition = array(); + $menu_definition['id'] = $this->getPluginId(); + $menu_definition['title'] = $this->values['title']; + $menu_definition['menu_name'] = $this->values['menu_name']; + $menu_definition['parent'] = $this->values['parent']; + $menu_definition['weight'] = $this->values['weight']; + $menu_definition['class'] = '\Drupal\menu_link\Plugin\Menu\MenuLinkField'; + $menu_definition['form_class'] = '\Drupal\menu_link\Plugin\Menu\Form\MenuLinkFieldForm'; + $menu_definition['metadata']['entity_id'] = $this->getEntity()->id(); + $menu_definition['metadata']['entity_type_id'] = $this->getEntity()->getEntityTypeId(); + $menu_definition['metadata']['field_name'] = $this->definition->getFieldDefinition()->getName(); + + $url = $this->getEntity()->urlInfo(); + $menu_definition['route_name'] = $url->getRouteName(); + $menu_definition['route_parameters'] = $url->getRouteParameters(); + + return $menu_definition; + } + +} diff --git a/core/modules/menu_link/src/Plugin/Field/FieldWidget/MenuLinkWidget.php b/core/modules/menu_link/src/Plugin/Field/FieldWidget/MenuLinkWidget.php new file mode 100644 index 0000000..c80985d --- /dev/null +++ b/core/modules/menu_link/src/Plugin/Field/FieldWidget/MenuLinkWidget.php @@ -0,0 +1,148 @@ +menuParentSelector = $menu_parent_selector; + $this->account = $account; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + return new static( + $plugin_id, + $plugin_definition, + $configuration['field_definition'], + $configuration['settings'], + $configuration['third_party_settings'], + $container->get('menu.parent_form_selector'), + $container->get('current_user') + ); + } + + /** + * {@inheritdoc} + */ + public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) { + $default_title = isset($items[$delta]->title) ? $items[$delta]->title : NULL; + $default_description = isset($items[$delta]->description) ? $items[$delta]->description : NULL; + $default_weight = isset($items[$delta]->weight) ? $items[$delta]->weight : 0; + + $available_menus = $items->getSetting('available_menus'); + $menu = isset($items[$delta]->menu) ? $items[$delta]->menu : reset($available_menus); + $parent = isset($items[$delta]->parent) ? $items[$delta]->parent : ""; + $default_menu_parent = "$menu:$parent"; + + if ($this->account->hasPermission('administer menu')) { + $element['title'] = array( + '#type' => 'textfield', + '#title' => t('Menu link title'), + '#default_value' => $default_title, + ); + + $element['description'] = array( + '#type' => 'textarea', + '#title' => t('Description'), + '#default_value' => $default_description, + '#rows' => 1, + '#description' => t('Shown when hovering over the menu link.'), + ); + + $plugin_id = $parent ? $default_menu_parent : ''; + $parent_element = $this->menuParentSelector->parentSelectElement($default_menu_parent, $plugin_id, array_filter($available_menus)); + + $element['menu_parent'] = $parent_element; + $element['menu_parent']['#title'] = t('Parent item'); + $element['menu_parent']['#attributes']['class'][] = 'menu-parent-select'; + + $element['weight'] = array( + '#type' => 'number', + '#title' => t('Weight'), + '#default_value' => $default_weight, + '#description' => t('Menu links with lower weights are displayed before links with higher weights.'), + ); + } + else { + $element['title'] = array( + '#type' => 'value', + '#value' => $default_title, + ); + $element['description'] = array( + '#type' => 'value', + '#value' => $default_description, + ); + $element['weight'] = array( + '#type' => 'value', + '#value' => $default_weight, + ); + $element['menu_parent'] = array( + '#type' => 'value', + '#value' => $default_menu_parent, + ); + } + + return $element; + } + + /** + * {@inheritdoc} + */ + public function extractFormValues(FieldItemListInterface $items, array $form, FormStateInterface $form_state) { + parent::extractFormValues($items, $form, $form_state); + + // Extract menu/parent from single select element. + foreach ($items as $delta => $item) { + list($item->menu_name, $item->parent) = explode(':', $item->menu_parent, 2); + unset($item->menu_parent); + } + } + +} diff --git a/core/modules/menu_link/src/Plugin/Menu/Form/MenuLinkFieldForm.php b/core/modules/menu_link/src/Plugin/Menu/Form/MenuLinkFieldForm.php new file mode 100644 index 0000000..8dab8d4 --- /dev/null +++ b/core/modules/menu_link/src/Plugin/Menu/Form/MenuLinkFieldForm.php @@ -0,0 +1,44 @@ +menuLink->getEntity(); + + $form['info'] = array( + '#type' => 'item', + '#title' => $this->t('This link is provided by the %type: @label. The path cannot be edited.', array( + '%type' => $entity->getEntityType()->getLabel(), + '@url' => $entity->url(), + '@label' => $entity->label(), + )), + ); + + return $form; + } + +} + diff --git a/core/modules/menu_link/src/Plugin/Menu/MenuLinkField.php b/core/modules/menu_link/src/Plugin/Menu/MenuLinkField.php new file mode 100644 index 0000000..73985dd --- /dev/null +++ b/core/modules/menu_link/src/Plugin/Menu/MenuLinkField.php @@ -0,0 +1,108 @@ +entityManager = $entity_manager; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + return new static( + $configuration, + $plugin_id, + $plugin_definition, + $container->get('entity.manager') + ); + } + + /** + * {@inheritdoc} + */ + public function getTitle() { + return $this->pluginDefinition['title']; + } + + /** + * {@inheritdoc} + */ + public function getDescription() { + return $this->pluginDefinition['description']; + } + + /** + * {@inheritdoc} + */ + public function updateLink(array $new_definition_values, $persist) { + $field_name = $this->getMetaData()['field_name']; + + $this->pluginDefinition = $new_definition_values + $this->getPluginDefinition(); + if ($persist) { + $updated = array(); + foreach ($new_definition_values as $key => $value) { + $field = $this->getEntity()->{$field_name}; + if (isset($field->{$key})) { + $field->{$key} = $value; + $updated[] = $key; + } + } + if ($updated) { + $this->getEntity()->save(); + } + } + + return $this->pluginDefinition; + } + + /** + * Loads the entity the field was attached to. + * + * @return \Drupal\Core\Entity\EntityInterface|null + * Returns the entity, if exists. + */ + public function getEntity() { + $entity_type_id = $this->pluginDefinition['metadata']['entity_type_id']; + $entity_id = $this->pluginDefinition['metadata']['entity_id']; + $entity = $this->entityManager->getStorage($entity_type_id)->load($entity_id); + return $entity; + } + +} diff --git a/core/modules/menu_ui/menu_ui.module b/core/modules/menu_ui/menu_ui.module index 07fcb81..d45aa16 100644 --- a/core/modules/menu_ui/menu_ui.module +++ b/core/modules/menu_ui/menu_ui.module @@ -151,378 +151,6 @@ function menu_ui_block_view_system_menu_block_alter(array &$build, BlockPluginIn } /** - * Implements hook_ENTITY_TYPE_insert() for node entities. - */ -function menu_ui_node_insert(EntityInterface $node) { - menu_ui_node_save($node); -} - -/** - * Implements hook_ENTITY_TYPE_update() for node entities. - */ -function menu_ui_node_update(EntityInterface $node) { - menu_ui_node_save($node); -} - -/** - * Implements hook_ENTITY_TYPE_insert() for node_type entities. - */ -function menu_ui_node_type_insert(NodeTypeInterface $type) { - if ($type->isSyncing()) { - return; - } - \Drupal::config('menu.entity.node.' . $type->id()) - ->set('available_menus', array('main')) - ->set('parent', 'main:') - ->save(); -} - -/** - * Implements hook_ENTITY_TYPE_delete() for node_type entities. - */ -function menu_ui_node_type_delete(NodeTypeInterface $type) { - if ($type->isSyncing()) { - return; - } - \Drupal::config('menu.entity.node.' . $type->id())->delete(); -} - -/** - * Helper for hook_ENTITY_TYPE_insert() and hook_ENTITY_TYPE_update() for nodes. - */ -function menu_ui_node_save(EntityInterface $node) { - if (!empty($node->menu)) { - /** @var \Drupal\menu_link_content\MenuLinkContentInterface $entity */ - $definition = $node->menu; - if (trim($definition['title'])) { - if (!empty($definition['entity_id'])) { - $entity = entity_load('menu_link_content', $definition['entity_id']); - $entity->enabled->value = 1; - $entity->title->value = trim($definition['title']); - $entity->description->value = trim($definition['description']); - $entity->menu_name->value = $definition['menu_name']; - $entity->parent->value = $definition['parent']; - $entity->weight->value = isset($definition['weight']) ? $definition['weight'] : 0; - } - else { - // Create a new menu_link_content entity. - $entity = entity_create('menu_link_content', array( - 'title' => trim($definition['title']), - 'description' => trim($definition['description']), - 'route_name' => 'entity.node.canonical', - 'route_parameters' => array('node' => $node->id()), - 'menu_name' => $definition['menu_name'], - 'parent' => $definition['parent'], - 'weight' => isset($definition['weight']) ? $definition['weight'] : 0, - 'enabled' => 1, - 'bundle' => 'menu_link_content', - 'langcode' => $node->getUntranslated()->language()->id, - )); - } - if (!$entity->save()) { - drupal_set_message(t('There was an error saving the menu link.'), 'error'); - } - } - } -} - -/** - * Implements hook_ENTITY_TYPE_predelete() for node entities. - */ -function menu_ui_node_predelete(EntityInterface $node) { - // Delete all MenuLinkContent links that point to this node. - /** @var \Drupal\Core\Menu\MenuLinkManagerInterface $menu_link_manager */ - $menu_link_manager = \Drupal::service('plugin.manager.menu.link'); - $result = $menu_link_manager->loadLinksByRoute('entity.node.canonical', array('node' => $node->id())); - - if (!empty($result)) { - foreach ($result as $id => $instance) { - if ($instance->isDeletable() && strpos($id, 'menu_link_content:') === 0) { - $instance->deleteLink(); - } - } - } -} - -/** - * Implements hook_node_prepare_form(). - */ -function menu_ui_node_prepare_form(NodeInterface $node, $operation, FormStateInterface $form_state) { - if (empty($form_state['menu_link_definition'])) { - // Prepare the node for the edit form so that $node->menu always exists. - $node_type_config = \Drupal::config('menu.entity.node.' . $node->getType()); - $menu_name = strtok($node_type_config->get('parent'), ':'); - $definition = FALSE; - if ($node->id()) { - $id = FALSE; - // Give priority to the default menu - $type_menus = $node_type_config->get('available_menus'); - if (in_array($menu_name, $type_menus)) { - $query = \Drupal::entityQuery('menu_link_content') - ->condition('route_name', 'entity.node.canonical') - ->condition('route_parameters', serialize(array('node' => $node->id()))) - ->condition('menu_name', $menu_name) - ->sort('id', 'ASC') - ->range(0, 1); - $result = $query->execute(); - - $id = (!empty($result)) ? reset($result) : FALSE; - } - // Check all allowed menus if a link does not exist in the default menu. - if (!$id && !empty($type_menus)) { - $query = \Drupal::entityQuery('menu_link_content') - ->condition('route_name', 'entity.node.canonical') - ->condition('route_parameters', serialize(array('node' => $node->id()))) - ->condition('menu_name', array_values($type_menus), 'IN') - ->sort('id', 'ASC') - ->range(0, 1); - $result = $query->execute(); - - $id = (!empty($result)) ? reset($result) : FALSE; - } - if ($id) { - $menu_link = MenuLinkContent::load($id); - $definition = array( - 'entity_id' => $menu_link->id(), - 'id' => $menu_link->getPluginId(), - 'title' => $menu_link->getTitle(), - 'description' => $menu_link->getDescription(), - 'menu_name' => $menu_link->getMenuName(), - 'parent' => $menu_link->getParentId(), - 'weight' => $menu_link->getWeight(), - ); - } - } - - if (!$definition) { - $definition = array( - 'entity_id' => 0, - 'id' => '', - 'title' => '', - 'description' => '', - 'menu_name' => $menu_name, - 'parent' => '', - 'weight' => 0, - ); - } - // Set default values. - $form_state['menu_link_definition'] = $definition; - } -} - -/** - * Implements hook_form_BASE_FORM_ID_alter() for node_form. - * - * Adds menu item fields to the node form. - * - * @see menu_ui_node_submit() - */ -function menu_ui_form_node_form_alter(&$form, FormStateInterface $form_state) { - // Generate a list of possible parents (not including this link or descendants). - // @todo This must be handled in a #process handler. - $node = $form_state['controller']->getEntity(); - $definition = $form_state['menu_link_definition']; - $type = $node->getType(); - /** @var \Drupal\Core\Menu\MenuParentFormSelectorInterface $menu_parent_selector */ - $menu_parent_selector = \Drupal::service('menu.parent_form_selector'); - $menu_names = menu_ui_get_menus(); - $type_menus = \Drupal::config("menu.entity.node.$type")->get('available_menus'); - $available_menus = array(); - foreach ($type_menus as $menu) { - $available_menus[$menu] = $menu_names[$menu]; - } - if ($definition['id']) { - $default = $definition['menu_name'] . ':' . $definition['parent']; - } - else { - $default = \Drupal::config('menu.entity.node.'.$type)->get('parent'); - } - $parent_element = $menu_parent_selector->parentSelectElement($default, $definition['id'], $available_menus); - // If no possible parent menu items were found, there is nothing to display. - if (empty($parent_element)) { - return; - } - - $form['menu'] = array( - '#type' => 'details', - '#title' => t('Menu settings'), - '#access' => \Drupal::currentUser()->hasPermission('administer menu'), - '#open' => (bool) $definition['id'], - '#group' => 'advanced', - '#attached' => array( - 'library' => array('menu/drupal.menu'), - ), - '#tree' => TRUE, - '#weight' => -2, - '#attributes' => array('class' => array('menu-link-form')), - ); - $form['menu']['enabled'] = array( - '#type' => 'checkbox', - '#title' => t('Provide a menu link'), - '#default_value' => (int) (bool) $definition['id'], - ); - $form['menu']['link'] = array( - '#type' => 'container', - '#parents' => array('menu'), - '#states' => array( - 'invisible' => array( - 'input[name="menu[enabled]"]' => array('checked' => FALSE), - ), - ), - ); - - // Populate the element with the link data. - foreach (array('id', 'entity_id') as $key) { - $form['menu']['link'][$key] = array('#type' => 'value', '#value' => $definition[$key]); - } - - $form['menu']['link']['title'] = array( - '#type' => 'textfield', - '#title' => t('Menu link title'), - '#default_value' => $definition['title'], - ); - - $form['menu']['link']['description'] = array( - '#type' => 'textarea', - '#title' => t('Description'), - '#default_value' => $definition['description'], - '#rows' => 1, - '#description' => t('Shown when hovering over the menu link.'), - ); - - $form['menu']['link']['menu_parent'] = $parent_element; - $form['menu']['link']['menu_parent']['#title'] = t('Parent item'); - $form['menu']['link']['menu_parent']['#attributes']['class'][] = 'menu-parent-select'; - - $form['menu']['link']['weight'] = array( - '#type' => 'number', - '#title' => t('Weight'), - '#default_value' => $definition['weight'], - '#description' => t('Menu links with lower weights are displayed before links with higher weights.'), - ); -} - -/** - * Implements hook_node_submit(). - * - * @see menu_ui_form_node_form_alter() - */ -function menu_ui_node_submit(EntityInterface $node, $form, FormStateInterface $form_state) { - if (!$form_state->isValueEmpty('menu')) { - $definition = $form_state->getValue('menu'); - if (empty($definition['enabled'])) { - if ($definition['entity_id']) { - $entity = entity_load('menu_link_content', $definition['entity_id']); - $entity->delete(); - } - } - elseif (trim($definition['title'])) { - // Decompose the selected menu parent option into 'menu_name' and 'parent', - // if the form used the default parent selection widget. - if (!empty($definition['menu_parent'])) { - list($menu_name, $parent) = explode(':', $definition['menu_parent'], 2); - $definition['menu_name'] = $menu_name; - $definition['parent'] = $parent; - } - // @todo Figure out how to save this data without adding non-Field API - // properties to the node entity. https://www.drupal.org/node/2310173 - // We have to tack this onto the node so we can save it later when we - // have a node ID for any new node. - $node->menu = $definition; - } - } -} - -/** - * Implements hook_form_FORM_ID_alter(). - * - * Adds menu options to the node type form. - * - * @see NodeTypeForm::form(). - * @see menu_ui_form_node_type_form_submit(). - */ -function menu_ui_form_node_type_form_alter(&$form, FormStateInterface $form_state) { - /** @var \Drupal\Core\Menu\MenuParentFormSelectorInterface $menu_parent_selector */ - $menu_parent_selector = \Drupal::service('menu.parent_form_selector'); - $menu_options = menu_ui_get_menus(); - $type = $form_state['controller']->getEntity(); - if ($type->id()) { - $config_values = \Drupal::config('menu.entity.node.' . $type->id())->get(); - } - else { - $config_values = array( - 'available_menus' => array('main'), - 'parent' => 'main:', - ); - } - $form['menu'] = array( - '#type' => 'details', - '#title' => t('Menu settings'), - '#attached' => array( - 'library' => array('menu_ui/drupal.menu_ui.admin'), - ), - '#group' => 'additional_settings', - ); - $form['menu']['menu_options'] = array( - '#type' => 'checkboxes', - '#title' => t('Available menus'), - '#default_value' => $config_values['available_menus'], - '#options' => $menu_options, - '#description' => t('The menus available to place links in for this content type.'), - ); - // @todo See if we can avoid pre-loading all options by changing the form or - // using a #process callback. https://www.drupal.org/node/2310319 - // To avoid an 'illegal option' error after saving the form we have to load - // all available menu parents. Otherwise, it is not possible to dynamically - // add options to the list using ajax. - $options = $menu_parent_selector->getParentSelectOptions(''); - $form['menu']['menu_parent'] = array( - '#type' => 'select', - '#title' => t('Default parent item'), - '#default_value' => $config_values['parent'], - '#options' => $options, - '#description' => t('Choose the menu item to be the default parent for a new link in the content authoring form.'), - '#attributes' => array('class' => array('menu-title-select')), - ); - - $form['actions']['submit']['#validate'][] = 'menu_ui_form_node_type_form_validate'; - $form['actions']['submit']['#submit'][] = 'menu_ui_form_node_type_form_submit'; -} - -/** - * Submit handler for forms with menu options. - * - * @see menu_ui_form_node_type_form_alter(). - */ -function menu_ui_form_node_type_form_validate(&$form, FormStateInterface $form_state) { - $available_menus = array_filter($form_state->getValue('menu_options')); - // If there is at least one menu allowed, the selected item should be in - // one of them. - if (count($available_menus)) { - $menu_item_id_parts = explode(':', $form_state->getValue('menu_parent')); - if (!in_array($menu_item_id_parts[0], $available_menus)) { - form_set_error('menu_parent', $form_state, t('The selected menu item is not under one of the selected menus.')); - } - } - else { - $form_state->setValue('menu_parent', ''); - } -} - -/** - * Submit handler for forms with menu options. - * - * @see menu_ui_form_node_type_form_alter(). - */ -function menu_ui_form_node_type_form_submit(&$form, FormStateInterface $form_state) { - $type = $form_state['controller']->getEntity(); - \Drupal::config('menu.entity.node.' . $type->id()) - ->set('available_menus', array_values(array_filter($form_state->getValue('menu_options')))) - ->set('parent', $form_state->getValue('menu_parent')) - ->save(); -} - -/** * Return an associative array of the custom menus names. * * @param $all