Overview

When working with Drupal 8, sometimes we will want to do things like extending the configuration of core or another module, extending a form provided by core or another module, and/or overriding forms on a route. At Jaypan, we recently came across a situation like this, where we needed to add a new field to the site for site description, to be used in structured data (aka RDF) for the site we were building. This needed to be a global field, so the most natural place to set the value for the field was on the basic site settings page, located at /admin/config/system/site-information.

In this tutorial, we will explain the method we used to achieve this functionality, going over the given steps, with an explanation of what is happening along the way.

Requirements and Setup

To follow along with this tutorial, you will have to know how to create a module in Drupal 8, and you will need to understand how the Form API works, as we will not be covering these topics at all. On top of this, a knowledge of routes, services, and configuration will be beneficial, though not absolutely required.

To get started on this tutorial, you will create a module with a machine name of describe_site

Steps

In order to achieve our goal of adding a field for site description to the site settings page, we need to go through the following steps:

  • Extend Drupal 8 core's system.site configuration, creating the system.site.description configuration exists
  • Extend the site settings form, adding a textarea for the site description
  • Tell the routing system to use our extended form, rather than the form provided by core

So, let's get to it!

Step 1: Extend Drupal 8 core's Extend Drupal 8 core's system.site configuration

Drupal core provides the system.site configuration with the following values:

  • uuid
  • name
  • mail
  • slogan
  • etc...

We want to add an additional item to this configuration: description. To do this, we will create the following file: describe_site/config/schema/describe_site.schema.yml, and add the following code:

# We want to extend the system.site configuration
system.site:
  mapping:
    # Our field name is 'description'
    description:
      type: string
      label: 'Site Description'

In the above code, we have mapped description, which is a string, to the system.site configuration. When Drupal compiles the configuration, it merges the original system.site configuration with the configuration provided by our module, maintaining the original configuration with the configuration we've added.

Next, we need to create a form that will allow us to set the value of the description.

Step 2: Extend the site settings form

The next step we need to take is to add a textarea to the existing site settings form. To keep our code as slim and maintainable as possible, we will use the form provided by core, by extending it to provide a new textarea into which the description will be added, and setting our description to be saved to configuration when the form is submitted.

The original form provided by core is Drupal\system\Form\SiteInformationForm. We will extend this form, overriding the buildForm() to add our textarea, and overriding the submitForm() method to save the value.

The first thing we need to do is create our form at describe_site/src/Form/DescribeSiteSiteInformationForm.php, where we will add the following class:

span class="co1">// Classes referenced in this class:
// This is the form we are extending
/**
 * Configure site information settings for this site.
 *//**
	 * {@inheritdoc}
	 */// Retrieve the system.site configuration
'system.site');
 
		// Get the original form from the class we are extending
// Add a textarea to the site information section of the form for our
		// description
'site_information']['site_description'] = [
		  '#type' => 'textarea',
		  '#title' => t('Site description'),
		  // The default value is the new value we added to our configuration
		  // in step 1
		  '#default_value''description'),
		  '#description' => $this->t('The description of the site'/**
	 * {@inheritdoc}
	 */// Now we need to save the new description to the
		// system.site.description configuration.
		$this->config('system.site')
			// The site_description is retrieved from the submitted form values
			// and saved to the 'description' element of the system.site configuration
			->set('description''site_description'))
			// Make sure to save the configuration
			->save();
 
		// Pass the remaining values off to the original form that we have extended,
		// so that they are also saved

As you can see in the above code, we've added a new textarea named site_description to the form, and we are saving that value to the configuration when it is submitted. So now the last thing we need to do is tell Drupal to use our form, instead of the original form, when accessing the site settings page.

Step 3: Tell the routing system to use our extended form

The first thing to do in determining how to override the route, is to determine exactly what route it is we need to override. In this case, the route we want to override is system.site_information_settings which can be found in the file system.routing.yml. Let's take a look at the route in question:

system.site_information_settings:
  path: '/admin/config/system/site-information'
  defaults:
    _form: 'Drupal\system\Form\SiteInformationForm'
    _title: 'Basic site settings'
  requirements:
    _permission: 'administer site configuration'

As you can see, this route loads the form we've overridden, by setting _form in the defaults for the route.

To override this, we will create a route subscriber class that extends the Drupal\Core\Routing\RouteSubscriberBase, implementing the alterRoutes() method.

To do this, we first need to create the file describe_site/src/Routing/DescribeSiteRouteSuscriber.php. In this file, we will place the following code:

span class="co1">// Classes referenced in this class
/**
 * Listens to the dynamic route events.
 *//**
	 * {@inheritdoc}
	 */// Change form for the system.site_information_settings route
		// to Drupal\describe_site\Form\DescribeSiteSiteInformationForm
		// First, we need to act only on the system.site_information_settings route.
'system.site_information_settings'))
		{
			// Next, we need to set the value for _form to the form we have created.
'_form', 'Drupal\describe_site\Form\DescribeSiteSiteInformationForm');
		}
	}
}

There is one last step that needs to happen before this route will be used. We need to tell Drupal that we have a class that we have created a route subscriber. To do this, we will create the file describe_site/describe_site.services.yml:

# 
services:
  # This is an arbitrary name, but should be made description
  describe_site.route_subscriber:
    # Tell Drupal which class to use
    class: 'Drupal\describe_site\Routing\DescribeSiteRouteSubscriber'
    # This next code is the key, as it tells Drupal to use our class when
    # building routes.
    tags:
      - { name: event_subscriber }

With this .yml file, Drupal now knows to look for our class when it is building routes. When it builds the route, it will set our form to be used instead of the default provided by core.

Summary

So there you have it. With the code in this tutorial, we've overridden the form provided by Drupal core, with our own form that extends the form provided by Drupal core, and our form ties in with our configuration value that we've added by extending Drupal core's configuration.

After enabling this module (or clearing the cache if the module was already enabled), when yougo to the system settings page, there will be a new textarea into which you can save the site description.