Successfully reported this slideshow.
Your SlideShare is downloading. ×

Using the Features API

Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Upcoming SlideShare
Laravel intake 37 all days
Laravel intake 37 all days
Loading in …3
×

Check these out next

1 of 20 Ad
Advertisement

More Related Content

Slideshows for you (20)

Viewers also liked (20)

Advertisement

Similar to Using the Features API (20)

Advertisement

Recently uploaded (20)

Using the Features API

  1. 1. The Features API Making your modules Feature friendly.
  2. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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); } } }
  19. 19. The End Product
  20. 20. Questions?

×