Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Experiences in migrating a Drupal 7 module to Drupal 8

Experiences in migrating a Drupal 7 module to Drupal 8

https://2017.drupalcamp-frankfurt.de/node/231

In this session, I will describe my experiences in updating a Drupal module from Drupal 7 to Drupal 8 (the adsense module). The session will describe the lessons learned in this process, including the removal of the previous "sub-module as plugins" system, and it's replacement with a true plugin system based on the infrastructure provided by Drupal 8. It will also advocate for a thorough removal of the .module file as much as possible. Some tools helpful for module development will also be addressed including:

- Composer - to manage external dependencies.
- Drupal Module Upgrader - for automatic update of code from D7 to D8.
- Coder - static checks for coding standards.

Main points to discuss on the subject of module development for Drupal 8:

- module.info.yml and the other YAML files
- Object Oriented Programming
- PHP's PSR-4 and the module file structure
- PHP Annotations
- The Drupal 8 plugin system
- Forms
- Blocks
- Twig templates
- Page controllers and the routing system

https://www.youtube.com/watch?v=7dilUIWgYo0&ab_channel=DrupalCampFrankfurt

João Ventura

April 22, 2017
Tweet

More Decks by João Ventura

Other Decks in Programming

Transcript

  1. EXPERIENCES IN MIGRATING A DRUPAL 7 MODULE TO DRUPAL 8

    João Ventura (@jcnventura) Wunder Germany 22.4.2017 DRUPAL CAMP FRANKFURT 2017 #DCFFM17
  2. Personal background Senior Developer at Wunder (Germany). Part of Drupal

    Portugal community (sometimes). Drupal user since Drupal 4.6. Maintainer of the print and adsense modules (+ others). 1 patch in D7 (moved drupal_eval to php_eval). 22 patches in D8.
  3. print + adsense Maintainer of these modules since Drupal 5

    Used at fi rst in personal site (scratch my own itch) Allowed me to contribute to Drupal on my own free time Porting from Drupal 5 to 6: easy, able to follow core Porting from Drupal 6 to 7: hard, had to adapt multiple times to changing API
  4. Drupal 5 → Drupal 6 https://www.drupal.org/update/modules/5/6 • 82 API changes!

    • CCK (Content types) • Languages / Translations • Menu • Schema API
  5. Drupal 6 → Drupal 7 https://www.drupal.org/update/modules/6/7 264 API changes! hook_nodeapi

    -> hook_node_xxx (same for + hook_block) CCK (Fields in core) Render API (and render arrays…)
  6. Lessons learned with Drupal 7 Wait for beta. Don’t chase

    core. Leverage the improved system. Don’t just upgrade it. Coder upgrade provided some help. But in retrospective, pretty easy to upgrade a module.
  7. Excerpt of “Pirates of the Caribbean: At World's End” under

    the fair-use rule. (C) 2007 Walt Disney Pictures / Jerry Bruckheimer Films.
  8. L e t ’ s g e t Te c

    h n i c a l From “Ada Lovelace: The First Computer Programmer” http://iq.intel.com/ada-lovelace-the- fi rst-computer-programmer/
  9. .info → .info.yml adsense.info name = AdSense core description =

    (…) package = Adsense core = 7.x con fi gure = admin/con fi g/services/ adsense adsense.info.yml name: 'AdSense' type: module description: (…) package: Adsense core: 8.x con fi gure: adsense.main_settings
  10. Composer fi le { "name": "drupal/adsense", "description": "Displays Google AdSense

    ads on your site to earn revenue.", "type": "drupal-module", "homepage": "https://drupal.org/project/adsense", "authors": [ { "name": "João Ventura", "homepage": "https://www.drupal.org/u/jcnventura" } ], "support": { "issues": "https://www.drupal.org/project/issues/adsense" }, "license": "GPL-2.0+" }
  11. Variables adsense.module de fi ne('ADSENSE_BASIC_ID_DEFAULT', ‘’) adsense.admin.inc variable_get('adsense_basic_id', ADSENSE_BASIC_ID_DEFAULT) adsense.install

    variable_del(‘adsense_basic_id’)
 con fi g/install/adsense.settings.yml adsense_basic_id: ‘’ src/Form/AdsenseIdSettings.php $con fi g = \Drupal::con fi g('adsense.settings'); $con fi g->get(‘adsense_basic_id’)

  12. Upgrade path migration_templates/d7_adsense_settings.yml id: d7_adsense_settings label: AdSense 7 con fi

    guration migration_tags: - Drupal 7 source: plugin: variable variables: - adsense_basic_id process: adsense_basic_id: adsense_basic_id destination: plugin: con fi g con fi g_name: adsense.settings
  13. Menu routing adsense.module function adsense_menu() { $items = array(); $items['admin/settings/adsense']

    = array( 'title' => 'AdSense', 'description' => ‘…’, 'page callback' => 'drupal_get_form', 'page arguments' => array('adsense_main_settings'), 'access arguments' => array('administer adsense'), ' fi le' => 'adsense.admin.inc', );
 adsense.routing.yml adsense.main_settings: path: /admin/con fi g/services/adsense defaults: _title: AdSense _form: \Drupal\adsense\Form\AdsenseMainSettings requirements: _permission: 'administer adsense'
  14. Con fi guration form adsense.admin.inc function adsense_id_settings() { $form['adsense_basic_id'] =

    array( '#type' => 'text fi eld', '#title' => t(…), '#required' => TRUE, '#default_value' => variable_get(), '#description' => t(…), ); $form['#validate'][] = '_adsense_id_settings_validate'; return system_settings_form($form); } src/Form/AdsenseIdSettings.php class AdsenseIdSettings extends Con fi gFormBase { public function getFormId() { return 'adsense_id_settings'; } protected function getEditableCon fi gNames() { return ['adsense.settings']; } public function buildForm(array $form, FormStateInterface $form_state) { $form['adsense_basic_id'] = [ '#type' => 'text fi eld', '#title' => t(…), '#required' => TRUE, '#default_value' => $con fi g->get(…), '#description' => t(…), '#pattern' => 'pub-[0-9]+', ]; return parent::buildForm($form, $form_state); }
  15. Blocks adsense_managed.module function adsense_managed_block_info() function adsense_managed_block_con fi gure($delta = ‘’)

    function adsense_managed_block_save($delta = ‘', $edit = array()) function adsense_managed_block_view($delta = ‘')
 src/Plugin/Block/ManagedAdBlock.php /** * Provides an AdSense managed ad block. * @Block( * id = "adsense_managed_ad_block", * admin_label = @Translation("Managed ad"), * category = @Translation("Adsense") * ) */ class ManagedAdBlock extends BlockBase implements AdBlockInterface { public function defaultCon fi guration() public function blockForm ($form, FormStateInterface $form_state) public function blockSubmit($form, FormStateInterface $form_state) public function build() }
  16. Annotations / Plugins src/Annotation/AdsenseAd.php /** * De fi nes an

    adsense ad item annotation object. * Plugin Namespace: Plugin\adsense\AdsenseAd. * @Annotation */ class AdsenseAd extends Plugin { public $id; public $name; public $isSearch; public $needsSlot; }
 src/Plugin/AdsenseAd/ManagedAd.php /** * Provides an AdSense managed ad unit. * @AdsenseAd( * id = "managed", * name = @Translation("Content ads"), * isSearch = FALSE, * needsSlot = TRUE * ) */ class ManagedAd extends ContentAdBase { Drupal 7: plugin system via submodules and hook_adsense_* API Drupal 8: real plugin system, based on Annotations
  17. Twig template templates/adsense-managed-async.html.twig <script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script> <!-- {{ format }}

    --> <ins class="adsbygoogle" style="display:inline-block;width:{{ width }}px;height:{{ height }}px" data-ad-client="ca-{{ client }}" data-ad-slot="{{ slot }}"></ins> <script> (adsbygoogle = window.adsbygoogle || []).push({}); </script>
  18. Lessons learned Drupal 8 Easy path Drupal module upgrader. Keep

    code in .module fi les. Make it work. Hard path Object-oriented-programming (Single responsibility principle, Plugins, etc.). No code other than hook_something() in .module fi le. Rewrite from scratch.
  19. Drupal Module Upgrader https://www.drupal.org/project/drupalmoduleupgrader Handles the boring parts Converts module.info

    to module.info.yml Converts your hook_menu() to module.routing.yml Converts the con fi guration forms to src/Form/FormName.php
  20. Coder Sniffer https://www.drupal.org/project/coder Installing Coder Sniffer: https://www.drupal.org/node/1419988 drupalcs: signals all

    code standards violations (coder sniffer). drupalcbf: automatically fi xes everything it can (coder beauti fi er).