Drupal 8: Theming

Post on 07-Aug-2015

149 views 4 download

Tags:

Transcript of Drupal 8: Theming

Drupal 8: ThemingDrupal 8: ThemingTheming basics & TWIG for Drupal 8 modulesTheming basics & TWIG for Drupal 8 modules

Drupal Meetup StuttgartDrupal Meetup Stuttgart

07/02/2015

1. Introduction:1. Introduction:Template EnginesTemplate Engines

Once upon a time, in a D7 module...Once upon a time, in a D7 module...

function mymodule_block_content() {

$output = '';

$users = mymodule_get_some_users();

$output = '<ul class="list" style="margin-top:10px">'; foreach ($users as $user) { $output .= '<li class="item"><em>' . $user->name . '</em></li>'; } $output .= '</ul>';

return $output

}

Markup and styling mixed with business logicHardly to be overwritten

We can do this a little bit better:We can do this a little bit better:function mymodule_block_content() { $users = mymodule_get_some_users(); $output = theme('mymodule_block', $users); return $output}

function mymodule_theme() { return array( 'mymodule_block' => array( 'variables' => array('users' => NULL), ), );}

function theme_mymodule_block($variables) { $users = $variables['users']; $output = '<ul class="list" style="margin-top:10px">'; foreach ($users as $user) { $output .= '<li class="item"><em>' . $user->name . '</em></li>'; } $output .= '</ul>'; return $output}

Can be overwritten, in template.php(mytheme_mymodule_block)

We can do this much more better:We can do this much more better:function mymodule_block_content() { $users = mymodule_get_some_users(); $output = theme('mymodule_block', $users); return $output}

function mymodule_theme() { return array( 'mymodule_block' => array( 'variables' => array('users' => NULL), 'template' => 'mymodule_block' ), );}

and in mymodule_block.tpl.php:

<ul class="list" style="margin-top:10px"><?php foreach ($users as $user) : ?> <li class="item"><em><?php print $user->name; ?></em></li><?php endforeach; ?></ul>

Template file can be copied and overwrittenAnd maybe use CSS, not markup or inline styles...

Voilá, a Template Engine!Voilá, a Template Engine!(aka Theme Engine)

Drupal 4.7 / 5 / 6 / 7: PHPTemplateDrupal 8: TWIG

Variables

What's wrong with PHPTemplate?What's wrong with PHPTemplate?

Drupal proprietary stuffRequires PHP knowledgeHard to readPotentially insecure, e.g. printing malicous stringsEmpowers business logic, e.g. DB queriesOne typo can take your site offlineSooo old-style

So Drupal 8 goesSo Drupal 8 goes

PHPTemplatePHPTemplate SmartySmarty PHPTALPHPTAL TWIG TWIG

2. Building a Drupal 82. Building a Drupal 8ThemeTheme

Create a theme folder structureCreate a theme folder structure

- config - schema - mytheme.schema- css - base.css - layout.css- images- js - special.js- libraries - flexslider- templates - node.html.twig - page.html.twiglogo.svgscreenshot.pngmytheme.breakpoints.ymlmytheme.info.ymlmytheme.libraries.ymlmytheme.theme

/themes/custom/mytheme/

Tell Drupal about your themeTell Drupal about your theme

name: 'My theme'type: themedescription: 'Just a sample theme for Drupal 8.'package: Customcore: 8.xlibraries: - mytheme/globalstylesheets-remove: - core/assets/vendor/normalize-css/normalize.cssregions: header: Header content: Content sidebar_first: 'Sidebar first' footer: Footer

/themes/custom/mytheme/mytheme.info.yml

Tell Drupal about css/js libraries in your themeTell Drupal about css/js libraries in your theme

# This one is specified in mytheme.info.yml and loaded on all pagesglobal: version: VERSION css: theme: css/base.css {} css/layout.css: {}

# Those are needed in some special places and loaded via #attached['library']special: version: VERSION css: theme: css/special.css: {} js: js/special.js: {}flexslider: version: '2.5.0' css: theme: libraries/flexslider/flexslider.css: {} js: libraries/flexslider/jquery.flexslider.js: {} dependencies: - core/jquery

/themes/custom/mytheme/mytheme.libraries.yml

Add preprocessing stuff, if neededAdd preprocessing stuff, if needed

<?php

/** * Implements hook_element_info_alter(). */function mytheme_element_info_alter(&$type) { // We require Modernizr for button styling. if (isset($type['button'])) { $type['button']['#attached']['library'][] = 'core/modernizr'; }}

/themes/custom/mytheme/mytheme.theme

Formerly known as template.php!

Specify breakpoints, if neededSpecify breakpoints, if needed

mytheme.mobile: label: mobile mediaQuery: '' weight: 2 multipliers: - 1xmytheme.narrow: label: narrow mediaQuery: 'all and (min-width: 560px) and (max-width: 850px)' weight: 1 multipliers: - 1xmytheme.wide: label: wide mediaQuery: 'all and (min-width: 851px)' weight: 0 multipliers: - 1x

/themes/custom/mytheme/mytheme.breakpoints.yml

Add the remaining stuff...Add the remaining stuff...TemplatesScriptsStylesheetsImagesLogoScreenshot...

3. Theming basics for3. Theming basics formodulesmodules

Good News!Good News!Not so many changesNot so many changesMain difference: no more theme() functions!

Registering templatesRegistering templates(no more theme functions!)

function mymodule_theme($existing, $type, $theme, $path) { return array( 'mymodule_something' => array( 'variables' => array('something' => NULL, 'otherthing' => NULL), ), );}

hook_theme(), in your module file

Create a templateCreate a template(*.html.twig, not *.tpl.php)

{% if something %} <p> {{ something }} {{ otherthing }} </p>{% endif %}

mymodule-something.html.twig, in your module's templatefolder (/modules/custom/mymodule/templates)

Use this somewhereUse this somewhere(using render array, not theme())

...

$output = array( '#theme' => 'mymodule_something', '#something' => 'Something', '#otherthing' => 'Otherthing',);

...

Somewhere in your code (controller, plugin, ...)

Alter some stuffAlter some stuff(mainly provided by other modules)

/** * Implements hook_preprocess_HOOK(). */function yourmodule_preprocess_mymodule_something(&$variables) {

...

}

In your module file or theme

4. TWIG Basics:4. TWIG Basics:SyntaxSyntax

Print / Output:

{{ some content }}{{ some content }} Comments:

{# this is a comment #}{# this is a comment #} Execute statements:

{% expression %}{% expression %}

5. TWIG Basics:5. TWIG Basics:VariablesVariables

Accessing variablesAccessing variablesSimple variables (strings, numbers, booleans):{{ foo }}

Complex variables (arrays / objects):

Objects & arrays:{{ foo.bar }}Alternative:{{ attribute(foo, 'bar') }}

Only arrays:{{ foo['bar'] }}

Example from views module:

{% if attributes -%} <div{{ attributes }}>{% endif %} {% if title %} <h3>{{ title }}</h3> {% endif %} <{{ list.type }}{{ list.attributes }}> {% for row in rows %} <li{{ row.attributes }}>{{ row.content }}</li> {% endfor %} </{{ list.type }}>{% if attributes -%} </div>{% endif %}

Assigning values to variablesAssigning values to variables

{% set foo = 'bar' %}

{% set foo, bar = 'foo', 'bar' %}

{% set foo = [1, 2] %}{% set foo = {'foo': 'bar'} %}{% set foo = 'foo' ~ 'bar' %}

{% set foo %} <div id="pagination"> ... </div>{% endset %}

More examples:

http://twig.sensiolabs.org/doc/tags/set.html

6. TWIG Basics:6. TWIG Basics:Control structuresControl structures

{% if ordered_list %} <ol>{% else %} <ul>{% endif %}

IF ... THEN ... ELSE ... ENDIF

{% for item in items %} <li>{{ item }}</li>{% endfor %}

FOR ... ENDFOR

{% include '@mytheme/parts/footer.html.twig' %}

INCLUDE -> fetch another template file

{% block footer %} © Copyright 2015 drubb{% endblock %}

BLOCK -> section that can be repeated, or overwritten by other template files

7. TWIG Basics:7. TWIG Basics:Filters & FunctionsFilters & Functions

{{ title|upper|trim('.') }}

{% filter upper %} This text becomes uppercase{% endfilter %}

More examples: abs, first, last, length, lower, reverse, round,...)

http://twig.sensiolabs.org/doc/filters/index.html

General Twig filters

Drupal specific filtersTranslate:<a href="{{ url('<front>') }}" title="{{ 'Home'|t }}" rel="home" class="site-logo"></a>

Without:{{ content|without('links') }}

Safe join:{{ items|safe_join(", ") }}

More examples:https://www.drupal.org/node/2357633

Filter: simple transformations on output

{{ max(1, 3, 2) }}

{{ random(['apple', 'orange', 'citrus']) }}

More examples:

http://twig.sensiolabs.org/doc/functions/index.html

General Twig functions

Drupal specific functionsUrl:<a href="{{ url('<front>') }}" title="{{ 'Home'|t }}" rel="home" class="site-logo"></a>

Path:{{ path('entity.node.canonical', {'node': node->id()}) }}

More examples:

https://www.drupal.org/node/2486991

Function: takes arguments to compute output

8. TWIG Basics:8. TWIG Basics:InheritanceInheritance

<header> ...</header>

<article> ...</article>

<footer> {% block footer %} <h4>This is the footer coming from Template 1!</h4> {% endblock%}</footer>

Second template (special.html.twig)

First template (default.html.twig)

{% extends "default.html.twig" %}

{% block footer %} {{ parent() }} <h5>But there's a second line now!</h5>{% endblock%}

9. TWIG Basics:9. TWIG Basics:ExampleExample

{#/** * @file * Theme override to display a block. * * Available variables: * - ... * * @see template_preprocess_block() */#}{% set classes = [ 'block', 'block-' ~ configuration.provider|clean_class, ]%}<div{{ attributes.addClass(classes) }}> {{ title_prefix }} {% if label %} <h2{{ title_attributes }}>{{ label }}</h2> {% endif %} {{ title_suffix }} {% block content %} {{ content }} {% endblock %}</div>

block.html.twig

Thank You!Thank You!

http://slides.com/drubbhttp://slideshare.net/drubb