# FusionAuth QuickStart for Drupal QuickStart integration of Drupal web application with FusionAuth. > For the index of this section of the site, see [llms.txt](https://4002.18-224-161-104.sslip.io/docs/llms.txt) ![Drupal](https://4002.18-224-161-104.sslip.io/img/icons/drupal.svg) In this QuickStart, you are going to build an application with Drupal and integrate it with FusionAuth. You'll be building it for [ChangeBank](https://www.youtube.com/watch?v=CXDxNCzUspM), a global leader in converting dollars into coins. It'll have areas reserved for users who have logged in as well as public facing sections. The Docker Compose file and source code for a complete application are available at [https://github.com/FusionAuth/fusionauth-quickstart-php-drupal-web](https://github.com/FusionAuth/fusionauth-quickstart-php-drupal-web). ## Prerequisites * [PHP](https://www.php.net/downloads.php) 8.1.0+ * [Composer](https://getcomposer.org/) * [GD extension](https://www.php.net/manual/en/book.image.php) * [Docker](https://www.docker.com): The quickest way to stand up FusionAuth. (There are [other ways](https://4002.18-224-161-104.sslip.io/docs/get-started/download-and-install.md).) Note This app has been tested with Drupal 10.1.5. This example should work with other compatible versions of Drupal 10. Drupal 10 requires PHP 8.1.0+ and MariaDB 10.3.7+, MySQL 5.7.8+, or Percona 5.7.8+. ## General Architecture Here's a typical application login flow before FusionAuth: ```mermaid sequenceDiagram participant User participant App as Application User ->> App : View Homepage User ->> App : Click Login Link App ->> User : Show Login Form User ->> App : Fill Out and Submit Login Form App ->> App : Authenticates User App ->> User : Display User's Account or Other Info ``` Request flow during login before FusionAuth And here's the same application login flow after introducing FusionAuth: ```mermaid sequenceDiagram participant User participant App as Application participant FusionAuth User ->> App : View Homepage User ->> App : Click Login Link (to FusionAuth) User ->> FusionAuth : View Login Form FusionAuth ->> User : Show Login Form User ->> FusionAuth : Fill Out and Submit Login Form FusionAuth ->> FusionAuth : Authenticates User FusionAuth ->> User: Go to Redirect URI User ->> App: Request the Redirect URI App ->> FusionAuth : Is User Authenticated? FusionAuth ->> App : User is Authenticated App ->> User : Display User's Account or Other Info ``` Request flow during login after FusionAuth In general, you are introducing FusionAuth in order to normalize and consolidate user data. This helps make sure it is consistent and up-to-date as well as offloading your login security and functionality to FusionAuth. ## Getting Started In this section, you'll get FusionAuth up and running on your machine and create a Drupal application. ### Clone The Code First off, grab the code from the repository and change into that directory. ```shell-session $ git clone https://github.com/FusionAuth/fusionauth-quickstart-php-drupal-web.git ``` ```shell-session $ cd fusionauth-quickstart-php-drupal-web ``` ### Create Your Drupal Application The `complete-application` directory in the repository already contains a complete Drupal application but for demonstration purposes, this tutorial shows how to create a new application from scratch and then switch the volumes in the `docker-compose.yml` file to point to the new application. Start by creating a new Drupal 10 project and changing to the project directory with the following command. ```shell-session $ composer create-project drupal/recommended-project:10.1.5 "your-application" && cd your-application ``` Next, make two changes in the `docker-compose.yml` file to allow you to use your new Drupal application. Note If you want to use the existing application at any point, revert the following two changes and then rebuild the Docker containers and volumes. On the `web` service, change `volumes` from `./complete-application:/opt/drupal:cached` to `./your-application:/opt/drupal:cached`. Under the `db2` service, change the key `MYSQL_DATABASE` from `drupaldb` to `changebank`. This updates the database name so that you are not using the same database as the existing complete application. Save your changes and then run the following command to get the application up and running. ```shell-session $ docker compose up -d ``` Once the application is up and running, navigate to [http://localhost/](http://localhost/) and you should be redirected to the Drupal installation wizard at [http://localhost/core/install.php](http://localhost/core/install.php). Run through the wizard and fill in all required fields. Make sure to enter the following. On Step 1 , choose your language and click Save and continue . On Step 2 , choose `Standard` profile and click Save and continue . On Step 4 , enter the following database connection details. * **Database type**: Pick the `MySQL, MariaDB, Percona Server, or equivalent` option. * **Database name**: `changebank`. * **Database username**: `drupal`. * **Database password**: `verybadpassword`. * Expand Advanced options. * Set **Host** to `db2`. * Set the **port number** to `3307`. Click Save and continue . On Step 6 , enter the following values. * **Site name**: `Change Bank`. * **Site email address**: `admin@example.com`. * **Username**: `admin`. * **Password**: `verybadpassword`. * **Confirm password**: `verybadpassword`. * **Email address**: `admin@example.com`. Click Save and continue . Once you've completed the installation wizard, you should be taken to the welcome page. Now you can install OpenID Connect to handle authenticating with FusionAuth and the Admin Toolbar module to add a bit of quality of life when navigating the Drupal administration menu. In a terminal, run the following command from the `your-application` directory. ```shell-session $ composer require 'drupal/openid_connect:3.x-dev@dev' 'drupal/admin_toolbar:^3.4' ``` #### Enabling Extensions Via UI You can enable the modules by visiting the extensions page of your Drupal application at [http://localhost/admin/modules](http://localhost/admin/modules). Search for "OpenID Connect" and "Admin Toolbar" using the **Filter** field. Select the module checkboxes and click the Install button. #### Enabling Extensions With Drush Alternatively, you can use Drush to enable the modules. Drush is a command line shell and Unix scripting interface for Drupal, available as a [composer package](https://packagist.org/packages/drush/drush). Install it by running the following command. ```shell-session $ composer require drush/drush ``` You might need to restart your containers for the changes to take effect. You can do so by running the following command. ```shell-session $ docker compose restart ``` Once the containers are up and running, connect to the Drupal container terminal to run Drush commands. ```shell-session $ docker compose exec web bash ``` Run the following command to enable the modules. ```shell-session $ vendor/bin/drush pm-enable openid_connect admin_toolbar ``` Confirm with yes when prompted. ```plaintext Do you want to continue? (yes/no) [yes]: yes ``` You can use Drush to run many commands and perform common tasks in Drupal. Other popular commands include: * `vendor/bin/drush cr` clears the cache. * `vendor/bin/drush pm-enable ` enables a module. * `vendor/bin/drush updb` updates the database. * `vendor/bin/drush uli` generates a one-time login link for a user. For the full list of Drush commands, visit [https://www.drush.org/12.2.0/commands/all/](https://www.drush.org/12.2.0/commands/all/). ### Run FusionAuth Via Docker You'll find a Docker Compose file (`docker-compose.yml`) and an environment variables configuration file (`.env`) in the root directory of the repo. Assuming you have Docker installed, you can stand up FusionAuth on your machine with the following. ```shell-session $ docker compose up -d ``` Here you are using a bootstrapping feature of FusionAuth called [Kickstart](https://4002.18-224-161-104.sslip.io/docs/get-started/download-and-install/development/kickstart.md). When FusionAuth comes up for the first time, it will look at the `kickstart/kickstart.json` file and configure FusionAuth to your specified state. Note If you ever want to reset the FusionAuth application, you need to delete the volumes created by Docker Compose by executing `docker compose down -v`, then re-run `docker compose up -d`. FusionAuth will be initially configured with these settings: * Your client Id is `e9fdb985-9173-4e01-9d73-ac2d60d1dc8e`. * Your client secret is `super-secret-secret-that-should-be-regenerated-for-production`. * Your example username is `richard@example.com` and the password is `password`. * Your admin username is `admin@example.com` and the password is `password`. * The base URL of FusionAuth is `http://localhost:9011/`. You can log in to the [FusionAuth admin UI](http://localhost:9011/admin) and look around if you want to, but with Docker and Kickstart, everything will already be configured correctly. Note If you want to see where the FusionAuth values came from, they can be found in the [FusionAuth app](http://localhost:9011/admin). The tenant Id is found on the Tenants page. To see the Client Id and Client Secret, go to the Applications page and click the `View` icon under the actions for the ChangeBank application. You'll find the Client Id and Client Secret values in the `OAuth configuration` section. Caution The `.env` file contains passwords. In a real application, always add this file to your `.gitignore` file and never commit secrets to version control. ## Authentication To set up your Drupal application to use FusionAuth for authentication, head to [http://localhost/admin/config/people/openid-connect](http://localhost/admin/config/people/openid-connect) on your Drupal site. Add a new client by clicking on \+ Generic OAuth 2.0 and fill in the details as follows: * **Name**: `FusionAuth` * **Client ID**: `e9fdb985-9173-4e01-9d73-ac2d60d1dc8e` * **Client secret**: `super-secret-secret-that-should-be-regenerated-for-production` * **Authorization endpoint**: `http://host.docker.internal:9011/oauth2/authorize` * **Token endpoint**: `http://host.docker.internal:9011/oauth2/token` * **UserInfo endpoint**: `http://host.docker.internal:9011/oauth2/userinfo` Note You may need to update your hosts file to include an entry for `127.0.0.1 host.docker.internal` if it's not already present. On macOS and Linux you can achieve this by running the following command: ```plaintext echo "127.0.0.1 host.docker.internal" | sudo tee -a /etc/hosts ``` Scroll down and click Create OpenID Connect client . While on the page that lists your newly created client, click the Settings tab. Under the section OpenID buttons display in user login form , change the value from `Hidden` to `Below` to display the Login with FusionAuth button on the login page. Scroll down and click Save configuration to save the settings. Before you test the authentication flow, you need to make a small change to allow visitors to create accounts on the Drupal application. Navigate to [http://localhost/admin/config/people/accounts](http://localhost/admin/config/people/accounts) and change **Who can register accounts?** to `Visitors` and uncheck **Require email verification when a visitor creates an account**. Save the configuration. You need to flush the cache for the changes to take effect. You can flush the cache in Drupal in two ways: * By navigating to [http://localhost/admin/config/development/performance](http://localhost/admin/config/development/performance) and clicking the Clear all caches button. * Or by running the `vendor/bin/drush cr` command in the Drupal Docker container terminal. ### Test Authentication Now you can test the authentication flow. In the browser, navigate to [http://localhost/user/logout](http://localhost/user/logout) to log out of the Drupal application. Navigate to [http://localhost/user/login](http://localhost/user/login) and click on the Login with FusionAuth button. You should be taken to the FusionAuth login page. Log in with the username `richard@example.com` and password `password`. You should be redirected back to the Drupal application once logged in. ## Customization In this section, you'll turn your application into a trivial banking application with some styling. You're going to create a module called "Changebank" that will handle the logic for making change from dollars, and add a couple of blocks to the application. ### Generate Changebank Module In your terminal, run the following command in the Drupal Docker container. ```shell-session $ vendor/bin/drush generate module ``` You will be presented with the module creation wizard. Fill it out as follows: ```plaintext Welcome to module generator! Module name: Changebank Module machine name [changebank]: changebank Module description: Provides a way to make change from dollars. Package [Custom]: Custom Dependencies (comma separated): Would you like to create module file [No]: Yes Would you like to create install file [No]: No Would you like to create README.md file [No]: No The following directories and files have been created or updated: - /opt/drupal/web/modules/changebank/changebank.info.yml - /opt/drupal/web/modules/changebank/changebank.module ``` Now you will expand on the module by generating two blocks, a form, a controller, and a routing file. To generate the first block, run the following command and complete the wizard. ```shell-session $ vendor/bin/drush generate block ``` You will be presented with the block creation wizard. Fill it out as follows: ```plaintext Welcome to block generator! Module machine name: changebank Block admin label: User Email Block Plugin ID [changebank_user_email_block]: useremailblock Plugin class [UseremailblockBlock]: UserEmailBlock Block category [Custom]: Custom Make the block configurable? [No]: No Would you like to inject dependencies? [No]: No Create access callback? [No]: No The following directories and files have been created or updated: - /opt/drupal/web/modules/changebank/src/Plugin/Block/UserEmailBlock.php ``` Generate the second block with the same block generation command as before. ```shell-session $ vendor/bin/drush generate block ``` Enter the following information: ```plaintext Welcome to block generator! Module machine name: changebank Block admin label: User Login Logout Block Plugin ID [changebank_user_login_logout_block]: userloginlogoutlock Plugin class [UserloginlogoutlockBlock]: UserLoginLogoutBlock Block category [Custom]: Custom Make the block configurable? [No]: No Would you like to inject dependencies? [No]: No Create access callback? [No]: No The following directories and files have been created or updated: - /opt/drupal/web/modules/changebank/src/Plugin/Block/UserLoginLogoutBlock.php ``` To generate the form, run the following command. ```shell-session $ vendor/bin/drush generate form ``` You will be presented with the form wizard. Fill it out as follows: ```plaintext Welcome to form generator! Module machine name: changebank Module name [Changebank]: Changebank Class [ExampleForm]: ChangebankForm Would you like to create a route for this form? [Yes]: No The following directories and files have been created or updated: - /opt/drupal/web/modules/changebank/src/Form/ChangebankForm.php ``` Next, generate a controller with the following command. ```shell-session $ vendor/bin/drush generate controller ``` You will be presented with the controller wizard. Fill it out as follows: ```plaintext Welcome to controller generator! Module machine name: changebank Module name [Changebank]: Changebank Class [ChangebankController]: ChangebankController Would you like to inject dependencies? [No]: No Would you like to create a route for this controller? [Yes]: No The following directories and files have been created or updated: - /opt/drupal/web/modules/changebank/src/Controller/ChangebankController.php ``` Finally, generate a routing file with the following command. ```shell-session $ vendor/bin/drush generate routing ``` You will be presented with the routing wizard. Fill it out as follows: ```plaintext Module machine name: changebank Module name [Changebank]: Changebank The following directories and files have been created or updated: - /opt/drupal/web/modules/changebank/changebank.routing.yml ``` ### Customizing The Module Now that you have all the files you need in your custom module, you can customize them. You will be editing the following files: * `ChangebankForm.php` * `ChangebankController.php` * `changebank.routing.yml` * `UserEmailBlock.php` * `UserLoginLogoutBlock.php` * `changebank.module` #### Customize The Changebank Form In your text editor, select the `ChangebankForm.php` file located at `your-application/web/modules/changebank/src/Form/ChangebankForm.php`. Clear the existing boilerplate contents and add the following code. ```php get('result'); $form['result_wrapper'] = [ '#type' => 'container', '#attributes' => [ 'class' => ['changebank-result-wrapper'], ], ]; if ($form_state->get('result')) { $form['result_wrapper']['result'] = [ '#markup' => $result, ]; } $form['amount'] = [ '#type' => 'number', '#title' => $this->t('Amount in USD: $'), '#required' => TRUE, '#min' => 0, '#step' => 0.01, ]; $form['submit'] = [ '#type' => 'submit', '#value' => $this->t('Make Change'), ]; return $form; } /** * {@inheritdoc} */ public function submitForm(array &$form, FormStateInterface $form_state) { $amount = $form_state->getValue('amount'); $amount_in_cents = round($amount * 100); $quarters = floor($amount_in_cents / 25); $amount_in_cents %= 25; $dimes = floor($amount_in_cents / 10); $amount_in_cents %= 10; $nickels = floor($amount_in_cents / 5); $amount_in_cents %= 5; $pennies = $amount_in_cents; $coins = []; if ($quarters > 0) { $coins[] = "@quarters quarters"; } if ($dimes > 0) { $coins[] = "@dimes dimes"; } if ($nickels > 0) { $coins[] = "@nickels nickels"; } if ($pennies > 0) { $coins[] = "@pennies pennies"; } $result = $this->t('We can make change for $@dollars with ' . implode(', ', $coins) . '!', [ '@dollars' => $amount, '@quarters' => $quarters, '@dimes' => $dimes, '@nickels' => $nickels, '@pennies' => $pennies, ]); $form_state->setRebuild(TRUE); $form_state->set('result', $result); \Drupal::state()->set('changebank_form_value', $result); } } ``` #### Customize The Controller In your text editor, select the `ChangebankController.php` file located at `your-application/web/modules/changebank/src/Controller/ChangebankController.php` and replace the content with the following code. ```php formBuilder()->getForm('\Drupal\changebank\Form\ChangebankForm'); $build['form'] = $form; return $build; } /** * Displays the form submission value on the account page. */ public function accountBalance() { $value = \Drupal::state()->get('changebank_form_value'); $arguments = ($value) ? $value->getArguments() : []; $dollars = $arguments['@dollars'] ?? 0; return [ '#markup' => '$' . $dollars . '', '#cache' => [ 'contexts' => [ 'session', ], 'max-age' => 0, ], ]; } } ``` #### Customize The Routing Next you'll set up two routes, one for the form and one for the account page. Select the `changebank.routing.yml` file located at `your-application/web/modules/changebank/changebank.routing.yml` and replace the content with the following configuration. ```yaml changebank.makechange: path: '/makechange' defaults: _title: 'We Make Change' _controller: '\Drupal\changebank\Controller\ChangebankController::build' _form: 'Drupal\changebank\Form\ChangebankForm' requirements: _user_is_logged_in: 'TRUE' changebank.account: path: '/account' defaults: _title: 'Your Balance' _controller: '\Drupal\changebank\Controller\ChangebankController::accountBalance' requirements: _user_is_logged_in: 'TRUE' ``` #### Customize The User Email Block You'll use the User Email Block to display the current user's email address in a block. Select the `UserEmailBlock.php` file located at `your-application/web/modules/changebank/src/Plugin/Block/UserEmailBlock.php` and replace the content with the following code. ```php currentUser = $current_user; } /** * {@inheritdoc} */ public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { return new static( $configuration, $plugin_id, $plugin_definition, $container->get('current_user') ); } /** * {@inheritdoc} */ public function build() { $email = $this->currentUser->getEmail(); return [ '#markup' => $this->t('@email', ['@email' => $email]), ]; } } ``` #### Customize The User Login And Logout Block You'll use the User Login And Logout Block to display a login button for anonymous users and a logout button for authenticated users. Select the `UserLoginLogoutBlock.php` file located at `your-application/web/modules/changebank/src/Plugin/Block/UserLoginLogoutBlock.php` and replace the content with the following code. ```php currentUser = $current_user; } /** * {@inheritdoc} */ public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { return new static( $configuration, $plugin_id, $plugin_definition, $container->get('current_user') ); } /** * {@inheritdoc} */ public function build() { $roles = $this->currentUser->getRoles(); if (in_array('anonymous', $roles)) { return [ '#markup' => $this->t(''), ]; } else { return [ '#markup' => $this->t(''), ]; } } } ``` #### Customize The `changebank.module` File To make the blocks available to the application, you need to make some changes to the `changebank.module` file located at `your-application/web/modules/changebank/changebank.module`. Add the following. ```php t('User Email Block'), 'cache' => DRUPAL_CACHE_PER_ROLE, ]; $blocks['user_login_logout_block'] = [ 'info' => t('User Login Logout Block'), 'cache' => DRUPAL_CACHE_PER_ROLE, ]; return $blocks; } ``` #### Enable The Changebank Module To enable the Changebank module, navigate to [http://localhost/admin/modules](http://localhost/admin/modules) while logged in as admin and select the checkbox next to the Changebank module item. Click the Install button. Note You can also enable the module by running the following command in the Drupal Docker container. ```shell-session $ vendor/bin/drush pm-enable changebank ``` ### Add Styling In this section, you're going to add a theme to the application, along with a couple of templates and some basic styling. #### Download A Theme A theme called "Barrio Bootstrap 5" will give you a good starting point for styling the application. Run the following command from a terminal in the `your-application` directory to add the theme to the project. ```shell-session $ composer require 'drupal/bootstrap_barrio:^5.5' ``` #### Create A Subtheme Next, you'll create a subtheme of the Barrio Bootstrap 5 theme. You will notice a folder called `subtheme` in the `your-application/web/themes/contrib/bootstrap_barrio` directory. First, create a directory called `custom` in `your-application`, and a directory called `subtheme` in `custom`. ```shell-session $ mkdir -p web/themes/custom/subtheme ``` Copy the `your-application/web/themes/contrib/bootstrap_barrio/subtheme` directory into `your-application/web/themes/custom/subtheme`. ```shell-session $ cp -r web/themes/contrib/bootstrap_barrio/subtheme/* web/themes/custom/subtheme ``` Enter the subtheme folder and edit the `bootstrap_barrio_subtheme.info.yml` file. Change the name of the theme from `Bootstrap Barrio Subtheme` to `Changebank`, and change the description from `Basic structure for a Bootstrap Barrio SubTheme` to `Subtheme for Changebank`. #### Enable The Theme To enable the theme, navigate to [http://localhost/admin/appearance](http://localhost/admin/appearance) and click the Install button for both "Bootstrap Barrio 5.5.14" and "Changebank 5.5.14". Click the Set as default button for "Changebank 5.5.14". While you are here, let's add the Changebank logo to the application. Click Settings on Changebank 5.5.14, then scroll down and click Logo image . Uncheck the Use the logo supplied by the theme checkbox, and upload the [Changebank logo](https://github.com/FusionAuth/fusionauth-quickstart-php-drupal-web/blob/main/complete-application/default-content/files/changebank-logo.png) in the **Upload logo image** field. Save the configuration. #### Install And Enable Twig Tweak The Twig Tweak module will make it easier to render content in the templates you create later. Twig Tweak is a small module that provides a Twig extension with some useful functions and filters that can improve the developer experience. Run the following command in the `your-application` directory to download the module. ```shell-session $ composer require 'drupal/twig_tweak:^3.2' ``` Enable the module by navigating to [http://localhost/admin/modules](http://localhost/admin/modules), selecting the checkbox next to Twig Tweak, and clicking the Install button. Note You can also enable the module with the following command in the Drupal Docker container. ```shell-session $ vendor/bin/drush pm-enable twig_tweak ``` #### Add Templates In the subtheme directory of your application, you'll add a couple of templates to override the default templates provided by the Bootstrap Barrio theme. This will allow you to customize the markup of the application. The `page--front.html.twig` template file you will create uses an image that is currently not in your application. To copy the image to your application, run the following command from `your-application` directory. ```shell-session $ cp ../complete-application/web/sites/default/files/money-new.jpg web/sites/default/files/money-new.jpg ``` Navigate to `your-application/web/themes/custom/subtheme/templates/`. If the `templates` directory is not there, you may need to create it. In the templates directory, create the following files: * `page--front.html.twig` * `block--system-branding-block.html.twig` * `region--secondary-menu.html.twig` In the page template for the front page (called `page--front.html.twig`), add the following code. ```twig {% extends "@bootstrap_barrio/layout/page.html.twig" %} {# /** * @file * Bootstrap Barrio's theme implementation to display a single page. * * The doctype, html, head and body tags are not in this template. Instead they * can be found in the html.html.twig template normally located in the * core/modules/system directory. * * Available variables: * * General utility variables: * - base_path: The base URL path of the Drupal installation. Will usually be * "/" unless you have installed Drupal in a sub-directory. * - is_front: A flag indicating if the current page is the front page. * - logged_in: A flag indicating if the user is registered and signed in. * - is_admin: A flag indicating if the user has permission to access * administration pages. * * Site identity: * - front_page: The URL of the front page. Use this instead of base_path when * linking to the front page. This includes the language domain or prefix. * - logo: The url of the logo image, as defined in theme settings. * - site_name: The name of the site. This is empty when displaying the site * name has been disabled in the theme settings. * - site_slogan: The slogan of the site. This is empty when displaying the site * slogan has been disabled in theme settings. * Page content (in order of occurrence in the default page.html.twig): * - node: Fully loaded node, if there is an automatically-loaded node * associated with the page and the node ID is the second argument in the * page's path (e.g. node/12345 and node/12345/revisions, but not * comment/reply/12345). * * Regions: * - page.top_header: Items for the top header region. * - page.top_header_form: Items for the top header form region. * - page.header: Items for the header region. * - page.header_form: Items for the header form region. * - page.highlighted: Items for the highlighted region. * - page.primary_menu: Items for the primary menu region. * - page.secondary_menu: Items for the secondary menu region. * - page.featured_top: Items for the featured top region. * - page.content: The main content of the current page. * - page.sidebar_first: Items for the first sidebar. * - page.sidebar_second: Items for the second sidebar. * - page.featured_bottom_first: Items for the first featured bottom region. * - page.featured_bottom_second: Items for the second featured bottom region. * - page.featured_bottom_third: Items for the third featured bottom region. * - page.footer_first: Items for the first footer column. * - page.footer_second: Items for the second footer column. * - page.footer_third: Items for the third footer column. * - page.footer_fourth: Items for the fourth footer column. * - page.footer_fifth: Items for the fifth footer column. * - page.breadcrumb: Items for the breadcrumb region. * * Theme variables: * - navbar_top_attributes: Items for the header region. * - navbar_attributes: Items for the header region. * - content_attributes: Items for the header region. * - sidebar_first_attributes: Items for the highlighted region. * - sidebar_second_attributes: Items for the primary menu region. * * @see template_preprocess_page() * @see bootstrap_barrio_preprocess_page() * @see html.html.twig */ #} {# see https://www.drupal.org/project/drupal/issues/953034#comment-14192130 #} {% set sidebar_first_exists = page.sidebar_first|render|striptags('