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