Skip to main content

Extending the functionality of a contrib module in Drupal can enhance its usefulness without altering the original codebase. This article provides a step-by-step guide on how to add custom configuration options to an existing contrib module, using the sitewide_alert module as an example. We will extend its configuration by adding new settings through a separate custom module named sitewide_alert_ext.


  • Drupal 10 installation
  • sitewide_alert contrib module installed and enabled
  • Basic knowledge of Drupal module development



Step 1: Create Your Custom Module

First, you need to create a new custom module. In your Drupal installation, navigate to the /web/modules/custom/ directory.  Create a folder named sitewide_alert_ext.  Within this folder, create the following files:

name: 'Extended Sitewide Alert Configuration'
type: module
description: 'Extends the Sitewide Alert configuration with additional settings.'
package: Custom
core_version_requirement: ^10
 - drupal:sitewide_alert



'administer sitewide alert settings extension':
 title: 'Administer extended sitewide alert settings'


Step 2: Define the Configuration Form

Create a new PHP class to handle the form by adding a new folder called src/Form within your module directory and creating a file named ExtendedSitewideAlertConfigForm.php:


namespace Drupal\sitewide_alert_ext\Form;

use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Messenger\MessengerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

class ExtendedSitewideAlertConfigForm extends FormBase {

   * The messenger service.
   * @var \Drupal\Core\Messenger\MessengerInterface
  protected $messenger;

   * The configuration factory service, used for retrieving and storing configuration.
   * @var \Drupal\Core\Config\ConfigFactoryInterface
  protected $configFactory;

   * Constructor for the ExtendedSitewideAlertConfigForm.
   * @param \Drupal\Core\Messenger\MessengerInterface $messenger
   *   The messenger service for showing notifications.
   * @param \Drupal\Core\Config\ConfigFactoryInterface $configFactory
   *   The config factory for handling configurations.
  public function __construct(MessengerInterface $messenger, ConfigFactoryInterface $configFactory) {
    $this->messenger = $messenger;
    $this->configFactory = $configFactory;

   * {@inheritdoc}
  public static function create(ContainerInterface $container) {
    return new static(

   * {@inheritdoc}
  public function getFormId() {
    return 'sitewide_alert_ext_settings_form';

   * Builds the form for sitewide alert extension settings.
   * @param array $form
   *   An associative array containing the structure of the form.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The current state of the form.
   * @return array
   *   The form structure.
  public function buildForm(array $form, FormStateInterface $form_state) {
    $config = $this->configFactory->get('sitewide_alert_ext.settings');

    $form['max_alerts'] = [
      '#type' => 'select',
      '#title' => $this->t('Maximum number of alerts displayed'),
      '#options' => range(1, 5),
      '#default_value' => $config->get('max_alerts'),

    $form['alert_title'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Alert title'),
      '#default_value' => $config->get('alert_title'),

    $form['alert_message'] = [
      '#type' => 'textarea',
      '#title' => $this->t('Alert message when more than maximum alerts'),
      '#default_value' => $config->get('alert_message'),

    $form['alert_color'] = [
      '#type' => 'color',
      '#title' => $this->t('Alert colour'),
      '#default_value' => $config->get('alert_color'),

    // Submit button for saving the configuration.
    $form['actions']['submit'] = [
      '#type' => 'submit',
      '#value' => $this->t('Save configuration'),
      '#button_type' => 'primary',

    return $form;

   * Handles form submissions; saves the new configuration values.
   * @param array &$form
   *   The form render array.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The current state of the form.
  public function submitForm(array &$form, FormStateInterface $form_state) {
    // Save the configuration using the values provided in the form.
        ->set('max_alerts', $form_state->getValue('max_alerts'))
        ->set('alert_title', $form_state->getValue('alert_title'))
        ->set('alert_message', $form_state->getValue('alert_message'))
        ->set('alert_color', $form_state->getValue('alert_color'))

    // Inform the user that settings have been successfully saved.
    $this->messenger->addMessage($this->t('Your settings have been saved.'));


Step 3: Define Routing and Menu Links

In your module folder, create sitewide_alert_ext.routing.yml:

 path: '/admin/config/sitewide_alerts/extension'
   _form: '\Drupal\sitewide_alert_ext\Form\ExtendedSitewideAlertConfigForm'
   _title: 'Extended Sitewide Alert Settings'
   _permission: 'administer sitewide alert settings extension'
   _admin_route: TRUE


And sitewide_alert_ext.links.task.yml for the tab:

 route_name: entity.sitewide_alert.config_form.extension
 title: 'Extension'
 base_route: entity.sitewide_alert.config_form
 weight: 10


Step 4: Enable the Module and Clear Cache

Use Drush or the Drupal admin UI to enable the sitewide_alert_ext module:

drush en sitewide_alert_ext


Clear the cache to make sure your changes are applied:

drush cr


Step 5: Test the New Configuration

Navigate to the Sitewide Alert settings in the admin panel. You should see a new tab labeled "Extension" alongside the original settings tab. This new tab will contain the fields you added.



Extending a contrib module's functionality using a custom module allows you to tailor the functionality to meet specific needs without hacking the original module, facilitating easier updates and maintenance. This example demonstrates how Drupal's modular architecture encourages flexible enhancements while maintaining system integrity.

Related articles

Andrew Fletcher31 May 2024
Connecting AWS S3 with Docker for Drupal 10
Recently, I encountered an issue where my local Docker environment refused to connect to AWS S3, although everything worked seamlessly in AWS-managed environments. This challenge was not just a technical hurdle; it was a crucial bottleneck that needed resolution to ensure smooth Drupal deployments...