Cocomore AG
#DrupalCampES | Valencia 2014

Modes and Formatters

DrupalCamp Valencia 2014

http://jsbalsera.github.io/modes_and_formatters/
(And the code is in the other branches)

By Jesús Sanchez Balsera

Your speaker today

@jsbalsera (Drupal.org, Twitter, etc.)

What else?

  • Working at
  • A couple of years working with Drupal.
  • Some other years working with PHP: Code Igniter, Cake PHP, home-made frameworks...

What will this be about?

  • Showing content can be messy.
Look at me, ma'! I'm drupaling!

What this will be about?

  • Showing content can be messy.
  • Backend and frontend developers disagree about who has to do some things.
  • hook_node_view, templates, preprocess functions...
  • Not to talk about Display Suite, Panels...
What can I do?
Article node type fields.

Dirty things

hook_preprocess_page


  if (isset($var['node'])) {
    $node = $var['node'];
  }
  elseif (arg(0) == 'node' && is_numeric(arg(1)) && arg(2) !== 'edit') {
    $node = node_load(arg(1));
  }

  if (isset($node) && isset($node->type) && $node->type == 'article') {
  }
        

hook_node_view


  if (!empty($node) && "article" == $node->type) {
    if (arg(0) == 'node') {
       unset($node->content['field_integers']);
    }
  }
        

Logic in the template files

I won't show examples of that.

View Modes

admin/structure/types/manage/article/display

View Modes

View Modes


function mymodule_entity_info_alter(&$entity_info) {
  $entity_info['node']['view modes'] += array(
    'example_mode' => array(
      'label' => t('Example view mode'),
      'custom settings' => TRUE,
    )
  );
}
    
Don't forget to clear the cache...

View Modes

View Modes

Using View Modes: Views.

Using View Modes: Views.

Using View Modes: Nodeblock.

Using View Modes: Entity Reference.

Styling the view mode


function hook_theme_preprocess_node(&$vars) {
  $vars['theme_hook_suggestions'][] = 'node__' . $vars['view_mode'];
  $vars['theme_hook_suggestions'][] = 'node__' . $vars['type'] .
    '__' . $vars['view_mode'];
}
    

How to hide title and submit information?

  • Using a custom template.
Using extra-fields.
https://github.com/timcosgrove/extra_fields

Making your life easier

  • Entity view modes: UI to define custom view modes for entities, adding template suggestions.
  • Display suite Much more functionality... and complexity.

Formatters

Field formatters specify how fields are displayed.

Formatters

Formatters

Only TWO hooks are mandatory (although there are more):
  • hook_field_formatter_info
  • hook_field_formatter_view

Formatters

And there are other interesting hooks:
  • hook_formatter_settings_form
  • hook_field_formatter_settings_summary

Showing only one item.


function mymodule_field_formatter_info() {
  return array(
    'mymodule_only_one' => array(
      'label' => t('Only one item'),
      'description' => t('Displays only the first item of a multievaluated one'),
      'field types' => array('number_integer', 'number_decimal', 'number_float'),
      'settings' => array(),
    ),
  );
}
        

Showing only one item.

Showing only one item.


function mymodule_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
  $element = array();

  if ($items) {
    switch ($display['type']) {
      case 'mymodule_only_one':
        $item = array_shift($items);

        $element[0] = array('#markup' => $item['value']);
        break;
    }
  }

  return $element;
}
        

Showing only one item.

Adding the items.


function mymodule_field_formatter_info() {
  return array(
    'mymodule_addition' => array(
      'label' => t('Addition Formatter'),
      'description' => t('Displays the result of the addition of all the field items'),
      'field types' => array('number_integer', 'number_decimal', 'number_float'),
      'settings' => array(),
    ),
  );
}
        

Adding the items.

Adding the items.


function mymodule_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
  $element = array();

  if ($items) {
    switch ($display['type']) {
      case 'mymodule_addition':
        $result = 0;
        foreach ($items as $item) {
          $result += $item['value'];
        }

        $element[0] = array('#markup' => $result);
        break;
    }
  }

  return $element;
}
        

Adding the items.

Formatter with settings and summary.


// hook_field_formatter_info
'mymodule_headline' => array(
  'label' => t('Headline'),
  'descriptions' => t('Display a headline as a Hx (H1, H2, H3...) HTML tag'),
  'field types' => array('text'),
  'settings' => array(
    'headline_type' => 'H3',
  ),
),
        
function mymodule_field_formatter_settings_form($field, $instance, $view_mode, $form, &$form_state) {
  $display = $instance['display'][$view_mode];
  $settings = $display['settings'];

  $element = array();

  if ($display['type'] == 'mymodule_headline') {
    $element['headline_type'] = array(
      '#title' => t('Headline Type'),
      '#type' => 'select',
      '#default_value' => $settings['headline_type'],
      '#options' => array(
        'H1' => 'H1', 'H2' => 'H2', 'H3' => 'H3',
      ),
      '#required' => TRUE,
    );
  }

  return $element;
}
function mymodule_field_formatter_settings_summary($field, $instance, $view_mode){
  $display = $instance['display'][$view_mode];
  $settings = $display['settings'];

  $summary = '';

  if ($display['type'] == 'mymodule_headline') {
    $summary = t('Type: @headline_type', array(
       '@headline_type' => $settings['headline_type']));
  }

  return $summary;
}
// hook_field_formatter_view().
case 'mymodule_headline':
  $tag = $display['settings']['headline_type'];
  if (!in_array($tag, array('H1', 'H2', 'H3'))) {
    $tag = 'H3';
  }
  foreach ($items as $delta => $item) {
    $element[$delta] = array(
      '#markup' => format_string('!text', array(
        '!tag' => strtolower($tag),
        '!text' => $item['safe_value'],
        )),
      );
  }
break;

Cool modules

  • field_multiple_limit: Provides settings to limit the number of values to display on fields with multiple values.
  • field_formatter_settings: Provides missing alter hooks for field formatter settings and summaries
  • //article.features.field_instance.inc
    // Exported field_instance: 'node-article-field_text'
    $field_instances['node-article-field_text'] = array(
      'bundle' => 'article',
      'default_value' => NULL,
      'deleted' => 0,
      'description' => '',
      'display' => array(
        'example_mode' => array(
          'label' => 'hidden',
          'module' => 'mymodule',
          'settings' => array(
            'headline_type' => 'H1',
          ),
          'type' => 'mymodule_headline',
          'weight' => 1,
        ),
    How it will be done?
    View modes out of the box via UI.
    Related to entity types.
    // entity.view_mode.node.example_mode.yml
    id: node.example_mode
    label: 'Example mode'
    targetEntityType: node
    status: true
    cache: true
    uuid: f2776549-fc5d-49de-9600-bb8fee1d13d3
    langcode: en
    dependencies:
      module:
        - node
    
    site/default/files/config_{...}/active/
    After enabling the view mode in Structure -> Content Types -> Article -> Manage display - Custom display settings:
    entity.view_display.node.article.example_mode.yml
    id: node.article.example_mode
    uuid: 0ed265dc-c5c8-4bbf-a500-bc87ee15c2f0
    targetEntityType: node
    bundle: article
    mode: example_mode
    content:
      field_image:
        type: image
        weight: -1
        settings:
          image_style: large
          image_link: ''
        label: hidden
      body:
        type: text_default
        weight: 0
    settings: {  }
        label: hidden
      field_tags:
        type: taxonomy_term_reference_link
        weight: 10
        settings: {  }
        label: above
      comment:
        type: comment_default
        weight: 20
        settings:
          pager_id: '0'
        label: hidden
    hidden:
      langcode: true
    status: true
    New thing! Form modes
    Instead of hiding rendered fields, you can hide form items :-)

    Form modes

    admin/config/people/accounts/form-display

    Form modes

    Form modes

    Writing a formatter in D8.

    Good bye field_formatter hooks! Hello plugins!

    Writing a formatter in D8.

    modules/mymodule structure:
    
    .
    ├── lib
    │   └── Drupal
    │       └── mymodule
    │           └── Plugin
    │               └── Field
    │                   └── FieldFormatter
    │                       └── MymoduleHeadlineFormatter.php
    └── mymodule.info.yml
    
        
    MymoduleHeadlineFormatter.php
    /**
    * Plugin implementation of the 'mymodule_headline' formatter.
    *
    * @FieldFormatter(
    *   id = "mymodule_headline",
    *   label = @Translation("Headline"),
    *   field_types = {
    *     "text",
    *     "text_long",
    *   },
    *   edit = {
    *     "editor" = "plain_text"
    *   }
    * )
    */
    class MymoduleHeadlineFormatter extends FormatterBase {
    

    Writing a formatter in D8.

    • Hooks --> a class.
    • hook_field_formatter_info --> annotations (and discovery).
    • Method defaultSettings
    • hook_field_formatter_view --> viewElements
    • hook_formatter_settings_form --> settingsForm
    • hook_field_formatter_settings_summary --> settingsSummary.
    • $settings['setting'] --> $this->getSetting('setting')

    Writing a formatter in D8.

    It's similar, but way better!

    THE END

    Special thanks to:
    • Pablo Lopez @plopesc: Reviews, suggestions and tons of help, also the addition formatter was get from his session Get on with Field API at Drupalcamp Spain 2013
    • Samuel Solís @estoyausente, Marcelo Tosco @capynet, Lowell Montgomery: tons of reviews.
    • Nestalí Guerrero @nesta_, Jose Luis Bellido @jlbellido, Carmen García @mcgarcia: Betatesting
    • Drupalcamp organizers and all the sponsors that make this Drupalcamp possible.
    • All the Drupal community, especially my Cocomore colleagues, for helping me learn and grow everyday!

    THE END

    • ¡Gracias!
    • Let's talk!
    • You can find me in IRC, write me on Twitter, Drupal.org... jsbalsera