Code-driven Development:Using Features Effectively in D6 and D7       Antonio De Marco       Andrea Pescetti         anton...
Code         Settings             ContentFilesystem   Database
Code              ContentSettings Filesystem   Database
How can multiple developers work together on the same project?
Sharing database dumps?
Major drawbacks• Not ideal for a distributed team• Makes it difficult to push settings to production• Content and settings ...
Put everything in code
Major benefits• Code can be versioned• Conflicts can be solved• Content and settings are separated• Easy to push changes to ...
Features: storing configuration in code
feature_news.infocore = "6.x"dependencies[] = "context"dependencies[] = "features"dependencies[] = "imagecache"dependencie...
From DB to code and vice versa  $ # Dump your changes into code.  $ drush features-update feature_name  $ # Restore your c...
Want to add a component to a feature?1. add it to the .info file2. $ drush features-update feature_name
Want to remove a component from a feature?  1. remove it from the .info file  2. $ drush features-update feature_name
Project bootstrap
project.makeproject.profile
project.makecore = "6.x"; Contribprojects[features][version] = "1.0"projects[features][subdir] = "contrib"projects[views][...
project.profile/**  * Implementation of hook_profile_details().  */function project_profile_details() {   return array(   ...
Use the controller featureto keep track of developmentEnable/disable other features, store sitewide   configuration, share ...
Code-driven workflow
Controller Feature WorkflowDeveloper A                                                                                     ...
Controller Feature WorkflowDeveloper A                                                            TimeDeveloper B          ...
Features are modules.Modules can be updated via hook_update_N()
hook_update_N()/**  * Enabling Rules module  */function feature_controller_update_6001() {   $return = array();   $modules...
Controller Feature Workflow              6001Developer A                                                        TimeDevelop...
Controller Feature Workflow              6001Developer A                                                                   ...
hook_update_N()/**  * Removing contributor role  */function feature_controller_update_6002() {   $return = array();   $rol...
Controller Feature Workflow              6001Developer A                                                                   ...
Controller Feature Workflow              6001Developer A                                                                   ...
hook_update_N()/**  * Adding Nuvole OpenID to admin account  */function feature_controller_update_6003() {   $return = arr...
project.make...projects[inline][type] = "module"projects[inline][download][type] = "cvs"projects[inline][download][module]...
Controller Feature Workflow              6001Developer A                                                                   ...
Controller Feature Workflow              6001Developer A                                                                   ...
hook_update_N() is not enough. Structural updates go in hook_install() too
Controller Feature Workflow              6001Developer A                                                 TimeDeveloper B   ...
hook_install()/** * Implementation of hook_install() */function feature_controller_install() {  $return = array();    $mod...
Controller Feature Workflow              6001Developer A                                                                   ...
Controller Feature Workflow              6001Developer A                                                                   ...
hook_update_N()/**  * Enabling News feature  */function feature_controller_update_6004() {   $return = array();   $modules...
/** * Implementation of hook_install() */function feature_controller_install() {  $return = array();    $modules = array(r...
Controller Feature Workflow              6001Developer A                                                                   ...
Code conventions for a better world.
Feature namespace# Feature News (feature_news)Views                feature_news_blocks                     feature_news_li...
Content type namespace# News (news)CCK Fields           field_news_pictures                     field_news_linksImagecache...
Features BoundariesPackage functionalities in a logical way
Features Inheritance Re-use and extend features
Drupal 7
Installation profiles are like modules            project.info           project.install           project.profile
project.infoname = Projectdescription = Project Description.core = 7.xdependencies[] = "context"dependencies[] = "features...
project.install/**  * Enabling Rules module  */function project_update_6001() {   $return = array();   $modules = array(ru...
project.profile/** * Implementation of hook_install_tasks() */function project_install_tasks($install_state) {    ...}/** ...
http://chicago2011.drupal.org/training/
See also:Installation Profiles As A Development Tool              by Florian Loretanhttp://bxl2011.drupaldays.org/node/280
Thank You. http://nuvole.org   @nuvoleweb
Code driven development: using Features effectively in Drupal 6 and 7
Code driven development: using Features effectively in Drupal 6 and 7
Upcoming SlideShare
Loading in …5
×

Code driven development: using Features effectively in Drupal 6 and 7

10,067 views

Published on

Code driven development: using Features effectively in Drupal 6 and 7

  1. 1. Code-driven Development:Using Features Effectively in D6 and D7 Antonio De Marco Andrea Pescetti antonio@nuvole.org andrea@nuvole.org
  2. 2. Code Settings ContentFilesystem Database
  3. 3. Code ContentSettings Filesystem Database
  4. 4. How can multiple developers work together on the same project?
  5. 5. Sharing database dumps?
  6. 6. Major drawbacks• Not ideal for a distributed team• Makes it difficult to push settings to production• Content and settings are mixed in one db dump• Easy to lose control
  7. 7. Put everything in code
  8. 8. Major benefits• Code can be versioned• Conflicts can be solved• Content and settings are separated• Easy to push changes to production
  9. 9. Features: storing configuration in code
  10. 10. feature_news.infocore = "6.x"dependencies[] = "context"dependencies[] = "features"dependencies[] = "imagecache"dependencies[] = "imagefield"description = "Publish news."features[content][] = "news-field_news_image"features[context][] = "feature_news_list"features[ctools][] = "context:context:3"features[ctools][] = "strongarm:strongarm:1"features[imagecache][] = "news-badge"features[imagecache][] = "news-m"features[imagecache][] = "news-s"features[node][] = "news"...name = "Feature News"package = "Features"project = "feature_news"version = "6.x-1.0-dev"
  11. 11. From DB to code and vice versa $ # Dump your changes into code. $ drush features-update feature_name $ # Restore your changes into the db. $ drush features-revert feature_name
  12. 12. Want to add a component to a feature?1. add it to the .info file2. $ drush features-update feature_name
  13. 13. Want to remove a component from a feature? 1. remove it from the .info file 2. $ drush features-update feature_name
  14. 14. Project bootstrap
  15. 15. project.makeproject.profile
  16. 16. project.makecore = "6.x"; Contribprojects[features][version] = "1.0"projects[features][subdir] = "contrib"projects[views][version] = "2.11"projects[views][subdir] = "contrib"projects[inline][version] = "1.0"projects[inline][subdir] = "contrib"...
  17. 17. project.profile/** * Implementation of hook_profile_details(). */function project_profile_details() { return array( name => Project, description => Project Description’, );}/** * Implementation of hook_profile_modules(). */function project_profile_modules() { $modules = array( cck, views, features, feature_controller, ...
  18. 18. Use the controller featureto keep track of developmentEnable/disable other features, store sitewide configuration, share changes, etc...
  19. 19. Code-driven workflow
  20. 20. Controller Feature WorkflowDeveloper A TimeDeveloper B Time Start: both Developers run installation, Controller Feature is enabled.
  21. 21. Controller Feature WorkflowDeveloper A TimeDeveloper B Time Developer A enables Rules module, Developer B does other work on the project.
  22. 22. Features are modules.Modules can be updated via hook_update_N()
  23. 23. hook_update_N()/** * Enabling Rules module */function feature_controller_update_6001() { $return = array(); $modules = array(rules); drupal_install_modules($modules); $return[] = array(success => TRUE, query => Enabling Rules module); return $return;} feature_controller.install
  24. 24. Controller Feature Workflow 6001Developer A TimeDeveloper B Time DevA$ svn ci -m “Enable Rules module.” Developer A commits his changes.
  25. 25. Controller Feature Workflow 6001Developer A TimeDeveloper B Time DevB$ svn up && dr updatedb -y && dr cc all Developer B updates his local copy and wants to remove a user role.
  26. 26. hook_update_N()/** * Removing contributor role */function feature_controller_update_6002() { $return = array(); $role_name = contributor; $result = db_query("SELECT rid FROM {role} WHERE name=%s", $role_name); while ($role = db_fetch_object($result)) { $rid = $role->rid; $return[] = update_sql("DELETE FROM {role} WHERE rid = $rid"); $return[] = update_sql("DELETE FROM {users_roles} WHERE rid = $rid"); } return $return;} feature_controller.install
  27. 27. Controller Feature Workflow 6001Developer A TimeDeveloper B 6002 Time DevB$ svn ci -m “Removed contributor role.” Developer B commits his changes.
  28. 28. Controller Feature Workflow 6001Developer A TimeDeveloper B 6002 Time Click. Click. Click. DevB$ patch -p0 < inline.patch Click. Click. Click. Developer B adds an OpenID account for admin and patches the Inline module.
  29. 29. hook_update_N()/** * Adding Nuvole OpenID to admin account */function feature_controller_update_6003() { $return = array(); $uid = 1; $claimed_id = http://admin.myopenid.com/; $return[] = update_sql("DELETE FROM {authmap} WHERE authname = $claimed_id"); $return[] = update_sql("INSERT INTO {authmap}(uid, authname, module) VALUES($uid, $claimed_id, openid)"); return $return;} feature_controller.install
  30. 30. project.make...projects[inline][type] = "module"projects[inline][download][type] = "cvs"projects[inline][download][module] = "contributions/modules/inline"projects[inline][download][revision] = "HEAD:2010-03-06"projects[inline][subdir] = "contrib"...;; Patches;projects[inline][patch][] = "http://drupal.org/files/issues/inline.patch"
  31. 31. Controller Feature Workflow 6001Developer A TimeDeveloper B 6002 6003 Time DevB$ svn ci -m “Add OpenID for admin. Patching Inline” Developer B commits his changes.
  32. 32. Controller Feature Workflow 6001Developer A TimeDeveloper B 6002 6003 Time Developer C Time DevC$ svn co http://svn.nuvole.org/project Developer C joins.
  33. 33. hook_update_N() is not enough. Structural updates go in hook_install() too
  34. 34. Controller Feature Workflow 6001Developer A TimeDeveloper B 6002 6003 Time Developer C Timefeature_controller_install()
  35. 35. hook_install()/** * Implementation of hook_install() */function feature_controller_install() { $return = array(); $modules = array(rules); drupal_install_modules($modules); $return[] = array(success => TRUE, query => Enable Rules module.); $uid = 1; $claimed_id = http://nuvole.myopenid.com/; $return[] = update_sql("INSERT INTO {authmap}(uid, authname, module) VALUES($uid, $claimed_id, openid)"); return $return;} feature_controller.install
  36. 36. Controller Feature Workflow 6001Developer A TimeDeveloper B 6002 6003 Time Developer C Time Click. Click. Click. Developer C installs the project.
  37. 37. Controller Feature Workflow 6001Developer A TimeDeveloper B 6002 6003 Time Developer C Time Click. Click. Click. Developer C creates and enables a new feature.
  38. 38. hook_update_N()/** * Enabling News feature */function feature_controller_update_6004() { $return = array(); $modules = array(feature_news); features_install_modules($modules); $return[] = array(success => TRUE, query => Enabling News); return $return;} feature_controller.install
  39. 39. /** * Implementation of hook_install() */function feature_controller_install() { $return = array(); $modules = array(rules); drupal_install_modules($modules); $return[] = array(success => TRUE, query => Enable Rules module.); $uid = 1; $claimed_id = http://nuvole.myopenid.com/; $return[] = update_sql("INSERT INTO {authmap}(uid, authname, module) VALUES($uid, $claimed_id, openid)"); $modules = array(feature_news); features_install_modules($modules); $return[] = array(success => TRUE, query => Enabling News); return $return;} feature_controller.install
  40. 40. Controller Feature Workflow 6001Developer A TimeDeveloper B 6002 6003 Time Developer C 6004 Time DevC$ svn ci -m “News Feature.” Developer C commits his changes.
  41. 41. Code conventions for a better world.
  42. 42. Feature namespace# Feature News (feature_news)Views feature_news_blocks feature_news_list feature_news_node feature_news_taxonomyContexts feature_news_front feature_news_listOpenlayers Presets feature_news_small_map feature_news_big_map
  43. 43. Content type namespace# News (news)CCK Fields field_news_pictures field_news_linksImagecache Presets news-s news-m news-l news-portrait
  44. 44. Features BoundariesPackage functionalities in a logical way
  45. 45. Features Inheritance Re-use and extend features
  46. 46. Drupal 7
  47. 47. Installation profiles are like modules project.info project.install project.profile
  48. 48. project.infoname = Projectdescription = Project Description.core = 7.xdependencies[] = "context"dependencies[] = "features"dependencies[] = "feature_controller"...files[] = project.profile
  49. 49. project.install/** * Enabling Rules module */function project_update_6001() { $return = array(); $modules = array(rules); drupal_install_modules($modules); $return[] = array(success => TRUE, query => Enabling Rules module); return $return;}/** * Removing contributor role */function project_update_6002() { $return = array(); $role_name = contributor; $result = db_query("SELECT rid FROM {role} WHERE name=%s", $role_name); while ($role = db_fetch_object($result)) { $rid = $role->rid; $return[] = update_sql("DELETE FROM {role} WHERE rid = $rid"); $return[] = update_sql("DELETE FROM {users_roles} WHERE rid = $rid"); } return $return;}
  50. 50. project.profile/** * Implementation of hook_install_tasks() */function project_install_tasks($install_state) { ...}/** * Implementation of hook_form_FORM_ID_alter() */function project_form_install_configure_form_alter(&$form, $form_state) { ...}
  51. 51. http://chicago2011.drupal.org/training/
  52. 52. See also:Installation Profiles As A Development Tool by Florian Loretanhttp://bxl2011.drupaldays.org/node/280
  53. 53. Thank You. http://nuvole.org @nuvoleweb

×