/me

  • Drupal dreamer at Ymbra
  • @pcambra in the Internets
  • Coding and development track chair for DrupalCon Amsterdam

Drupal 8 initiatives

  • New to Drupal 8
  • Initiative leaders appointed by Dries
  • Better focus, visibility and reach
  • Organise better the community effort: Birds of a feather flock together

Drupal 8 initiatives

Who's behind them?

Under the hood

Before Twig

block.tpl.php

<?php if (isset($block_html_id)): ?>
  <div id="<?php print $block_html_id; ?>" <?php print $attributes; ?>>
<?php else: ?>
  <div <?php print $attributes; ?>>
<?php endif; ?>
<?php print render($title_prefix); ?>
<?php if ($label): ?>
  <h2<?php print $title_attributes; ?>><?php print $label; ?></h2>
<?php endif;?>
  <?php print render($title_suffix); ?>
  <div<?php print $content_attributes; ?>>
    <?php print render($content) ?>
  </div>
</div>
   	  

After Twig

block.html.twig

<div{{ attributes.addClass(classes) }}>
  {{ title_prefix }}
  {% if label %}
    <h2{{ title_attributes }}>{{ label }}</h2>
  {% endif %}
  {{ title_suffix }}

  <div{{ content_attributes.addClass('content') }}>
    {% block content %}
      {{ content }}
    {% endblock %}
  </div>
</div>
   	  

There's a "new" autoloader in town

Yes, the PSR-4 thing

  • Proposal for Standard Request
  • Updates PSR-0 with a simpler folder structure
  • Code discovery and loading made simple
  • This means no more files[] in the .info or obscure includes in the code

Honey, we've shrunk "the Drupal"

PHP filter is gone

Aren't we feeling safer?

  • It might have been handy but at a high price
  • Security & performance could be easily compromised by non savvy users
  • Upgrade between versions got harder as PHP code could have been ANYWHERE
  • For those willing to take the risk, there's a module for that!

And this fellas too

  • Profile
  • Blog
  • Trigger
  • Dashboard
  • OpenID
  • Poll
  • Garland

"Disabled modules are
broken beyond repair"

Bye bye module disable

You won't be missed, will you?

  • Disabling a module means disabling the interfaces
  • Data integrity risk when data is not up to date
  • It worked well in the past, when life was simpler
  • Removed module_disable() and enable/disable hooks
  • All installed modules are always installed and loaded
  • Oh wait: Will there be a module for this? "Disable modules"

Menu module is gone!

But wait a second before panicking and running away!

The new (and shiny) menu system

  • Routes are the starting point
  • There's a subsystem for each of the menu components
  • Menu items, tabs, actions and contextual links are defined in yml files
  • Custom items are created in the UI and have their own table
  • Two new modules: Menu UI and Menu link content

Anatomy of a menu in Drupal 7


$items['admin/structure/types/manage/%node_type'] = array(
  'title' => 'Edit content type',
  'title callback' => 'node_type_page_title',
  'title arguments' => array(4),
  'page callback' => 'drupal_get_form',
  'page arguments' => array('node_type_form', 4),
  'access arguments' => array('administer content types'),
  'file' => 'content_types.inc',
  'type' => MENU_NORMAL,
);
      

How routes are defined

  • Routes are defined in a <module_name>.routing.yml file
  • Routes map the paths with the controllers
  • Access checks, wildcards, methods, etc are supported
entity.node_type.edit_form:
  path: '/admin/structure/types/manage/{node_type}'
  defaults:
    _entity_form: 'node_type.edit'
  requirements:
    _permission: 'administer content types'
      

Different menu link types

Contextual, action, task and menu links

  • Defined in yml files (i.e. node.links.task.yml)
  • Create menu elements rendered in the page
  • Custom menu links are also available as content entities
  node.overview_types:
    title: 'Content types'
    parent: system.admin_structure
    description: 'Manage content types'
    route_name: node.overview_types
      

Actually, "the Drupal" has grown larger than ever

Migrate in core

  • Upgrade path will be based in migrate
  • Only useful for simple use cases in the past
  • Migrations are the way to go, even for Drupal to Drupal
  • Migrate for Drupal 8 uses best practices and is testable

Migrate in core

We define everything in yaml now, baby

migrate.migration.d6_user_role.yml

id: d6_user_role
source:
plugin: d6_user_role
process:
id:
  -
    plugin: machine_name
    source: name
  -
    plugin: dedupe_entity
    entity_type: user_role
    field: id
  -
    plugin: user_update_8002
label: name
(...)
destination:
plugin: entity:user_role
      

Migrate in core

The process, source, destination & load systems are pluggable

/**
* This plugin creates a machine name.
*
* @MigrateProcessPlugin(
*   id = "machine_name"
* )
*/
class MachineName extends ProcessPluginBase {
(...)

public function transform($value, MigrateExecutable $migrate_executable, Row $row, $destination_property) {
  $new_value = $this->getTransliteration()->transliterate($value, Language::LANGCODE_DEFAULT, '_');
  $new_value = strtolower($new_value);
  $new_value = preg_replace('/[^a-z0-9_]+/', '_', $new_value);
  return preg_replace('/_+/', '_', $new_value);
}
      

Wait... plugins?

An Overview of the Drupal 8 Plugin System

Joe Shindelar, Thursday · 10:45-11:45

Actions API

Actions are now plugins!

  • Action module in Drupal 7 didn't add a lot of value
  • Actions are now annotated plugins
  • New configured actions without user input: config entities
  • Action module will become just a user interface
  • Simplified Views Bulk Operations in core!

Actions API

abstract class ConfigurableActionBase extends ActionBase
        implements ConfigurablePluginInterface, PluginFormInterface {
//
interface ConfigurablePluginInterface {
  public function getConfiguration();
  public function setConfiguration(array $configuration);
  public function defaultConfiguration();
}
//
interface PluginFormInterface {
  public function buildConfigurationForm(array $form, array &$form_state);
  public function validateConfigurationForm(array &$form, array &$form_state);
  public function submitConfigurationForm(array &$form, array &$form_state);
}
      

Actions API

Example: configured action

  $action = entity_create('action', array(
    'id' => 'user_add_role_action.' . $role->id(),
    'type' => 'user',
    'label' => t('Add the @label role to the selected users',
    	array('@label' => $role->label())),
    'configuration' => array(
      'rid' => $role->id(),
    ),
    'plugin' => 'user_add_role_action',
  ));
  $action->save();
      

Wait... config entities?

About configuration entities

  • Share API with content entities
  • Configuration system storage
  • Can be created on install by yml files
  • Normally user created
  • Not fieldable

Now, let's talk about fields (& friends)

New field types

Making site builders happy

  • New goodies for site builders. Out of the box
  • Simplified ports of the equivalent Drupal 7 modules.
  • New field types:
    • Entity reference
    • Date (and time)
    • Email & Telephone
    • Link

Comment as a field

Drupal 7: comment settings attached to node types and stored in variables

  • Comment settings are now a field.
  • Attach comments to any entity type.
  • Several comment fields per entity type.
  • "Reuse existing field" for alike comment configurations in different bundles.
  • There will be a upgrade path! migrate path!

Fields & CMI

  • Field & instance definitions: YAML files
  • Human readable (no more serialised storage)
  • Can be deployed between environments
  • Deleted fields and instances are kept in "state" until data is purged

Field (storage) definition

field.storage.user.user_picture.yml

id: user.user_picture
status: true
langcode: en
name: user_picture
entity_type: user
type: image
settings:
  uri_scheme: public
  default_image:
    fid: null
module: image
cardinality: 1
translatable: false
dependencies:
  module:
    - image
    - user
      

Field (instance) definition

field.field.user.user.user_picture.yml

id: user.user.user_picture
status: true
langcode: en
entity_type: user
bundle: user
field_name: user_picture
label: Picture
description: 'Your virtual face or picture.'
required: false
default_value: {  }
default_value_function: ''
settings:
  file_extensions: 'png gif jpg jpeg'
  file_directory: pictures
  max_filesize: '30 KB'
(..)
field_type: image
dependencies:
  entity:
    - field.storage.user.user_picture
  	  

Just yesterday...

Field (instance) definition

field.field.user.user.user_picture.yml

id: user.user.user_picture
status: true
langcode: en
entity_type: user
bundle: user
field_name: user_picture name: user_picture
label: Picture
description: 'Your virtual face or picture.'
required: false
default_value: {  }
default_value_function: ''
settings:
file_extensions: 'png gif jpg jpeg'
file_directory: pictures
max_filesize: '30 KB'
(..)
field_type: image
dependencies:
entity:
  - field.storage.user.user_picture
    

Drupal 8 CMI on Managed Workflow

Matt Cheney, David Strauss, Wednesday · 13:00-14:00

CRUD API changes for fields

Drupal 7 has field_create_field(), field_create_instance(), update, delete and dozens of other field API crud functions and hooks.

$field_storage = entity_create('field_storage_config', array(
  'entity_type' => 'node',
  'name' => 'field_image',
  'type' => 'image',
));
$field->save();
entity_create('field_config', array(
  'field_name' => 'field_image',
  'entity_type' => 'node',
  'label' => 'Image',
  'bundle' => 'article',
))->save();
    

CRUD API changes for fields

Update and delete fields

$field = entity_load('field_config', 'node.article.field_image');
$field->cardinality = 3;
$field->settings['foo'] = 'bar';
$field->save();

$field->delete();

+
hook_entity_presave()
hook_entity_delete()
...
      

Fields & Plugins

Widgets, formatters & field types are pluggable components

  • In Drupal 7, they are based in hooks or magic callbacks, such as hook_field_validate()
  • Field storage backends - critical to swap to entity based storage
  • Drupal 8:
    • Plugin API
    • Classes
    • Inheritance

Annotated plugins

mymodule/lib/Plugin/field/widget/MyWidget.php

/**
 * @FieldWidget(
 *   id = "mymodule_widget",
 *   label = @Translation("My awesome widget"),
 *   field_types = {
 *     "text"
 *   }
 * )
 */
class MyWidget extends WidgetBase {
	  

Widgets

mymodule/lib/Plugin/field/widget/MyWidget.php

class MyWidget extends WidgetBase {

 public function settingsForm(array $form, array &$form_state);
 public function formElement(array $items, array &$form, array &$form_state);
 public function errorElement(array $element, array $error,
 								array $form, array &$form_state);
 public function massageFormValues(array $values, array $form, array &$form_state);

}
      

Formatters

mymodule/lib/Plugin/field/formatter/MyFormatter.php

class MyFormatter extends FormatterBase {

  public function settingsForm(array $form, array &$form_state);
  public function settingsSummary();
  public function prepareView(array $entities, $langcode,array &$items);
  public function view(EntityInterface $entity, $langcode, array $items);

}
      

Field API is dead. Long live Entity Field API!

Multiple stars, Thursday · 14:15-15:15

In the dock!

Without these people (and many more) this wouldn't have been possible