SlideShare a Scribd company logo
Friday, 16 November, 12
Friday, 16 November, 12
11/16/12




          Coding for Config
          Install Profile Development Using Features




Friday, 16 November, 12
What is an
           install
           profile?



Friday, 16 November, 12
Distributions provide site features
               and functions for a specific type of
               site as a single download containing
               Drupal core, contributed modules,
               themes, and pre-defined
               configuration.




Friday, 16 November, 12
They make it possible to quickly set
               up a complex, use-specific site in
               fewer steps than if installing and
               configuring elements individually.




Friday, 16 November, 12
Distributions
           vs.
           Install Profiles



Friday, 16 November, 12
Distribution Requirements

                          • Only GPL-compatible libraries
                          • No cloned sandboxes
                          • No includes[] directive
                          • Only d.o modules and themes
                          • Must use drupal-org-
                            core.make
                          • Must define git branches


Friday, 16 November, 12
Install Profile Requirements

                          • Provide site features and
                            functions for a specific type
                            of site as a single download




Friday, 16 November, 12
Hard and Soft
               Configuration




Friday, 16 November, 12
Hard config




Friday, 16 November, 12
It has a
           machine name.
           It is easy to
           export.


Friday, 16 November, 12
Soft config




Friday, 16 November, 12
It has a
           numeric ID.
           It is hard to
           export.


Friday, 16 November, 12
When? Where?
           Why?




Friday, 16 November, 12
How do
           you make
           an install
           profile?


Friday, 16 November, 12
You’ll need...




Friday, 16 November, 12
[profile].info
               [profile].profile
               [profile].install




Friday, 16 November, 12
build-[profile].make
               drupal-org.make
               drupal-org-core.make




Friday, 16 November, 12
modules/
                 contrib/
                 custom/
                 features/




Friday, 16 November, 12
themes/
                 contrib/
                 custom/




Friday, 16 November, 12
tmp/
                 docs/
                 tests/
                 snippets/
                 scripts/
                  build-dev.sh
                  build-prod.sh




Friday, 16 November, 12
[profile].info
               [profile].profile
               [profile].install

               build-[profile].make
               drupal-org.make
               drupal-org-core.make

               modules/
                 custom/
                 features/
                 contrib/

               libraries/

               themes/
                 custom/
                 contrib/

               tmp/
                 docs/
                 tests/
                 snippets/
                 scripts/
                   build-dev.sh
                   build-prod.sh




Friday, 16 November, 12
File contents




Friday, 16 November, 12
Friday, 16 November, 12
[profile].info
               [profile].profile
               [profile].install




Friday, 16 November, 12
name = Spark
               description = Cutting-edge authoring experience improvements for
               Drupal.
               version = "7.x-1.0-alpha5"
               core = 7.x
               php = 5.3

               ; The distribution_name property is used in the installer and other
               places as
               ; a label for the software being installed.
               distribution_name = Spark

               ; Required modules (Core)
               ; Copy/pasted from standard.info
               dependencies[] = block
               dependencies[] = color
               dependencies[] = comment
               dependencies[] = contextual
               dependencies[] = dblog
               dependencies[] = field_ui
               dependencies[] = file
               dependencies[] = help
               dependencies[] = image
               dependencies[] = list
               dependencies[] = menu
               dependencies[] = number




Friday, 16 November, 12
<?php
               /**
                * @file
                * Enables modules and site configuration for a standard site
               installation.
                */

               /**
                * Implements hook_form_FORM_ID_alter() for install_configure_form().
                *
                * Allows the profile to alter the site configuration form.
                */
               function spark_form_install_configure_form_alter(&$form, $form_state) {
                 // Pre-populate the site name with the server name.
                 $form['site_information']['site_name']['#default_value'] =
               $_SERVER['SERVER_NAME'];
               }




Friday, 16 November, 12
<?php
               /**
                * @file
                * Install, update and uninstall functions for the spark install
               profile.
                */

               /**
                * Implements hook_install().
                *
                * Perform actions to set up the site for this profile.
                *
                * @see system_install()
                */
               function spark_install() {
                 ...
               }




Friday, 16 November, 12
<?php
               /**
                * @file
                * Install, update and uninstall functions for the spark install
               profile.
                */

               /**
                * Implements hook_install().
                *
                * Perform actions to set up the site for this profile.
                *
                * @see system_install()
                */
               function spark_install() {
                 ...
               }

               /**
                * Implements hook_update_N().
                *   Description of hook update.
                */
               function spark_update_10001(&$sandbox) {
                 ...
               }




Friday, 16 November, 12
<?php
               /**
                * @file
                * Install, update and uninstall functions for the spark install
               profile.
                */

               /**
                * Implements hook_install().
                *
                * Perform actions to set up the site for this profile.
                *
                * @see system_install()
                */
               function spark_install() {
                 ...
               }

               /**
                * Implements hook_update_N().
                *   Description of hook update.
                */
               function spark_update_10001(&$sandbox) {
                 ...
               }




Friday, 16 November, 12
Example
           install hooks




Friday, 16 November, 12
Set Variables
               /**
                * Implements hook_update_N().
                *   Enables default and admin themes.
                */
               function profilename_update_10001(&$sandbox) {

                   theme_enable(array('default_theme'));

                   variable_set('theme_default', 'default_theme');

                   variable_set('node_admin_theme', '1');

                   return t('The admin and default themes have been set.');
               }




Friday, 16 November, 12
Populate Menus
                    /**
                     * Implements hook_update_N().
                     *    Generate menu links
                     */
                    function profilename_update_10002(&$sandbox) {
                       cache_clear_all();
                       //generate the menu links array
                       //for the header menu

                          $menu_links = array();
                          $menu_links['home'] = array(
                             'link_path' => '<front>',
                             'link_title' => t('Home'),
                             'weight' => 0,
                          );
                          $menu_links['about'] = array(
                             'link_path' => 'about-us',
                             'link_title' => t('About Us'),
                             'weight' => 0,
                          );




Friday, 16 November, 12
Populate Menus


                          //run menu_link_save on all of the items.
                          foreach ($menu_links as $menu_link) {
                            $menu_link['menu_name'] = 'menu-header';
                            $menu_link['module'] = 'menu';
                            menu_link_save($menu_link);
                          }

                          menu_cache_clear_all();

                          // Success!
                          return t('Menu links have been generated');
                    }




Friday, 16 November, 12
Set blocks to regions
               /**
                * Implements hook_update_N().
                *    Set copyright blocks to its region.
                */
               function profilename_update_10003(&$sandbox) {
                  //pull in the theme name
                  global $theme_key;

                  // Set our block values
                  $values = array(
                     array(
                        'module' => 'custom_module',
                        'delta' => 'copyright',
                        'region' => 'footer',
                        'theme' => $theme_key,
                        'pages' => '',
                        'cache' => 8,
                        'status' => 1,
                        'weight' => 0,
                     ),
                  );




Friday, 16 November, 12
Set blocks to regions
                  // If a db_entry for these blocks exists, delete it
                  foreach ($values as $position => $record) {
                    $result = db_select('block', 'b')
                      ->fields('b')
                      ->condition('module', $record['module'], '=')
                      ->condition('delta', $record['delta'], '=')
                      ->condition('theme', $theme_key, '=')
                      ->execute()
                      ->fetchAssoc();
                    if (!empty($result['bid'])) {
                      db_delete('block')
                      ->condition('module', $record['module'], '=')
                      ->condition('delta', $record['delta'], '=')
                      ->condition('theme', $theme_key, '=')
                      ->execute();
                    }
                  }




Friday, 16 November, 12
Set blocks to regions


                 // Insert into the database any block values that aren't already
               present
                 foreach ($values as $record) {
                   $query = db_insert('block')->fields(array('module', 'delta',
               'theme', 'status', 'weight', 'region', 'pages', 'cache'));
                   $query->values($record);
                   $insert_result = $query->execute();
                 }

                   // Success!
                    return t('Copyright blocks has been placed in the footer.');
               }




Friday, 16 November, 12
Populate a Vocabulary
               function profilename_requirements($phase) {
                 $requirements = array();
                 // Ensure translations don't break at install time
                 $t = get_t();
                 if ($phase == 'install' || $phase == 'update') {
                   // Load taxonomy.module during install & updates
                   if (!is_null(module_load_include('module', 'taxonomy'))) {
                      $requirements['taxonomy'] = array(
                        'title' => $t('Taxonomy Module'),
                        'value' => $t('Taxonomy module loaded'),
                        'severity' => REQUIREMENT_OK,
                     );
                   }
                   else {
                     $requirements['taxonomy'] = array(
                        'title' => $t('Taxonomy Module'),
                        'value' => $t('Taxonomy module not loaded'),
                        'severity' => REQUIREMENT_ERROR,
                     );
                   }

                   }
                   return $requirements;
               }



Friday, 16 November, 12
Populate a Vocabulary
               /**
                * Implements hook_update_N().
                *    Create vocabulary and taxonomy terms
                */
               function profilename_update_10004(&$sandbox) {
                  // Get the vocabulary
                  $vocab = taxonomy_vocabulary_machine_name_load('terms');

                  // If it's not created, do so (expected result)
                  if(empty($vocab)) {
                    $vocab = array(
                       'name' => 'Terms',
                       'machine_name' => 'terms',
                       'description' => 'A list of technical terms',
                       'hierarchy' => '0',
                       'module' => 'taxonomy',
                       'weight' => '0',
                    );
                    taxonomy_vocabulary_save((object)$vocab);
                  }




Friday, 16 November, 12
Populate a Vocabulary

                  // Confirm that we've created it
                  $vocab = taxonomy_vocabulary_machine_name_load('terms');

                  // If we haven't created it, stop
                  if (empty($vocab)) {
                    return t('Failed to create vocabulary.');
                  }

                  // Else if the "terms" vocabulary exists, populate it.
                  $terms = array(
                     'Drupal' => 'A content management system',
                     'Module' => 'A functional component of Drupal',
                  );




Friday, 16 November, 12
Populate a Vocabulary

                 // For each term defined in the above array, add it to the
               "terms" vocabulary.
                 foreach ($terms as $term_name => $term_description) {
                   $term = new stdClass();
                   $term->vid = $vocab->vid;
                   $term->name = $term_name;
                   $term->description = $term_description;
                   taxonomy_term_save($term);
                 }

                   // Success!
                   return t('Created vocabulary and taxonomy terms');
               }




Friday, 16 November, 12
build-[profile].make
               drupal-org.make
               drupal-org-core.make




Friday, 16 November, 12
build-spark.make


               api = 2
               core = 7.x
               ; Include the definition for how to build Drupal core directly,
               including patches:
               includes[] = drupal-org-core.make

               ; Download the Spark install profile and recursively build all its
               dependencies:
               projects[spark][type] = profile
               projects[spark][download][type] = git
               projects[spark][download][branch] = 7.x-1.x




Friday, 16 November, 12
build-spark.make - with GIT!

               api = 2
               core = 7.x
               ; Include the definition for how to build Drupal core directly,
               including patches:
               includes[] = drupal-org-core.make

               ; Download the Spark install profile and recursively build all its
               dependencies:
               projects[spark][type] = profile
               projects[spark][download][git]= git
               projects[spark][download][url] = http://git.drupal.org/project/spark.git
               projects[spark][download][revision] = master




Friday, 16 November, 12
drupal-org-core.make
               ; A separate drupal-org-core.make file makes it so we can apply core
               patches if we need to.

               api = 2
               core = 7.x
               projects[drupal][type] = core
               projects[drupal][version] = 7.15

               ; CORE PATCHES
               ; Hide the profiles under /profiles, so Spark is the only one. This
               allows the installation to start at the Language selection screen,
               bypassing a baffling and silly choice, especially for non-native
               speakers.
               projects[drupal][patch][1780598] = http://drupal.org/files/spark-
               install-1780598-5.patch
               ; This requires a core bug fix to not show the profile selection page
               when only one profile is visible.
               projects[drupal][patch][1074108] = http://drupal.org/files/1074108-
               skip-profile-16-7.x-do-not-test.patch




Friday, 16 November, 12
drupal-org.make
               ; This is a standard make file for packaging the distribution along
               with any contributed modules/themes or external libraries. Some
               examples are below.
               ; See http://drupal.org/node/159730 for more details.

               api = 2
               core = 7.x

               ; Contributed modules; standard.

               projects[responsive_bartik][type] = theme
               projects[responsive_bartik][version] = 1.x-dev
               projects[responsive_bartik][subdir] = contrib

               projects[ctools][type] = module
               projects[ctools][version] = 1.2
               projects[ctools][subdir] = contrib
               ; Fix incompatibilities with jQuery 1.7.
               projects[ctools][patch][1494860] = "http://drupal.org/files/ctools-
               dependent-js-broken-with-jquery-1.7-1494860-30.patch"




Friday, 16 November, 12
tmp/
                 docs/
                 tests/
                 snippets/
                 scripts/
                  build-dev.sh
                  build-prod.sh




Friday, 16 November, 12
build-dev.sh
               #!/bin/bash

               # USAGE
               # Run this script as given.
               #
               # $ bash build-dev.sh [ /fullpath/to/project.make ] [ /fullpath/to/
               build/project ]
               #
               # (Default paths are for Vagrant VM.)

               # Bail if non-zero exit code
               set -e

               PROJECT=profilename

               # Set from args
               BUILD_FILE="$1"
               BUILD_DEST="$2"




Friday, 16 November, 12
build-dev.sh
               # Drush make the site structure
               drush make ${BUILD_FILE} ${BUILD_DEST} 
                 --working-copy 
                 --prepare-install 
                 --yes 
                 --no-gitinfofile

               chmod 666 ${BUILD_DEST}/sites/default/settings.php

               echo "Appending settings.php snippets..."
               for f in ${BUILD_DEST}/profiles/${PROJECT}/tmp/snippets/*.settings.php
               do
                 # Concatenate newline and snippet, then append to settings.php
                 echo "" | cat - $f | tee -a ${BUILD_DEST}/sites/default/settings.php
               > /dev/null
               done

               chmod 444 ${BUILD_DEST}/sites/default/settings.php
               cd ${BUILD_DEST}
               drush cc all




Friday, 16 November, 12
[profile].info
               [profile].profile
               [profile].install

               build-[profile].make
               drupal-org.make
               drupal-org-core.make

               modules/
                 custom/
                 features/
                 contrib/

               libraries/

               themes/
                 custom/
                 contrib/

               tmp/
                 docs/
                 tests/
                 snippets/
                 scripts/
                   build-dev.sh
                   build-prod.sh




Friday, 16 November, 12
Debate &
           discussion.




Friday, 16 November, 12
Erin Marchak                                     207-90C Centurian Dr

      Contact us:
                          Developer                  TF: 1.866.232.7456    Markham, Ontario
                          erin@myplanetdigital.com   Myplanetdigital.com   L3R 8C5




Friday, 16 November, 12

More Related Content

What's hot

MySql 5.7 Backup Script
MySql 5.7 Backup ScriptMySql 5.7 Backup Script
MySql 5.7 Backup Script
Hızlan ERPAK
 
Apache
ApacheApache
Apache
rsibbaluca
 
MariaDB training
MariaDB trainingMariaDB training
MariaDB training
Samuel Dos Santos Tolentino
 
Instalar PENTAHO 5 en CentOS 6
Instalar PENTAHO 5 en CentOS 6Instalar PENTAHO 5 en CentOS 6
Instalar PENTAHO 5 en CentOS 6
Moisés Elías Araya
 
hw1a
hw1ahw1a
Standby db creation commands
Standby db creation commandsStandby db creation commands
Standby db creation commands
Piyush Kumar
 
mapserver_install_linux
mapserver_install_linuxmapserver_install_linux
mapserver_install_linux
tutorialsruby
 
Instalacion ambiente web am en linux red hat
Instalacion ambiente web am en linux red hatInstalacion ambiente web am en linux red hat
Instalacion ambiente web am en linux red hat
Janneth Parra
 
Drupal 8 deploying
Drupal 8 deployingDrupal 8 deploying
Drupal 8 deploying
Andrew Siz
 
[INSIGHT OUT 2011] B12 better my sql security and administration(ronald)
[INSIGHT OUT 2011] B12 better my sql security and administration(ronald)[INSIGHT OUT 2011] B12 better my sql security and administration(ronald)
[INSIGHT OUT 2011] B12 better my sql security and administration(ronald)
Insight Technology, Inc.
 
Backup and Restore SALSA to a Secondary Server with a different IP address
Backup and Restore SALSA to a Secondary Server with a different IP addressBackup and Restore SALSA to a Secondary Server with a different IP address
Backup and Restore SALSA to a Secondary Server with a different IP address
Oscar OLVERA-IRIGOYEN, Ph.D
 
Using Perl Stored Procedures for MariaDB
Using Perl Stored Procedures for MariaDBUsing Perl Stored Procedures for MariaDB
Using Perl Stored Procedures for MariaDB
Antony T Curtis
 
Puppet Design Patterns
Puppet Design PatternsPuppet Design Patterns
Puppet Design Patterns
David Danzilio
 
Puppet | Custom Modules & Using the Forge
Puppet | Custom Modules & Using the ForgePuppet | Custom Modules & Using the Forge
Puppet | Custom Modules & Using the Forge
Aaron Bernstein
 
20100622 e z_find_slides_gig_v2.1
20100622 e z_find_slides_gig_v2.120100622 e z_find_slides_gig_v2.1
20100622 e z_find_slides_gig_v2.1
Gilles Guirand
 
httpd — Apache Web Server
httpd — Apache Web Serverhttpd — Apache Web Server
httpd — Apache Web Server
webhostingguy
 
My sql with querys
My sql with querysMy sql with querys
My sql with querys
NIRMAL FELIX
 
Pluggable database 3
Pluggable database 3Pluggable database 3
Pluggable database 3
Osama Mustafa
 

What's hot (18)

MySql 5.7 Backup Script
MySql 5.7 Backup ScriptMySql 5.7 Backup Script
MySql 5.7 Backup Script
 
Apache
ApacheApache
Apache
 
MariaDB training
MariaDB trainingMariaDB training
MariaDB training
 
Instalar PENTAHO 5 en CentOS 6
Instalar PENTAHO 5 en CentOS 6Instalar PENTAHO 5 en CentOS 6
Instalar PENTAHO 5 en CentOS 6
 
hw1a
hw1ahw1a
hw1a
 
Standby db creation commands
Standby db creation commandsStandby db creation commands
Standby db creation commands
 
mapserver_install_linux
mapserver_install_linuxmapserver_install_linux
mapserver_install_linux
 
Instalacion ambiente web am en linux red hat
Instalacion ambiente web am en linux red hatInstalacion ambiente web am en linux red hat
Instalacion ambiente web am en linux red hat
 
Drupal 8 deploying
Drupal 8 deployingDrupal 8 deploying
Drupal 8 deploying
 
[INSIGHT OUT 2011] B12 better my sql security and administration(ronald)
[INSIGHT OUT 2011] B12 better my sql security and administration(ronald)[INSIGHT OUT 2011] B12 better my sql security and administration(ronald)
[INSIGHT OUT 2011] B12 better my sql security and administration(ronald)
 
Backup and Restore SALSA to a Secondary Server with a different IP address
Backup and Restore SALSA to a Secondary Server with a different IP addressBackup and Restore SALSA to a Secondary Server with a different IP address
Backup and Restore SALSA to a Secondary Server with a different IP address
 
Using Perl Stored Procedures for MariaDB
Using Perl Stored Procedures for MariaDBUsing Perl Stored Procedures for MariaDB
Using Perl Stored Procedures for MariaDB
 
Puppet Design Patterns
Puppet Design PatternsPuppet Design Patterns
Puppet Design Patterns
 
Puppet | Custom Modules & Using the Forge
Puppet | Custom Modules & Using the ForgePuppet | Custom Modules & Using the Forge
Puppet | Custom Modules & Using the Forge
 
20100622 e z_find_slides_gig_v2.1
20100622 e z_find_slides_gig_v2.120100622 e z_find_slides_gig_v2.1
20100622 e z_find_slides_gig_v2.1
 
httpd — Apache Web Server
httpd — Apache Web Serverhttpd — Apache Web Server
httpd — Apache Web Server
 
My sql with querys
My sql with querysMy sql with querys
My sql with querys
 
Pluggable database 3
Pluggable database 3Pluggable database 3
Pluggable database 3
 

Viewers also liked

Selling Drupal to the Enterprise
Selling Drupal to the EnterpriseSelling Drupal to the Enterprise
Selling Drupal to the Enterprise
Myplanet Digital
 
UX Lessons from the USSR: The Trouble With Manifestos
UX Lessons from the USSR: The Trouble With ManifestosUX Lessons from the USSR: The Trouble With Manifestos
UX Lessons from the USSR: The Trouble With Manifestos
Myplanet Digital
 
Agile 101
Agile 101Agile 101
Agile 101
Myplanet Digital
 
Drupal As A RESTful Backend For Client Side Applications
Drupal As A RESTful Backend For Client Side ApplicationsDrupal As A RESTful Backend For Client Side Applications
Drupal As A RESTful Backend For Client Side Applications
Myplanet Digital
 
Open Advocacy - Citizens Connected Goes Open Source
Open Advocacy - Citizens Connected Goes Open SourceOpen Advocacy - Citizens Connected Goes Open Source
Open Advocacy - Citizens Connected Goes Open Source
Myplanet Digital
 
DataPublic: Building Drupal-Powered Open Government (Nik Garkusha, Microsoft ...
DataPublic: Building Drupal-Powered Open Government (Nik Garkusha, Microsoft ...DataPublic: Building Drupal-Powered Open Government (Nik Garkusha, Microsoft ...
DataPublic: Building Drupal-Powered Open Government (Nik Garkusha, Microsoft ...
Myplanet Digital
 
How to incrementally integrate QA in an Agile Development Process
How to incrementally integrate QA in an Agile Development ProcessHow to incrementally integrate QA in an Agile Development Process
How to incrementally integrate QA in an Agile Development Process
Myplanet Digital
 

Viewers also liked (7)

Selling Drupal to the Enterprise
Selling Drupal to the EnterpriseSelling Drupal to the Enterprise
Selling Drupal to the Enterprise
 
UX Lessons from the USSR: The Trouble With Manifestos
UX Lessons from the USSR: The Trouble With ManifestosUX Lessons from the USSR: The Trouble With Manifestos
UX Lessons from the USSR: The Trouble With Manifestos
 
Agile 101
Agile 101Agile 101
Agile 101
 
Drupal As A RESTful Backend For Client Side Applications
Drupal As A RESTful Backend For Client Side ApplicationsDrupal As A RESTful Backend For Client Side Applications
Drupal As A RESTful Backend For Client Side Applications
 
Open Advocacy - Citizens Connected Goes Open Source
Open Advocacy - Citizens Connected Goes Open SourceOpen Advocacy - Citizens Connected Goes Open Source
Open Advocacy - Citizens Connected Goes Open Source
 
DataPublic: Building Drupal-Powered Open Government (Nik Garkusha, Microsoft ...
DataPublic: Building Drupal-Powered Open Government (Nik Garkusha, Microsoft ...DataPublic: Building Drupal-Powered Open Government (Nik Garkusha, Microsoft ...
DataPublic: Building Drupal-Powered Open Government (Nik Garkusha, Microsoft ...
 
How to incrementally integrate QA in an Agile Development Process
How to incrementally integrate QA in an Agile Development ProcessHow to incrementally integrate QA in an Agile Development Process
How to incrementally integrate QA in an Agile Development Process
 

Similar to Coding For Config: Install Profile Development Using Features

Automating Drupal Development: Makefiles, features and beyond
Automating Drupal Development: Makefiles, features and beyondAutomating Drupal Development: Makefiles, features and beyond
Automating Drupal Development: Makefiles, features and beyond
Nuvole
 
2017-03-11 02 Денис Нелюбин. Docker & Ansible - лучшие друзья DevOps
2017-03-11 02 Денис Нелюбин. Docker & Ansible - лучшие друзья DevOps2017-03-11 02 Денис Нелюбин. Docker & Ansible - лучшие друзья DevOps
2017-03-11 02 Денис Нелюбин. Docker & Ansible - лучшие друзья DevOps
Омские ИТ-субботники
 
Oracle11g On Fedora14
Oracle11g On Fedora14Oracle11g On Fedora14
Oracle11g On Fedora14
kmsa
 
Oracle11g on fedora14
Oracle11g on fedora14Oracle11g on fedora14
Oracle11g on fedora14
Khalid Matar Albuflasah
 
Puppet at Opera Sofware - PuppetCamp Oslo 2013
Puppet at Opera Sofware - PuppetCamp Oslo 2013Puppet at Opera Sofware - PuppetCamp Oslo 2013
Puppet at Opera Sofware - PuppetCamp Oslo 2013
Cosimo Streppone
 
Build Automation of PHP Applications
Build Automation of PHP ApplicationsBuild Automation of PHP Applications
Build Automation of PHP Applications
Pavan Kumar N
 
Installing oracle grid infrastructure and database 12c r1
Installing oracle grid infrastructure and database 12c r1Installing oracle grid infrastructure and database 12c r1
Installing oracle grid infrastructure and database 12c r1
Voeurng Sovann
 
9 steps to install and configure postgre sql from source on linux
9 steps to install and configure postgre sql from source on linux9 steps to install and configure postgre sql from source on linux
9 steps to install and configure postgre sql from source on linux
chinkshady
 
Oracle API Gateway Installation
Oracle API Gateway InstallationOracle API Gateway Installation
Oracle API Gateway Installation
Rakesh Gujjarlapudi
 
Linux configer
Linux configerLinux configer
Linux configer
MD. AL AMIN
 
Welcome aboard the team
Welcome aboard the teamWelcome aboard the team
Welcome aboard the team
Roberto Peruzzo
 
12c (12.1) Database installation on Solaris 11(11.2)
12c (12.1) Database  installation on Solaris 11(11.2)12c (12.1) Database  installation on Solaris 11(11.2)
12c (12.1) Database installation on Solaris 11(11.2)
K Kumar Guduru
 
Generators
GeneratorsGenerators
Generators
Allan Davis
 
Bundling Packages and Deploying Applications with RPM
Bundling Packages and Deploying Applications with RPMBundling Packages and Deploying Applications with RPM
Bundling Packages and Deploying Applications with RPM
Alexander Shopov
 
Introduction to JumpStart
Introduction to JumpStartIntroduction to JumpStart
Introduction to JumpStart
Scott McDermott
 
Ant_quick_guide
Ant_quick_guideAnt_quick_guide
Ant_quick_guide
ducquoc_vn
 
Bacula - Backup system
Bacula - Backup systemBacula - Backup system
Bacula - Backup system
Mohammad Parvin
 
OpenNebula, the foreman and CentOS play nice, too
OpenNebula, the foreman and CentOS play nice, tooOpenNebula, the foreman and CentOS play nice, too
OpenNebula, the foreman and CentOS play nice, too
inovex GmbH
 
Kolla project onboarding - OpenStack Summit Berlin 2018
Kolla project onboarding - OpenStack Summit Berlin 2018Kolla project onboarding - OpenStack Summit Berlin 2018
Kolla project onboarding - OpenStack Summit Berlin 2018
Eduardo Gonzalez Gutierrez
 
Drupal cambs ansible for drupal april 2015
Drupal cambs ansible for drupal april 2015Drupal cambs ansible for drupal april 2015
Drupal cambs ansible for drupal april 2015
Ryan Brown
 

Similar to Coding For Config: Install Profile Development Using Features (20)

Automating Drupal Development: Makefiles, features and beyond
Automating Drupal Development: Makefiles, features and beyondAutomating Drupal Development: Makefiles, features and beyond
Automating Drupal Development: Makefiles, features and beyond
 
2017-03-11 02 Денис Нелюбин. Docker & Ansible - лучшие друзья DevOps
2017-03-11 02 Денис Нелюбин. Docker & Ansible - лучшие друзья DevOps2017-03-11 02 Денис Нелюбин. Docker & Ansible - лучшие друзья DevOps
2017-03-11 02 Денис Нелюбин. Docker & Ansible - лучшие друзья DevOps
 
Oracle11g On Fedora14
Oracle11g On Fedora14Oracle11g On Fedora14
Oracle11g On Fedora14
 
Oracle11g on fedora14
Oracle11g on fedora14Oracle11g on fedora14
Oracle11g on fedora14
 
Puppet at Opera Sofware - PuppetCamp Oslo 2013
Puppet at Opera Sofware - PuppetCamp Oslo 2013Puppet at Opera Sofware - PuppetCamp Oslo 2013
Puppet at Opera Sofware - PuppetCamp Oslo 2013
 
Build Automation of PHP Applications
Build Automation of PHP ApplicationsBuild Automation of PHP Applications
Build Automation of PHP Applications
 
Installing oracle grid infrastructure and database 12c r1
Installing oracle grid infrastructure and database 12c r1Installing oracle grid infrastructure and database 12c r1
Installing oracle grid infrastructure and database 12c r1
 
9 steps to install and configure postgre sql from source on linux
9 steps to install and configure postgre sql from source on linux9 steps to install and configure postgre sql from source on linux
9 steps to install and configure postgre sql from source on linux
 
Oracle API Gateway Installation
Oracle API Gateway InstallationOracle API Gateway Installation
Oracle API Gateway Installation
 
Linux configer
Linux configerLinux configer
Linux configer
 
Welcome aboard the team
Welcome aboard the teamWelcome aboard the team
Welcome aboard the team
 
12c (12.1) Database installation on Solaris 11(11.2)
12c (12.1) Database  installation on Solaris 11(11.2)12c (12.1) Database  installation on Solaris 11(11.2)
12c (12.1) Database installation on Solaris 11(11.2)
 
Generators
GeneratorsGenerators
Generators
 
Bundling Packages and Deploying Applications with RPM
Bundling Packages and Deploying Applications with RPMBundling Packages and Deploying Applications with RPM
Bundling Packages and Deploying Applications with RPM
 
Introduction to JumpStart
Introduction to JumpStartIntroduction to JumpStart
Introduction to JumpStart
 
Ant_quick_guide
Ant_quick_guideAnt_quick_guide
Ant_quick_guide
 
Bacula - Backup system
Bacula - Backup systemBacula - Backup system
Bacula - Backup system
 
OpenNebula, the foreman and CentOS play nice, too
OpenNebula, the foreman and CentOS play nice, tooOpenNebula, the foreman and CentOS play nice, too
OpenNebula, the foreman and CentOS play nice, too
 
Kolla project onboarding - OpenStack Summit Berlin 2018
Kolla project onboarding - OpenStack Summit Berlin 2018Kolla project onboarding - OpenStack Summit Berlin 2018
Kolla project onboarding - OpenStack Summit Berlin 2018
 
Drupal cambs ansible for drupal april 2015
Drupal cambs ansible for drupal april 2015Drupal cambs ansible for drupal april 2015
Drupal cambs ansible for drupal april 2015
 

More from Myplanet Digital

Drupal With SMS And Telephony For Fun And Profit
Drupal With SMS And Telephony For Fun And ProfitDrupal With SMS And Telephony For Fun And Profit
Drupal With SMS And Telephony For Fun And Profit
Myplanet Digital
 
101 Exciting Tips To Get The Site You Need While Saving Time And Money (And G...
101 Exciting Tips To Get The Site You Need While Saving Time And Money (And G...101 Exciting Tips To Get The Site You Need While Saving Time And Money (And G...
101 Exciting Tips To Get The Site You Need While Saving Time And Money (And G...
Myplanet Digital
 
Stumbling Your Way to Succes: A Myplanet Tale
Stumbling Your Way to Succes: A Myplanet TaleStumbling Your Way to Succes: A Myplanet Tale
Stumbling Your Way to Succes: A Myplanet Tale
Myplanet Digital
 
Learning from Shopkeepers: Content Strategy for eCommerce
Learning from Shopkeepers: Content Strategy for eCommerceLearning from Shopkeepers: Content Strategy for eCommerce
Learning from Shopkeepers: Content Strategy for eCommerce
Myplanet Digital
 
Adaptive Content: Designing For The Unknown
Adaptive Content: Designing For The UnknownAdaptive Content: Designing For The Unknown
Adaptive Content: Designing For The Unknown
Myplanet Digital
 
Responsive Design: Drupal Business Summit (Erik von Stackelberg, Myplanet Dig...
Responsive Design: Drupal Business Summit (Erik von Stackelberg, Myplanet Dig...Responsive Design: Drupal Business Summit (Erik von Stackelberg, Myplanet Dig...
Responsive Design: Drupal Business Summit (Erik von Stackelberg, Myplanet Dig...
Myplanet Digital
 
Capturing Community (Michael Silverman, Duo Consulting)
Capturing Community (Michael Silverman, Duo Consulting)Capturing Community (Michael Silverman, Duo Consulting)
Capturing Community (Michael Silverman, Duo Consulting)
Myplanet Digital
 
Open Source at The ROM
Open Source at The ROMOpen Source at The ROM
Open Source at The ROM
Myplanet Digital
 
Case Study: Drupal Enabled Mobile -Ontario Physical Health Education Associat...
Case Study: Drupal Enabled Mobile -Ontario Physical Health Education Associat...Case Study: Drupal Enabled Mobile -Ontario Physical Health Education Associat...
Case Study: Drupal Enabled Mobile -Ontario Physical Health Education Associat...
Myplanet Digital
 
Gerry Dimnik's RCM Case Study-DBS 2011
Gerry Dimnik's RCM Case Study-DBS 2011Gerry Dimnik's RCM Case Study-DBS 2011
Gerry Dimnik's RCM Case Study-DBS 2011
Myplanet Digital
 
Benoit Marchand's BMO Case Study-DBS 2011
Benoit Marchand's BMO Case Study-DBS 2011Benoit Marchand's BMO Case Study-DBS 2011
Benoit Marchand's BMO Case Study-DBS 2011
Myplanet Digital
 
Sean Crowley's Government Talk-DBS 2011
Sean Crowley's Government Talk-DBS 2011Sean Crowley's Government Talk-DBS 2011
Sean Crowley's Government Talk-DBS 2011
Myplanet Digital
 

More from Myplanet Digital (12)

Drupal With SMS And Telephony For Fun And Profit
Drupal With SMS And Telephony For Fun And ProfitDrupal With SMS And Telephony For Fun And Profit
Drupal With SMS And Telephony For Fun And Profit
 
101 Exciting Tips To Get The Site You Need While Saving Time And Money (And G...
101 Exciting Tips To Get The Site You Need While Saving Time And Money (And G...101 Exciting Tips To Get The Site You Need While Saving Time And Money (And G...
101 Exciting Tips To Get The Site You Need While Saving Time And Money (And G...
 
Stumbling Your Way to Succes: A Myplanet Tale
Stumbling Your Way to Succes: A Myplanet TaleStumbling Your Way to Succes: A Myplanet Tale
Stumbling Your Way to Succes: A Myplanet Tale
 
Learning from Shopkeepers: Content Strategy for eCommerce
Learning from Shopkeepers: Content Strategy for eCommerceLearning from Shopkeepers: Content Strategy for eCommerce
Learning from Shopkeepers: Content Strategy for eCommerce
 
Adaptive Content: Designing For The Unknown
Adaptive Content: Designing For The UnknownAdaptive Content: Designing For The Unknown
Adaptive Content: Designing For The Unknown
 
Responsive Design: Drupal Business Summit (Erik von Stackelberg, Myplanet Dig...
Responsive Design: Drupal Business Summit (Erik von Stackelberg, Myplanet Dig...Responsive Design: Drupal Business Summit (Erik von Stackelberg, Myplanet Dig...
Responsive Design: Drupal Business Summit (Erik von Stackelberg, Myplanet Dig...
 
Capturing Community (Michael Silverman, Duo Consulting)
Capturing Community (Michael Silverman, Duo Consulting)Capturing Community (Michael Silverman, Duo Consulting)
Capturing Community (Michael Silverman, Duo Consulting)
 
Open Source at The ROM
Open Source at The ROMOpen Source at The ROM
Open Source at The ROM
 
Case Study: Drupal Enabled Mobile -Ontario Physical Health Education Associat...
Case Study: Drupal Enabled Mobile -Ontario Physical Health Education Associat...Case Study: Drupal Enabled Mobile -Ontario Physical Health Education Associat...
Case Study: Drupal Enabled Mobile -Ontario Physical Health Education Associat...
 
Gerry Dimnik's RCM Case Study-DBS 2011
Gerry Dimnik's RCM Case Study-DBS 2011Gerry Dimnik's RCM Case Study-DBS 2011
Gerry Dimnik's RCM Case Study-DBS 2011
 
Benoit Marchand's BMO Case Study-DBS 2011
Benoit Marchand's BMO Case Study-DBS 2011Benoit Marchand's BMO Case Study-DBS 2011
Benoit Marchand's BMO Case Study-DBS 2011
 
Sean Crowley's Government Talk-DBS 2011
Sean Crowley's Government Talk-DBS 2011Sean Crowley's Government Talk-DBS 2011
Sean Crowley's Government Talk-DBS 2011
 

Coding For Config: Install Profile Development Using Features

  • 3. 11/16/12 Coding for Config Install Profile Development Using Features Friday, 16 November, 12
  • 4. What is an install profile? Friday, 16 November, 12
  • 5. Distributions provide site features and functions for a specific type of site as a single download containing Drupal core, contributed modules, themes, and pre-defined configuration. Friday, 16 November, 12
  • 6. They make it possible to quickly set up a complex, use-specific site in fewer steps than if installing and configuring elements individually. Friday, 16 November, 12
  • 7. Distributions vs. Install Profiles Friday, 16 November, 12
  • 8. Distribution Requirements • Only GPL-compatible libraries • No cloned sandboxes • No includes[] directive • Only d.o modules and themes • Must use drupal-org- core.make • Must define git branches Friday, 16 November, 12
  • 9. Install Profile Requirements • Provide site features and functions for a specific type of site as a single download Friday, 16 November, 12
  • 10. Hard and Soft Configuration Friday, 16 November, 12
  • 11. Hard config Friday, 16 November, 12
  • 12. It has a machine name. It is easy to export. Friday, 16 November, 12
  • 13. Soft config Friday, 16 November, 12
  • 14. It has a numeric ID. It is hard to export. Friday, 16 November, 12
  • 15. When? Where? Why? Friday, 16 November, 12
  • 16. How do you make an install profile? Friday, 16 November, 12
  • 18. [profile].info [profile].profile [profile].install Friday, 16 November, 12
  • 19. build-[profile].make drupal-org.make drupal-org-core.make Friday, 16 November, 12
  • 20. modules/ contrib/ custom/ features/ Friday, 16 November, 12
  • 21. themes/ contrib/ custom/ Friday, 16 November, 12
  • 22. tmp/ docs/ tests/ snippets/ scripts/ build-dev.sh build-prod.sh Friday, 16 November, 12
  • 23. [profile].info [profile].profile [profile].install build-[profile].make drupal-org.make drupal-org-core.make modules/ custom/ features/ contrib/ libraries/ themes/ custom/ contrib/ tmp/ docs/ tests/ snippets/ scripts/ build-dev.sh build-prod.sh Friday, 16 November, 12
  • 24. File contents Friday, 16 November, 12
  • 26. [profile].info [profile].profile [profile].install Friday, 16 November, 12
  • 27. name = Spark description = Cutting-edge authoring experience improvements for Drupal. version = "7.x-1.0-alpha5" core = 7.x php = 5.3 ; The distribution_name property is used in the installer and other places as ; a label for the software being installed. distribution_name = Spark ; Required modules (Core) ; Copy/pasted from standard.info dependencies[] = block dependencies[] = color dependencies[] = comment dependencies[] = contextual dependencies[] = dblog dependencies[] = field_ui dependencies[] = file dependencies[] = help dependencies[] = image dependencies[] = list dependencies[] = menu dependencies[] = number Friday, 16 November, 12
  • 28. <?php /** * @file * Enables modules and site configuration for a standard site installation. */ /** * Implements hook_form_FORM_ID_alter() for install_configure_form(). * * Allows the profile to alter the site configuration form. */ function spark_form_install_configure_form_alter(&$form, $form_state) { // Pre-populate the site name with the server name. $form['site_information']['site_name']['#default_value'] = $_SERVER['SERVER_NAME']; } Friday, 16 November, 12
  • 29. <?php /** * @file * Install, update and uninstall functions for the spark install profile. */ /** * Implements hook_install(). * * Perform actions to set up the site for this profile. * * @see system_install() */ function spark_install() { ... } Friday, 16 November, 12
  • 30. <?php /** * @file * Install, update and uninstall functions for the spark install profile. */ /** * Implements hook_install(). * * Perform actions to set up the site for this profile. * * @see system_install() */ function spark_install() { ... } /** * Implements hook_update_N(). * Description of hook update. */ function spark_update_10001(&$sandbox) { ... } Friday, 16 November, 12
  • 31. <?php /** * @file * Install, update and uninstall functions for the spark install profile. */ /** * Implements hook_install(). * * Perform actions to set up the site for this profile. * * @see system_install() */ function spark_install() { ... } /** * Implements hook_update_N(). * Description of hook update. */ function spark_update_10001(&$sandbox) { ... } Friday, 16 November, 12
  • 32. Example install hooks Friday, 16 November, 12
  • 33. Set Variables /** * Implements hook_update_N(). * Enables default and admin themes. */ function profilename_update_10001(&$sandbox) { theme_enable(array('default_theme')); variable_set('theme_default', 'default_theme'); variable_set('node_admin_theme', '1'); return t('The admin and default themes have been set.'); } Friday, 16 November, 12
  • 34. Populate Menus /** * Implements hook_update_N(). * Generate menu links */ function profilename_update_10002(&$sandbox) { cache_clear_all(); //generate the menu links array //for the header menu $menu_links = array(); $menu_links['home'] = array( 'link_path' => '<front>', 'link_title' => t('Home'), 'weight' => 0, ); $menu_links['about'] = array( 'link_path' => 'about-us', 'link_title' => t('About Us'), 'weight' => 0, ); Friday, 16 November, 12
  • 35. Populate Menus //run menu_link_save on all of the items. foreach ($menu_links as $menu_link) { $menu_link['menu_name'] = 'menu-header'; $menu_link['module'] = 'menu'; menu_link_save($menu_link); } menu_cache_clear_all(); // Success! return t('Menu links have been generated'); } Friday, 16 November, 12
  • 36. Set blocks to regions /** * Implements hook_update_N(). * Set copyright blocks to its region. */ function profilename_update_10003(&$sandbox) { //pull in the theme name global $theme_key; // Set our block values $values = array( array( 'module' => 'custom_module', 'delta' => 'copyright', 'region' => 'footer', 'theme' => $theme_key, 'pages' => '', 'cache' => 8, 'status' => 1, 'weight' => 0, ), ); Friday, 16 November, 12
  • 37. Set blocks to regions // If a db_entry for these blocks exists, delete it foreach ($values as $position => $record) { $result = db_select('block', 'b') ->fields('b') ->condition('module', $record['module'], '=') ->condition('delta', $record['delta'], '=') ->condition('theme', $theme_key, '=') ->execute() ->fetchAssoc(); if (!empty($result['bid'])) { db_delete('block') ->condition('module', $record['module'], '=') ->condition('delta', $record['delta'], '=') ->condition('theme', $theme_key, '=') ->execute(); } } Friday, 16 November, 12
  • 38. Set blocks to regions // Insert into the database any block values that aren't already present foreach ($values as $record) { $query = db_insert('block')->fields(array('module', 'delta', 'theme', 'status', 'weight', 'region', 'pages', 'cache')); $query->values($record); $insert_result = $query->execute(); } // Success! return t('Copyright blocks has been placed in the footer.'); } Friday, 16 November, 12
  • 39. Populate a Vocabulary function profilename_requirements($phase) { $requirements = array(); // Ensure translations don't break at install time $t = get_t(); if ($phase == 'install' || $phase == 'update') { // Load taxonomy.module during install & updates if (!is_null(module_load_include('module', 'taxonomy'))) { $requirements['taxonomy'] = array( 'title' => $t('Taxonomy Module'), 'value' => $t('Taxonomy module loaded'), 'severity' => REQUIREMENT_OK, ); } else { $requirements['taxonomy'] = array( 'title' => $t('Taxonomy Module'), 'value' => $t('Taxonomy module not loaded'), 'severity' => REQUIREMENT_ERROR, ); } } return $requirements; } Friday, 16 November, 12
  • 40. Populate a Vocabulary /** * Implements hook_update_N(). * Create vocabulary and taxonomy terms */ function profilename_update_10004(&$sandbox) { // Get the vocabulary $vocab = taxonomy_vocabulary_machine_name_load('terms'); // If it's not created, do so (expected result) if(empty($vocab)) { $vocab = array( 'name' => 'Terms', 'machine_name' => 'terms', 'description' => 'A list of technical terms', 'hierarchy' => '0', 'module' => 'taxonomy', 'weight' => '0', ); taxonomy_vocabulary_save((object)$vocab); } Friday, 16 November, 12
  • 41. Populate a Vocabulary // Confirm that we've created it $vocab = taxonomy_vocabulary_machine_name_load('terms'); // If we haven't created it, stop if (empty($vocab)) { return t('Failed to create vocabulary.'); } // Else if the "terms" vocabulary exists, populate it. $terms = array( 'Drupal' => 'A content management system', 'Module' => 'A functional component of Drupal', ); Friday, 16 November, 12
  • 42. Populate a Vocabulary // For each term defined in the above array, add it to the "terms" vocabulary. foreach ($terms as $term_name => $term_description) { $term = new stdClass(); $term->vid = $vocab->vid; $term->name = $term_name; $term->description = $term_description; taxonomy_term_save($term); } // Success! return t('Created vocabulary and taxonomy terms'); } Friday, 16 November, 12
  • 43. build-[profile].make drupal-org.make drupal-org-core.make Friday, 16 November, 12
  • 44. build-spark.make api = 2 core = 7.x ; Include the definition for how to build Drupal core directly, including patches: includes[] = drupal-org-core.make ; Download the Spark install profile and recursively build all its dependencies: projects[spark][type] = profile projects[spark][download][type] = git projects[spark][download][branch] = 7.x-1.x Friday, 16 November, 12
  • 45. build-spark.make - with GIT! api = 2 core = 7.x ; Include the definition for how to build Drupal core directly, including patches: includes[] = drupal-org-core.make ; Download the Spark install profile and recursively build all its dependencies: projects[spark][type] = profile projects[spark][download][git]= git projects[spark][download][url] = http://git.drupal.org/project/spark.git projects[spark][download][revision] = master Friday, 16 November, 12
  • 46. drupal-org-core.make ; A separate drupal-org-core.make file makes it so we can apply core patches if we need to. api = 2 core = 7.x projects[drupal][type] = core projects[drupal][version] = 7.15 ; CORE PATCHES ; Hide the profiles under /profiles, so Spark is the only one. This allows the installation to start at the Language selection screen, bypassing a baffling and silly choice, especially for non-native speakers. projects[drupal][patch][1780598] = http://drupal.org/files/spark- install-1780598-5.patch ; This requires a core bug fix to not show the profile selection page when only one profile is visible. projects[drupal][patch][1074108] = http://drupal.org/files/1074108- skip-profile-16-7.x-do-not-test.patch Friday, 16 November, 12
  • 47. drupal-org.make ; This is a standard make file for packaging the distribution along with any contributed modules/themes or external libraries. Some examples are below. ; See http://drupal.org/node/159730 for more details. api = 2 core = 7.x ; Contributed modules; standard. projects[responsive_bartik][type] = theme projects[responsive_bartik][version] = 1.x-dev projects[responsive_bartik][subdir] = contrib projects[ctools][type] = module projects[ctools][version] = 1.2 projects[ctools][subdir] = contrib ; Fix incompatibilities with jQuery 1.7. projects[ctools][patch][1494860] = "http://drupal.org/files/ctools- dependent-js-broken-with-jquery-1.7-1494860-30.patch" Friday, 16 November, 12
  • 48. tmp/ docs/ tests/ snippets/ scripts/ build-dev.sh build-prod.sh Friday, 16 November, 12
  • 49. build-dev.sh #!/bin/bash # USAGE # Run this script as given. # # $ bash build-dev.sh [ /fullpath/to/project.make ] [ /fullpath/to/ build/project ] # # (Default paths are for Vagrant VM.) # Bail if non-zero exit code set -e PROJECT=profilename # Set from args BUILD_FILE="$1" BUILD_DEST="$2" Friday, 16 November, 12
  • 50. build-dev.sh # Drush make the site structure drush make ${BUILD_FILE} ${BUILD_DEST} --working-copy --prepare-install --yes --no-gitinfofile chmod 666 ${BUILD_DEST}/sites/default/settings.php echo "Appending settings.php snippets..." for f in ${BUILD_DEST}/profiles/${PROJECT}/tmp/snippets/*.settings.php do # Concatenate newline and snippet, then append to settings.php echo "" | cat - $f | tee -a ${BUILD_DEST}/sites/default/settings.php > /dev/null done chmod 444 ${BUILD_DEST}/sites/default/settings.php cd ${BUILD_DEST} drush cc all Friday, 16 November, 12
  • 51. [profile].info [profile].profile [profile].install build-[profile].make drupal-org.make drupal-org-core.make modules/ custom/ features/ contrib/ libraries/ themes/ custom/ contrib/ tmp/ docs/ tests/ snippets/ scripts/ build-dev.sh build-prod.sh Friday, 16 November, 12
  • 52. Debate & discussion. Friday, 16 November, 12
  • 53. Erin Marchak 207-90C Centurian Dr Contact us: Developer TF: 1.866.232.7456 Markham, Ontario erin@myplanetdigital.com Myplanetdigital.com L3R 8C5 Friday, 16 November, 12