0

Please advice how we can extend the core block class Drupal\system\Plugin\Block\SystemBrandingBlock to add custom method.

In my case, I want to include function buildToArray() to get the block data in array format rather than rendered array.

Existing build() method:

public function build() { $build = []; $site_config = $this->configFactory->get('system.site'); $build['site_logo'] = [ '#theme' => 'image', '#uri' => theme_get_setting('logo.url'), '#alt' => $this->t('Home'), '#access' => $this->configuration['use_site_logo'], ]; $build['site_name'] = [ '#markup' => $site_config->get('name'), '#access' => $this->configuration['use_site_name'], ]; $build['site_slogan'] = [ '#markup' => $site_config->get('slogan'), '#access' => $this->configuration['use_site_slogan'], ]; return $build; } 

Required method to add:

public function buildToArray() { $site_config = $this->configFactory->get('system.site'); return [ 'site_logo' => theme_get_setting('logo.url'), 'site_name' => $site_config->get('name'), 'site_slogan' => $this->configuration['use_site_slogan'], ]; } 
2
  • 1
    Hello, and welcome to Drupal Answers! Could you please describe what you've tried, what hasn't worked, and post any relevant code? Commented Jan 28, 2022 at 18:28
  • @Beau Thank you for your comment. I have updated the question to more specific. Commented Jan 29, 2022 at 5:25

2 Answers 2

0

If you are using Drupal 9 and don't want to create a block duplication here is the simplest way to override a block class: To override Block class you can use hook_block_alter like this.

/** * Implements hook_block_alter(). */ function [MODULE]_block_alter(&$definitions) { foreach ($definitions as $id => $definition) { // Check on your plugin Id here. if ($id === 'system_branding_block') { // Set your new class here. $definitions[$id]['class'] = 'Drupal\MODULE\Plugin\Block\SystemBrandingBlockAlter'; } } } 

And then create your new class SystemBrandingBlockAlter in MODULE/src/Plugin/Block like this:

<?php namespace Drupal\MODULE\Plugin\Block; use Drupal\system\Plugin\Block\SystemBrandingBlock; class SystemBrandingBlockAlter extends SystemBrandingBlock { public function build() { $site_config = $this->configFactory->get('system.site'); return [ 'site_logo' => theme_get_setting('logo.url'), 'site_name' => $site_config->get('name'), 'site_slogan' => $this->configuration['use_site_slogan'], ]; } } 

Now the responsible class for your block is Drupal\MODULE\Plugin\Block\SystemBrandingBlockAlter and not Drupal\system\Plugin\Block\SystemBrandingBlock

3
  • Thank you so much. This is exactly what I'm looking for. Commented Feb 4, 2022 at 13:14
  • In definitions array, we can see 'provider' => 'system' but we'll override the block class from our custom module. Will it make any impact? Commented Feb 4, 2022 at 13:17
  • if you check of 'provider' == 'system' you will override all classes of blocks created by system module not only SystemBrandingBlock Commented Feb 5, 2022 at 0:08
0

Extending a Block

To extend the block, you'll define a new block, as described in the following tutorial, except that you would extend the class Drupal\system\Plugin\Block\SystemBrandingBlock, instead of the class Drupal\Core\Block\BlockBase. You can then add your custom method to the newly defined block.

https://www.valuebound.com/resources/blog/drupal-8-how-to-create-a-custom-block-programatically

Alternative consideration

If what you need from SystemBrandingBlock is just the data, and not necessarily an actual block, I would advise to instead define a service that provides the data from your buildToArray() method.

Comment Responses

It is true that this will create a new block type, in addition to the SystemBrandingBlock. Blocks are managed, organized and retrieved by the Block Plugin Manager. You could write a decorator for this service and override the getDefinitions() method in order to prevent the original SystemBrandingBlock from being available as a plugin definition, achieving the effect of replacing the original SystemBrandingBlock with your new block.

It still sounds to me like a service is what you need. By examining the code in the original SystemBrandingBlock class definition, we see that SystemBrandingBlock only relies on one service, config.factory. So your service only needs to inject the config.factory service in order to retrieve the information that you need for the buildToArray() method (which might be better renamed as something like getBrandingInfo()). Defining a service in this way means that you won't need to worry about implementing or deploying a block (which doesn't seem to be what you need, anyway), or needing to write a service decorator.

Bear in mind, also, that the SystemBrandingBlock is not the original source of the data, but rather a plugin for displaying those data in a rendered format. The block is completely irrelevant if all you want are the data.

Finally, speaking in broader terms, Drupal is organized largely around plugins, services and dependency injection, and becoming familiar with these concepts will give you the tools to systematically solve many problems in Drupal.

6
  • Thank you for your suggestions. Commented Jan 31, 2022 at 9:39
  • I want to extend all available blocks. The first approach "Extending a block" leads to blocks duplication. The second approach "From service" I could not access the protected properties of the block so I have to implement that block logic in the service. Commented Feb 2, 2022 at 7:26
  • you answer gave me another perspective. Thanks Commented Feb 4, 2022 at 13:13
  • As far as I understand, we can override the blocks by hook_block_alter and plugin decorator. I'm clear about the hook. Can you please give an example about plugin decorator for the block. It will help for many since there is no proper documentation about plugin decorator. Commented Feb 4, 2022 at 13:31
  • In Drupal, all plugin types are managed by a plugin manager, which is a service. A plugin decorator is really a service decorator for a plugin manager. Here is a great tutorial on Drupal 8 service decorators: phase2technology.com/blog/…. In your case, you'll want to decorate the service whose ID is plugin.manager.block. But I still feel that a custom service of your own is what you really need, and will require less work. Commented Feb 4, 2022 at 13:56

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.