Sprint: Rebuild theme layer for Drupal 8

We encourage users to post events happening in the community to the community events group on https://www.drupal.org.
jenlampton's picture
Start: 
2012-04-20 10:00 - 2012-04-22 18:00 America/Los_Angeles
Organizers: 
Event type: 
Sprint

A sprint to tear down and rebuild the theme system for D8 based on ideas based the ideas outlined below. We'll be gathering a few key people in San Francisco at the Chapter Three offices to formulate a plan and build a working example.

We invite everyone else who's interested in cleaning up Drupal's theme layer to please participate remotely, we'll be on IRC in the #drupal-themesprint channel from 10am Pacific onward each day, April 20th, 21st and 22nd.

1) John Albin's core conversation:
http://denver2012.drupal.org/content/re-thinking-rendertheme-layers

2) Jacine's blog:
http://jacine.net/post/19652705220/theme-system

3) Nate+Jen+Carl's session proposal:
http://denver2012.drupal.org/program/sessions/token-templates-new-templa...

4) Kris's blocks/layouts/context initiative:
http://groups.drupal.org/drupal-8-blocks-layouts-everywhere-initiative

5) Chx's core issue:
Let's keep discussion about the theme system happening here

http://drupal.org/node/1499460

Comments

Here's the brain-dump concept

quicksketch's picture

Here's the brain-dump concept of before and after token templates for field.tpl.php

field.tpl.php before:

<div class="<?php print $classes; ?>"<?php print $attributes; ?>>
  <?php if (!$label_hidden): ?>
    <div class="field-label"<?php print $title_attributes; ?>><?php print $label ?>:&nbsp;</div>
  <?php endif; ?>
  <div class="field-items"<?php print $content_attributes; ?>>
    <?php foreach ($items as $delta => $item): ?>
      <div class="field-item <?php print $delta % 2 ? 'odd' : 'even'; ?>"<?php print $item_attributes[$delta]; ?>><?php print render($item); ?></div>
    <?php endforeach; ?>
  </div>
</div>

field.tpl.php tokenized:

<div class="[classes]"[attributes]>
  <?php if (!tk('field:label')): ?>
    <div class="field-label"[field:title_attributes]>[field:label]:&nbsp;</div>
  <?php endif; ?>
  <div class="field-items"[field:content_attributes]>
    <?php foreach ($items as $item): ?>
      <div class="field-item"[field:<?php print $item; ?>:attributes]>[field:<?php print $item; ?>]</div>
    <?php endforeach; ?>
  </div>
</div>

Hate to sound negative as

DesignDolphin's picture

Hate to sound negative as well, but that looks inlegible and way overcomplicated to me.

Personally this is easier for me to work with:

function show_value_field($field_name, $entity, $value_set, $amount, $display_type, $value_type)

Where:
$field_name = the field name | Required
$entity = entity type (multiple values allowed) | Optional (defaults to show all)
$value_set = set values (1), non set values (2), all values (3) | Optional (defaults to 1)
$amount = show single value (1), specify number of values (2), all values (3) | Optional (defaults to 1)
$display_type = use a (custom) field.tpl.php (1), use plain value (2) | Optional (defaults to 1)
$value_type = plain text (1), int (2), url (3), img (4), etc(?) | Optional (defaults to 1)

Link: http://drupal.org/node/1813084

It's more or less the same thing, but the other way round.

I could live with it if it was Twiggynized though. If I can still read it.

I like your second example better. Thank you for that.

Because with PHP, HTML and Twig mixed with each other like in the first example my eye keeps losing the code. It's very disorienting, sorry to say. :-(

Double post. Drupal Groups

DesignDolphin's picture

Double post.

Drupal Groups does this sometimes.

I hate to sounds negative

nomonstersinme's picture

I hate to sounds negative here.. I'm no Drupal expert and I dont want to act like I know the answer to the issues with the theme system but I don't think this is a good solution. Front end developers are used to php variables adding tokens is a whole other layer that will only make people like me want to use Drupal less and less. Please reconsider.

Like I said below, this isn't

mikey_p's picture

Like I said below, this isn't really about "adding tokens" as much as it is "replacing render arrays and render elements."

Drupal 7 has already moved to a point where having a nothing but string variables in a template is a thing of the past. The complexity of the Field API and it's formatters means that there is no single, simple way to represent the data that a field could return, since it's configurable via the UI. As it is now, there really is no simple way to do what this proposal is suggesting unless you like working in arrays that are 2-10 layers deep and understand the difference between theme functions that take arguments vs. theme functions that take elements, and so on.

Point still stands.

kalms's picture

Then I'd say the problem is not in the theme layer, but elsewhere. Because she is right, it is way too complex and only serves to alienate designers/frontend devs.

I hate to sound negative,

AmyStephen's picture

I hate to sound negative, too, but I believe there is way too much PHP code in there!

IMO, this is what I would hope the field.tpl.php tokenized (whatever that is) should look like when you are done modernizing the templating:

<div {{class}}>
  {{label}}
    <div {{label-class}}>{{label-value}}</div>
  {{/label}}
  <div {{item-class}}>
    {{#items}}
  <div {{another-div-and-class-come-on-drupal}}>
    {{item-field-like-name}}
  </div>
  {{/items}}
  </div>
</div>

Time to put PHP devs out of the frontend development business and position for the productivity tools coming out of the ruby world. Mustache and Twig (especially since Drupal is integrating some Symfony2) is the way to go.

The actual templating

mikey_p's picture

The actual templating language is not an issue, Drupal has had, and probably will have pluggable template languages for some time to come. The real problem is that due to making it possible to configure Drupal's output and formatting from the user interface, there is no clear cut way to represent that data as a plain variable, and Drupal's theme system has slowly moved to render arrays and elements, which are difficult to work with, and non-intuitive for themers (and I'd argue developers as well).

i.e. see

mikey_p's picture

i.e. see https://github.com/renebakx/twig-for-drupal for an example of Twig for Drupal.

Cool - have not seen the Twig

AmyStephen's picture

Cool - have not seen the Twig one yet. Maybe you've seen Damz's Mustache example? https://github.com/damz/mustache-drupal -- it's very good.

Mustache (and Twig is close) are becoming a standard for frontend devs. A big benefit is that the skills used to create JSON/Ajax templates (or a dozen other languages) end up being the same as the skills they use to create PHP templates. http://mustache.github.com/

I think we'll start seeing frontend devs focusing only on the presentation layer - which can be put into any CMS / environment.

The cryptic stuff (arrays, etc.) can be hidden away in a Template Class method that extends the mustache/twig class. So, one time - a PHP dev writes a method called item-class which outputs class="field-items"[field:content_attributes]> -- and then from that point on, frontend devs can use {{item-class}}.

So, if it's difficult to fix that complexity, not a problem, you can at least hide it from those who will simply walk away because the learning curve is too high.

As far as User Interface goes - I think it's important to think about the frontend devs job as being separate from the CMS. Picture them coming with a fully functioning HTML mockup. Something generated from HAML for example -- or -- something built from snippets of Foundation or Twitter Bootstrap. All they will want to do is get that layout into Drupal -- pixel perfect.

Same is true of SASS and LESS -- those environments are where the frontend dev wants to work - not in Drupal - so figuring out how to get it in from their world - wear they have perfected these designs -- where their customers have approved -- without jacking it up but bringing it in pixel perfect - is the trick. Personally, I wouldn't focus on building it from scratch in Drupal. As time goes on, I don't believe frontend devs will want that. I think that will seem more and more out of touch as these frontend dev tools mature.

Loops and IFs?

quicksketch's picture

Hey Amy,

This template we used specifically because it had a loop in it and we wanted to see what that would look like. Most templates don't have loops, but a lot of them will still have conditionals. From that perspective we have two options:

  • Change the theming layer to use a templating language (like twig in your example)
  • Use PHP as the theming layer but add a token system

The token system makes it so that you have safe, sanitized data that is generated as needed. Developers and most themers know basic PHP already so they don't have to learn anything new. Really taking a look at twig, I can't say that I'm impressed that it seems more clean in any way than PHP. See the example templates at http://twig.sensiolabs.org/doc/templates.html

Sadly, I suspect you'll want

AmyStephen's picture

Sadly, I suspect you'll want both options rather than either/or. ;-)

I agree that PHP devs like PHP as a templating language. There are also a lot of existing websites that use that approach and changing them completely will seldom be an option. Provided you can integrate with a templating solution like Mustache or Twig, then those who wish to use it that can.

I also find Twig to be just as cryptic as PHP and I am not certain I see the gains with it. My example was in Mustache and shows loops and conditionals, too, just like your PHP one. Much less cryptic than Twig.

Having worked with it a bit, I can see why it to be gaining in acceptance and has interfaces for many environments - JS and PHP and Ruby and C++, etc. I wonder if it is emerging as a defacto standard. When you consider a PHP dev advanced Twig and a frontend dude made Mustache, the subtle differences make more sense.

Tokens are the way to go allowing you to encapsulate a lot of cryptic and complicated code. Since you can create a class that extends Mustache, it'll be easy to reuse those tokens in that environment.

This is a great initiative - combined with all the other work going on, Drupal 8 will be something to behold.

My example was in Mustache

quicksketch's picture

My example was in Mustache and shows loops and conditionals, too, just like your PHP one. Much less cryptic than Twig.

Thanks I hadn't realized that, looking again I see what you're doing there. I have to agree that Mustache seems much cleaner than twig and much less "code-y". That said, we still have theme engines in Drupal, so either approach could be written as a pluggable alternative to strait PHP.

In any case, having a token-like architecture (not necessarily a token-like syntax like my example) provides consistent, safe, printable output, which could be utilized by any templating system. Right now our templates are a mix of safe and unsafe PHP variables, some that are data and some that are strings. The result of this approach would be that we would have a way of defining all the safe content and only generate that content as needed, rather than making hundreds of variables that most of the time don't get used at all.

restful

dozymoe's picture

/me scratched head.

Um, a bit off topic. Been hearing about D8 going restful, does that mean that every token will be resolved to a URI?

Err, just trying to get the big picture.

No, the most granular level

EclipseGc's picture

No, the most granular level at which that should ever happen on the GET text/html side should be blocks.

While I wish the overall

mikey_p's picture

While I wish the overall complexity was less and this level of granularity in templates wasn't required at all, I think this is a brilliant approach to solving this problem. I gave a presentation on this subject at the Pacific Northwest Drupal Summit (a few days before I heard about token templates) and I didn't really have a good solution to present, and was trying to just raise awareness about the problem.

To drive the point home I ended up playing a game with the audience of "arguments or render element" where I would name a theme function from Drupal 7 and have the audience try to guess what that theme function specifies. Some of the examples were obvious, but others totally stumped the audience. Most of the folks in my presentation seemed to think that I was missing the point and should just install more modules to get what I want, such as Display Suite, Omega theme and Delta module, but I still think that misses the point of reducing complexity.

I applaud the intent of this

xtfer's picture

I applaud the intent of this approach, however there are some areas which will impact it which wont actually be fully functional by the time of the sprint, namely plugins and layout controls.

Jacine's post is probably the closest conceptually to what the poorly named Blocks Everywhere initiative is aiming for, however simplicity is key. Fundamentally, you cant expect to be able to theme everything that comes your way using prebuilt components like lists or somesuch, so you end up with complexity. Plugins go some way to solving this, as the widget becomes more modular, but you can still only provide a subset of implementations in core, because you are dealing with an open world problem.

Display Suite has tried to solve this problem, partly, by unifying the API around renderable elements. In 6.x, its a nightmare, as all properties are essentially custom. 7.x is better. But, the lesson is this, what makes uniform content rendering possible is standardised content rendering, and that happens when elements define their own formatters transparently. The themer shouldn't need to know what theme functions are required, ever, even if they intend to change the theme function used.

Another Example with only PHP

quicksketch's picture

In response to @nomonstersinme above, here's an example that avoids the "mixed" syntaxes of PHP + tokens by always using PHP for all output, but generating the safe, consistent output on the fly by using a token_print() function. Again, using a theme engine like twig or mustache, this could be converted to a shorter syntax, but the important thing is that we're providing a mechanism for safe and consistent output.

<div class="<?php token_print('classes'); ?>"<?php token_print('attributes'); ?>>
  <?php if (!token_value('field:label')): ?>
    <div class="field-label"<?php token_print('field:title_attributes'); ?>><?php token_print('field:label'); ?>:&nbsp;</div>
  <?php endif; ?>
  <div class="field-items"<?php token_print('field:content_attributes'); ?>>
    <?php foreach ($items as $item): ?>
      <div class="field-item"<?php token_print("field:$item:attributes"); ?>><?php token_print("field:$item"); ?></div>
    <?php endforeach; ?>
  </div>
</div>

This isn't bad

Zarabadoo's picture

I sat and talked with quicksketch and Jenlampton near the end of the code sprint Friday and find myself not minding this too much. I absolutely did not like the initial implementation at the top of this thread. This is better than pure tokens as it does not require requiting a whole other language to get the proper logic in place. It seems to be a nice little halfway point between a placeholder style system and our phptemplate system.

I am sure there are plenty of gotchas and details to work on with this. We have remember this is pseudo code and is to get the ideas out there. It is best not to reject it entirely. There was one bug with quicksketch's code above with the foreach loop that he found while i was looking over his shoulder. We should use $key and not $item. There should also be a final call at the bottom fo the template to print out whatever has not been specifically called. Maybe a simple token_print() can act as a catchall. This is one of the best parts of render($content) that I would hate to lose.

<div class="<?php token_print('classes'); ?>"<?php token_print('attributes'); ?>>
  <?php if (!token_value('field:label')): ?>
    <div class="field-label"<?php token_print('field:title_attributes'); ?>>
      <?php token_print('field:label'); ?>:
    </div>
  <?php endif; ?>
  <div class="field-items"<?php token_print('field:content_attributes'); ?>>
    <?php foreach ($items as $key => $item): ?>
      <div class="field-item"<?php token_print("field:$key:attributes"); ?>>
        <?php token_print("field:$key"); ?>
      </div>
    <?php endforeach; ?>
  </div>
  <?php token_print(); ?>
</div>

One of the other things not mentioned was his ideas for hook_token_info() and hook_token_info_alter(). It seems like more functions, but it does give us one thing that should help beginners: the ability to put help documents that a themer can access. This information could be accessed by adding a function like token_help() in the tpl.

Consistency and security could improve with this. As what is said in a comment further down the page, there will be some level of insecurity due to the ability to use php. This goes for template.php and tpl files. Setting the use of token_print() (or whatever it would be called) as the best practice could help with it. I know people do not always use best practices, but if we can teach people to use t(), we can teach them this. The idea is that this would sanitize the output. In order to do it properly, a consistent structure would be required so we do not sanitize the wrong thing and get lovely bits of exploded markup on the page.

Being able to edit individual pieces concerns me a bit. If I understand this properly, the output for the token will not exist until it is called. This would make things a bit rough for me as I am one of those people that probably uses preprocess functions for adding classes and sometimes structures so I don't have a billion tpl files strewn about.

The breaking up of the stack has me a bit concerned also. Our base output should be "content" and not "field" in this case. Attributes and classes shouldn't be in "content", but should also not be lone variables placed with a print() implementation. for consistency's sake.

Before this is done, getting an example on how this would role into a standard theme function should be on the list to do. I imagine it can be done in a very similar way, but I can see there being some gotchas there too.

I like this approach the best so far

Senpai's picture

I like this approach the best so far, simply because it looks easy on the eyes.

Two questions though.
Is <?php token_print('field:title_attributes'); ?>
easier for a beginning themer to understand than
<?php print render($item); ?> ?

Also, with this latest approach, are themers gonna have heart attacks caused by the copious amounts of double-carets? (i.e. <div class="field-item"<?php token_print("field:$item:attributes"); ?>>)


Joel Farris | my 'certified to rock' score
Transparatech
http://transparatech.com
619.717.2805

Really I'd say "no", but only

quicksketch's picture

Really I'd say "no", but only if you're working with a renderable variable. The problem today is some variables are "renderables" that take render/drupal_render/drupal_render_children, and some things are just strings, and other variables are objects that as a themer you shouldn't ever print out at all. With this approach, everything you print out would always be through token_print(), you'd never have string variables any more, and any variables you can use for logic constructs (particularly loops) only.

Twig Troll

RobLoach's picture

Tokens for rendering seem like an interesting idea. Here's an example of it using Twig:

<div class="{{ classes }}" {{ attributes }}>
  {% if label_hidden %}
    <div class="field-label"{{ title_attributes }}>{{ $label }}:&nbsp;</div>
  {% endif %}
  <div class="field-items"{{ content_attributes }}>
    {% for delta in items %}
      <div class="field-item {{ delta // 2 ? 'odd' : 'even'; }}"{{ item_attributes.delta }}>{{ item|render }}</div>
    {% endfor %}
  </div>
</div>

As long as PHP is available

swentel's picture

As long as PHP is available in template files, you can never be sure you're going to get safe output. This is especially true in custom themes and I've seen many examples in security reviews I've done for websites built in Drupal. So the only way we garantee safe output is:

  • Banning using PHP anymore in template files
  • Removing the ability of overriding theming functions in template.php

The functions for safe output are available: check_markup, content_format (CCK 6), drupal_render/render - although you can't be sure about that either depending which theme function is used (especially in custom modules). It's one of the reasons that I feel like a new system is not going to garantee us safe output. And it adds a new set of functions people need to learn as well.

We do need to think about consistency, that is so true. And we are sending too many variables into templates files, that again is the root of many potential exploits and confusion for themers. So I think, what we really need to solve, is what we're actually sending to template files, in any context, whether it's a page, node, field, field, block, html etc. That should be consistent in any context, which D7 in a way, imo, took some nice steps already.

As xtfer already mentioned, D7 was a great relief for me as a maintainer of Display suite because of the render api and introduction of entities. It allowed me to create tpl files for any entity which are extremely simple:

<div class="class="<?php print $classes;?> clearfix"">
  <?php if ($left): ?>
    <div class="group-left<?php print $left_classes; ?>">
      <?php print $left; ?>
    </div>
  <?php endif; ?>
  <?php if ($right): ?>
    <div class="group-right<?php print $right_classes; ?>">
      <?php print $right; ?>
    </div>
  <?php endif; ?>
</div>

Templates files for nodes/users/taxonomies are easily readable and our themers almost never touch any template file, ever. The same applies to how display suite now handles field rendering (through simple theming functions). The fences project more or less does the same approach. They all still have the possibility to add evil PHP, but it shouldn't matter anymore here.

So, yes, we do need think about this, I do not doubt that (and I don't have all the exact answers, or even know the 'right' solution), we just need to make sure we 'fix' it at the right level.

I'm going to try and be available on IRC during those sprint days as I'm really interested in this matter. Man, I should really live in the US to be more available face to face for such sprints :)

Clean HTML & CSS

drupal a11y's picture

In my opinion, and I use some additional modules for this, the current standard nested drupal code is a mess from html & css-designers view.

As frontend-developer I really like to be able to have an own html/css structure/definitions and also the possibility to define own classes & id´s and then there´s not really a need for all this drupal classes or the nested div-html.

For the code cleaning I love to use "semantic views", "semantic fields" & "field-formats".
Also "Fieldgroup" or "Views" offer a possibilities to create e.g. "wrapper / container"-div´s which are very important for layouts inside the "main content"-areas.

All in all I would love to define the wrapping-html and classes in cck without any needs to get into the php-level.

This conversation should be

afox's picture

This conversation should be moved to http://drupal.org/node/1499460. There's no reason in keeping two separate discussions.

Also, people at the frontendunited.org will be definitely dealing with this issue in Amsterdam at the same time. Let's make this a full community effort and join forces instead of dealing with the same thing at the same time in separate corners of the earth.

That issue queue...

chrisjlee's picture

Looks like that issue queue got closed by chx just now.

Frontend United

mortendk's picture

Im gonna gather a bunch of fronend devs & help out from our side - were starting the sprint Friday & will make sure that theres ppl around all weekend to come with input & help etc.

This is gonna be amazing!

/morten.dk king of rock
morten.dk | geek Royale

I'll try to help where I can

pixelmord's picture

I'll try to help where I can attending the sprint in Amsterdam during Frontent United

****************
wunderkraut - Da wächst etwas..... www.wunderkraut.com

The case for Twig

moronicbajebus's picture

I think Twig needs to be front and center at the theme layer. What I suggest does mean some substantial changes.

It is not a programming language

Understand that Twig (which is based on the Django template language) is not a programming language. Programming languages and programming paradigms are designed to solve types of problems. The mechanism are not always best suited to solve the issue of take a whole lot of different data and convert it into a string output.

PHP as template promotes bad practices

There is a lot of stuff going on in templates that needs to be in the control logic and not the display logic. Unfortunately this regularly occurs because the data is such a mess coming back. It is only half there or it requires you to make a series of calls to retrive the information. The developers need to pass better data - Drupal needs to have better data structures.

Twig is a template language

As a template language, Twig is about taking data and outputting it. It is designed with features in mind for this purpose.

We should not explicitly set variables in the templates. I know Twig allows it, but we should avoid it. We will only use the template for the purpose of output.

Features

The feature set of Twig can be achieved with PHP - I am not going to lie about that - but it makes it so much easier. It is designed - it is tuned - for the task of templating.

Filters

Filters are so simple but so damn useful. Take a variable and modify it for output. You can easily chain them together.

{{ name|striptags|title }}

Including other templates

Yes PHP has include. But it is not quite that simple to include other templates in Drupal. This would allow for a clean syntax with Drupal hooking in behind to pull in the correct template file.

Easy looping

The difference between looping in PHP and Twig is that PHP is a whole lot more use cases for looping where Twig has like one or two. For creating output, you are only needing to do a foreach loop over either an array or hash. This means the syntax and features can be improved.

<ul>
    {% for user in users %}
        <li>{{ user.username }}</li>
    {% endfor %}
</ul>

In addition, it gives you some additional variables and helpers for common scenarios.

  • Is it the first element? Check with loop.first
  • Is it the last element? Check with loop.filast
  • What is the index of the element? Check with loop.index for starting at 1 or loop.index0 for starting at 0
  • How many elements are after this? Check with loop.revindex for starting at 1 or loop.revindex0 for starting at 0
  • What if there are no elements? Use the {% else %} tag to catch when the collection is empty
  • How do I apply alternating classes? Use the cycle function to handle it

OO Templates

By using extend you can really make your life easier. Your templates can extend and then over-ride sections of the parent template. The base template define sections that can be over-ridden. You can have multiple levels of inheritances and sections within sections.

Right now if for a Video node template I needed to change one section of the general node template, I would have to have to copy wholesale the node template and then make the changes. Not very DRY. With extend I can extend the node template and change the section.

Conclusion

Can we just PHP instead of a robust template language - sure. We could also just use C or assembly to build websites instead of PHP. Twig is designed to address the needs of front-end developers turning data into HTML (or other) output.

It is designed with features

DesignDolphin's picture

It is designed with features in mind for this purpose.

Open unbiased question:

Was it designed by designers for programmers, or by programmers for designers?

<ul>
    {% for user in users %}
        <li>{{ user.username }}</li>
    {% endfor %}
</ul>

Drupal is gonna give me RSI if I read this stuff, and it is already heavy on code.

What about this instead?

<ul>
{for user in users}
<li>{user.username}</li>
{endfor}
</ul>

That types a lot quicker, and is a bit easier to read as well.

There is a lot of hype around this Twig thing in Drupal. But, what are the changes I will still have to open something like template.php, and write PHP code, now mixed with Twig? Wouldn't that make things more complicated? Also will I retain functionality with the front-end or am I going to be stuck with functions which I can't use fully (and have to rewrite everything in a function)? You know, how it goes, an IT porject is announced with great hype, carried through, and then it's found that it doesn't live up to the hype. Twig still gives me that vibe.

I read A LOT of criticism from front-end developers, but at times I wonder if this Twig thing is pushed to much. Trust us it will be good for you, this from the CMS with one of the worst theming in the business. I hope you can understand why were sceptical.

@moronicbajebus Please keep

jenlampton's picture

@moronicbajebus Please keep comments about twig vs php in this issue:
http://drupal.org/node/1499460

This thread should be about the sprint :)

Theme development

Group organizers

Group notifications

This group offers an RSS feed. Or subscribe to these personalized, sitewide feeds: