diff --git a/core/lib/Drupal/Core/Field/TypedData/FieldItemDataDefinition.php b/core/lib/Drupal/Core/Field/TypedData/FieldItemDataDefinition.php index c18e987..bd717c9 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/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..6a1bd20 --- /dev/null +++ b/core/modules/menu_link/src/Plugin/Field/FieldType/MenuLinkItem.php @@ -0,0 +1,172 @@ +menuPluginManager = \Drupal::service('plugin.manager.menu.link'); + } + + /** + * {@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(); + } + + /** + * @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..53ba81d --- /dev/null +++ b/core/modules/menu_link/src/Plugin/Field/FieldWidget/MenuLinkWidget.php @@ -0,0 +1,110 @@ +menuParentSelector = $menu_parent_selector; + } + + /** + * {@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') + ); + } + + /** + * {@inheritdoc} + */ + public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) { + $element['title'] = array( + '#type' => 'textfield', + '#title' => t('Menu link title'), + '#default_value' => isset($items[$delta]->title) ? $items[$delta]->title : NULL, + ); + + $element['description'] = array( + '#type' => 'textarea', + '#title' => t('Description'), + '#default_value' => isset($items[$delta]->description) ? $items[$delta]->description: NULL, + '#rows' => 1, + '#description' => t('Shown when hovering over the menu link.'), + ); + + $menu = isset($items[$delta]->menu) ? $items[$delta]->menu : 'tools'; + $parent = isset($items[$delta]->parent) ? $items[$delta]->parent : ""; + $parent_element = $this->menuParentSelector->parentSelectElement("$menu:$parent"); + + $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' => isset($items[$delta]->weight) ? $items[$delta]->weight: 0, + '#description' => t('Menu links with lower weights are displayed before links with higher weights.'), + ); + + 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..3cde2d4 --- /dev/null +++ b/core/modules/menu_link/src/Plugin/Menu/Form/MenuLinkFieldForm.php @@ -0,0 +1,28 @@ + 'item', + '#title' => $this->t('This link is provided by the %type with ID @id. The path cannot be edited.', array('@name' => $this->getModuleName($provider))), + ); + } + +} + 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..e9e35a2 --- /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. + */ + protected 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; + } + +}