extending twig

29
Extending Twig Gerry Vandermaesen

Upload: gerry-vandermaesen

Post on 07-Aug-2015

92 views

Category:

Software


2 download

TRANSCRIPT

Page 1: Extending Twig

Extending Twig

Gerry Vandermaesen

Page 2: Extending Twig

About me

• @gerryvdm 🐦

• Web developer at King Foo 🐵 (Intracto Group)

• SensioLabs Certified Symfony Developer 👑

• Drupal noob 😟

Page 3: Extending Twig

Twig Templating Engine

• Fast 🏃

• Secure 🔑

• Flexible 🐍

• Replaces PHPTemplate in D8 👏

Page 4: Extending Twig

Basic syntax

<h1>{{ article.title }}</h1> <p>Published on {{ article.createdAt | date('d/m/Y') }}</p> {% if article.summary %} <p>{{ article.summary }}</p> {% endif %}<div>{{ article.content }}</div> <ul class="tags"> {% for tag in article.tags %} <li>{{ tag }}</li> {% endfor %}</ul>

Page 5: Extending Twig

Some cool Twig features

Page 6: Extending Twig

Template inheritance

{# parent.html.twig #}

<!doctype html> <html> <head> <title> {% block title %}DUG Belgium{% endblock %} </title> </head> <body> {% block body %}{% endblock %} </body> </html>

Page 7: Extending Twig

Template inheritance

{# child.html.twig #}{% extends "parent.html.twig" %}{% block title %}Blog - {{ parent() }}{% endblock %} {% block body %} <h1>Blog</h1> {% block content %}{% endblock %} {% endblock %}

Page 8: Extending Twig

Template inheritance

{# grandchild.html.twig #}{% extends "child.html.twig" %}{% block content %} <h3>{{ post.title }}</h3> <div>{{ post.content }}</div> {% endblock %}

Page 9: Extending Twig

Functions

{# get a PHP constant #}{{ constant("Some\\ClassName::CONSTANT_NAME") }}{# dump a variable's content #}{{ dump(foo) }}{# get random element #}{{ random(["apple", "banana"]) }}

Page 10: Extending Twig

Filters

{{ "some random title" | title }}{# outputs "Some Random Title" #}

{{ "now" | date_modify("+1 day") | date("d/m/Y") }}{# outputs "26/06/2016" #}{% set fruits = ["banana", "apple", "pear", "kiwi"] %}{{ fruits | slice(1, 2) | join(", ") }}{# outputs "apple, pear" #}{{ "combo chain" | upper | lower | upper | lower | upper }}{# outputs "COMBO CHAIN" #}

Page 11: Extending Twig

Tags

{% spaceless %} <h2> Lorem ipsum </h2> {% endspaceless %} {# outputs "<h2>Lorem ipsum</h2>" #}

Page 12: Extending Twig

Macros

{# macros.html.twig #}{% macro link_email(email, label) %} <a href="mailto:{{ email }}"> {{- label | default(email) -}} </a> {% endmacro %} {# foo.html.twig #}{% import "macros.html.twig" as macro %}<p>Contact me at {{ macro.link_email("[email protected]") }}</p>

Page 13: Extending Twig

Extending Twig

Page 14: Extending Twig

General workflow

• Implement an extension (extend \Twig_Extension)

• Register the extension in the Twig environment

• Profit 💰 💰 💰

Page 15: Extending Twig

Writing an extension

<?php// modules/twig_demo/src/Twig/ExampleExtension.phpnamespace Drupal\twig_demo\Twig;class ExampleExtension extends \Twig_Extension{ public function getName() { return 'example'; }}

Page 16: Extending Twig

Registering the extension

# modules/twig_demo/twig_demo.services.ymlservices: twig.example_extension: class: Drupal\twig_demo\Twig\ExampleExtension tags: - { name: twig.extension }

Page 17: Extending Twig

Adding custom functions<?phpclass ExampleExtension extends \Twig_Extension{ public function getFunctions() { return array( new \Twig_SimpleFunction( 'gravatar', array($this, ‘generateGravatarUrl') ) ); } public function generateGravatarUrl($email, $size = 100) { return sprintf('http://www.gravatar.com/avatar/%s?s=%s', md5($email), $size ); }}

Page 18: Extending Twig

Invoking our function

<p> <img src="{{ gravatar('[email protected]', 50) }}”> </p>

Page 19: Extending Twig

Adding custom filters<?phpclass ExampleExtension extends \Twig_Extension{ public function getFilters() { return array( new \Twig_SimpleFilter( 'highlight', array($this, 'highlight'), array('is_safe' => array('html' => true)) ) ); } public function highlight($subject, $search) { $highlighted = sprintf('<span style="background: yellow; font-weight: bold;">%s</span>', $search); return str_replace($search, $highlighted, $subject); }}

Page 20: Extending Twig

Invoking our filter

<p> {{ "Hello, world. Goodbye, world!” | highlight('world') }} </p>

Page 21: Extending Twig

Adding global variables<?phpclass ExampleExtension extends \Twig_Extension{ private $container; public function __construct(ContainerInterface $container) { $this->container = $container; } public function getGlobals() { return array( 'pi' => M_PI, 'modules' => array_keys( $this->container->getParameter('container.modules') ) ); }}

Page 22: Extending Twig

Using our globals

<p>Pi ~= {{ pi | round(6) }}</p> <p>{{ modules | join(', ') }}</p>

Page 23: Extending Twig

Defining custom tests<?phpclass ExampleExtension extends \Twig_Extension{ public function getTests() { return array( new \Twig_SimpleTest('today', array($this, 'testIfToday')) ); } public function testIfToday($value) { $today = new \DateTime('now'); if (!$value instanceof \DateTimeInterface) { $value = new \DateTime($value); } return $value->format('Y-m-d') === $today->format('Y-m-d'); }}

Page 24: Extending Twig

Using our custom test

{% if '2015-06-25' is today %} <p>It is Drupal User Group meeting today</p> {% endif %}{% if '2015-12-25' is today %} <p>It is Christmas today</p> {% endif %}

Page 25: Extending Twig

Defining custom tags

<?phpclass ExampleExtension extends \Twig_Extension{ public function getTokenParsers() { return array( new MarkdownTokenParser() ); }}

Page 26: Extending Twig

Writing a token parser<?phpnamespace Drupal\twig_demo\Twig;class MarkdownTokenParser extends \Twig_TokenParser{ public function parse(\Twig_Token $token) { $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); $body = $this->parser->subparse(array($this, 'decideMarkdownEnd'), true); $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); return new MarkdownNode($body, $token->getLine(), $this->getTag()); } public function decideMarkdownEnd(\Twig_Token $token) { return $token->test('endmarkdown'); } public function getTag() { return 'markdown'; }}

Page 27: Extending Twig

Writing a node class<?phpnamespace Drupal\twig_demo\Twig;class MarkdownNode extends \Twig_Node{ public function __construct(\Twig_NodeInterface $body, $line, $tag = 'markdown') { parent::__construct(array('body' => $body), array(), $line, $tag); } public function compile(\Twig_Compiler $compiler) { $compiler ->addDebugInfo($this) ->write("ob_start();\n") ->subcompile($this->getNode('body')) ->write("echo \\Michelf\\Markdown::defaultTransform(ob_get_clean());\n") ; }}

Page 28: Extending Twig

Questions?

Page 29: Extending Twig

• https://github.com/gerryvdm/dug

• http://www.slideshare.net/gerryvdm/extending-twig