alengo/block-settings-bundle
Replaces per-section Sulu form metadata visitors with a single config-driven visitor that injects multiple block settings sections in order, cutting boilerplate service classes and registrations down to one YAML list.
Check platform requirements before requiring: 1.1.0 targets Symfony 8, which means PHP 8.4+. If you're still on Symfony 6.4/7.x or PHP 8.2/8.3, pin the previous line instead:
# Symfony 8 / PHP 8.4+
composer require alengo/block-settings-bundle:^1.1
# Older Symfony (stay on the 1.0 line)
composer require alengo/block-settings-bundle:^1.0
Install the package:
composer require alengo/block-settings-bundle
Enable the bundle in config/bundles.php:
Alengo\SuluBlockSettingsBundle\BlockSettingsBundle::class => ['all' => true],
Configure sections in config/packages/alengo_block_settings.yaml:
alengo_block_settings:
sections:
- content_block_settings_theme
- content_block_settings_spacing
Create XML forms for each section (e.g., config/forms/content_block_settings_theme.xml):
<form xmlns="...">
<key>content_block_settings_theme</key>
<properties>
<section name="theme">
<property name="template_theme" type="select">
<!-- Define options -->
</property>
</section>
</properties>
</form>
Extend a block's settings with a theme selector and spacing controls without writing custom FormMetadataVisitor classes. The bundle injects these sections into the content_block_settings form automatically.
Note for Laravel developers: this is a Sulu/Symfony bundle, not a Laravel package. There is no service provider or
config/*.phppublishing — configuration is YAML, the container is Symfony's, and the extension point is Sulu'sFormMetadataVisitorchain.
Define the XML form (e.g., content_block_settings_background.xml) with properties like:
<property name="background_color" type="color" />
<property name="background_image" type="media" />
Add the section key to alengo_block_settings.yaml:
alengo_block_settings:
sections:
- content_block_settings_theme
- content_block_settings_background # New section
Clear cache to apply changes:
php bin/console cache:clear
Dynamic block types: Use the bundle to inject settings for custom block types (e.g., custom_block_settings).
alengo_block_settings:
form_key: custom_block_settings
sections:
- custom_block_settings_layout
Conditional injection: Leverage Sulu’s FormMetadataVisitor priority to override or extend existing settings.
symfony/*: ^8.0 will make composer update unresolvable against a Sulu that still caps at 7.x.composer require symfony/framework-bundle:^8.0 --with-all-dependencies), then the bundle, then run cache:clear. Doing it in the reverse order usually dead-ends Composer.var/log/dev.log.alengo_block_settings.yaml and section forms carry over unchanged.sections. Reorder for UI consistency.Form Key Mismatch:
form_key in config doesn’t match the target form (e.g., content_block_settings), sections won’t inject.XmlFormMetadataLoader matches the bundle’s config.Duplicate Sections:
sections, the first occurrence is used.var_dump($form->getKey()) in a custom visitor.Cache Dependencies:
php bin/console cache:clear
Symfony 8 requirement drift (new in 1.1.0):
symfony/*: ^7.0 will fail at composer install, not at runtime — so the failure shows up in pipeline setup, not in tests.config.platform.php in composer.json (or the CI image) alongside the constraint, and add a composer why-not symfony/framework-bundle 8.0 check when resolution fails to see which package is holding you back.Mixed-version bundles: if other Alengo/Sulu add-ons still declare symfony/*: ^6.4|^7.0, you cannot adopt 1.1.0 piecemeal. Either upgrade the whole set or keep the app on the 1.0 line until they catch up.
Inspect injected forms: Override the visitor temporarily to log form structure:
// src/Admin/FormMetadataVisitor/CustomVisitor.php
public function visitFormMetadata(FormMetadata $formMetadata, FormMetadataVisitorContext $context) {
if ($formMetadata->getKey() === 'content_block_settings') {
var_dump($formMetadata->getProperties());
}
}
Check XML validation: Invalid XML (e.g., missing key or section tags) will cause silent failures. Validate with:
php bin/console debug:container Alengo\SuluBlockSettingsBundle\BlockSettingsFormMetadataVisitor
Verify the resolved versions after the upgrade:
composer show alengo/block-settings-bundle
composer show symfony/framework-bundle
php bin/console about
If the bundle reports 1.1.0 but symfony/framework-bundle is still 7.x, the resolution came from a --ignore-platform-reqs or a stale lock file — delete composer.lock and re-resolve.
Custom Visitor Logic: Override the visitor to add dynamic behavior (e.g., skip sections based on block type):
# config/services.yaml
App\Admin\FormMetadataVisitor\CustomBlockSettingsVisitor:
tags:
- { name: sulu_admin.form_metadata_visitor, priority: -5 }
Dynamic Section Loading:
Load sections from a database or API by extending BlockSettingsFormMetadataVisitor:
public function visitFormMetadata(FormMetadata $formMetadata, FormMetadataVisitorContext $context) {
if ($formMetadata->getKey() === $this->formKey) {
$dynamicSections = $this->sectionLoader->loadDynamicSections();
foreach ($dynamicSections as $section) {
$this->loadSection($section, $formMetadata);
}
}
}
Form Metadata Hooks:
Use Symfony’s kernel.event_listener to modify forms before injection:
services:
App\EventListener\BlockSettingsFormListener:
tags:
- { name: kernel.event_listener, event: sulu_admin.form_metadata_loaded, method: onFormLoaded }
Symfony 8 event/listener signatures:
Subclassing the bundle visitor is supported, but Symfony 8 tightened several method signatures across the framework. If you overrode a parent method with a looser signature, you'll now get a fatal Declaration must be compatible error at container compile time — re-check your custom visitors' visitFormMetadata() signature against the bundle's class.
How can I help you explore Laravel packages today?