SlideShare a Scribd company logo
1 of 7
Download to read offline
Using Drupal Features in B­Translator
Features are very useful for building Drupal profiles (re-usable applications). They provide a
way to capture and save in code the customizations that are done to a Drupal
site/application. Here I will describe how I use them in B-Translator.
Table Of Contents
• Benefits of using features
• Creating features
• Customizing features manually
• Making features configurable
• Saving and restoring private variables
Benefits Of Using Features
Some of the main benefits of using features are these:
1. They help the development and maintenance of the application.
Customization/configuration changes can be tracked and versioned (for example in
git) just like the code of the application.
2. They help the installation of a new instance of the application. Customizations can be
replayed (applied) easily on a new installation of the application, without having to
repeat them manually.
3. They make the application structured (as opposed to monolithic). For
example drupalchat is offered as a feature and can be installed very easily by
installing the feature. But sites that do not want to use it just don't install that
feature.
For more details about features (and their features) you can read these blogs:
• http://scotthadfield.ca/2011/09/21/features-part-2-managing-your-feature
• http://scotthadfield.ca/2011/09/30/features-part-3-re-usable-features
Creating Features
Features can be created and managed through UI. However I find the UI for creating
features not suitable (tedious, sluggish, unreliable), at least when creating features for a
Drupal profile. Fortunately they can also be fully managed from the command line
(with drush):
drush help --filter=features
First of all, we can get a list of all the so called features components:
drush @dev help features-components
drush @dev features-components '%:%' > features-components.txt
These are all the possible chunks of configuration that can be saved in a feature. All we
have to do is to search and select the ones that are relevant for the feature that we want to
build and then create a feature with these components. This will automatically generate the
code (Drupal API) that is necessary to apply these configurations.
For example, these are the components that I have selected for the layout feature (which is
supposed to re-construct automatically the layout and look of a freshly installed B-
Translator site):
variable:theme_bootstrap1_settings
variable:theme_default
box:headerbox
context:admin
context:content
context:frontpage
context:page
context:sitewide
context:translations
views_view:front_page
variable:site_frontpage
menu_links:main-menu:<front>
menu_links:main-menu:node/9
menu_links:main-menu:translations
menu_links:main-menu:node/1
menu_links:main-menu:contact
menu_custom:navig-menu
menu_links:navig-menu:translations
menu_links:navig-menu:node/9
menu_links:navig-menu:translations/search
menu_links:navig-menu:node/1
menu_links:navig-menu:contact
These include the theme, blocks layout, the front page view, and the menus.
Now I can create a feature that includes these components with a command like this:
drush @dev features-export 
--destination=profiles/btranslator/modules/features 
btranslator_layout $(cat layout_components)
It creates a feature on the directory:
/var/www/btranslator_dev/profiles/btranslator/modules/features/btranslator_layout/
Other features that I have created are:
btranslator_disqus, btranslator_invite, btranslator_sharethis, btranslator_captcha,btranslator
_drupalchat, btranslator_janrain, btranslator_simplenews, btranslator_mass_contact,btranslat
or_googleanalytics, etc. In order to recreate them easily, the script create-features.sh can
be used. It will create a feature for each list of components that is on the
directory components/.
The file create-features.sh has a content like this:
#!/bin/bash
### Create all the features.
### However some features need manual customization
### after being created (for example btranslator_layout).
drush="drush --yes @dev"
destination="profiles/btranslator/modules/features"
function create_feature
{
components=$1
feature_name="btranslator_$(basename $components)"
xargs --delimiter=$'n' --arg-file=$components 
$drush features-export --destination=$destination $feature_name
}
### go to the directory of the script
cd $(dirname $0)
### clear cache etc.
$drush cc all
rm -f components/*~
### create a feature for each file in 'components/'
for components in $(ls components/*)
do
echo "===> $components"
create_feature $components
done
Customizing Features Manually
A feature is basically just a Drupal module (although it is generated automatically by the
command features-export). So, we can further customize it manually if needed. And
sometimes there is the need for manual customization because the automatic generation
cannot get always everything right. In the case of the layout feature I added the file
btranslator_layout.install, which uses hook_enable() to make further customizations
after the feature is installed.
<?php
/**
* Implements hook_enable().
*/
function btranslator_layout_enable() {
_btranslator_layout_create_aliases();
_btranslator_layout_add_login_link();
_btranslator_layout_block_settings();
}
function _btranslator_layout_create_aliases() {
$aliases = array(
'udhezuesi' => 'Udhëzuesi i Përkthyesit',
'about' => 'About',
);
foreach ($aliases as $alias => $title) {
$query = "SELECT nid FROM {node} WHERE title='$title' AND status=1";
$nid = db_query($query)->fetchField();
if ($nid == FALSE) continue;
$source = "node/$nid";
db_query("DELETE FROM {url_alias} WHERE source='$source' AND
alias='$alias'");
$args = array('source' => $source, 'alias' => $alias);
path_save($args);
}
}
function _btranslator_layout_add_login_link() {
$query = "DELETE FROM {menu_links}
WHERE menu_name='user-menu'
AND link_path='user/login'
AND link_title='Login' AND plid='0' ";
db_query($query);
$login = array(
'menu_name' => 'user-menu',
'link_path' => 'user/login',
'link_title' => 'Login',
'plid' => '0',
'router_path' => 'user/login',
);
menu_link_save($login);
}
function _btranslator_layout_block_settings() {
// set the title of the menu block as Navigation
db_query("UPDATE {block} SET title='Navigation'
WHERE theme='bootstrap1' AND delta='navig-menu'");
// remove the title of the block user-menu
db_query("UPDATE {block} SET title='<none>'
WHERE theme='bootstrap1' AND delta='user-menu'");
// disable all the blocks for theme bootstrap1
// their place is managed by module context
db_query("UPDATE {block} SET status = '0' WHERE theme = 'bootstrap1'");
}
It creates aliases, which cannot be handled properly by the features. It creates a Login menu
link, which is not handled propperly by the features (although in general menu links can be
handled quite well by the features). It also sets the correct settings for the blocks in a
simple way, although there are other ways to handle them by the features.
Making Features Configurable
Some of the features are required and will be automatically installed when the (btranslator)
profile is installed, and some others are optional and can be installed later by the site
administrator, if they wish. Most of these features are closely related to some contrib
modules and basically just save default/reasonable values for the configuration settings of
the module.
Some of these modules are just wrappers to external API services, like disqus, sharethis,
janrain, recaptcha, googleanalytics, etc. Usually they need some API keys or any other
private attributes that are different from site to site. We cannot save these private
attributes on the feature, because they are specific for each different site. But we would
like to offer the administrator/maintainer of the (B-Translator) application an easy way to
manage them, without having to search up and down among a huge number of
configuration options available to the Drupal admin. In order to do this, I have customized
the automatically generated features, taking advantage of the fact that they are just Drupal
modules, and anything that works for Drupal modules works for them too.
For example, for the feature btranslator_googleanalytics, I have added this line
on btranslator_googleanalytics.module:
include_once 'btranslator_googleanalytics.admin.inc';
I have also created the file btranslator_googleanalytics.admin.inc with a content like this:
<?php
/**
* @file
* Configuration of googleanalytics.
*/
/**
* Implements hook_menu().
*/
function btranslator_googleanalytics_menu() {
$items = array();
$items['admin/config/btranslator/googleanalytics'] = array(
'title' => 'GoogleAnalytics',
'description' => 'Private GoogleAnalytics settings.',
'page callback' => 'drupal_get_form',
'page arguments' => array('btranslator_googleanalytics_config'),
'access arguments' => array('btranslator-admin'),
);
return $items;
}
/**
* Custom settings for GoogleAnalytics.
*
* @return
* An array containing form items to place on the module settings page.
*/
function btranslator_googleanalytics_config() {
$form = array();
$form['googleanalytics_account'] = array(
'#title' => t('Web Property ID'),
'#type' => 'textfield',
'#default_value' => variable_get('googleanalytics_account', 'UA-'),
'#size' => 15,
'#maxlength' => 20,
'#required' => TRUE,
'#description' => t('This ID is unique to each site you want to track
separately, and is in the form of UA-xxxxxxx-yy.
To get a Web Property ID, <a href="@analytics">
register your site with Google Analytics</a>,
or if you already have registered your site,
go to your Google Analytics Settings page
to see the ID next to every site profile.
<a href="@webpropertyid">Find more information
in the documentation</a>.',
array('@analytics' =>
'http://www.google.com/analytics/',
'@webpropertyid' =>
url('https://developers.google.com/analytics/resources/concepts/gaConceptsAccoun
ts',
array('fragment' =>
'webProperty')))),
);
return system_settings_form($form);
}
It creates a configuration page for GoogleAnalytics under the section of B-Translator
configurations. This admin/config page allows the site administrator to set quickly and
easily the account ID of GoogleAnalytics. All this is just normal Drupal stuff, which can be
done for any Drupal module. Nothing specially related to features. For my convenience, I
have copied the definition of the form field from the googleanalytics Drupal module itself
(from the file googleanalytics.abmin.inc).
Saving And Restoring Private Variables
If we cannot and should not keep private settings/attributes in features, then there should
be some other easy way for the site administrators to backup and restore them, without
making them public and available to everyone. This can be done by the script save-private-
vars.sh. It takes a list of variables from private-vars.txt and creates the file restore-
private-vars.php which keeps the values of these variables and can restore them. It works
like this:
features/save-private-vars.sh @dev
drush @dev php-script restore-private-vars.php
The file private-vars.txt looks like this:
disqus_domain
disqus_userapikey
disqus_publickey
disqus_secretkey
sharethis_publisherID
sharethis_twitter_handle
sharethis_twitter_suffix
rpx_apikey
simplenews_from_address
simplenews_test_address
mass_contact_default_sender_email
mass_contact_default_sender_name
recaptcha_private_key
recaptcha_public_key
googleanalytics_account
The script save-private-vars.sh has a content like this:
#!/bin/bash
### Save sensitive/private variables that should not be made public.
echo "Usage: $0 [@drush_alias]"
drush_alias=$1
drush="drush $drush_alias"
cat <<EOF > restore-private-vars.php
<?php
/**
* Backup of sensitive/private variables, that are specific
* only for this instance of B-Translator. This file should
* never be made public.
*/
// define variables
EOF
while read var_name
do
$drush vget "$var_name" --exact --pipe >> restore-private-vars.php
done < $(dirname $0)/private-vars.txt
cat <<EOF >> restore-private-vars.php
// set variables
foreach ($variables as $var_name => $var_value) {
variable_set($var_name, $var_value);
}
EOF
echo "
Restore variables with the command:
$drush php-script restore-private-vars.php
"
It can be useful as well to keep different sets of private variables for
the live, test and dev sites.

More Related Content

What's hot

Zend Framework 2 - presentation
Zend Framework 2 - presentationZend Framework 2 - presentation
Zend Framework 2 - presentation
yamcsha
 
Zend - Installation And Sample Project Creation
Zend - Installation And Sample Project Creation Zend - Installation And Sample Project Creation
Zend - Installation And Sample Project Creation
Compare Infobase Limited
 
PloneNG: What's new in Plone 4.2, 4.3, and beyond
PloneNG: What's new in Plone 4.2, 4.3, and beyondPloneNG: What's new in Plone 4.2, 4.3, and beyond
PloneNG: What's new in Plone 4.2, 4.3, and beyond
David Glick
 
Design patterns revisited with PHP 5.3
Design patterns revisited with PHP 5.3Design patterns revisited with PHP 5.3
Design patterns revisited with PHP 5.3
Fabien Potencier
 

What's hot (20)

Behaviour Driven Development con Behat & Drupal
Behaviour Driven Development con Behat & DrupalBehaviour Driven Development con Behat & Drupal
Behaviour Driven Development con Behat & Drupal
 
CMake Tutorial
CMake TutorialCMake Tutorial
CMake Tutorial
 
Developing a Joomla 3.x Component using RAD/FOF - Joomladay UK 2014
Developing a Joomla 3.x Component using RAD/FOF - Joomladay UK 2014Developing a Joomla 3.x Component using RAD/FOF - Joomladay UK 2014
Developing a Joomla 3.x Component using RAD/FOF - Joomladay UK 2014
 
Ansible Project Deploy (phpbenelux 2015)
Ansible Project Deploy (phpbenelux 2015)Ansible Project Deploy (phpbenelux 2015)
Ansible Project Deploy (phpbenelux 2015)
 
Effective CMake
Effective CMakeEffective CMake
Effective CMake
 
Zend Framework 2 - presentation
Zend Framework 2 - presentationZend Framework 2 - presentation
Zend Framework 2 - presentation
 
C make tutorial
C make tutorialC make tutorial
C make tutorial
 
Zend - Installation And Sample Project Creation
Zend - Installation And Sample Project Creation Zend - Installation And Sample Project Creation
Zend - Installation And Sample Project Creation
 
Java and XPages
Java and XPagesJava and XPages
Java and XPages
 
Building a Dynamic Website Using Django
Building a Dynamic Website Using DjangoBuilding a Dynamic Website Using Django
Building a Dynamic Website Using Django
 
Introduction To Ant1
Introduction To  Ant1Introduction To  Ant1
Introduction To Ant1
 
short_intro_to_CMake_(inria_REVES_team)
short_intro_to_CMake_(inria_REVES_team)short_intro_to_CMake_(inria_REVES_team)
short_intro_to_CMake_(inria_REVES_team)
 
Building Content Types with Dexterity
Building Content Types with DexterityBuilding Content Types with Dexterity
Building Content Types with Dexterity
 
PloneNG: What's new in Plone 4.2, 4.3, and beyond
PloneNG: What's new in Plone 4.2, 4.3, and beyondPloneNG: What's new in Plone 4.2, 4.3, and beyond
PloneNG: What's new in Plone 4.2, 4.3, and beyond
 
Custom module and theme development in Drupal7
Custom module and theme development in Drupal7Custom module and theme development in Drupal7
Custom module and theme development in Drupal7
 
CMake - Introduction and best practices
CMake - Introduction and best practicesCMake - Introduction and best practices
CMake - Introduction and best practices
 
Design patterns revisited with PHP 5.3
Design patterns revisited with PHP 5.3Design patterns revisited with PHP 5.3
Design patterns revisited with PHP 5.3
 
Introduction to Apache Ant
Introduction to Apache AntIntroduction to Apache Ant
Introduction to Apache Ant
 
Maven 3.0 at Øredev
Maven 3.0 at ØredevMaven 3.0 at Øredev
Maven 3.0 at Øredev
 
Django Architecture Introduction
Django Architecture IntroductionDjango Architecture Introduction
Django Architecture Introduction
 

Viewers also liked

8 Web Practices for Drupal
8  Web Practices for Drupal8  Web Practices for Drupal
8 Web Practices for Drupal
Wingston
 
Staging Drupal 8 31 09 1 3
Staging Drupal 8 31 09 1 3Staging Drupal 8 31 09 1 3
Staging Drupal 8 31 09 1 3
Drupalcon Paris
 
Drupal in the Cloud with Windows Azure
Drupal in the Cloud with Windows AzureDrupal in the Cloud with Windows Azure
Drupal in the Cloud with Windows Azure
Ford AntiTrust
 

Viewers also liked (17)

GeorgiaGov's move to Drupal - presentation by Nikhil Deshpande @nikofthehill
GeorgiaGov's move to Drupal - presentation by Nikhil Deshpande @nikofthehillGeorgiaGov's move to Drupal - presentation by Nikhil Deshpande @nikofthehill
GeorgiaGov's move to Drupal - presentation by Nikhil Deshpande @nikofthehill
 
8 Web Practices for Drupal
8  Web Practices for Drupal8  Web Practices for Drupal
8 Web Practices for Drupal
 
Staging Drupal 8 31 09 1 3
Staging Drupal 8 31 09 1 3Staging Drupal 8 31 09 1 3
Staging Drupal 8 31 09 1 3
 
Migrate
MigrateMigrate
Migrate
 
Drupal Migration
Drupal MigrationDrupal Migration
Drupal Migration
 
Drush 5.0 (DrupalCamp LA 2012) - Chris Charlton
Drush 5.0 (DrupalCamp LA 2012) - Chris CharltonDrush 5.0 (DrupalCamp LA 2012) - Chris Charlton
Drush 5.0 (DrupalCamp LA 2012) - Chris Charlton
 
Moving In: how to port your content from * to Drupal
Moving In: how to port your content from * to DrupalMoving In: how to port your content from * to Drupal
Moving In: how to port your content from * to Drupal
 
Building Archivable Websites
Building Archivable WebsitesBuilding Archivable Websites
Building Archivable Websites
 
Recipes for Drupal distributions
Recipes for Drupal distributionsRecipes for Drupal distributions
Recipes for Drupal distributions
 
Create Website In Indian Languages using drupal
Create Website In Indian Languages using drupalCreate Website In Indian Languages using drupal
Create Website In Indian Languages using drupal
 
Moving Drupal to the Cloud
Moving Drupal to the CloudMoving Drupal to the Cloud
Moving Drupal to the Cloud
 
Drupal in the Cloud with Windows Azure
Drupal in the Cloud with Windows AzureDrupal in the Cloud with Windows Azure
Drupal in the Cloud with Windows Azure
 
Data migration to Drupal using the migrate module
Data migration to Drupal using the migrate moduleData migration to Drupal using the migrate module
Data migration to Drupal using the migrate module
 
Migraine Drupal - syncing your staging and live sites
Migraine Drupal - syncing your staging and live sitesMigraine Drupal - syncing your staging and live sites
Migraine Drupal - syncing your staging and live sites
 
Content Staging in Drupal 8
Content Staging in Drupal 8Content Staging in Drupal 8
Content Staging in Drupal 8
 
Managing Translation Workflows in Drupal 7
Managing Translation Workflows in Drupal 7Managing Translation Workflows in Drupal 7
Managing Translation Workflows in Drupal 7
 
Migration from Legacy CMS to Drupal
Migration from Legacy CMS to DrupalMigration from Legacy CMS to Drupal
Migration from Legacy CMS to Drupal
 

Similar to Using Drupal Features in B-Translator

Drush. Why should it be used?
Drush. Why should it be used?Drush. Why should it be used?
Drush. Why should it be used?
Sergei Stryukov
 
Drupal 7-api-2010-11-10
Drupal 7-api-2010-11-10Drupal 7-api-2010-11-10
Drupal 7-api-2010-11-10
Shamsher Alam
 

Similar to Using Drupal Features in B-Translator (20)

Introduction And Basics of Modules in Drupal 7
Introduction And Basics of Modules in Drupal 7 Introduction And Basics of Modules in Drupal 7
Introduction And Basics of Modules in Drupal 7
 
Dashboard
DashboardDashboard
Dashboard
 
13th Sep, Drupal 7 advanced training by TCS
13th Sep, Drupal 7 advanced training by TCS 13th Sep, Drupal 7 advanced training by TCS
13th Sep, Drupal 7 advanced training by TCS
 
Features everywhere
Features everywhere Features everywhere
Features everywhere
 
Drupal 7 Theming - Behind the scenes
Drupal 7 Theming - Behind the scenes Drupal 7 Theming - Behind the scenes
Drupal 7 Theming - Behind the scenes
 
SynapseIndia drupal presentation on drupal best practices
SynapseIndia drupal  presentation on drupal best practicesSynapseIndia drupal  presentation on drupal best practices
SynapseIndia drupal presentation on drupal best practices
 
Drupal Day 2012 - Automating Drupal Development: Make!les, Features and Beyond
Drupal Day 2012 - Automating Drupal Development: Make!les, Features and BeyondDrupal Day 2012 - Automating Drupal Development: Make!les, Features and Beyond
Drupal Day 2012 - Automating Drupal Development: Make!les, Features and Beyond
 
Drupal 8 - Core and API Changes
Drupal 8 - Core and API ChangesDrupal 8 - Core and API Changes
Drupal 8 - Core and API Changes
 
Drupal 7 Features - Introduction - Basics
Drupal 7 Features - Introduction - BasicsDrupal 7 Features - Introduction - Basics
Drupal 7 Features - Introduction - Basics
 
Drupal Best Practices
Drupal Best PracticesDrupal Best Practices
Drupal Best Practices
 
Mageguru - magento custom module development
Mageguru -  magento custom module development Mageguru -  magento custom module development
Mageguru - magento custom module development
 
Simple module Development in Joomla! 2.5
Simple module Development in Joomla! 2.5Simple module Development in Joomla! 2.5
Simple module Development in Joomla! 2.5
 
First Steps in Drupal Code Driven Development
First Steps in Drupal Code Driven DevelopmentFirst Steps in Drupal Code Driven Development
First Steps in Drupal Code Driven Development
 
Advanced Module development
Advanced Module developmentAdvanced Module development
Advanced Module development
 
Drupal features knowledge sharing
Drupal features   knowledge sharingDrupal features   knowledge sharing
Drupal features knowledge sharing
 
An Introduction to Drupal
An Introduction to DrupalAn Introduction to Drupal
An Introduction to Drupal
 
Drush. Why should it be used?
Drush. Why should it be used?Drush. Why should it be used?
Drush. Why should it be used?
 
Drupal 8 Configuration Management
Drupal 8 Configuration ManagementDrupal 8 Configuration Management
Drupal 8 Configuration Management
 
Drupal Theme Development - DrupalCon Chicago 2011
Drupal Theme Development - DrupalCon Chicago 2011Drupal Theme Development - DrupalCon Chicago 2011
Drupal Theme Development - DrupalCon Chicago 2011
 
Drupal 7-api-2010-11-10
Drupal 7-api-2010-11-10Drupal 7-api-2010-11-10
Drupal 7-api-2010-11-10
 

More from Dashamir Hoxha

Easy Blogging With Emacs -- Cheatsheet
Easy Blogging With Emacs -- CheatsheetEasy Blogging With Emacs -- Cheatsheet
Easy Blogging With Emacs -- Cheatsheet
Dashamir Hoxha
 
Autobiography of Benjamin Franklin
Autobiography of Benjamin FranklinAutobiography of Benjamin Franklin
Autobiography of Benjamin Franklin
Dashamir Hoxha
 
Certificate -- Dashamir Hoxha -- edX/BerkeleyX -- CS169.1x Software as Service
Certificate -- Dashamir Hoxha -- edX/BerkeleyX -- CS169.1x Software as ServiceCertificate -- Dashamir Hoxha -- edX/BerkeleyX -- CS169.1x Software as Service
Certificate -- Dashamir Hoxha -- edX/BerkeleyX -- CS169.1x Software as Service
Dashamir Hoxha
 
Certificate -- Dashamir Hoxha -- edX/BerkeleyX -- CS188.1x Artificial Intelli...
Certificate -- Dashamir Hoxha -- edX/BerkeleyX -- CS188.1x Artificial Intelli...Certificate -- Dashamir Hoxha -- edX/BerkeleyX -- CS188.1x Artificial Intelli...
Certificate -- Dashamir Hoxha -- edX/BerkeleyX -- CS188.1x Artificial Intelli...
Dashamir Hoxha
 
Certificate -- Dashamir Hoxha -- edX/BerkeleyX -- CS169.2x Advanced Software ...
Certificate -- Dashamir Hoxha -- edX/BerkeleyX -- CS169.2x Advanced Software ...Certificate -- Dashamir Hoxha -- edX/BerkeleyX -- CS169.2x Advanced Software ...
Certificate -- Dashamir Hoxha -- edX/BerkeleyX -- CS169.2x Advanced Software ...
Dashamir Hoxha
 
Certificate -- Dashamir Hoxha -- edX/MITx -- 6.00x Introduction to Computer S...
Certificate -- Dashamir Hoxha -- edX/MITx -- 6.00x Introduction to Computer S...Certificate -- Dashamir Hoxha -- edX/MITx -- 6.00x Introduction to Computer S...
Certificate -- Dashamir Hoxha -- edX/MITx -- 6.00x Introduction to Computer S...
Dashamir Hoxha
 
phpWebApp presentation
phpWebApp presentationphpWebApp presentation
phpWebApp presentation
Dashamir Hoxha
 

More from Dashamir Hoxha (20)

Easy Blogging With Emacs -- Cheatsheet
Easy Blogging With Emacs -- CheatsheetEasy Blogging With Emacs -- Cheatsheet
Easy Blogging With Emacs -- Cheatsheet
 
Autobiography of Benjamin Franklin
Autobiography of Benjamin FranklinAutobiography of Benjamin Franklin
Autobiography of Benjamin Franklin
 
Easy Blogging With Emacs
Easy Blogging With EmacsEasy Blogging With Emacs
Easy Blogging With Emacs
 
IT Strategy of Albanian Customs
IT Strategy of Albanian CustomsIT Strategy of Albanian Customs
IT Strategy of Albanian Customs
 
Strategjia për IT-në e Doganës Shqiptare
Strategjia për IT-në e Doganës ShqiptareStrategjia për IT-në e Doganës Shqiptare
Strategjia për IT-në e Doganës Shqiptare
 
Certificate -- Dashamir Hoxha -- edX/BerkeleyX -- CS169.1x Software as Service
Certificate -- Dashamir Hoxha -- edX/BerkeleyX -- CS169.1x Software as ServiceCertificate -- Dashamir Hoxha -- edX/BerkeleyX -- CS169.1x Software as Service
Certificate -- Dashamir Hoxha -- edX/BerkeleyX -- CS169.1x Software as Service
 
Certificate -- Dashamir Hoxha -- edX/BerkeleyX -- CS188.1x Artificial Intelli...
Certificate -- Dashamir Hoxha -- edX/BerkeleyX -- CS188.1x Artificial Intelli...Certificate -- Dashamir Hoxha -- edX/BerkeleyX -- CS188.1x Artificial Intelli...
Certificate -- Dashamir Hoxha -- edX/BerkeleyX -- CS188.1x Artificial Intelli...
 
Certificate -- Dashamir Hoxha -- edX/BerkeleyX -- CS169.2x Advanced Software ...
Certificate -- Dashamir Hoxha -- edX/BerkeleyX -- CS169.2x Advanced Software ...Certificate -- Dashamir Hoxha -- edX/BerkeleyX -- CS169.2x Advanced Software ...
Certificate -- Dashamir Hoxha -- edX/BerkeleyX -- CS169.2x Advanced Software ...
 
Certificate -- Dashamir Hoxha -- edX/MITx -- 6.00x Introduction to Computer S...
Certificate -- Dashamir Hoxha -- edX/MITx -- 6.00x Introduction to Computer S...Certificate -- Dashamir Hoxha -- edX/MITx -- 6.00x Introduction to Computer S...
Certificate -- Dashamir Hoxha -- edX/MITx -- 6.00x Introduction to Computer S...
 
Udhëzuesi i Kturtle
Udhëzuesi i KturtleUdhëzuesi i Kturtle
Udhëzuesi i Kturtle
 
PPPoE With Mikrotik and Radius
PPPoE With Mikrotik and RadiusPPPoE With Mikrotik and Radius
PPPoE With Mikrotik and Radius
 
PPPoE With Mikrotik and Radius
PPPoE With Mikrotik and RadiusPPPoE With Mikrotik and Radius
PPPoE With Mikrotik and Radius
 
Using OpenFire With OpenLDAP
Using OpenFire With OpenLDAPUsing OpenFire With OpenLDAP
Using OpenFire With OpenLDAP
 
phpWebApp presentation
phpWebApp presentationphpWebApp presentation
phpWebApp presentation
 
phpWebApp article
phpWebApp articlephpWebApp article
phpWebApp article
 
Managing HotSpot Clients With FreeRadius
Managing HotSpot Clients With FreeRadiusManaging HotSpot Clients With FreeRadius
Managing HotSpot Clients With FreeRadius
 
The Digital Signature and the X.509/OpenPGP Authentication Models
The Digital Signature and the X.509/OpenPGP Authentication ModelsThe Digital Signature and the X.509/OpenPGP Authentication Models
The Digital Signature and the X.509/OpenPGP Authentication Models
 
Building a Gateway Server
Building a Gateway ServerBuilding a Gateway Server
Building a Gateway Server
 
An Algorithm for Incremental Multi-Resolution Modeling
An Algorithm for Incremental Multi-Resolution ModelingAn Algorithm for Incremental Multi-Resolution Modeling
An Algorithm for Incremental Multi-Resolution Modeling
 
SugarCE For Small And Medium Enterprises
SugarCE For Small And Medium EnterprisesSugarCE For Small And Medium Enterprises
SugarCE For Small And Medium Enterprises
 

Recently uploaded

Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
vu2urc
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
Joaquim Jorge
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
giselly40
 

Recently uploaded (20)

08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
 
Tech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdfTech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdf
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 

Using Drupal Features in B-Translator

  • 1. Using Drupal Features in B­Translator Features are very useful for building Drupal profiles (re-usable applications). They provide a way to capture and save in code the customizations that are done to a Drupal site/application. Here I will describe how I use them in B-Translator. Table Of Contents • Benefits of using features • Creating features • Customizing features manually • Making features configurable • Saving and restoring private variables Benefits Of Using Features Some of the main benefits of using features are these: 1. They help the development and maintenance of the application. Customization/configuration changes can be tracked and versioned (for example in git) just like the code of the application. 2. They help the installation of a new instance of the application. Customizations can be replayed (applied) easily on a new installation of the application, without having to repeat them manually. 3. They make the application structured (as opposed to monolithic). For example drupalchat is offered as a feature and can be installed very easily by installing the feature. But sites that do not want to use it just don't install that feature. For more details about features (and their features) you can read these blogs: • http://scotthadfield.ca/2011/09/21/features-part-2-managing-your-feature • http://scotthadfield.ca/2011/09/30/features-part-3-re-usable-features Creating Features Features can be created and managed through UI. However I find the UI for creating features not suitable (tedious, sluggish, unreliable), at least when creating features for a Drupal profile. Fortunately they can also be fully managed from the command line (with drush): drush help --filter=features First of all, we can get a list of all the so called features components: drush @dev help features-components drush @dev features-components '%:%' > features-components.txt
  • 2. These are all the possible chunks of configuration that can be saved in a feature. All we have to do is to search and select the ones that are relevant for the feature that we want to build and then create a feature with these components. This will automatically generate the code (Drupal API) that is necessary to apply these configurations. For example, these are the components that I have selected for the layout feature (which is supposed to re-construct automatically the layout and look of a freshly installed B- Translator site): variable:theme_bootstrap1_settings variable:theme_default box:headerbox context:admin context:content context:frontpage context:page context:sitewide context:translations views_view:front_page variable:site_frontpage menu_links:main-menu:<front> menu_links:main-menu:node/9 menu_links:main-menu:translations menu_links:main-menu:node/1 menu_links:main-menu:contact menu_custom:navig-menu menu_links:navig-menu:translations menu_links:navig-menu:node/9 menu_links:navig-menu:translations/search menu_links:navig-menu:node/1 menu_links:navig-menu:contact These include the theme, blocks layout, the front page view, and the menus. Now I can create a feature that includes these components with a command like this: drush @dev features-export --destination=profiles/btranslator/modules/features btranslator_layout $(cat layout_components) It creates a feature on the directory: /var/www/btranslator_dev/profiles/btranslator/modules/features/btranslator_layout/ Other features that I have created are: btranslator_disqus, btranslator_invite, btranslator_sharethis, btranslator_captcha,btranslator _drupalchat, btranslator_janrain, btranslator_simplenews, btranslator_mass_contact,btranslat or_googleanalytics, etc. In order to recreate them easily, the script create-features.sh can be used. It will create a feature for each list of components that is on the directory components/. The file create-features.sh has a content like this: #!/bin/bash ### Create all the features. ### However some features need manual customization
  • 3. ### after being created (for example btranslator_layout). drush="drush --yes @dev" destination="profiles/btranslator/modules/features" function create_feature { components=$1 feature_name="btranslator_$(basename $components)" xargs --delimiter=$'n' --arg-file=$components $drush features-export --destination=$destination $feature_name } ### go to the directory of the script cd $(dirname $0) ### clear cache etc. $drush cc all rm -f components/*~ ### create a feature for each file in 'components/' for components in $(ls components/*) do echo "===> $components" create_feature $components done Customizing Features Manually A feature is basically just a Drupal module (although it is generated automatically by the command features-export). So, we can further customize it manually if needed. And sometimes there is the need for manual customization because the automatic generation cannot get always everything right. In the case of the layout feature I added the file btranslator_layout.install, which uses hook_enable() to make further customizations after the feature is installed. <?php /** * Implements hook_enable(). */ function btranslator_layout_enable() { _btranslator_layout_create_aliases(); _btranslator_layout_add_login_link(); _btranslator_layout_block_settings(); } function _btranslator_layout_create_aliases() { $aliases = array( 'udhezuesi' => 'Udhëzuesi i Përkthyesit',
  • 4. 'about' => 'About', ); foreach ($aliases as $alias => $title) { $query = "SELECT nid FROM {node} WHERE title='$title' AND status=1"; $nid = db_query($query)->fetchField(); if ($nid == FALSE) continue; $source = "node/$nid"; db_query("DELETE FROM {url_alias} WHERE source='$source' AND alias='$alias'"); $args = array('source' => $source, 'alias' => $alias); path_save($args); } } function _btranslator_layout_add_login_link() { $query = "DELETE FROM {menu_links} WHERE menu_name='user-menu' AND link_path='user/login' AND link_title='Login' AND plid='0' "; db_query($query); $login = array( 'menu_name' => 'user-menu', 'link_path' => 'user/login', 'link_title' => 'Login', 'plid' => '0', 'router_path' => 'user/login', ); menu_link_save($login); } function _btranslator_layout_block_settings() { // set the title of the menu block as Navigation db_query("UPDATE {block} SET title='Navigation' WHERE theme='bootstrap1' AND delta='navig-menu'"); // remove the title of the block user-menu db_query("UPDATE {block} SET title='<none>' WHERE theme='bootstrap1' AND delta='user-menu'"); // disable all the blocks for theme bootstrap1 // their place is managed by module context db_query("UPDATE {block} SET status = '0' WHERE theme = 'bootstrap1'"); } It creates aliases, which cannot be handled properly by the features. It creates a Login menu link, which is not handled propperly by the features (although in general menu links can be handled quite well by the features). It also sets the correct settings for the blocks in a simple way, although there are other ways to handle them by the features. Making Features Configurable Some of the features are required and will be automatically installed when the (btranslator)
  • 5. profile is installed, and some others are optional and can be installed later by the site administrator, if they wish. Most of these features are closely related to some contrib modules and basically just save default/reasonable values for the configuration settings of the module. Some of these modules are just wrappers to external API services, like disqus, sharethis, janrain, recaptcha, googleanalytics, etc. Usually they need some API keys or any other private attributes that are different from site to site. We cannot save these private attributes on the feature, because they are specific for each different site. But we would like to offer the administrator/maintainer of the (B-Translator) application an easy way to manage them, without having to search up and down among a huge number of configuration options available to the Drupal admin. In order to do this, I have customized the automatically generated features, taking advantage of the fact that they are just Drupal modules, and anything that works for Drupal modules works for them too. For example, for the feature btranslator_googleanalytics, I have added this line on btranslator_googleanalytics.module: include_once 'btranslator_googleanalytics.admin.inc'; I have also created the file btranslator_googleanalytics.admin.inc with a content like this: <?php /** * @file * Configuration of googleanalytics. */ /** * Implements hook_menu(). */ function btranslator_googleanalytics_menu() { $items = array(); $items['admin/config/btranslator/googleanalytics'] = array( 'title' => 'GoogleAnalytics', 'description' => 'Private GoogleAnalytics settings.', 'page callback' => 'drupal_get_form', 'page arguments' => array('btranslator_googleanalytics_config'), 'access arguments' => array('btranslator-admin'), ); return $items; } /** * Custom settings for GoogleAnalytics. * * @return * An array containing form items to place on the module settings page. */ function btranslator_googleanalytics_config() { $form = array(); $form['googleanalytics_account'] = array(
  • 6. '#title' => t('Web Property ID'), '#type' => 'textfield', '#default_value' => variable_get('googleanalytics_account', 'UA-'), '#size' => 15, '#maxlength' => 20, '#required' => TRUE, '#description' => t('This ID is unique to each site you want to track separately, and is in the form of UA-xxxxxxx-yy. To get a Web Property ID, <a href="@analytics"> register your site with Google Analytics</a>, or if you already have registered your site, go to your Google Analytics Settings page to see the ID next to every site profile. <a href="@webpropertyid">Find more information in the documentation</a>.', array('@analytics' => 'http://www.google.com/analytics/', '@webpropertyid' => url('https://developers.google.com/analytics/resources/concepts/gaConceptsAccoun ts', array('fragment' => 'webProperty')))), ); return system_settings_form($form); } It creates a configuration page for GoogleAnalytics under the section of B-Translator configurations. This admin/config page allows the site administrator to set quickly and easily the account ID of GoogleAnalytics. All this is just normal Drupal stuff, which can be done for any Drupal module. Nothing specially related to features. For my convenience, I have copied the definition of the form field from the googleanalytics Drupal module itself (from the file googleanalytics.abmin.inc). Saving And Restoring Private Variables If we cannot and should not keep private settings/attributes in features, then there should be some other easy way for the site administrators to backup and restore them, without making them public and available to everyone. This can be done by the script save-private- vars.sh. It takes a list of variables from private-vars.txt and creates the file restore- private-vars.php which keeps the values of these variables and can restore them. It works like this: features/save-private-vars.sh @dev drush @dev php-script restore-private-vars.php The file private-vars.txt looks like this: disqus_domain disqus_userapikey disqus_publickey disqus_secretkey sharethis_publisherID
  • 7. sharethis_twitter_handle sharethis_twitter_suffix rpx_apikey simplenews_from_address simplenews_test_address mass_contact_default_sender_email mass_contact_default_sender_name recaptcha_private_key recaptcha_public_key googleanalytics_account The script save-private-vars.sh has a content like this: #!/bin/bash ### Save sensitive/private variables that should not be made public. echo "Usage: $0 [@drush_alias]" drush_alias=$1 drush="drush $drush_alias" cat <<EOF > restore-private-vars.php <?php /** * Backup of sensitive/private variables, that are specific * only for this instance of B-Translator. This file should * never be made public. */ // define variables EOF while read var_name do $drush vget "$var_name" --exact --pipe >> restore-private-vars.php done < $(dirname $0)/private-vars.txt cat <<EOF >> restore-private-vars.php // set variables foreach ($variables as $var_name => $var_value) { variable_set($var_name, $var_value); } EOF echo " Restore variables with the command: $drush php-script restore-private-vars.php " It can be useful as well to keep different sets of private variables for the live, test and dev sites.