SlideShare a Scribd company logo
The Features API

Making your modules Feature
         friendly.
What is the API thing?
Features is designed to capture module
“state” information and allows it to be
reproduced on any server.

The features API allows module coders to
add functions that allow this “State” to be
transferred.

Reference: API.txt file in Features module
Some Terminology
Feature module – A special module that captures the “state” of
module components needed for the function it defines. E.g.
profiles
Component Type – A grouping of configuration objects
Component – A configuration object that can be exported, e.g. a
view, content type, or CCK field. Components are listed in the
“edit component” field of the create feature page.
Machine Name – An identifier that is unique in and across sites
(as opposed to an DB id field which unique only on a site).
Exportable component – An exportable setting that can exist
only in code. E.g. a view.
Faux-Exportable component – a exportable setting that needs
to be in the db. Settings of this type are used to synchronize
entries in the DB using machine names
Feature Component Hashes
The Feature module code maintains various md5 hashes
that are use to compare states. Basically these hashes
are for:
   The state defined by the site settings
   The state defined by the current feature module code
   The last known state set by feature module code
These are used to generate the component status shown
in the Features management page.
Feature States
The status of the Feature component as displayed on the
Manage Features pages.
Default – All three component hashes match
Overridden – Site settings do not match
Needs Review – All three hashes are different. E.g.,
     local overrides with new feature code.
Rebuildable – Site settings match previous settings but
      the feature code is new.
Rebuilding – A rarely “seen” transient state that is set
      when a component is being synced with DB.
The API Hooks
-`hook_features_api()` defines the component types
- `hook_features_export()` processes a list of components,
       detecting any dependencies or further components
- `hook_features_export_options()` provides an array of
       components that can be exported for a given type.
- `hook_features_export_render()` renders a set of
       components to code as a defaults hook.
- `hook_features_revert()` reverts components of a feature
       back to their default (as defined in code) state.
-`hook_features_rebuild()` updates faux-exportable
      components back to their default state.
Reference: features.api.php in Features module code
A Case Study
Need:
The ldapauth module (part of LDAP Integration suite) has
some complex settings that often need to be duplicate
across a lot of server. Features support is a great way to do
this.
Requirements:
Transfer the module settings that fall into two types:
- Global settings stored as persistent variables
- LDAP server definitions (can be more than one) are stored
  in the ldapauth table.
A Case Study
Strategy:
  Create two Features component types to support the two
  kinds of settings.
  Utilize Strongarm and Ctools API/Code to simplify coding


Issues:
  The LDAP Server settings use DB generated id fields that
  do not map across server.
Adding Machine Name Support
In order to make the LDAP server configuration entries
exportable, they needed to support a cross site machine
name. This was done by:
• Adding a Machine name field to the ldapauth DB
• Adding code to retrieve/update ldapauth table entries by
  machine name ( ldapauth_server_load() )
• Modifying the admin screen to allow for autogeneration /
  editing of machine names. ( ldapauth_admin_form() )
• Modifying the initial install process to include this new field.
  ( ldapauth_schema() )
• Modifying the update process to add field and populate it.
  ( ldapauth_update_6005() )
Define the Component Types
The part of the Features API to implement is hook_features_api(). Here’s
the one for ldapauth:
function ldapauth_features_api() {
  $info = array(
    'ldap_servers' => array(
       'name' => 'LDAP Integration',
       'default_hook' => 'default_ldap_servers',
       'default_file' => FEATURES_DEFAULTS_INCLUDED_COMMON,
       'feature_source' => TRUE,
       'file' => drupal_get_path('module‘,'ldapauth‘).'/ldapauth.features.inc',
    )
  );
  if ( module_exists('strongarm') ) {
    $info['ldap_settings'] = array(
       'name' => 'LDAP Integration',
       'default_hook' => 'default_ldap_settings',
       'default_file' => FEATURES_DEFAULTS_INCLUDED_COMMON,
       'feature_source' => TRUE,
       'file' => drupal_get_path('module‘,'ldapauth‘).'/ldapauth.features.inc',
    );
  }
  return $info;
}
Component Type Options
For each component type, the <component>_features_export_options()
hook needs to be implements. This tells the Features management GUI
what components to display under each type.
function ldap_servers_features_export_options() {
  module_load_include('inc', 'ldapauth', 'includes/ldap.core');
  $options = array();
  $servers = ldapauth_server_load_all();
  foreach ( $servers as $server ) {
    $options[$server->machine_name] = $server->name;
  }
  return $options;
}
function ldap_settings_features_export_options() {
  $info = array(
    'ldapauth_login_process’=>t('Authentication‘).': ‘.t('Authentication mode'),
    'ldapauth_login_conflict’=>t('Authentication‘).': ‘.t('User conflict resolve pr
    'ldapauth_forget_passwords’=>t('Authentication‘).': ‘.t('Store user passwords')
    'ldapauth_sync_passwords’=>t('Authentication‘).': ‘.t('Sync passwords'),
    'ldapauth_create_users’=>t('Authentication‘).': ‘.t('Create new users'),
    'ldapauth_alter_username_field’ =>t('Authentication‘).': ‘.t('Alter user name f
    'ldapauth_disable_pass_change’=>t('Authentication‘).': ‘.t('Remove password fie
    'ldapauth_alter_email_field’=>t('Authentication‘).': ‘.t('Alter email field'),
  );
  ldapauth_submodules("ldap_settings", $info);
  return $info;
}
Features Export List
The features_export hook generates the information that goes into the
features module .info file at build time. Each component type needs one.
For the LDAP Global settings, we just define the module dependencies
and them make use of Strongarm’s variable_features_export() function.

function ldap_settings_features_export($data, &$export, $module_name = "") {
  $export['dependencies']['ldapauth'] = 'ldapauth';
  $submodules = ldapauth_submodules('ldap_settings');
  foreach ( $submodules as $submodule ) {
    if ( module_exists($submodule ) ) {
      $export['dependencies'][$submodule] = $submodule;
    }
  }
  return variable_features_export($data, $export, $module_name);
}
Features Export List
For the LDAP Server setting, we define the module dependencies
and return a list of server definition machine names that the user has
selected in the GUI.


function ldap_servers_features_export($data, &$export, $module_name = "") {
  module_load_include('inc', 'ldapauth', 'includes/ldap.core');
  $export['dependencies']['ldapauth'] = 'ldapauth';
  $submodules = ldapauth_submodules('ldap_servers');
  foreach ( $submodules as $submodule ) {
    if ( module_exists($submodule ) ) {
      $export['dependencies'][$submodule] = $submodule;
    }
  }
  foreach ( $data as $component ) {
    $export['features']['ldap_servers'][$component] = $component;
  }
  return array();
}
Features Export Render
The features_export_render hook generates the information that goes
into the features module code file(s) at build time. Each component type
needs one.
This feature is also used to generate the md5 hash tag to check for
override and other status.
For the LDAP Global settings, we just make use of Strongarm’s
variable_features_export_render() function.

function ldap_settings_features_export_render($module, $data) {
  return variable_features_export_render($module, $data);
}
Features Export Render
For the LDAP Server settings, we need to generate the code to create a
servers array with the machine name as a key and it’s settings as a value.
function ldap_servers_features_export_render($module, $data, $export) {
  module_load_include('inc', 'ldapauth', 'includes/ldap.core');
  $code = array();
  $code[] = ' $servers = array();';
  if ( is_null($export) ) {// If this is an override check, export all current servers
    $servers = ldapauth_server_load_all(TRUE);
    foreach ($servers as $server) {
      unset($server->sid);
      $server = (array) $server;
      ksort($server); // Sort because updated tables don't match, new tables
      $code[] =" $servers['{$server['machine_name']}'] = “.features_var_export($server, ‘ ‘)."
    }
  } else {
    foreach ($data as $name) {
      $server = ldapauth_server_load($name);
      unset($server->sid);
      $server = (array) $server;
      ksort($server);
      $code[] = " $servers['{$name}'] = " . features_var_export($server, ' ') . ";";
    }
  }
  $code[] = ' return $servers;';
  $code = implode("n", $code);
  return array('default_ldap_servers' => $code );
}
The check for import or override check is because if there is a new server entry,
it should be flagged as an override condition.
Features Rebuild
The features_rebuild hook is called when a feature is first installed.
Each component type needs one.
For the LDAP Global settings, we just make use of Strongarm’s
variable_features_rebuild () function.

function ldap_settings_features_rebuild($module) {
  variable_features_rebuild($module);
}

For the LDAP server settings, we need to get the settings in code and add any
NON-existent server.
function ldap_servers_features_rebuild($module) {
  module_load_include('inc', 'ldapauth', 'includes/ldap.core');
  $servers = module_invoke($module, 'default_ldap_servers');
  foreach ($servers as $server) {
    $existing_server = ldapauth_server_load($server['machine_name']);
    if ( empty($existing_server) ) {
      ldapauth_server_save($server);
    }
  }
}
Features Revert

The features_revert hook is called when a feature is
“reverted” to the settings defined in the feature code
via the admin GUI.

For the LDAP Global settings, we just make use of
Strongarm’s function.
function ldap_settings_features_rebuild($module) {
  variable_features_revert($module);
}
Features Revert
  For the LDAP server settings, any server entry not defined in the code needs
  to be deleted. Any existing server entry that is defined in code definition needs
  to have it settings update to match the code. Finally, any server entry defined
  in the code but not in the DB need to be created.

function ldap_servers_features_revert($module) {
  module_load_include('inc', 'ldapauth', 'includes/ldap.core');
  $default_servers = module_invoke($module, 'default_ldap_servers');
  $servers = ldapauth_server_load_all(TRUE);
  $existing_servers = array();
  // Update any existing servers in feature and delete those not in the feature.
  foreach ( $servers as $server ) {
    $machine_name = $server->machine_name;
    $existing_servers[$machine_name] = $machine_name;
    if ( isset($default_servers[$machine_name]) ) { // Update servers
      $default_servers[$machine_name]['sid'] = $server->sid;
      ldapauth_server_save($default_servers[$machine_name], TRUE);
    } else { // Delete server
      ldapauth_server_delete($server, TRUE);
    }
  }
  // Add any servers in the feature that don't exist.
  foreach ( $default_servers as $server ) {
    if ( ! isset($existing_servers[$server['machine_name']]) ) { // Add in default server not in
      unset($server['sid']);
      ldapauth_server_save($server, TRUE);
    }
  }
}
The End Product
Questions?

More Related Content

What's hot

Web注入+http漏洞等描述
Web注入+http漏洞等描述Web注入+http漏洞等描述
Web注入+http漏洞等描述
fangjiafu
 

What's hot (20)

MidCamp 2016 - Demystifying AJAX Callback Commands in Drupal 8
MidCamp 2016 - Demystifying AJAX Callback Commands in Drupal 8MidCamp 2016 - Demystifying AJAX Callback Commands in Drupal 8
MidCamp 2016 - Demystifying AJAX Callback Commands in Drupal 8
 
Jsp Notes
Jsp NotesJsp Notes
Jsp Notes
 
Drupal8Day: Demystifying Drupal 8 Ajax Callback commands
Drupal8Day: Demystifying Drupal 8 Ajax Callback commandsDrupal8Day: Demystifying Drupal 8 Ajax Callback commands
Drupal8Day: Demystifying Drupal 8 Ajax Callback commands
 
Php Unit With Zend Framework Zendcon09
Php Unit With Zend Framework   Zendcon09Php Unit With Zend Framework   Zendcon09
Php Unit With Zend Framework Zendcon09
 
Play!ng with scala
Play!ng with scalaPlay!ng with scala
Play!ng with scala
 
Михаил Крайнюк - Form API + Drupal 8: Form and AJAX
Михаил Крайнюк - Form API + Drupal 8: Form and AJAXМихаил Крайнюк - Form API + Drupal 8: Form and AJAX
Михаил Крайнюк - Form API + Drupal 8: Form and AJAX
 
Zend framework service
Zend framework serviceZend framework service
Zend framework service
 
Drupal 7 Theming - Behind the scenes
Drupal 7 Theming - Behind the scenes Drupal 7 Theming - Behind the scenes
Drupal 7 Theming - Behind the scenes
 
Getting Started-with-Laravel
Getting Started-with-LaravelGetting Started-with-Laravel
Getting Started-with-Laravel
 
How to execute an oracle stored procedure with nested table as a parameter fr...
How to execute an oracle stored procedure with nested table as a parameter fr...How to execute an oracle stored procedure with nested table as a parameter fr...
How to execute an oracle stored procedure with nested table as a parameter fr...
 
Jsf
JsfJsf
Jsf
 
Web注入+http漏洞等描述
Web注入+http漏洞等描述Web注入+http漏洞等描述
Web注入+http漏洞等描述
 
Raybiztech Guide To Backbone Javascript Library
Raybiztech Guide To Backbone Javascript LibraryRaybiztech Guide To Backbone Javascript Library
Raybiztech Guide To Backbone Javascript Library
 
JavaServer Faces 2.0 - JavaOne India 2011
JavaServer Faces 2.0 - JavaOne India 2011JavaServer Faces 2.0 - JavaOne India 2011
JavaServer Faces 2.0 - JavaOne India 2011
 
Catalyst patterns-yapc-eu-2016
Catalyst patterns-yapc-eu-2016Catalyst patterns-yapc-eu-2016
Catalyst patterns-yapc-eu-2016
 
REST API with CakePHP
REST API with CakePHPREST API with CakePHP
REST API with CakePHP
 
Unit testing after Zend Framework 1.8
Unit testing after Zend Framework 1.8Unit testing after Zend Framework 1.8
Unit testing after Zend Framework 1.8
 
WebGUI Developers Workshop
WebGUI Developers WorkshopWebGUI Developers Workshop
WebGUI Developers Workshop
 
Spring Web Views
Spring Web ViewsSpring Web Views
Spring Web Views
 
A Peek At The Future: Going Beyond JavaServer Faces 2.0 With RichFaces 4
A Peek At The Future: Going Beyond JavaServer Faces 2.0 With RichFaces 4A Peek At The Future: Going Beyond JavaServer Faces 2.0 With RichFaces 4
A Peek At The Future: Going Beyond JavaServer Faces 2.0 With RichFaces 4
 

Viewers also liked

Nerolac Machine
Nerolac MachineNerolac Machine
Nerolac Machine
zahid khan
 
Cuca entrevista gilberto gil
Cuca entrevista gilberto gilCuca entrevista gilberto gil
Cuca entrevista gilberto gil
Aline Carvalho
 
Jg t 169-2005 隔墙板行标
Jg t 169-2005 隔墙板行标Jg t 169-2005 隔墙板行标
Jg t 169-2005 隔墙板行标
guestee1be40f
 
LAVC Opening Day power pt.
LAVC Opening Day power pt.LAVC Opening Day power pt.
LAVC Opening Day power pt.
polaselm
 
Hp ra za oracle grid final.
Hp ra za oracle grid   final.Hp ra za oracle grid   final.
Hp ra za oracle grid final.
Oracle Hrvatska
 
Els Nombres Cuàntics
Els Nombres CuànticsEls Nombres Cuàntics
Els Nombres Cuàntics
victor11bcn
 
Auto Cad Work Presentation
Auto Cad Work PresentationAuto Cad Work Presentation
Auto Cad Work Presentation
guest93215b
 
Trial
TrialTrial
Trial
CCSU
 

Viewers also liked (20)

Nerolac Machine
Nerolac MachineNerolac Machine
Nerolac Machine
 
Кизел, Постановление № 68 от 06.04
Кизел, Постановление № 68 от 06.04Кизел, Постановление № 68 от 06.04
Кизел, Постановление № 68 от 06.04
 
Spreker Marketing trends 2016 - USP Consultancy / Installatie Marketing Platform
Spreker Marketing trends 2016 - USP Consultancy / Installatie Marketing PlatformSpreker Marketing trends 2016 - USP Consultancy / Installatie Marketing Platform
Spreker Marketing trends 2016 - USP Consultancy / Installatie Marketing Platform
 
Cuca entrevista gilberto gil
Cuca entrevista gilberto gilCuca entrevista gilberto gil
Cuca entrevista gilberto gil
 
Jg t 169-2005 隔墙板行标
Jg t 169-2005 隔墙板行标Jg t 169-2005 隔墙板行标
Jg t 169-2005 隔墙板行标
 
Preliminary results from a survey on the use of metrics and evaluation strate...
Preliminary results from a survey on the use of metrics and evaluation strate...Preliminary results from a survey on the use of metrics and evaluation strate...
Preliminary results from a survey on the use of metrics and evaluation strate...
 
mhealth - hype or help?
mhealth - hype or help?mhealth - hype or help?
mhealth - hype or help?
 
Telebras decreto
Telebras decreto Telebras decreto
Telebras decreto
 
LAVC Opening Day power pt.
LAVC Opening Day power pt.LAVC Opening Day power pt.
LAVC Opening Day power pt.
 
2011 worldfootwearyearbook
2011 worldfootwearyearbook2011 worldfootwearyearbook
2011 worldfootwearyearbook
 
Hp ra za oracle grid final.
Hp ra za oracle grid   final.Hp ra za oracle grid   final.
Hp ra za oracle grid final.
 
Poems
PoemsPoems
Poems
 
Snakes
SnakesSnakes
Snakes
 
Labci Presentation
Labci PresentationLabci Presentation
Labci Presentation
 
Greece4ever
Greece4everGreece4ever
Greece4ever
 
Els Nombres Cuàntics
Els Nombres CuànticsEls Nombres Cuàntics
Els Nombres Cuàntics
 
8 robotkatt
8 robotkatt8 robotkatt
8 robotkatt
 
Imagenes de vinto
Imagenes de vintoImagenes de vinto
Imagenes de vinto
 
Auto Cad Work Presentation
Auto Cad Work PresentationAuto Cad Work Presentation
Auto Cad Work Presentation
 
Trial
TrialTrial
Trial
 

Similar to Using the Features API

10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
arcware
 
Web applications with Catalyst
Web applications with CatalystWeb applications with Catalyst
Web applications with Catalyst
svilen.ivanov
 
GHC Participant Training
GHC Participant TrainingGHC Participant Training
GHC Participant Training
AidIQ
 
VPN Access Runbook
VPN Access RunbookVPN Access Runbook
VPN Access Runbook
Taha Shakeel
 

Similar to Using the Features API (20)

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
 
Zend framework service
Zend framework serviceZend framework service
Zend framework service
 
Silex Cheat Sheet
Silex Cheat SheetSilex Cheat Sheet
Silex Cheat Sheet
 
Silex Cheat Sheet
Silex Cheat SheetSilex Cheat Sheet
Silex Cheat Sheet
 
Rails3 way
Rails3 wayRails3 way
Rails3 way
 
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
 
PHPSpec - the only Design Tool you need - 4Developers
PHPSpec - the only Design Tool you need - 4DevelopersPHPSpec - the only Design Tool you need - 4Developers
PHPSpec - the only Design Tool you need - 4Developers
 
SproutCore and the Future of Web Apps
SproutCore and the Future of Web AppsSproutCore and the Future of Web Apps
SproutCore and the Future of Web Apps
 
SCR Annotations for Fun and Profit
SCR Annotations for Fun and ProfitSCR Annotations for Fun and Profit
SCR Annotations for Fun and Profit
 
Using Geeklog as a Web Application Framework
Using Geeklog as a Web Application FrameworkUsing Geeklog as a Web Application Framework
Using Geeklog as a Web Application Framework
 
Symfony2 from the Trenches
Symfony2 from the TrenchesSymfony2 from the Trenches
Symfony2 from the Trenches
 
Web applications with Catalyst
Web applications with CatalystWeb applications with Catalyst
Web applications with Catalyst
 
Symfony2 - from the trenches
Symfony2 - from the trenchesSymfony2 - from the trenches
Symfony2 - from the trenches
 
Mule data weave_10
Mule data weave_10Mule data weave_10
Mule data weave_10
 
Rails is not just Ruby
Rails is not just RubyRails is not just Ruby
Rails is not just Ruby
 
GHC Participant Training
GHC Participant TrainingGHC Participant Training
GHC Participant Training
 
VPN Access Runbook
VPN Access RunbookVPN Access Runbook
VPN Access Runbook
 
Simplify Your Rails Controllers With a Vengeance
Simplify Your Rails Controllers With a VengeanceSimplify Your Rails Controllers With a Vengeance
Simplify Your Rails Controllers With a Vengeance
 
Framework
FrameworkFramework
Framework
 
関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい
 

More from cgmonroe

More from cgmonroe (13)

Structured SEO Data Overview and How To
Structured SEO Data Overview and How ToStructured SEO Data Overview and How To
Structured SEO Data Overview and How To
 
Structured SEO Data: An overview and how to for Drupal
Structured SEO Data:  An overview and how to for DrupalStructured SEO Data:  An overview and how to for Drupal
Structured SEO Data: An overview and how to for Drupal
 
Tips on Securing Drupal Sites - DrupalCamp Atlanta (DCA)
Tips on Securing Drupal Sites - DrupalCamp Atlanta (DCA)Tips on Securing Drupal Sites - DrupalCamp Atlanta (DCA)
Tips on Securing Drupal Sites - DrupalCamp Atlanta (DCA)
 
Tips on Securing Drupal Sites
Tips on Securing Drupal SitesTips on Securing Drupal Sites
Tips on Securing Drupal Sites
 
Becoming "Facet"-nated with Search API
Becoming "Facet"-nated with Search APIBecoming "Facet"-nated with Search API
Becoming "Facet"-nated with Search API
 
Intro to drupal module internals asheville
Intro to drupal module internals ashevilleIntro to drupal module internals asheville
Intro to drupal module internals asheville
 
Using Content Delivery Networks with Drupal
Using Content Delivery Networks with DrupalUsing Content Delivery Networks with Drupal
Using Content Delivery Networks with Drupal
 
Solr facets and custom indices
Solr facets and custom indicesSolr facets and custom indices
Solr facets and custom indices
 
HTML Purifier, WYSIWYG, and TinyMCE
HTML Purifier, WYSIWYG, and TinyMCEHTML Purifier, WYSIWYG, and TinyMCE
HTML Purifier, WYSIWYG, and TinyMCE
 
The Drupal Strongarm Module - Tips and Tricks.
The Drupal Strongarm Module - Tips and Tricks.The Drupal Strongarm Module - Tips and Tricks.
The Drupal Strongarm Module - Tips and Tricks.
 
Intro to CSS Selectors in Drupal
Intro to CSS Selectors in DrupalIntro to CSS Selectors in Drupal
Intro to CSS Selectors in Drupal
 
Drupal Workflow Concepts
Drupal Workflow ConceptsDrupal Workflow Concepts
Drupal Workflow Concepts
 
TriDUG WebFM Presentation
TriDUG WebFM PresentationTriDUG WebFM Presentation
TriDUG WebFM Presentation
 

Recently uploaded

Search and Society: Reimagining Information Access for Radical Futures
Search and Society: Reimagining Information Access for Radical FuturesSearch and Society: Reimagining Information Access for Radical Futures
Search and Society: Reimagining Information Access for Radical Futures
Bhaskar Mitra
 

Recently uploaded (20)

Speed Wins: From Kafka to APIs in Minutes
Speed Wins: From Kafka to APIs in MinutesSpeed Wins: From Kafka to APIs in Minutes
Speed Wins: From Kafka to APIs in Minutes
 
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered QualitySoftware Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
 
Introduction to Open Source RAG and RAG Evaluation
Introduction to Open Source RAG and RAG EvaluationIntroduction to Open Source RAG and RAG Evaluation
Introduction to Open Source RAG and RAG Evaluation
 
Search and Society: Reimagining Information Access for Radical Futures
Search and Society: Reimagining Information Access for Radical FuturesSearch and Society: Reimagining Information Access for Radical Futures
Search and Society: Reimagining Information Access for Radical Futures
 
UiPath Test Automation using UiPath Test Suite series, part 3
UiPath Test Automation using UiPath Test Suite series, part 3UiPath Test Automation using UiPath Test Suite series, part 3
UiPath Test Automation using UiPath Test Suite series, part 3
 
UiPath Test Automation using UiPath Test Suite series, part 2
UiPath Test Automation using UiPath Test Suite series, part 2UiPath Test Automation using UiPath Test Suite series, part 2
UiPath Test Automation using UiPath Test Suite series, part 2
 
Measures in SQL (a talk at SF Distributed Systems meetup, 2024-05-22)
Measures in SQL (a talk at SF Distributed Systems meetup, 2024-05-22)Measures in SQL (a talk at SF Distributed Systems meetup, 2024-05-22)
Measures in SQL (a talk at SF Distributed Systems meetup, 2024-05-22)
 
Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........
 
Connector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a buttonConnector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a button
 
Knowledge engineering: from people to machines and back
Knowledge engineering: from people to machines and backKnowledge engineering: from people to machines and back
Knowledge engineering: from people to machines and back
 
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
 
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
 
Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...
 
IESVE for Early Stage Design and Planning
IESVE for Early Stage Design and PlanningIESVE for Early Stage Design and Planning
IESVE for Early Stage Design and Planning
 
Assuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyesAssuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyes
 
In-Depth Performance Testing Guide for IT Professionals
In-Depth Performance Testing Guide for IT ProfessionalsIn-Depth Performance Testing Guide for IT Professionals
In-Depth Performance Testing Guide for IT Professionals
 
Custom Approval Process: A New Perspective, Pavel Hrbacek & Anindya Halder
Custom Approval Process: A New Perspective, Pavel Hrbacek & Anindya HalderCustom Approval Process: A New Perspective, Pavel Hrbacek & Anindya Halder
Custom Approval Process: A New Perspective, Pavel Hrbacek & Anindya Halder
 
When stars align: studies in data quality, knowledge graphs, and machine lear...
When stars align: studies in data quality, knowledge graphs, and machine lear...When stars align: studies in data quality, knowledge graphs, and machine lear...
When stars align: studies in data quality, knowledge graphs, and machine lear...
 
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
 
How world-class product teams are winning in the AI era by CEO and Founder, P...
How world-class product teams are winning in the AI era by CEO and Founder, P...How world-class product teams are winning in the AI era by CEO and Founder, P...
How world-class product teams are winning in the AI era by CEO and Founder, P...
 

Using the Features API

  • 1. The Features API Making your modules Feature friendly.
  • 2. What is the API thing? Features is designed to capture module “state” information and allows it to be reproduced on any server. The features API allows module coders to add functions that allow this “State” to be transferred. Reference: API.txt file in Features module
  • 3. Some Terminology Feature module – A special module that captures the “state” of module components needed for the function it defines. E.g. profiles Component Type – A grouping of configuration objects Component – A configuration object that can be exported, e.g. a view, content type, or CCK field. Components are listed in the “edit component” field of the create feature page. Machine Name – An identifier that is unique in and across sites (as opposed to an DB id field which unique only on a site). Exportable component – An exportable setting that can exist only in code. E.g. a view. Faux-Exportable component – a exportable setting that needs to be in the db. Settings of this type are used to synchronize entries in the DB using machine names
  • 4. Feature Component Hashes The Feature module code maintains various md5 hashes that are use to compare states. Basically these hashes are for: The state defined by the site settings The state defined by the current feature module code The last known state set by feature module code These are used to generate the component status shown in the Features management page.
  • 5. Feature States The status of the Feature component as displayed on the Manage Features pages. Default – All three component hashes match Overridden – Site settings do not match Needs Review – All three hashes are different. E.g., local overrides with new feature code. Rebuildable – Site settings match previous settings but the feature code is new. Rebuilding – A rarely “seen” transient state that is set when a component is being synced with DB.
  • 6. The API Hooks -`hook_features_api()` defines the component types - `hook_features_export()` processes a list of components, detecting any dependencies or further components - `hook_features_export_options()` provides an array of components that can be exported for a given type. - `hook_features_export_render()` renders a set of components to code as a defaults hook. - `hook_features_revert()` reverts components of a feature back to their default (as defined in code) state. -`hook_features_rebuild()` updates faux-exportable components back to their default state. Reference: features.api.php in Features module code
  • 7. A Case Study Need: The ldapauth module (part of LDAP Integration suite) has some complex settings that often need to be duplicate across a lot of server. Features support is a great way to do this. Requirements: Transfer the module settings that fall into two types: - Global settings stored as persistent variables - LDAP server definitions (can be more than one) are stored in the ldapauth table.
  • 8. A Case Study Strategy: Create two Features component types to support the two kinds of settings. Utilize Strongarm and Ctools API/Code to simplify coding Issues: The LDAP Server settings use DB generated id fields that do not map across server.
  • 9. Adding Machine Name Support In order to make the LDAP server configuration entries exportable, they needed to support a cross site machine name. This was done by: • Adding a Machine name field to the ldapauth DB • Adding code to retrieve/update ldapauth table entries by machine name ( ldapauth_server_load() ) • Modifying the admin screen to allow for autogeneration / editing of machine names. ( ldapauth_admin_form() ) • Modifying the initial install process to include this new field. ( ldapauth_schema() ) • Modifying the update process to add field and populate it. ( ldapauth_update_6005() )
  • 10. Define the Component Types The part of the Features API to implement is hook_features_api(). Here’s the one for ldapauth: function ldapauth_features_api() { $info = array( 'ldap_servers' => array( 'name' => 'LDAP Integration', 'default_hook' => 'default_ldap_servers', 'default_file' => FEATURES_DEFAULTS_INCLUDED_COMMON, 'feature_source' => TRUE, 'file' => drupal_get_path('module‘,'ldapauth‘).'/ldapauth.features.inc', ) ); if ( module_exists('strongarm') ) { $info['ldap_settings'] = array( 'name' => 'LDAP Integration', 'default_hook' => 'default_ldap_settings', 'default_file' => FEATURES_DEFAULTS_INCLUDED_COMMON, 'feature_source' => TRUE, 'file' => drupal_get_path('module‘,'ldapauth‘).'/ldapauth.features.inc', ); } return $info; }
  • 11. Component Type Options For each component type, the <component>_features_export_options() hook needs to be implements. This tells the Features management GUI what components to display under each type. function ldap_servers_features_export_options() { module_load_include('inc', 'ldapauth', 'includes/ldap.core'); $options = array(); $servers = ldapauth_server_load_all(); foreach ( $servers as $server ) { $options[$server->machine_name] = $server->name; } return $options; } function ldap_settings_features_export_options() { $info = array( 'ldapauth_login_process’=>t('Authentication‘).': ‘.t('Authentication mode'), 'ldapauth_login_conflict’=>t('Authentication‘).': ‘.t('User conflict resolve pr 'ldapauth_forget_passwords’=>t('Authentication‘).': ‘.t('Store user passwords') 'ldapauth_sync_passwords’=>t('Authentication‘).': ‘.t('Sync passwords'), 'ldapauth_create_users’=>t('Authentication‘).': ‘.t('Create new users'), 'ldapauth_alter_username_field’ =>t('Authentication‘).': ‘.t('Alter user name f 'ldapauth_disable_pass_change’=>t('Authentication‘).': ‘.t('Remove password fie 'ldapauth_alter_email_field’=>t('Authentication‘).': ‘.t('Alter email field'), ); ldapauth_submodules("ldap_settings", $info); return $info; }
  • 12. Features Export List The features_export hook generates the information that goes into the features module .info file at build time. Each component type needs one. For the LDAP Global settings, we just define the module dependencies and them make use of Strongarm’s variable_features_export() function. function ldap_settings_features_export($data, &$export, $module_name = "") { $export['dependencies']['ldapauth'] = 'ldapauth'; $submodules = ldapauth_submodules('ldap_settings'); foreach ( $submodules as $submodule ) { if ( module_exists($submodule ) ) { $export['dependencies'][$submodule] = $submodule; } } return variable_features_export($data, $export, $module_name); }
  • 13. Features Export List For the LDAP Server setting, we define the module dependencies and return a list of server definition machine names that the user has selected in the GUI. function ldap_servers_features_export($data, &$export, $module_name = "") { module_load_include('inc', 'ldapauth', 'includes/ldap.core'); $export['dependencies']['ldapauth'] = 'ldapauth'; $submodules = ldapauth_submodules('ldap_servers'); foreach ( $submodules as $submodule ) { if ( module_exists($submodule ) ) { $export['dependencies'][$submodule] = $submodule; } } foreach ( $data as $component ) { $export['features']['ldap_servers'][$component] = $component; } return array(); }
  • 14. Features Export Render The features_export_render hook generates the information that goes into the features module code file(s) at build time. Each component type needs one. This feature is also used to generate the md5 hash tag to check for override and other status. For the LDAP Global settings, we just make use of Strongarm’s variable_features_export_render() function. function ldap_settings_features_export_render($module, $data) { return variable_features_export_render($module, $data); }
  • 15. Features Export Render For the LDAP Server settings, we need to generate the code to create a servers array with the machine name as a key and it’s settings as a value. function ldap_servers_features_export_render($module, $data, $export) { module_load_include('inc', 'ldapauth', 'includes/ldap.core'); $code = array(); $code[] = ' $servers = array();'; if ( is_null($export) ) {// If this is an override check, export all current servers $servers = ldapauth_server_load_all(TRUE); foreach ($servers as $server) { unset($server->sid); $server = (array) $server; ksort($server); // Sort because updated tables don't match, new tables $code[] =" $servers['{$server['machine_name']}'] = “.features_var_export($server, ‘ ‘)." } } else { foreach ($data as $name) { $server = ldapauth_server_load($name); unset($server->sid); $server = (array) $server; ksort($server); $code[] = " $servers['{$name}'] = " . features_var_export($server, ' ') . ";"; } } $code[] = ' return $servers;'; $code = implode("n", $code); return array('default_ldap_servers' => $code ); } The check for import or override check is because if there is a new server entry, it should be flagged as an override condition.
  • 16. Features Rebuild The features_rebuild hook is called when a feature is first installed. Each component type needs one. For the LDAP Global settings, we just make use of Strongarm’s variable_features_rebuild () function. function ldap_settings_features_rebuild($module) { variable_features_rebuild($module); } For the LDAP server settings, we need to get the settings in code and add any NON-existent server. function ldap_servers_features_rebuild($module) { module_load_include('inc', 'ldapauth', 'includes/ldap.core'); $servers = module_invoke($module, 'default_ldap_servers'); foreach ($servers as $server) { $existing_server = ldapauth_server_load($server['machine_name']); if ( empty($existing_server) ) { ldapauth_server_save($server); } } }
  • 17. Features Revert The features_revert hook is called when a feature is “reverted” to the settings defined in the feature code via the admin GUI. For the LDAP Global settings, we just make use of Strongarm’s function. function ldap_settings_features_rebuild($module) { variable_features_revert($module); }
  • 18. Features Revert For the LDAP server settings, any server entry not defined in the code needs to be deleted. Any existing server entry that is defined in code definition needs to have it settings update to match the code. Finally, any server entry defined in the code but not in the DB need to be created. function ldap_servers_features_revert($module) { module_load_include('inc', 'ldapauth', 'includes/ldap.core'); $default_servers = module_invoke($module, 'default_ldap_servers'); $servers = ldapauth_server_load_all(TRUE); $existing_servers = array(); // Update any existing servers in feature and delete those not in the feature. foreach ( $servers as $server ) { $machine_name = $server->machine_name; $existing_servers[$machine_name] = $machine_name; if ( isset($default_servers[$machine_name]) ) { // Update servers $default_servers[$machine_name]['sid'] = $server->sid; ldapauth_server_save($default_servers[$machine_name], TRUE); } else { // Delete server ldapauth_server_delete($server, TRUE); } } // Add any servers in the feature that don't exist. foreach ( $default_servers as $server ) { if ( ! isset($existing_servers[$server['machine_name']]) ) { // Add in default server not in unset($server['sid']); ldapauth_server_save($server, TRUE); } } }