0

I'm working on a custom module to change the administrative menu structure. A few extra menu items are added; for some of them, I want to be able the change the name via a configuration page of the module.

This might sound like a lot of work for creating a few menu items, and it might be, but I hope it will save me some time in the future when setting up the site for my clients.

I think it is a good way to learn how to create custom modules with configuration pages (I only created modules without configuration pages) till now.

I have a custom module in the modules/custom/svds_adminmenu folder. Structure inside this folder is:

  • src
    • Form
      • ModuleConfigurationPage.php
  • svds_adminmenu.info.yml
  • svds_adminmenu.module
  • svds_adminmenu.routing.yml

This is what I have at this moment:

ModuleConfigurationPage.php

namespace Drupal\svds_adminmenu\Form;

use Drupal\Core\Form\ConfigFormBase;
use Drupal\Core\Form\FormStateInterface;

/**
 * Defines a form that configures forms module settings.
 */
class ModuleConfigurationForm extends ConfigFormBase {

    /**
     * {@inheritdoc}
     */
    public function getFormId() {
        return 'svds_adminmenu_admin_settings';
    }

    /**
     * {@inheritdoc}
     */
    protected function getEditableConfigNames() {
        return [
            'svds_adminmenu.settings',
        ];
    }

    /**
     * {@inheritdoc}
     */
    public function buildForm(array $form, FormStateInterface $form_state) {
        $config = $this->config('svds_adminmenu.settings');
        $form['link_title'] = [
            '#type' => 'textfield',
            '#title' => $this->t('Link Title'),
            '#default_value' => $config->get('link_title'),
        ];
        $form['link_path'] = [
            '#type' => 'textfield',
            '#title' => $this->t('Link Path'),
            '#default_value' => $config->get('link_path'),
        ];
        return parent::buildForm($form, $form_state);
    }

    /**
     * {@inheritdoc}
     */
    public function submitForm(array &$form, FormStateInterface $form_state) {
        $values = $form_state->getValues();
        $this->config('svds_adminmenu.settings')
            ->set('link_title', $values['link_title'])
            ->set('link_path', $values['link_path'])
            ->save();
        parent::submitForm($form, $form_state);
    }
}

svds_adminmenu.info.yml

name: Change Admin Menu
description: 'Change Admin Menu'
type: module
package: SVDS
core: 8.x
configure: svds_adminmenu.admin_settings

svds_adminmenu.module
I first created the module so it creates the menu items on install, now I want to change it to create/edit on configuration page save. So I don't want to use the hook_install anymore.

use Drupal\menu_link_content\Entity\MenuLinkContent;

function svds_adminmenu_install() /*don't want to use this hook anymore*/
{
    $menu_main = 'administration';

    $content_overview = MenuLinkContent::create([
        'title' => 'Content Overview',
        'link' => ['uri' => 'internal:/admin/content'],
        'menu_name' => $menu_main,
        'expanded' => FALSE,
        'parent' => 'system.admin_content',
        'weight' => -10,
        'id' => 1000,
    ]);

    $content_overview->save();

    $content_edit = MenuLinkContent::create([
        'title' => 'Edit Content',
        'link' => ['uri' => 'internal:/admin/content'],
        'menu_name' => $menu_main,
        'expanded' => TRUE,
        'parent' => 'system.admin_content',
        'weight' => 1,
        'id' => 1001,
    ]);

    $content_edit->save();

    $content_edit_sub = MenuLinkContent::create([
        'title' => /* CONFIG LINK TITLE HERE */,
        'link' => ['uri' => /* CONFIG LINK PATH HERE */],
        'menu_name' => $menu_main,
        'expanded' => TRUE,
        'parent' => 1002,
        'weight' => 0,
    ]);

    $content_edit_sub->save();
}


function svds_adminmenu_uninstall(){
    $menu_link = MenuLinkContent::load(1000);
    $menu_link->delete();
    $menu_link = MenuLinkContent::load(1001);
    $menu_link->delete();
    $menu_link = MenuLinkContent::load(1002);
    $menu_link->delete();
}

svds_adminmenu.routing.yml

svds_adminmenu.admin_settings:
  path: '/admin/config/svds/admin_menu'
  defaults:
    _form: '\Drupal\svds_adminmenu\Form\ModuleConfigurationForm'
    _title: 'SVDS Admin Menu Configuration'
  requirements:
    _permission: 'administer site configuration'

So I know how to programmatically create menu items, and I have a configuration page. Now I have to connect the two things together: When the configuration is changed, the module should run again to change the menu.

I found this to fetch the configuration data.

$variables['var'] = \Drupal::config('my_module.settings')->get('var');

I have to trigger my action via some kind of hook, and I don't know which one. It should only trigger once after the configuration is changed, not on a preprocess function, or something similar.

So how can I do this?

  • You don't need a hook, that code would usually go in your config form's submit method. Could you update the question with a bit more info about what you mean by "change the menu"? What do you need to happen precisely? Creating/editing a menu item is easy, but it's not clear if that's all you need to know, or what your config form should contain – Clive Jul 5 '18 at 18:45
  • I changed my question, added extra code to give a better idea of what I want. – Joost Jul 5 '18 at 21:25
0

So as Clive said I don't need a hook and .module file to do this. This is what I did.

I copied the code from my .module file to the ModuleConfigurationPage.php and put it inside the submitForm function:

public function submitForm(array &$form, FormStateInterface $form_state) {
    $menu_main = 'administration';
    //catch values from the form
    $linkTitle = ($form['settings']['main']['link_title']['#value']);
    $linkPath = ($form['settings']['main']['link_path']['#value']);

    //delete dynamically created menu items
    for($i = 1000; $i <= 1002; $i++){
        $menu_link = MenuLinkContent::load($i);
        if($menu_link) {
            $menu_link->delete();
        }
    }

    //create content overview link in content dropdown
    $content_overview = MenuLinkContent::create([
        'title' => 'Content Overview',
        'link' => ['uri' => 'internal:/admin/content'],
        'menu_name' => $menu_main,
        'expanded' => FALSE,
        'parent' => 'system.admin_content',
        'weight' => -10,
        'id' => 1000,
    ]);

    $content_overview->save();

    //create content edit content link in content dropdown
    $content_edit = MenuLinkContent::create([
        'title' => 'Edit Content',
        'link' => ['uri' => 'internal:/admin/content'],
        'menu_name' => $menu_main,
        'expanded' => TRUE,
        'parent' => 'system.admin_content',
        'weight' => 1,
        'id' => 1001,
    ]);

    $content_edit->save();

    //create menu item with config settings
    $content_edit_sub = MenuLinkContent::create([
        'title' => $linkTitle,
            'link' => ['uri' => 'internal:'.$linkPath],
            'menu_name' => $menu_main,
            'expanded' => TRUE,
            'parent' => 1002,
            'weight' => 0,
     ]);

    $content_edit_sub->save();

    //set new config values
    $this->config('svds_adminmenu.settings')
        ->set('link_title', $linkTitle)
        ->set('link_path', $linkPath)
        ->save();

    //refresh menu cache to see changes
    $renderCache = \Drupal::service('cache.menu');
    $renderCache->invalidateAll();

    //submit form
    parent::submitForm($form, $form_state);
}

This way the menu gets updated each time you click the submit button.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.