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

Altering, Extending, and Enhancing, Drupal 8

Altering, Extending, and Enhancing, Drupal 8

Presentation that describes the various ways that Drupal module developers will be able to interact with Drupal 8 core to alter existing functionality, extend Drupal, and enhance it with new functionality.

As well as how the various design patterns work in-case they might be useful to implement in your own projects.



May 10, 2016


  1. Altering, Extending, and Enhancing, Drupal MidWestPHP - 2017 Joe (@eojthebrave)

    Shindelar http://lb.cm/mEP
  2. Hi, I’m Joe @eojthebrave

  3. What’s This All About? • How modules enhance Drupal •

    Plugins, Services, Events, and Hooks • Example use-cases for each • Choosing the right tool for the job
  4. Don’t hack core.

  5. Let others change your module without hacking

  6. ? i

  7. Don’t hack, use a hook, or
 maybe write a plugin,

    create a service, or subscribe to an event.
  8. Plugins

  9. Plugins • Extend Drupal with interchangeable units of functionality •

    Implement an Interface + meta-data* • A design pattern, not a finished product
  10. None
  11. Examples of Plugins • Blocks • Field formatters • Views

    row style • Actions • etc.
  12. Elements of the Plugin System • Plugin types • Discovery

    • Factory • Plugins
  13. Plugin Recipe 1. Determine the type of plugin? • Where

    does the meta-data and code go? 2. Is there a base class I can extend? 3. Implement the interface, and provide meta-data so that the plugin manager can find your instance.
  14. modules/icecream/Plugin/Flavor/Chocolate.php namespace Drupal\icecream\Plugin\Flavor; use Drupal\icecream\FlavorBase; /** * Provides a 'chocolate'

    flavor. * * @Flavor( * id = "chocolate", * name = @Translation("Chocolate"), * price = 1.75 * ) */ class Chocolate extends FlavorBase { public function slogan() { return t('The other best flavor.'); } }
  15. user.links.menu.yml YAML user.page: title: 'My account' weight: -10 route_name: user.page

    menu_name: account user.logout: weight: 10 menu_name: account class: Drupal\user\Plugin\Menu\LoginLogoutMenuLink
  16. Plugin Types Recipe • Plugins that perform similar functionality are

    of the same plugin type. • You can implement your own new plugin types using DefaultPluginManager • Choose a discovery method • Determine factory to use for initialization • Define an Interface and BaseClass
  17. Plugin Resources • https://drupalize.me/blog/201407/drupal-8-plugins- explained • https://drupalize.me/blog/201409/unravelling- drupal-8-plugin-system • https://www.drupal.org/docs/8/api/plugin-api

  18. Services

  19. Services • Global utilities with a known Interface • Services

    can be swapped • Easier to test • Better reusability
  20. Examples of Services • Caching & Database Access • Asset

    (JS/CSS) optimizer • Plugin Manager / Module Handler / Event Dispatcher • API integration • Validation handlers
  21. https://api.drupal.org/api/drupal/services/8

  22. Service Recipe 1. Choose a unique name. HINT: Use your

    module name as a prefix, ‘mymodule.service_name’ 2. Define an Interface, and then implement it 3. Register the service in a mymodule.services.yml file 4. Access it via the container using the unique name \Drupal::service(‘mymodule.service_name’)
  23. core/modules/breakpoint/breakpoint.services.yml services:
 class: Drupal\breakpoint\BreakpointManager
 arguments: ['@module_handler', '@theme_handler', '@cache.discovery', '@string_translation']

 - { name: plugin_manager_cache_clear }
  24. Service Resources • https://api.drupal.org/api/drupal/ core%21core.api.php/group/container/8 • https://drupalize.me/videos/introduction- dependency-injection • https://drupalize.me/series/module-development-

    essentials • https://www.drupal.org/node/2133171 http://lb.cm/mEP
  25. Events

  26. Events • React to application actions/conditions without modifying the application

    itself. • Events are a common pattern in OOP, hooks are a bit of a Drupalism.
  27. Events Recipe - Subscribe 1. Determine the event name

    2. Define a service tagged ‘event_subscriber’ services: tommy_event_subscriber: class: Drupal\tommy\EventSubscriber\TommySubscriber tags: - {name: event_subscriber} modules/tommy/tommy.services.yml
  28. Events Recipe - Subscribe 3. Implement \Symfony\Component\EventDispatcher\EventSu bscriberInterface in the

    \Drupal\mymodule\EventSubscriber namespace modules/tommy/src/EventSubscriber/TommySubscriber.php // This should follow the PSR-4 standard, and use the EventSubscriber sub-namespace. namespace Drupal\tommy\EventSubscriber; class TommySubscriber implements EventSubscriberInterface { static function getSubscribedEvents() { $events[KernelEvents::REQUEST][] = array('checkForRedirection'); return $events; } public function checkForRedirection(GetResponseEvent $event) { // Do something awesome ... } }
  29. Events Recipe - Dispatch 1. Add a class in the

    Drupal/my_module/Events namespace. Documents event names. 2. Add a class for event objects that extends \Symfony\Component\EventDispatcher\Event, provides additional information about an event. 3. Use \Drupal\Component\EventDispatcher\Containe rAwareEventDispatcher::dispatch(); and pass it an event name, and object.

  31. Events Resources • https://drupalize.me/blog/201502/responding- events-drupal-8 • http://symfony.com/doc/current/components/ event_dispatcher/introduction.html • https://drupalize.me/series/module-development-

    essentials • https://api.drupal.org/api/drupal/ core%21core.api.php/group/events/8 http://lb.cm/mEP
  32. Hooks

  33. Hooks • Workhorse of past Drupal versions • Great for

    altering existing data • FAST! • At the time Drupal started using them they were the best option available
  34. Examples of Hooks • Altering forms, hook_form_alter() • Modify meta-data

    gathered by other means, e.g. field/entity info • Respond to “events”
  35. Hooks Recipe - Implement 1. Determine the name of the

    hook to implement.
 e.g. hook_form_alter() 2. Add a function to your .module file following the naming convention, replace “hook”, with your module name.
 e.g. example_form_alter() 3. Implement according to documentation 4. Clear cache
  36. Hook Implementation /**
 * Implements hook_user_login().
 function system_user_login(UserInterface $account)

 $config = \Drupal::config('system.date');
 // If the user has a NULL time zone, notify them to set a // time zone.
 if (!$account->getTimezone() && $config->get('timezone.user.configurable')
 && $config->get('timezone.user.warn')) {
 drupal_set_message(t('Configure your <a href=“:user-edit"> …
 } }
  37. Hooks Recipe - Invoke 1. Pick a unique name for

    your hook 2. Use \Drupal\Core\Extension\ModuleHand lerInterface methods // Invoke a standard hook on all enabled modules. $hook = ‘user_login’; \Drupal::moduleHandler()->invokeAll($hook, $args); // Invoke an alter style hook on all enabled modules. \Drupal::moduleHandler()->alter($type, &$data);
  38. Hooks Resources • {MODULE_NAME}.api.php • https://api.drupal.org/api/drupal/ core%21core.api.php/group/hooks/8 http://lb.cm/mEP

  39. Hooks or Events?

  40. Recap • Plugins provide interchangeable bits of functionality with one

    or many active • Services encapsulate functionality into discrete bundles with a known interface • Events allow objects to communicate • Hooks are good for altering forms and aggregated meta-data
  41. Thanks Twitter: @eojthebrave Email: joe@drupalize.me Slides: Feedback: http://lb.cm/mEP