Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
Part of meta-issue #1788918: [GTD] [META] Prepare for Twig main engine core inclusion until December 1
At the A designer-friendly theme system in Drupal 8? session in Munich, it seemed like the presenters were not sure whether D8/Twig could support preprocess functions as we use them today to alter variables before they are sent to the tpl file. I personally use them a lot in themes. Core does too.
Core themes examples:
// garland theme
function garland_preprocess_comment(&$vars) {
$vars['submitted'] = $vars['created'] . ' — ' . $vars['author'];
}
// bartik theme
function bartik_preprocess_node(&$variables) {
if ($variables['view_mode'] == 'full' && node_is_page($variables['node'])) {
$variables['classes_array'][] = 'node-full';
}
}
Core modules examples:
// toolbar.module
function toolbar_preprocess_html(&$vars) {
if (isset($vars['page']['page_top']['toolbar']) && user_access('access toolbar')) {
$vars['classes_array'][] = 'toolbar';
if (!_toolbar_is_collapsed()) {
$vars['classes_array'][] = 'toolbar-drawer';
}
}
}
// overlay.module
function overlay_preprocess_html(&$variables) {
if (overlay_get_mode() == 'child') {
// Add overlay class, so themes can react to being displayed in the overlay.
$variables['classes_array'][] = 'overlay';
}
}
// shortcut.module
function shortcut_preprocess_page(&$variables) {
// Only display the shortcut link if the user has the ability to edit
// shortcuts and if the page's actual content is being shown (for example,
// we do not want to display it on "access denied" or "page not found"
// pages).
if (shortcut_set_edit_access() && ($item = menu_get_item()) && $item['access']) {
$link = $_GET['q'];
$query_parameters = drupal_get_query_parameters();
if (!empty($query_parameters)) {
$link .= '?' . drupal_http_build_query($query_parameters);
}
$query = array(
'link' => $link,
'name' => drupal_get_title(),
);
$query += drupal_get_destination();
$shortcut_set = shortcut_current_displayed_set();
// Check if $link is already a shortcut and set $link_mode accordingly.
foreach ($shortcut_set->links as $shortcut) {
if ($link == $shortcut['link_path']) {
$mlid = $shortcut['mlid'];
break;
}
}
$link_mode = isset($mlid) ? "remove" : "add";
if ($link_mode == "add") {
$query['token'] = drupal_get_token('shortcut-add-link');
$link_text = shortcut_set_switch_access() ? t('Add to %shortcut_set shortcuts', array('%shortcut_set' => $shortcut_set->title)) : t('Add to shortcuts');
$link_path = 'admin/config/user-interface/shortcut/' . $shortcut_set->set_name . '/add-link-inline';
}
else {
$query['mlid'] = $mlid;
$link_text = shortcut_set_switch_access() ? t('Remove from %shortcut_set shortcuts', array('%shortcut_set' => $shortcut_set->title)) : t('Remove from shortcuts');
$link_path = 'admin/config/user-interface/shortcut/link/' . $mlid . '/delete';
}
if (theme_get_setting('shortcut_module_link')) {
$variables['title_suffix']['add_or_remove_shortcut'] = array(
'#attached' => array('css' => array(drupal_get_path('module', 'shortcut') . '/shortcut.css')),
'#prefix' => '<div class="add-or-remove-shortcuts ' . $link_mode . '-shortcut">',
'#type' => 'link',
'#title' => '<span class="icon"></span><span class="text">' . $link_text . '</span>',
'#href' => $link_path,
'#options' => array('query' => $query, 'html' => TRUE),
'#suffix' => '</div>',
);
}
}
}
Comments
Comment #1
scor CreditAttribution: scor commentedComment #2
Cameron Tod CreditAttribution: Cameron Tod commentedDoes this help at all? #1696786: Integrate Twig into core: Implementation issue
Comment #3
jenlamptonThe question isn't "can we still have preprocess functions". The question is "what will preprocess functions look like?" Will they be exactly the same? Renamed? Changed to only be called be on-demand?
Preprocess functions solve an order-of-execution problem for us. They allow one module delay the time at which stuff in the theme layer can be tampered with. We will most likely still need something like that. But we aren't sure what - exactly - that will look like. We currently have three phases:
1) creation - this is when variables get created and added for the first time into the "stuff" that the theme layer prints out (hook_theme).
2) modification - this is when stuff created by one module can be altered by another (or by a theme) (preprocess)
and 3) execution, this is when that stuff actually gets printed out.
The question is really if we need to still have three separate phases, or if our 2nd 'preprocess' phase could possibly happen at the same time as our 3rd phase making it more of a mid-process (or maybe just 'process')? and potentially saving some processing, if we can skip that step when it's not needed.
For the short term - it will remain the preprocess you know and love. We'll see how much we can get done before we start trying to tamper with what we know already works! :)
Comment #4
jenlamptonaccidental double post :/
Comment #5
bstoppel CreditAttribution: bstoppel commentedI don't understand all of the inner working of Drupal and Twig, but aren't theming preprocess functions a relic of the phptemplate engine?
Will the "prepocess" functions that Twig uses be a mix of Filters, Functions, Tags, Globals, etc that can extend Twig? http://twig.sensiolabs.org/doc/advanced.html
Comment #6
jenlamptonNot yet.
For now we'll be using them to get rid of all the PHP logic used in preparing variables for printing in the templates. The first step is to clean up our template files so that all they'll need to do is actually print the data needed. Preprocess will still be the layer where that data gets prepared.
We will have some filters and functions available in the template files (things like t we won't be able to get away from) but the whole point is to make the template files *just print markup*. All the magic that needs to go into generating that markup - the stuff that we do need a programing language to construct - should remain done in PHP and be moved to a more suitable place in the theme layer.
Comment #7
jenlamptonStealing this issue for the twig sandbox.
Comment #8
catchNot sure why this was moved to the Twig sandbox, if we're going to implement Twig in core we need to fix these issues in core.
Comment #9
webchickIt seems to be we've already figured this out, and the answer is "they look the same." Am I wrong?
Comment #10
steveoliver CreditAttribution: steveoliver commentedNot really. I think the differences are in the form of best practices:
1. Return render arrays instead of calling render() in preprocess; Vars printed in templates are render()ed by Twig.
2. Likewise, defer calls to filters like
t()
to Twig templates; Try to avoid calling these in preprocess.3. Minor, and not specific to Twig, but rather the theme cleanup in D8, but preprocess docblocks have a more standardized format.
See Twig coding standards and #1913208: [policy] Standardize template preprocess function documentation.
Did I miss anything?
Comment #11
steveoliver CreditAttribution: steveoliver commentedTo fill in the blanks between the original post and comment #10, here are a few other notes about preprocess:
1. There are some workarounds we've done, and optimizations we've yet to do or are in development to allow for 10.1 above. See #1920886: drupal_render() should check if it's rendering a 'render element' and if so call drupal_render_children() (inline) instead.
2. To summarize #10, we basically are taking the 'process' out of preprocess, and being clear about "preparing variables". We're actually working to kill #process. See #1843650: Remove the process layer (hook_process and hook_process_HOOK).
So yeah, things have basically worked themselves out to answer the question(s) here, I believe. So I'll change priority for and status for now and let someone else close or change this in case I'm missing anything. Maybe an issue summary?
Comment #12
star-szrI think at the very least we've answered the question posed in the OP, tentatively closing. IMO the issue summary here is probably not the best place to document the differences that @steveoliver pointed out.
Comment #13
Fabianx CreditAttribution: Fabianx commentedI'd rather see this postponed than fixed:
BECAUSE:
for example we found that template_preprocess puts a certain overhead on this.
With all converted to twig, we can do much more things that have not been possible before.
Example:
Change Attribute() to use a render like array (array('#typecast' => 'Attribute', 'class'= > ...)) instead of an object, which is way faster in terms of performance to lazy create. (see for example: http://www.lionsad.de/xhprof-kit/xhprof/xhprof_html/?symbol=template_pre... for 200 calls, it is 6 ms)
That would be a good candidate for example.
Comment #14
catchIs it possible to get proof of concepts for this up now prior to 100% conversion? I'm thinking if we had enough conversions in a branch to render a particular page 100% with twig for profiling.
Comment #15
jenlamptonI think we have an answer to this question over here, so I'm going to close this issue as a duplicate of #1886448: Rewrite the theme registry into a proper service.
Comment #15.0
jenlamptonUpdated issue summary.
Comment #16
scor CreditAttribution: scor commentedAny Twig experts around willing to confirm what the current situation is, and if https://gist.github.com/jenlampton/5654283 is a valid description of the reality. I doubt we can give a definite answer to the OP until Drupal 8 reaches a more stable status beyond beta.
Comment #17
star-szr@scor - the current situation is we have 1 and 2 (and I suppose 5) from that gist. Work was done on 3 and 4 but we ended up pushing that to 9.x, and we still have preprocess.