Allow overriding site header dropdown links

Created on 29 September 2021, over 3 years ago
Updated 4 January 2025, 20 days ago

Problem/Motivation

The construction of the dropdown links on the right side of the site header now occurs within \Drupal\opigno_dashboard\Plugin\Block\SiteHeaderBlock::buildUserDropdownMenu instead of within a template. This makes the links harder to override, and actually it is impossible with the current code because \Drupal\opigno_dashboard\Plugin\Block\SiteHeaderBlock::buildUserDropdownMenu is private instead of protected.

Steps to reproduce

Here is how I went about attempting to override the links:

Within foo.theme:

/**
 * Implements hook_preprocess_page().
 *
 * Preprocesses page.html.twig.
 */
function foo_preprocess_page(&$variables) {
  $block_manager = \Drupal::service('plugin.manager.block');
  if ($block_manager instanceof BlockManagerInterface) {
    $header = $block_manager->createInstance('foo_opigno_site_header_block');
    $variables['header'] = $header instanceof SiteHeaderBlock ? $header->build() : NULL;
  }
}

Within /web/modules/custom/foo/src/Plugin/Block/SiteHeaderBlock.php:

namespace Drupal\foo_opigno\Plugin\Block;

use Drupal\opigno_dashboard\Plugin\Block\SiteHeaderBlock as BaseSiteHeaderBlock;
use Drupal\Core\Link;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\Core\Url;
use Drupal\user\UserInterface;

/**
 * The site header block.
 * Extends the default Opigno site header block from opigno_dashboard module
 * so that we can customize it for Foo.
 *
 * @Block(
 *  id = "foo_opigno_site_header_block",
 *  admin_label = @Translation("Foo Opigno Site header block"),
 *  category = @Translation("Opigno"),
 * )
 *
 * @package Drupal\opigno_dashboard\Plugin\Block
 */
class SiteHeaderBlock extends BaseSiteHeaderBlock {

  /**
   * Prepare the user dropdown menu.
   * Customized to add invitations link and remove unnecessary links.
   *
   * @param \Drupal\Core\StringTranslation\TranslatableMarkup $role
   *   The user role.
   *
   * @return array
   *   The array to build the user dropdown menu.
   */
  protected function buildUserDropdownMenu(TranslatableMarkup $role): array {
    if (!$this->user instanceof UserInterface) {
      return [];
    }

    return [
      'name' => Link::createFromRoute($this->user->getDisplayName(), 'entity.user.canonical', ['user' => (int) $this->user->id()]),
      'role' => $role,
      'is_admin' => $this->user->hasPermission('access administration pages'),
      'links' => [
//        'help' => [
//          'title' => $this->t('Help'),
//          'path' => 'https://www.opigno.org',
//          'external' => TRUE,
//          'icon_class' => 'fi-rr-interrogation',
//        ],
//        'review' => [
//          'title' => $this->t('Review Opigno'),
//          'path' => 'https://reviews.capterra.com/new/135113?utm_source=vp&utm_medium=none&utm_term=&utm_content=&utm_campaign=vendor_request',
//          'external' => TRUE,
//          'icon_class' => 'fi-rr-comment',
//        ],
        'logout' => [
          'title' => $this->t('Logout'),
          'path' => Url::fromRoute('user.logout')->toString(),
          'icon_class' => 'fi-rr-sign-out',
        ],
      ],
    ];
  }
}

I then clear caches. If the method from my child class is private, the method from the parent class is still used (which is of course not what I want). If the method from my child class is public or protected I get a PHP error like:

PHP Fatal error:  Access level to Drupal\foo_opigno\Plugin\Block\SiteHeaderBlock::buildUserDropdownMenu() must be protected (as in class Drupal\opigno_dashboard\Plugin\Block\SiteHeaderBlock) or weaker in /app/web/modules/custom/foo_opigno/src/Plugin/Block/SiteHeaderBlock.php on line 52

Proposed resolution

If I change \Drupal\opigno_dashboard\Plugin\Block\SiteHeaderBlock::buildUserDropdownMenu to protected and also change my child class to protected all works as intended. I'm able to override the links as needed within my child class. In the case of my example above, only the Logout link appears.

I'm going to attach a patch to this because I have a feeling I won't be the only one who wants to customize these links for their needs.

Remaining tasks

User interface changes

API changes

Data model changes

✨ Feature request
Status

Needs review

Version

3.0

Component

Code

Created by

πŸ‡ΊπŸ‡ΈUnited States maskedjellybean Portland, OR

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • πŸ‡ΊπŸ‡ΈUnited States pearl.liang

    Hi maskedjellybean

    Thank you for your solution. It also works for me, but I have to make some adjustment to make it work. I am using Opigno 3.2.7. I am sharing my adjustment to anyone else who may encounter the same issue to save their time as you have saved my time.

    First, for what you wrote below,

    Within /web/modules/custom/foo/src/Plugin/Block/SiteHeaderBlock.php:
    namespace Drupal\foo_opigno\Plugin\Block;

    foo in the file path should be corrected to be foo_opigno

    Second, within foo.theme
    I had to add these two lines above your codes to make it work:

    use Drupal\Core\Block\BlockManagerInterface;
    use Drupal\cloud_module\Plugin\Block\SiteHeaderBlock;

Production build 0.71.5 2024