Slide 1

Slide 1 text

EXPERIENCES IN MIGRATING A DRUPAL 7 MODULE TO DRUPAL 8 João Ventura (@jcnventura) Wunder Germany 22.4.2017 DRUPAL CAMP FRANKFURT 2017 #DCFFM17

Slide 2

Slide 2 text

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.

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

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…)

Slide 7

Slide 7 text

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.

Slide 8

Slide 8 text

Excerpt of “Pirates of the Caribbean: At World's End” under the fair-use rule. (C) 2007 Walt Disney Pictures / Jerry Bruckheimer Films.

Slide 9

Slide 9 text

Drupal 7 → Drupal 8 https://www.drupal.org/update/modules/7/8 ??? API changes Symfony + Twig OOP Plugins Con fi g ….

Slide 10

Slide 10 text

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/

Slide 11

Slide 11 text

.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

Slide 12

Slide 12 text

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+" }

Slide 13

Slide 13 text

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’)


Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

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'

Slide 16

Slide 16 text

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); }

Slide 17

Slide 17 text

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() }

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

Twig template templates/adsense-managed-async.html.twig (adsbygoogle = window.adsbygoogle || []).push({});

Slide 20

Slide 20 text

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.

Slide 21

Slide 21 text

[email protected] www.wunder.io/de Agnes-Pockels-Bogen 1, D1.019; 80992 München Wunder Germany d.o: jcnventura Phone: +49.89.85636307 [email protected] João Ventura Any questions??

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

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).