If you're using the SonataPage bundle, you may have noticed that
some of the blocks offered are unnecessary or
non-functional.
We'll discuss how to hide these blocks from
the list cleanly, with a configuration file, and by overriding the
admin templates of SonataPage.
1 – The Configuration
We need to create a list of services that we don't want to display. This list will naturally go into the parameters of our services file:
#config/services.yaml
parameters:
sonata_page_excluded_blocks:
- 'sonata.media.block.gallery_list'
- 'sonata.media.block.feature_media'
- 'sonata.media.block.gallery'
To find out the name of the service to exclude, it's quite simple, it's in the URL when you click on it in the shared blocks creation view.
2 – Twig function to Retrieve Our Parameter
To hide the blocks, we're going to override SonataPage's templates. So we need to retrieve our configuration directly in our template. Therefore, we're going to create a Twig extension for our project. It's quite common, you probably already have one.
#src/Twig/Extension/AppExtension.php
<?php
namespace App\Twig;
use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;
class AppExtension extends AbstractExtension
{
private $sonata_page_excluded_blocks;
public function __construct(array $sonata_page_excluded_blocks)
{
$this->sonata_page_excluded_blocks = $sonata_page_excluded_blocks;
}
public function getFunctions(): array
{
return [
new TwigFunction('sonata_page_excluded_blocks', [$this, 'getSonataPageExcludedBlocks']),
];
}
public function getSonataPageExcludedBlocks(): array
{
return $this->sonata_page_excluded_blocks;
}
}
Then we need to reference it in the services.
services:
App\Twig\AppExtension:
arguments:
$sonata_page_excluded_blocks: '%sonata_page_excluded_blocks%'
3 – Overriding Templates
As you know, all templates can be overridden. Just locate the
template within your bundle. Generally, you just need to check the
list of Twig templates in the profiler. It's very often the first
one.

We see that our template is stored
in:
vendor/sonata-project/page-bundle/src/Resources/views/BlockAdmin/select_type.html.twig
To
override it, just put it in our template directory with the
path:
templates/bundles/NomDuBundle/FolderAfterViews/…/YourFile.html.twig
Which
gives
us:
templates/bundles/SonataPageBundle/BlockAdmin/select_type.html.twig
Once the file is copied, if we reload the page, we should find
the correct file in the list of templates on our Twig tab of the
profiler.

4 – Overriding the Block List in Our Template
We just have to retrieve our list of configured blocks from our parameters and recreate the variable used to create the array, without our blocks to exclude.
{% set excluded_blocks = sonata_page_excluded_blocks() %}
{% set filteredBlockServices = [] %}
{% for key, service in blockServices %}
{% if key not in excluded_blocks %}
{% set filteredBlockServices = filteredBlockServices|merge({(key): service}) %}
{% endif %}
{% endfor %}
{% set blockServices = filteredBlockServices %}
This gives us:
{#
templates/bundles/_SonataPageBundle/BlockAdmin/select_type.html.twig
#}
{% extends '@SonataAdmin/CRUD/action.html.twig' %}
{% block title %}{{ 'title_select_block_type'|trans({}, 'SonataPageBundle') }}{% endblock %}
{% block content %}
<div class="box box-success">
<div class="box-header">
<h3 class="box-title">
{{ 'title_select_block_type'|trans({}, 'SonataPageBundle') }}
</h3>
</div>
{# surcharge pour exclude des blocs #}
{% set excluded_blocks = sonata_page_excluded_blocks() %}
{% set filteredBlockServices = [] %}
{% for key, service in blockServices %}
{% if key not in excluded_blocks %}
{% set filteredBlockServices = filteredBlockServices|merge({(key): service}) %}
{% endif %}
{% endfor %}
{% set blockServices = filteredBlockServices %}
{# fin de surcharge pour exclude des blocs #}
<div class="box-body">
{% for code, blockService in blockServices %}
<div class="col-lg-2 col-md-3 col-sm-4 col-xs-6">
<a href="{{ admin.generateUrl('create', {'type': code}) }}"
class="btn btn-app btn-block sonata-block-type"
data-toggle="tooltip"
data-placement="top"
{% if blockService.metadata.description %}
title="{{ blockService.metadata.description|trans({}, blockService.metadata.domain|default('SonataBlockBundle')) }}"
{% endif %}
>
{% if not blockService.metadata.image %}
<i class="{{ blockService.metadata.option('class') }}" ></i>
{% else %}
<img src="{{ asset(blockService.metadata.image) }}" style="max-height: 20px; max-width: 100px;"/>
<br />
{% endif %}
<span>{{ blockService.metadata.title|trans({}, blockService.metadata.domain|default('SonataBlockBundle')) }}</span>
</a>
</div>
{% else %}
<span class="alert alert-info">{{ 'no_type_available'|trans({}, 'SonataPageBundle') }}</span>
{% endfor %}
<div class="clearfix"></div>
</div>
</div>
{% endblock %}
And if we reload the page, we should have the list, cleansed of our
blocks.

Instead of

6 – Overriding the Block List in the Page Composer
For the page composer, it's exactly the same manipulation. The file
to override
is:
vendor/sonata-project/page-bundle/src/Resources/views/PageAdmin/compose_container_show.html.twig
This
gives
us:
/templates/bundles/SonataPageBundle/PageAdmin/compose_container_show.html.twig
We
put exactly the same code, which gives us a complete file
following:
{#
/templates/bundles/SonataPageBundle/PageAdmin/compose_container_show.html.twig
#}
<div class="page-composer__container__view block-view-{{ container.id }}"
data-block-id="{{ container.id }}"
>
<h2 class="page-composer__container__view__header">{{ container.name }}</h2>
<span class="page-composer__container__view__notice">{{ 'notice'|trans({}, 'SonataPageBundle') }}</span>
{# surcharge pour exclude des blocs #}
{% set excluded_blocks = sonata_page_excluded_blocks() %}
{% set filteredBlockServices = [] %}
{% for key, service in blockServices %}
{% if key not in excluded_blocks %}
{% set filteredBlockServices = filteredBlockServices|merge({(key): service}) %}
{% endif %}
{% endfor %}
{% set blockServices = filteredBlockServices %}
{# fin de surcharge pour exclude des blocs #}
<div class="page-composer__block-type-selector">
<label>{{ 'composer.block.add.type'|trans({}, 'SonataPageBundle') }}</label>
<select class="page-composer__block-type-selector__select" style="width: auto">
{% for blockServiceId, blockService in blockServices %}
<option value="{{ blockServiceId }}">{{ blockService.metadata.title|trans({}, blockService.metadata.domain|default('SonataBlockBundle')) }}</option>
{% endfor %}
</select>
<a class="btn btn-action btn-small page-composer__block-type-selector__confirm"
href="{{ admin.generateObjectUrl('sonata.page.admin.block.create', page, {'composer': true}) }}"
><i class="fa fa-plus"></i></a>
<span class="page-composer__block-type-selector__loader">{{ 'loading'|trans({}, 'SonataPageBundle') }}</span>
<small class="page-composer__container__child-count pull-right">
{{ 'blocks'|trans({}, 'SonataPageBundle') }} <span class="badge">{{ container.children|length }}</span>
</small>
</div>
<ul class="page-composer__container__children">
{% for child in container.children %}
{% include '@SonataPage/BlockAdmin/compose_preview.html.twig' with {
'blockService': attribute(blockServices, child.type) ?? null
} %}
{% endfor %}
</ul>
</div>
