Another method which can be used to alter any block without additional #pre_render callback. Note that custom callback function is called after the system Drupal\block\BlockViewBuilder::preRender() and may be not rendered properly. For example, if you add content to an empty block using the method from the above comment then the title of the block will be lost.
Go to the src folder in your module and create OverrideAnyBlockContent.php file with the following content:
<?php
namespace Drupal\YOUR_MODULE;
/**
* Helper class to override any block content in a HOOK_block_view_alter().
*/
class OverrideAnyBlockContent {
/**
* The render array.
*
* @var array
* @see https://www.drupal.org/docs/8/api/render-api/render-arrays
*/
protected $renderArray;
public function __construct(array $render_array) {
$this->renderArray = $render_array;
}
public function getPlugin() {
return $this;
}
public function build() {
return $this->renderArray;
}
}
Then in YOUR_MODULE.module file:
function YOUR_MODULE_block_view_alter(array &$build, Drupal\Core\Block\BlockPluginInterface $block) {
if ($block->getBaseId() === 'system_powered_by_block') {
// @see https://www.drupal.org/docs/8/api/render-api/render-arrays
$render_array = [
'#type' => 'markup',
'#markup' => "Any text, HTML, {$php_variable}, whatever, ....",
];
// Uncomment the line below if you need to merge new render array with the
// original one.
// $render_array += $build['#block']->getPlugin()->build();
// Now block will be pre-rendered using new render array. No additional
// '#pre_render' callback is required.
// @see Drupal\block\BlockViewBuilder::preRender()
$build['#block'] = new Drupal\YOUR_MODULE\OverrideAnyBlockContent($render_array);
}
}
Taken from examples module issue: https://www.drupal.org/node/2893964