GrabDuck

Drupal 8 Installation Profiles | ADCI Solutions

:

As explained on drupal.org: “Installation profiles in Drupal 8 have all the functionality of modules, including access to hooks and plugins and, critically, the ability to provide configuration for your site in the form of .yml files”. It means that in Drupal 8 an installation profile can behave like a module: managing its own routes and declaring page callbacks, alter forms, declaring blocks, and most of these possibilities can be learned from any Drupal 8 module development guide.

In this tutorial I would like to focus on the key possibilities, that Drupal installation profile is loved for, those, that cannot be provided with the regular module.

So, what are the installation profiles (or distributions) used for? The primary usage of them is setting up the website and make it ready for usage right after the installation. That means, the process of installation will contain:
• Enabling modules,
• Creating entities,
• Gathering data from the user on the configuration page,
• Enabling themes,
• Setting up necessary configurations

We are going to create our own installation profile which will be called "example" and we will see, how these installation steps are handled.

Our installation profile will be located in its own profilename directory in the /profiles directory of our Drupal 8 installation. Within this folder there is a profilename.info.yml configuration file, which is the base thing for our installation profile to be recognized by Drupal. Let us take a closer look to it.

# The following three lines are required, our profile won’t work without them:
name: Example
type: profile
core: 8.x

# Optionally we may also give a description for our profile or declare our
# installation profile as a distribution, so that it'll be auto-selected.
# If the profile was declared as a distribution, normally we will not be able
# to see the profile's description, so it makes sense to use only one of the
# following parameters.

description: Example.
distribution:
  name: ADCI Solutions Example Profile.

# Note: if there are more then one distributions within the profiles/ folder,
# Drupal 8 will auto-select the one whose name goes first alphabethically.

In spite of the fact that drupal.org says that installation profiles must have both profilename.info.yml and profilename.profile files, having only profilename.info.yml file will be enough for our profile to be installed. However, our profile will not do anything useful, so let us make our profile install some modules and execute some code for us, which is the thing that profilename.install and profilename.profile files are being used for. The modules that we want to be enabled while our profile is being installed are listed in the profilename.info.yml file. Contributed and custom modules should also be listed in this file. We are going to take the modules list from the standard installation profile, which comes with Drupal 8 core. If there are some custom modules that you want to be enabled, it is recommended to put them inside of a profiles/profilename/modules directory. We are going to create a simple custom module just for the sake of an example. Now our profilename.info.yml file looks like this:

# The following three lines are required, our profile won’t work without them:
name: Example
type: profile
core: 8.x

# Optionally we may also give a description for our profile or declare our
# installation profile as a distribution, so that it'll be auto-selected.
# If the profile was declared as a distribution, normally we will not be able
# to see the profile's description, so it makes sense to use only one of the
# following parameters.

description: Example.
distribution:
  name: ADCI Solutions Example Profile.

# Note: if there are more then one distributions within the profiles/ folder,
# Drupal 8 will auto-select the one whose name goes first alphabethically.

dependencies:
  - node
  - history
  - block
  - breakpoint
  - ckeditor
  - color
  - config
  - comment
  - contextual
  - contact
  - menu_link_content
  - datetime
  - block_content
  - quickedit
  - editor
  - help
  - image
  - menu_ui
  - options
  - path
  - page_cache
  - dynamic_page_cache
  - taxonomy
  - dblog
  - search
  - shortcut
  - toolbar
  - field_ui
  - file
  - rdf
  - views
  - views_ui
  - tour
  - automated_cron
  - example_profile_module

And now we got closer to profilename.install file. This file should also be located within the profilename/ folder, and it’s primary purpose is performing actions for setting up the site, enabling some preferencies, granting users with permissions, creating menu shortcuts. In our example we are going to create a taxonomy vocabulary and a taxonomy term:

use Drupal\taxonomy\Entity\Vocabulary;
use Drupal\taxonomy\Entity\Term;

/**
 * Implements hook_install().
 *
 * Perform actions to set up the site for this profile.
 *
 * @see system_install()
 */
function example_install() {
  // First, do everything in standard profile.
  include_once DRUPAL_ROOT . '/core/profiles/standard/standard.install';
  standard_install();

  // Then we can perform our own actions.
  $vocabulary = Vocabulary::create(array(
    'vid' => 'example_profile_vocabulary',
    'name' => 'example profile vocabulary',
  ))->save();
  $term = Term::create(array(
    'parent' => array(),
    'name' => 'example term',
    'vid' => 'example_profile_vocabulary',
  ))->save();
}

The difference between profilename.install and profilename.profile purposes is much like the difference between regular module’s modulename.install and modulename.module files. So, this is a good place for all our hook_form_alters or other hook implementations. Say, Drupal 8 Standard installation profile has its own hook_form_FORM_ID_alter implementation for install_configure_form() which is kind of the same as in Drupal 7.

/**
 * Implements hook_form_FORM_ID_alter() for install_configure_form().
 *
 * Allows the profile to alter the site configuration form.
 */
function standard_form_install_configure_form_alter(&$form, FormStateInterface $form_state) {
  // Add a placeholder as example that one can choose an arbitrary site name.
  $form['site_information']['site_name']['#attributes']['placeholder'] = t('My site');
  $form['#submit'][] = 'standard_form_install_configure_submit';
}

But what is different from Drupal 7, is how the themes are enabled. We can include the themes in our profilename.info.yml file, and it's very easy to do, but the point is that it won't be enough. We are just enumerating the themes that will be enabled after installation, but none of them will be set by default.

# Adding these lines to our profilename.info.yml will only enable these themes.
themes:
  - bartik
  - seven

There is a new feature that came out with Drupal 8 and that is influencing the installation profiles' workflow as well: I am talking about the Drupal 8 Configuration system. It provides a central place for modules to store configuration data like your site name, or more complex information managed with configuration entities, such as views and content types and themes. Drupal 8 installation profiles can contain configuration files. You can start by taking the configuration directory (config folder) of an installed, configured site and copying it into a config folder in your profile. Or you may just take several configuration files you need and customize them according to your needs. We've taken a system.theme.yml config file and put it in the config/install folder of our profile. This configuration file will be applied during the installation process, and our example custom theme will be activated. Where can we take these config files from? Some of them are being kept in the core modules folders, or in the contributed ones, but the most easiest way is just to export them from an existing website.

It can even be done with drush, with the command drush confgig-export or shortened drush cex. Any content types, configurations, different odds and ends like image styles, date formats, can be exported be exported in corresponding .yml files. Just choose what you want to be installed with your profile, put the necessary files in your profilename/config/install folder and be happy :) As a final part, let us try to enable a couple of contributed modules with our profile. Much like in Drupal 7, Drupal 8 has the same process for packaging contrib modules, themes or libraries to a distribution. Say, you already have a running project with a set of necessary modules and themes, so what you want to do is to execute a well-known Drush command for generating a makefile for your distribution: drush make-generate drupal-org.make. All the modules and themes you have will be listed in this file. You may edit it, adding or removing the modules you want, and then move this file to your profilename/ folder. When pushing your distribution to drupal.org, it'll be populated with all the modules listed in this file. Just do not forget to add those in your profile dependencies in a profilename.info.yml file. You may also specify the Drupal core version to be installed, even with the patches to apply.

api = 2
core = 8.x

; Drupal Core
projects[drupal][type] = "core"
projects[drupal][version] = "8.0.0"
projects[drupal][patch][] = https://www.drupal.org/files/issues/2637194-12.patch

You may also use your distribution on your local environment, without pushing it to drupal.org. It's often useful to have your own distribution with a set of modules, that you get used to work with. In Drupal 8, there is also nothing new with this approach. All you have to do is to run drush make --no-core profiles/profilename/drupal-org.make inside of your web root, and Drush will download everything you've asked him to. It is important, however, to doublecheck if all the necessary modules were downloaded before running the installation process: Missing/unknown (or mis-spelled) modules in the profilename.info.yml will cause a fatal error (at least at 8.0.3) so be sure everything is spelled correctly there. And now, even if you did not yet work with Drupal 8, you have the basic idea of how it's working and how to make your own distribution or to upgrade your existing Drupal 7 distributions to Drupal 8.