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

Comments

maskedjellybean created an issue. See original summary.

maskedjellybean’s picture

StatusFileSize
new615 bytes
maskedjellybean’s picture

Status: Active » Needs review
codersrini’s picture

Thanks a lot for the patch. This helped and was able to override

pearl.liang’s picture

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;