SlideShare a Scribd company logo
1 of 48
DROPS THAT GROW THE WEB.




First Steps in Code Driven Development
          A 100% database-free development workflow.




                   Antonio De Marco
                      antonio@nuvole.org
Database Driven Development
Major pitfalls


• Not ideal for a distributed team
• Makes difficult to push settings to production
• Content and settings are mixed in one db dump
• Easy to lose control
Power to code
Major benefit


• Code can be versioned
• Conflicts can be solved
• Content and settings are separated
• Easy to push updates to production
What the Features module is all about?
Have you noticed that your features don't
 necessarily depend from the Features
               module?
Features is a “hook_default()” generator.


  CCK:           hook_content_default_fields()
  Contexts:      hook_context_default_contexts()
  Fieldgroups:   hook_fieldgroup_default_groups()
  Filters:       hook_filter_default_formats()
  Imagecache:    hook_imagecache_default_presets()
  Menu:          hook_menu_default_items()
  Node type:     hook_node_info()
  Permissions:   hook_user_default_permissions()
  Views:         hook_views_default_views()
/**
 * Helper to implementation of hook_views_default_views().
 */
function _atrium_views_default_views() {
  $views = array();

 // Exported view: atrium_book_current
 $view = new view;
 $view->name = 'atrium_book_current';
 $view->description = 'Atrium: book: helper';
 $view->tag = 'atrium';
 ...
/**
 * Helper to implementation of hook_content_default_fields().
 */
function _atrium_blog_content_default_fields() {
  $fields = array();

  // Exported field: field_referenced_book_page
  $fields[] = array(
    'field_name' => 'field_referenced_book_page',
    'type_name' => 'blog',
    'display_settings' => array(
   ...
Hook helpers are then called from within your feature’s hooks.

/**
  * Implementation of hook_content_default_fields().
  */
function atrium_blog_content_default_fields() {
   module_load_include('inc', 'atrium_blog', 'atrium_blog.defaults');
   $args = func_get_args();
   return call_user_func_array('_atrium_blog_content_default_fields', $args);
}

/**
  * Implementation of hook_views_default_views().
  */
function atrium_views_default_views() {
   module_load_include('inc', 'atrium', 'atrium.features.views');
   $args = func_get_args();
   return call_user_func_array('_atrium_views_default_views', $args);
}
What about the rest?
Do your tables use strings as primary keys?
Do your tables use strings as primary keys?


        Yes?
Do your tables use strings as primary keys?


        Yes? Really?
Do your tables use strings as primary keys?


        Yes? Really? Great! Then...
Meet CTools Export plugin
a.k.a. Get magic by altering your module's schema
An example: Strongarm and variables export.
/**
  * Implementation of hook_schema_alter().
  * Makes the variables table usable by ctools' export.inc.
  */
function strongarm_schema_alter(&$schema) {
   $schema['variable']['export'] = array(
      'key' => 'name',
      'identifier' => 'strongarm',
      'default hook' => 'strongarm',
      'api' => array(
         'owner' => 'strongarm',
         'api' => 'strongarm',
         'minimum_version' => 1,
         'current_version' => 1,
      ),
   );
   $schema['variable']['fields']['value']['serialize'] = TRUE;
}
In your .info file add:

features[variable][] = "theme_default"
And you will get:
And you will get:

/**
 * Helper to implementation of hook_strongarm().
 */
function _your_module_strongarm() {
  $export = array();
  $strongarm = new stdClass;
  $strongarm->disabled = FALSE;
  $strongarm->api_version = 1;
  $strongarm->name = 'theme_default';
  $strongarm->value = 'ginkgo';

    $export['theme_default'] = $strongarm;
    return $export;
}
Features keeps track of DB changes.
$ # Dump your changes into code.
$ drush features-update feature_name

$ # Restore your changes into the db.
$ drush features-revert feature_name
Want to add a component to the a feature?
Want to add a component to the a feature?


    1. add it to your feature_name.info
    2. $ drush features-update feature_name
Want to remove a component to the a feature?
Want to remove a component to the a feature?


      1. remove it from your feature_name.info
      2. $ drush features-update feature_name
Code conventions for a better world.
Feature namespace
# Feature News (feature_news)

Views                feature_news_blocks
                     feature_news_list
                     feature_news_node
                     feature_news_taxonomy

Contexts             feature_news_front
                     feature_news_list

Openlayers Presets   feature_news_small_map
                     feature_news_big_map
Content type namespace
# News (news)

CCK Fields           field_news_pictures
                     field_news_links

Imagecache Presets   news-s
                     news-m
                     news-l
                     news-portrait
Tip:


 Never share fields across several content types unless
        you have really good reasons to do so.

If you do so you will make your features hardly re-usable.
Meet your friends hook_install() and hook_update_N()
The Controller Feature
 a.k.a. a feature to rule them all
Create Menus

/**
 * Implementation of hook_install()
 */
function feature_controller_install() {

    db_query("INSERT INTO {menu_custom} (menu_name, title, description)
              VALUES ('%s', '%s', '%s')",
              'menu-content',
              'Content',
              'Manage your site content.');

}
Create Menu Items
/**
 * Implementation of hook_install()
 */
function feature_controller_install() {

    $item['link_title'] = t('Home');
    $item['link_path'] = '<front>';
    $item['menu_name'] = 'primary-links';
    $item['weight'] = -10;
    menu_link_save($item);

}
Do all kind of dirty things...

/**
 * Implementation of hook_install()
 */
function feature_controller_install() {

    // Add OpenID to admin user
    db_query("INSERT INTO {authmap} (uid, authname, module)
              VALUES(1, 'http://nuvole.myopenid.com/', 'openid')");

    // Weight feature_controller to come after other modules -- in particular, admin.
    db_query("UPDATE {system}
              SET weight = 1
              WHERE name = 'feature_controller' AND type = 'module'");
}
hook_update_N()
/**
  * Disabling comment module
  */
function feature_controller_update_6001() {
   $return = array();
   $modules = array('comment');
   module_disable($modules);
   $return[] = array('success' => TRUE,
                      'query' => 'Disabling modules: '.
                      implode(', ', $modules));
   return $return;
}
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;
}
hook_install()

/**
 * Implementation of hook_install()
 */
function feature_controller_install() {

    feature_controller_update_6001();
    feature_controller_update_6002();

}
Features architecture: what goes where.
Views



GROUP BY Arguments, Filters.
Context

      Same context different reactions.



feature_controller_frontpage: News block, Events block




                   That’s bad...
Context

Different contexts share the same conditions.


        feature_news_frontpage: News block
      feature_events_frontpage: Events block



                  That’s Good!
Extending features

    Are we ready?
  Does it make sense?
DROPS THAT GROW THE WEB.




Thank You.
 http://nuvole.org
   @nuvoleweb
   #codepower

More Related Content

What's hot

Angular Promises and Advanced Routing
Angular Promises and Advanced RoutingAngular Promises and Advanced Routing
Angular Promises and Advanced RoutingAlexe Bogdan
 
Drupal Development (Part 2)
Drupal Development (Part 2)Drupal Development (Part 2)
Drupal Development (Part 2)Jeff Eaton
 
Virtual Madness @ Etsy
Virtual Madness @ EtsyVirtual Madness @ Etsy
Virtual Madness @ EtsyNishan Subedi
 
How I started to love design patterns
How I started to love design patternsHow I started to love design patterns
How I started to love design patternsSamuel ROZE
 
Drupal Step-by-Step: How We Built Our Training Site, Part 1
Drupal Step-by-Step: How We Built Our Training Site, Part 1Drupal Step-by-Step: How We Built Our Training Site, Part 1
Drupal Step-by-Step: How We Built Our Training Site, Part 1Acquia
 
Silex meets SOAP & REST
Silex meets SOAP & RESTSilex meets SOAP & REST
Silex meets SOAP & RESTHugo Hamon
 
Introduction to CQRS and Event Sourcing
Introduction to CQRS and Event SourcingIntroduction to CQRS and Event Sourcing
Introduction to CQRS and Event SourcingSamuel ROZE
 
Django Class-based views (Slovenian)
Django Class-based views (Slovenian)Django Class-based views (Slovenian)
Django Class-based views (Slovenian)Luka Zakrajšek
 
WordCamp Montreal 2015: Combining Custom Post Types, Fields, and Meta Boxes t...
WordCamp Montreal 2015: Combining Custom Post Types, Fields, and Meta Boxes t...WordCamp Montreal 2015: Combining Custom Post Types, Fields, and Meta Boxes t...
WordCamp Montreal 2015: Combining Custom Post Types, Fields, and Meta Boxes t...allilevine
 
Routing in Drupal 8
Routing in Drupal 8Routing in Drupal 8
Routing in Drupal 8kgoel1
 
Decoupling the Ulabox.com monolith. From CRUD to DDD
Decoupling the Ulabox.com monolith. From CRUD to DDDDecoupling the Ulabox.com monolith. From CRUD to DDD
Decoupling the Ulabox.com monolith. From CRUD to DDDAleix Vergés
 
Goodbye hook_menu() - Routing and Menus in Drupal 8
Goodbye hook_menu() - Routing and Menus in Drupal 8Goodbye hook_menu() - Routing and Menus in Drupal 8
Goodbye hook_menu() - Routing and Menus in Drupal 8Exove
 
Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For BeginnersJonathan Wage
 
Drupal is Stupid (But I Love It Anyway)
Drupal is Stupid (But I Love It Anyway)Drupal is Stupid (But I Love It Anyway)
Drupal is Stupid (But I Love It Anyway)brockboland
 
The Origin of Lithium
The Origin of LithiumThe Origin of Lithium
The Origin of LithiumNate Abele
 

What's hot (20)

Amp Up Your Admin
Amp Up Your AdminAmp Up Your Admin
Amp Up Your Admin
 
Angular Promises and Advanced Routing
Angular Promises and Advanced RoutingAngular Promises and Advanced Routing
Angular Promises and Advanced Routing
 
Drupal Development (Part 2)
Drupal Development (Part 2)Drupal Development (Part 2)
Drupal Development (Part 2)
 
Virtual Madness @ Etsy
Virtual Madness @ EtsyVirtual Madness @ Etsy
Virtual Madness @ Etsy
 
How I started to love design patterns
How I started to love design patternsHow I started to love design patterns
How I started to love design patterns
 
Drupal Step-by-Step: How We Built Our Training Site, Part 1
Drupal Step-by-Step: How We Built Our Training Site, Part 1Drupal Step-by-Step: How We Built Our Training Site, Part 1
Drupal Step-by-Step: How We Built Our Training Site, Part 1
 
Silex meets SOAP & REST
Silex meets SOAP & RESTSilex meets SOAP & REST
Silex meets SOAP & REST
 
Introduction to CQRS and Event Sourcing
Introduction to CQRS and Event SourcingIntroduction to CQRS and Event Sourcing
Introduction to CQRS and Event Sourcing
 
Django Class-based views (Slovenian)
Django Class-based views (Slovenian)Django Class-based views (Slovenian)
Django Class-based views (Slovenian)
 
WordCamp Montreal 2015: Combining Custom Post Types, Fields, and Meta Boxes t...
WordCamp Montreal 2015: Combining Custom Post Types, Fields, and Meta Boxes t...WordCamp Montreal 2015: Combining Custom Post Types, Fields, and Meta Boxes t...
WordCamp Montreal 2015: Combining Custom Post Types, Fields, and Meta Boxes t...
 
Bacbkone js
Bacbkone jsBacbkone js
Bacbkone js
 
Routing in Drupal 8
Routing in Drupal 8Routing in Drupal 8
Routing in Drupal 8
 
Your Entity, Your Code
Your Entity, Your CodeYour Entity, Your Code
Your Entity, Your Code
 
Decoupling the Ulabox.com monolith. From CRUD to DDD
Decoupling the Ulabox.com monolith. From CRUD to DDDDecoupling the Ulabox.com monolith. From CRUD to DDD
Decoupling the Ulabox.com monolith. From CRUD to DDD
 
Goodbye hook_menu() - Routing and Menus in Drupal 8
Goodbye hook_menu() - Routing and Menus in Drupal 8Goodbye hook_menu() - Routing and Menus in Drupal 8
Goodbye hook_menu() - Routing and Menus in Drupal 8
 
201104 iphone navigation-based apps
201104 iphone navigation-based apps201104 iphone navigation-based apps
201104 iphone navigation-based apps
 
Drupal 8 Routing
Drupal 8 RoutingDrupal 8 Routing
Drupal 8 Routing
 
Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For Beginners
 
Drupal is Stupid (But I Love It Anyway)
Drupal is Stupid (But I Love It Anyway)Drupal is Stupid (But I Love It Anyway)
Drupal is Stupid (But I Love It Anyway)
 
The Origin of Lithium
The Origin of LithiumThe Origin of Lithium
The Origin of Lithium
 

Similar to First Steps in Drupal Code Driven Development

Symfony2 - from the trenches
Symfony2 - from the trenchesSymfony2 - from the trenches
Symfony2 - from the trenchesLukas Smith
 
Empowering users: modifying the admin experience
Empowering users: modifying the admin experienceEmpowering users: modifying the admin experience
Empowering users: modifying the admin experienceBeth Soderberg
 
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
 
Debugging in drupal 8
Debugging in drupal 8Debugging in drupal 8
Debugging in drupal 8Allie Jones
 
ZF2 for the ZF1 Developer
ZF2 for the ZF1 DeveloperZF2 for the ZF1 Developer
ZF2 for the ZF1 DeveloperGary Hockin
 
Web applications with Catalyst
Web applications with CatalystWeb applications with Catalyst
Web applications with Catalystsvilen.ivanov
 
Symfony2 from the Trenches
Symfony2 from the TrenchesSymfony2 from the Trenches
Symfony2 from the TrenchesJonathan Wage
 
Using the Features API
Using the Features APIUsing the Features API
Using the Features APIcgmonroe
 
前端MVC 豆瓣说
前端MVC 豆瓣说前端MVC 豆瓣说
前端MVC 豆瓣说Ting Lv
 
Building Large jQuery Applications
Building Large jQuery ApplicationsBuilding Large jQuery Applications
Building Large jQuery ApplicationsRebecca Murphey
 
Writing Maintainable JavaScript
Writing Maintainable JavaScriptWriting Maintainable JavaScript
Writing Maintainable JavaScriptAndrew Dupont
 
Zend Framework 1.9 Setup & Using Zend_Tool
Zend Framework 1.9 Setup & Using Zend_ToolZend Framework 1.9 Setup & Using Zend_Tool
Zend Framework 1.9 Setup & Using Zend_ToolGordon Forsythe
 
Magento Live Australia 2016: Request Flow
Magento Live Australia 2016: Request FlowMagento Live Australia 2016: Request Flow
Magento Live Australia 2016: Request FlowVrann Tulika
 
The state of hooking into Drupal - DrupalCon Dublin
The state of hooking into Drupal - DrupalCon DublinThe state of hooking into Drupal - DrupalCon Dublin
The state of hooking into Drupal - DrupalCon DublinNida Ismail Shah
 
"Angular.js Concepts in Depth" by Aleksandar Simović
"Angular.js Concepts in Depth" by Aleksandar Simović"Angular.js Concepts in Depth" by Aleksandar Simović
"Angular.js Concepts in Depth" by Aleksandar SimovićJS Belgrade
 
AngularJS Architecture
AngularJS ArchitectureAngularJS Architecture
AngularJS ArchitectureEyal Vardi
 
AngularJS Internal
AngularJS InternalAngularJS Internal
AngularJS InternalEyal Vardi
 

Similar to First Steps in Drupal Code Driven Development (20)

Extend sdk
Extend sdkExtend sdk
Extend sdk
 
Symfony2 - from the trenches
Symfony2 - from the trenchesSymfony2 - from the trenches
Symfony2 - from the trenches
 
AngularJs-training
AngularJs-trainingAngularJs-training
AngularJs-training
 
Empowering users: modifying the admin experience
Empowering users: modifying the admin experienceEmpowering users: modifying the admin experience
Empowering users: modifying the admin experience
 
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)
 
Debugging in drupal 8
Debugging in drupal 8Debugging in drupal 8
Debugging in drupal 8
 
ZF2 for the ZF1 Developer
ZF2 for the ZF1 DeveloperZF2 for the ZF1 Developer
ZF2 for the ZF1 Developer
 
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
 
Using the Features API
Using the Features APIUsing the Features API
Using the Features API
 
前端MVC 豆瓣说
前端MVC 豆瓣说前端MVC 豆瓣说
前端MVC 豆瓣说
 
Building Large jQuery Applications
Building Large jQuery ApplicationsBuilding Large jQuery Applications
Building Large jQuery Applications
 
Writing Maintainable JavaScript
Writing Maintainable JavaScriptWriting Maintainable JavaScript
Writing Maintainable JavaScript
 
Zend Framework 1.9 Setup & Using Zend_Tool
Zend Framework 1.9 Setup & Using Zend_ToolZend Framework 1.9 Setup & Using Zend_Tool
Zend Framework 1.9 Setup & Using Zend_Tool
 
Magento Live Australia 2016: Request Flow
Magento Live Australia 2016: Request FlowMagento Live Australia 2016: Request Flow
Magento Live Australia 2016: Request Flow
 
The state of hooking into Drupal - DrupalCon Dublin
The state of hooking into Drupal - DrupalCon DublinThe state of hooking into Drupal - DrupalCon Dublin
The state of hooking into Drupal - DrupalCon Dublin
 
"Angular.js Concepts in Depth" by Aleksandar Simović
"Angular.js Concepts in Depth" by Aleksandar Simović"Angular.js Concepts in Depth" by Aleksandar Simović
"Angular.js Concepts in Depth" by Aleksandar Simović
 
AngularJS Architecture
AngularJS ArchitectureAngularJS Architecture
AngularJS Architecture
 
AngularJS Internal
AngularJS InternalAngularJS Internal
AngularJS Internal
 
Introduction to angular js
Introduction to angular jsIntroduction to angular js
Introduction to angular js
 

More from Nuvole

The OpenEuropa Initiative
The OpenEuropa InitiativeThe OpenEuropa Initiative
The OpenEuropa InitiativeNuvole
 
CMI 2.0 session at Drupal DevDays in Cluj-Napoca
CMI 2.0 session at Drupal DevDays in Cluj-NapocaCMI 2.0 session at Drupal DevDays in Cluj-Napoca
CMI 2.0 session at Drupal DevDays in Cluj-NapocaNuvole
 
Advanced Configuration Management with Config Split et al.
Advanced Configuration Management with Config Split et al.Advanced Configuration Management with Config Split et al.
Advanced Configuration Management with Config Split et al.Nuvole
 
Introducing the UI Patterns module: use atomic UI components everywhere in Dr...
Introducing the UI Patterns module: use atomic UI components everywhere in Dr...Introducing the UI Patterns module: use atomic UI components everywhere in Dr...
Introducing the UI Patterns module: use atomic UI components everywhere in Dr...Nuvole
 
Drupal 8 Configuration Management with Features
Drupal 8 Configuration Management with FeaturesDrupal 8 Configuration Management with Features
Drupal 8 Configuration Management with FeaturesNuvole
 
Configuration Management in Drupal 8: A preview (DrupalCamp Alpe Adria 2014)
Configuration Management in Drupal 8: A preview (DrupalCamp Alpe Adria 2014)Configuration Management in Drupal 8: A preview (DrupalCamp Alpe Adria 2014)
Configuration Management in Drupal 8: A preview (DrupalCamp Alpe Adria 2014)Nuvole
 
Configuration Management in Drupal 8: A preview (DrupalDays Milano 2014)
Configuration Management in Drupal 8: A preview (DrupalDays Milano 2014)Configuration Management in Drupal 8: A preview (DrupalDays Milano 2014)
Configuration Management in Drupal 8: A preview (DrupalDays Milano 2014)Nuvole
 
Automating Drupal Development: Makefiles, features and beyond
Automating Drupal Development: Makefiles, features and beyondAutomating Drupal Development: Makefiles, features and beyond
Automating Drupal Development: Makefiles, features and beyondNuvole
 
Building and Maintaining a Distribution in Drupal 7 with Features
Building and Maintaining a  Distribution in Drupal 7 with FeaturesBuilding and Maintaining a  Distribution in Drupal 7 with Features
Building and Maintaining a Distribution in Drupal 7 with FeaturesNuvole
 
Remote Collaboration and Institutional Intranets with Drupal and Open Atrium
Remote Collaboration and Institutional Intranets with Drupal and Open AtriumRemote Collaboration and Institutional Intranets with Drupal and Open Atrium
Remote Collaboration and Institutional Intranets with Drupal and Open AtriumNuvole
 
Public Works Monitoring
Public Works MonitoringPublic Works Monitoring
Public Works MonitoringNuvole
 
Extending and Customizing Open Atrium
Extending and Customizing Open AtriumExtending and Customizing Open Atrium
Extending and Customizing Open AtriumNuvole
 
Code driven development: using Features effectively in Drupal 6 and 7
Code driven development: using Features effectively in Drupal 6 and 7Code driven development: using Features effectively in Drupal 6 and 7
Code driven development: using Features effectively in Drupal 6 and 7Nuvole
 
Features based development workflow
Features based development workflowFeatures based development workflow
Features based development workflowNuvole
 

More from Nuvole (14)

The OpenEuropa Initiative
The OpenEuropa InitiativeThe OpenEuropa Initiative
The OpenEuropa Initiative
 
CMI 2.0 session at Drupal DevDays in Cluj-Napoca
CMI 2.0 session at Drupal DevDays in Cluj-NapocaCMI 2.0 session at Drupal DevDays in Cluj-Napoca
CMI 2.0 session at Drupal DevDays in Cluj-Napoca
 
Advanced Configuration Management with Config Split et al.
Advanced Configuration Management with Config Split et al.Advanced Configuration Management with Config Split et al.
Advanced Configuration Management with Config Split et al.
 
Introducing the UI Patterns module: use atomic UI components everywhere in Dr...
Introducing the UI Patterns module: use atomic UI components everywhere in Dr...Introducing the UI Patterns module: use atomic UI components everywhere in Dr...
Introducing the UI Patterns module: use atomic UI components everywhere in Dr...
 
Drupal 8 Configuration Management with Features
Drupal 8 Configuration Management with FeaturesDrupal 8 Configuration Management with Features
Drupal 8 Configuration Management with Features
 
Configuration Management in Drupal 8: A preview (DrupalCamp Alpe Adria 2014)
Configuration Management in Drupal 8: A preview (DrupalCamp Alpe Adria 2014)Configuration Management in Drupal 8: A preview (DrupalCamp Alpe Adria 2014)
Configuration Management in Drupal 8: A preview (DrupalCamp Alpe Adria 2014)
 
Configuration Management in Drupal 8: A preview (DrupalDays Milano 2014)
Configuration Management in Drupal 8: A preview (DrupalDays Milano 2014)Configuration Management in Drupal 8: A preview (DrupalDays Milano 2014)
Configuration Management in Drupal 8: A preview (DrupalDays Milano 2014)
 
Automating Drupal Development: Makefiles, features and beyond
Automating Drupal Development: Makefiles, features and beyondAutomating Drupal Development: Makefiles, features and beyond
Automating Drupal Development: Makefiles, features and beyond
 
Building and Maintaining a Distribution in Drupal 7 with Features
Building and Maintaining a  Distribution in Drupal 7 with FeaturesBuilding and Maintaining a  Distribution in Drupal 7 with Features
Building and Maintaining a Distribution in Drupal 7 with Features
 
Remote Collaboration and Institutional Intranets with Drupal and Open Atrium
Remote Collaboration and Institutional Intranets with Drupal and Open AtriumRemote Collaboration and Institutional Intranets with Drupal and Open Atrium
Remote Collaboration and Institutional Intranets with Drupal and Open Atrium
 
Public Works Monitoring
Public Works MonitoringPublic Works Monitoring
Public Works Monitoring
 
Extending and Customizing Open Atrium
Extending and Customizing Open AtriumExtending and Customizing Open Atrium
Extending and Customizing Open Atrium
 
Code driven development: using Features effectively in Drupal 6 and 7
Code driven development: using Features effectively in Drupal 6 and 7Code driven development: using Features effectively in Drupal 6 and 7
Code driven development: using Features effectively in Drupal 6 and 7
 
Features based development workflow
Features based development workflowFeatures based development workflow
Features based development workflow
 

Recently uploaded

Top 10 Hubspot Development Companies in 2024
Top 10 Hubspot Development Companies in 2024Top 10 Hubspot Development Companies in 2024
Top 10 Hubspot Development Companies in 2024TopCSSGallery
 
Glenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security ObservabilityGlenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security Observabilityitnewsafrica
 
Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Hiroshi SHIBATA
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfpanagenda
 
Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfIngrid Airi González
 
UiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPathCommunity
 
QCon London: Mastering long-running processes in modern architectures
QCon London: Mastering long-running processes in modern architecturesQCon London: Mastering long-running processes in modern architectures
QCon London: Mastering long-running processes in modern architecturesBernd Ruecker
 
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Alkin Tezuysal
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc
 
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesThousandEyes
 
React Native vs Ionic - The Best Mobile App Framework
React Native vs Ionic - The Best Mobile App FrameworkReact Native vs Ionic - The Best Mobile App Framework
React Native vs Ionic - The Best Mobile App FrameworkPixlogix Infotech
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.Curtis Poe
 
2024 April Patch Tuesday
2024 April Patch Tuesday2024 April Patch Tuesday
2024 April Patch TuesdayIvanti
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsPixlogix Infotech
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxLoriGlavin3
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxLoriGlavin3
 
Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesKari Kakkonen
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI AgeCprime
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...Nikki Chapple
 

Recently uploaded (20)

Top 10 Hubspot Development Companies in 2024
Top 10 Hubspot Development Companies in 2024Top 10 Hubspot Development Companies in 2024
Top 10 Hubspot Development Companies in 2024
 
Glenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security ObservabilityGlenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security Observability
 
Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
 
Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdf
 
UiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to Hero
 
QCon London: Mastering long-running processes in modern architectures
QCon London: Mastering long-running processes in modern architecturesQCon London: Mastering long-running processes in modern architectures
QCon London: Mastering long-running processes in modern architectures
 
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
 
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
 
React Native vs Ionic - The Best Mobile App Framework
React Native vs Ionic - The Best Mobile App FrameworkReact Native vs Ionic - The Best Mobile App Framework
React Native vs Ionic - The Best Mobile App Framework
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.
 
2024 April Patch Tuesday
2024 April Patch Tuesday2024 April Patch Tuesday
2024 April Patch Tuesday
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and Cons
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
 
Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examples
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI Age
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
 

First Steps in Drupal Code Driven Development

  • 1. DROPS THAT GROW THE WEB. First Steps in Code Driven Development A 100% database-free development workflow. Antonio De Marco antonio@nuvole.org
  • 3.
  • 4. Major pitfalls • Not ideal for a distributed team • Makes difficult to push settings to production • Content and settings are mixed in one db dump • Easy to lose control
  • 6. Major benefit • Code can be versioned • Conflicts can be solved • Content and settings are separated • Easy to push updates to production
  • 7. What the Features module is all about?
  • 8. Have you noticed that your features don't necessarily depend from the Features module?
  • 9. Features is a “hook_default()” generator. CCK: hook_content_default_fields() Contexts: hook_context_default_contexts() Fieldgroups: hook_fieldgroup_default_groups() Filters: hook_filter_default_formats() Imagecache: hook_imagecache_default_presets() Menu: hook_menu_default_items() Node type: hook_node_info() Permissions: hook_user_default_permissions() Views: hook_views_default_views()
  • 10. /** * Helper to implementation of hook_views_default_views(). */ function _atrium_views_default_views() { $views = array(); // Exported view: atrium_book_current $view = new view; $view->name = 'atrium_book_current'; $view->description = 'Atrium: book: helper'; $view->tag = 'atrium'; ...
  • 11. /** * Helper to implementation of hook_content_default_fields(). */ function _atrium_blog_content_default_fields() { $fields = array(); // Exported field: field_referenced_book_page $fields[] = array( 'field_name' => 'field_referenced_book_page', 'type_name' => 'blog', 'display_settings' => array( ...
  • 12. Hook helpers are then called from within your feature’s hooks. /** * Implementation of hook_content_default_fields(). */ function atrium_blog_content_default_fields() { module_load_include('inc', 'atrium_blog', 'atrium_blog.defaults'); $args = func_get_args(); return call_user_func_array('_atrium_blog_content_default_fields', $args); } /** * Implementation of hook_views_default_views(). */ function atrium_views_default_views() { module_load_include('inc', 'atrium', 'atrium.features.views'); $args = func_get_args(); return call_user_func_array('_atrium_views_default_views', $args); }
  • 13. What about the rest?
  • 14. Do your tables use strings as primary keys?
  • 15. Do your tables use strings as primary keys? Yes?
  • 16. Do your tables use strings as primary keys? Yes? Really?
  • 17. Do your tables use strings as primary keys? Yes? Really? Great! Then...
  • 18. Meet CTools Export plugin a.k.a. Get magic by altering your module's schema
  • 19. An example: Strongarm and variables export.
  • 20. /** * Implementation of hook_schema_alter(). * Makes the variables table usable by ctools' export.inc. */ function strongarm_schema_alter(&$schema) { $schema['variable']['export'] = array( 'key' => 'name', 'identifier' => 'strongarm', 'default hook' => 'strongarm', 'api' => array( 'owner' => 'strongarm', 'api' => 'strongarm', 'minimum_version' => 1, 'current_version' => 1, ), ); $schema['variable']['fields']['value']['serialize'] = TRUE; }
  • 21. In your .info file add: features[variable][] = "theme_default"
  • 22.
  • 23. And you will get:
  • 24. And you will get: /** * Helper to implementation of hook_strongarm(). */ function _your_module_strongarm() { $export = array(); $strongarm = new stdClass; $strongarm->disabled = FALSE; $strongarm->api_version = 1; $strongarm->name = 'theme_default'; $strongarm->value = 'ginkgo'; $export['theme_default'] = $strongarm; return $export; }
  • 25. Features keeps track of DB changes.
  • 26. $ # Dump your changes into code. $ drush features-update feature_name $ # Restore your changes into the db. $ drush features-revert feature_name
  • 27. Want to add a component to the a feature?
  • 28. Want to add a component to the a feature? 1. add it to your feature_name.info 2. $ drush features-update feature_name
  • 29. Want to remove a component to the a feature?
  • 30. Want to remove a component to the a feature? 1. remove it from your feature_name.info 2. $ drush features-update feature_name
  • 31. Code conventions for a better world.
  • 32. Feature namespace # Feature News (feature_news) Views feature_news_blocks feature_news_list feature_news_node feature_news_taxonomy Contexts feature_news_front feature_news_list Openlayers Presets feature_news_small_map feature_news_big_map
  • 33. Content type namespace # News (news) CCK Fields field_news_pictures field_news_links Imagecache Presets news-s news-m news-l news-portrait
  • 34. Tip: Never share fields across several content types unless you have really good reasons to do so. If you do so you will make your features hardly re-usable.
  • 35. Meet your friends hook_install() and hook_update_N()
  • 36. The Controller Feature a.k.a. a feature to rule them all
  • 37. Create Menus /** * Implementation of hook_install() */ function feature_controller_install() { db_query("INSERT INTO {menu_custom} (menu_name, title, description) VALUES ('%s', '%s', '%s')", 'menu-content', 'Content', 'Manage your site content.'); }
  • 38. Create Menu Items /** * Implementation of hook_install() */ function feature_controller_install() { $item['link_title'] = t('Home'); $item['link_path'] = '<front>'; $item['menu_name'] = 'primary-links'; $item['weight'] = -10; menu_link_save($item); }
  • 39. Do all kind of dirty things... /** * Implementation of hook_install() */ function feature_controller_install() { // Add OpenID to admin user db_query("INSERT INTO {authmap} (uid, authname, module) VALUES(1, 'http://nuvole.myopenid.com/', 'openid')"); // Weight feature_controller to come after other modules -- in particular, admin. db_query("UPDATE {system} SET weight = 1 WHERE name = 'feature_controller' AND type = 'module'"); }
  • 40. hook_update_N() /** * Disabling comment module */ function feature_controller_update_6001() { $return = array(); $modules = array('comment'); module_disable($modules); $return[] = array('success' => TRUE, 'query' => 'Disabling modules: '. implode(', ', $modules)); return $return; }
  • 41. 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; }
  • 42. hook_install() /** * Implementation of hook_install() */ function feature_controller_install() { feature_controller_update_6001(); feature_controller_update_6002(); }
  • 45. Context Same context different reactions. feature_controller_frontpage: News block, Events block That’s bad...
  • 46. Context Different contexts share the same conditions. feature_news_frontpage: News block feature_events_frontpage: Events block That’s Good!
  • 47. Extending features Are we ready? Does it make sense?
  • 48. DROPS THAT GROW THE WEB. Thank You. http://nuvole.org @nuvoleweb #codepower

Editor's Notes