0

I'm creating a menu programatically using this code

$this->menu = $this->entityTypeManager->getStorage('menu')->create(
    [
      'id' => $properties['id'],
      'label' => $properties['label'],
      'langcode' => $properties['language'],
      'status' => TRUE,
    ]
  );
  // Save the menu.
  $this->menu->save();

When visiting the block ui I see the block is already created. It appears that I do not have responsibility for creating this block, although I don't seem to be able to load the block straight after creation of the menu. I need to place this block in a specific region programatically. What would be the preferred method of doing this be?

4
  • 1
    Yes, for each menu you get a block plugin derivative system_menu_block:[menu_id]. Using this as block plugin id you can place it programmatically, see drupal.stackexchange.com/questions/197013/…
    – 4uk4
    Jun 26, 2020 at 9:45
  • Thanks @4k4 for your prompt reply. It didn't really answer my question unfortunately. I've answered it myself below.
    – A Averill
    Jun 30, 2020 at 8:28
  • +1 for posting the final solution. But how is your approach different from the one I've linked in combination with the plugin id? Other than that you've added additional block settings?
    – 4uk4
    Jun 30, 2020 at 8:51
  • @4k4 In essence it is the same. The point of posting it was that a menu block is created automatically if its not already been created programatically when you visit the block layout page. This I found confusing initially and it was only through experimentation I found I could override that process.
    – A Averill
    Sep 17, 2020 at 11:55

1 Answer 1

1

After an intensive debug session I discovered the block is actually created when you place blocks and select the menu you have just created through the Block UI. That didn't fit with my requirements to place the block programatically so I took a look at the structure of an existing menu block and replicated that.

$this->block = $this->entityTypeManager->getStorage('block')->create(
    [
      'id' => $this->getBid($form_state->getValue('language')),
      'region' => 'header',
      'plugin' => 'system_menu_block:' . $this->menu->id(),
      'settings' => [
        'id' => 'system_menu_block:' . $this->menu->id(),
        'label' => $this->menu->label(),
        'provider' => 'system',
        'level' => 1,
        'depth' => 0,
        'expand_all_items' => FALSE,
      ],
      'theme' => 'mytheme_base_theme',
      'visibility' => [
        'language' => [
          'id' => 'language',
          'langcodes' => [
            $form_state->getValue('language') => $form_state->getValue('language'),
          ],
          'negate' => FALSE,
          'context_mapping' => [
            'language' => '@language.current_language_context:language_interface',
          ],
        ],
      ],
      'weight' => 100,
    ]
  );
  // Save the block.
  $this->block->save();

This achieved the result I was looking for. So far so good. I can now create menus and place them immediately after the menu is created.

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.