Future-Proof
Your Drupal 7 Site

DrupalCon Amsterdam 2014

Dave Reid / @davereid

davereid.github.io/future-proof

About Me


Senior Developer at Lullabot

Twitter: @davereid

IRC: davereid

Maintain amost 2% of contrib modules

Core subsystem maintainer

Father of two cats and one boy, and one on the way!



Objectives


For your site builders
and architects to make
informed choices now


Ease pain of site users
when switching to Drupal 8

User Interface

Spark Distribution

drupal.org/project/spark

Navbar

drupal.org/project/navbar

Inline Editing

drupal.org/project/quickedit

Official WYSIWYG: CKEditor

drupal.org/project/ckeditor

Responsive Bartik

drupal.org/project/responsive_bartik

HTML5

drupal.org/project/elements

drupal.org/project/html5_tools

VIEWS IN CORE!

drupal.org/project/views

Administration Views

drupal.org/project/admin_views


Views Bulk Operations (light)

drupal.org/project/views_bulk_operations


Views Responsive Grid

drupal.org/project/views_responsive_grid

Responsive Tables

drupal.org/project/responsive_tables

Breakpoints

drupal.org/project/breakpoints

Responsive Pictures

drupal.org/project/picture

Tours

drupal.org/project/joyride

Module page filtering

drupal.org/project/instantfilter



Simplified Menu Administration

drupal.org/project/simplified_menu_admin


Escape Admin

drupal.org/project/escape_admin


Caption Filter

drupal.org/project/caption_filter

<img data-align="center" data-caption="Test caption" ... />

Custom blocks (Bean)

drupal.org/project/bean


Reusable blocks: MultiBlock

drupal.org/project/multiblock

Field types

Entity reference

drupal.org/project/entityreference
NOT Node or User reference modules

Telephone

drupal.org/project/telephone
NOT phone module

Email (lite)

drupal.org/project/email

Datetime (Date lite)

drupal.org/project/date

Use the Date (ISO format) field type. Not the Date or Date (Unix timestamp) field types.

Backend

UUIDs

drupal.org/project/uuid

Render Cache

drupal.org/project/render_cache

drupal.org/project/entity_modified

Composer

For managing external auto-loadable (PSR-0/4) libraries

https://getcomposer.org

Composer

sites/all/composer.json

{
    "require": {
        "fale/isbn": "1.x-dev"
    }
}

Run composer install

// Make the sites/all/vendor libraries autoloadable.
require_once DRUPAL_ROOT . '/sites/all/vendor/autoload.php';
$result = \Isbn\Check::is10($isbn);

drupal.org/project/composer_vendor

drupal.org/project/composer_manager

API and Plugins

Plugin API in Drupal 8:
drupal.org/developing/api/8/plugins

Many ways to do the same thing in Drupal 7.

Hooks

/**
 * Implements hook_mymodule_hook_info().
 */
function example_mymodule_hook_info() {
  $info['example'] = array(
    'label' => t('Example implementation'),
    'callback' => 'example_mymodule_callback',
    'settings form' => 'example_mymodule_form',
  );
  return $info;
}

CTools plugins

function example_ctools_plugin_directory($module, $plugin) {
  if ($module == 'mymodule' && $plugin == 'hook') {
    return "plugins/$module/$plugin";
  }
}

// plugins/example/hook/example_implementation.inc
$plugin = array(
  'title' => t('Example implementation'),
  'class' => 'ExampleMyModuleHookImplementation',
);

// plugins/example/hook/ExampleImplementation.class.php
class ExampleMyModuleHookImplementation {
  // Does stuff.
}

Plugins in D7

lib/MyModuleHookPluginInterface.php
interface MyModuleHookPluginInterface {
  public function getDefaultConfig();
  public function doSomething();
}
lib/MyModuleHookPluginBase.php
abstract class MyModuleHookPluginBase implements MyModuleHookPluginInterface {
  /** @var array */
  public $config;

  public function __construct(array $config = array()) {
    $this->config = $config + $this->getDefaultConfig();
  }

  public function getDefaultConfig() {
    return array();
  }

  abstract public function doSomething();
}

Plugins in D7

example.module
function example_mymodule_hook_info() {
  $info['example'] =
    'label' => t('Example implementation'),
    'class' => 'ExampleMyModuleHookPlugin',
  );
  return $info;
}
example.info
files[] = lib/ExampleMyModuleHookPlugin.php
lib/ExampleMyModuleHookPlugin.php
class ExampleMyModuleHookPlugin extends MyModuleHookPluginBase {
  public function doSomething() {
    // Do stuff!
  }
}

Plugins in D7: Invoking

function mymodule_get_hook_instance($instance) {
  $info = module_invoke_all('mymodule_hook_info');
  drupal_alter('mymodule_hook_info', $info);
  if (isset($info[$instance])) {
    return new $class($config);
  }
  else {
    throw new Exception(...);
  }
}

$results = mymodule_get_hook_instance('example')->doSomething();

The Other Stuff

Configurable view/display modes

drupal.org/project/entity_view_mode

CMI

drupal.org/project/configuration???

Migrate is your friend

drupal.org/project/migrate

drupal.org/project/migrate_d2d

RESTful Web Services

drupal.org/project/restws

github.com/Gizra/restful

NOT services module

Translation

drupal.org/project/entity_translation

drupal.org/project/title

More More Things

PHPUnit
Symfony
Backbone.js
Underscore.js
Guzzle
JS local storage

Distribution: PreD8!

drupal.org/project/pred8

Things you should probably stop using

We don't want no scrubs

drupal.org/node/2116417

Thank you!
Questions?


Please rate this session at amsterdam2014.drupal.org/session/future-proof-your-drupal-7-site