Skip to content

Instantly share code, notes, and snippets.

@markhalliwell
Last active December 20, 2015 11:39
Show Gist options
  • Select an option

  • Save markhalliwell/6125045 to your computer and use it in GitHub Desktop.

Select an option

Save markhalliwell/6125045 to your computer and use it in GitHub Desktop.
Here's my "vision" on seeing the potential of what the theme system _could_ be.
<?php
// We implment something like hook_element_info() for themes.
// In theory, this identical to hook_theme(), but doesn't require
// a registry.
function system_theme_info() {
$info['foo_bar'] = array(
'variables' => array('title' => NULL, 'content' => NULL),
'context' => array('conditional_switch' => FALSE),
// Blah blah blah, rest of hook code.
);
return $info;
}
// We change the theme() signature to something like:
function theme($hook, array $variables = array(), array $context = array()) {
//code
}
// To render something we'd return something like:
return array(
'#theme' => 'foo_bar',
// Currently the "variables" are added with as a "hashed" key ie:
// #title => ...,
// #content => ...,
// This is really confusing and should be put into something like:
'#variables' => array(
'title' => t('Heading'),
'content' => t('My awesome content'),
),
// Variables should be reserved for what will actually be rendered.
// It's pointless to put logistical "variables" inside something that
// doesn't actually output rendered data. This is where "context"
// comes into play. Context should be reserved for adding or changing
// information that alters the flow of logic (ie: different outcome) or
// is only there for contextual support (ie: checking a node type).
// An example of this is passing things like $entity objects. We commonly
// see things like $variables['#node']. We never actually "render" the
// entity object, we just use it as contextual reference to build what
// _is_ rendered.
'#context' => array(
'conditional_switch' => TRUE,
'entity' => $entity,
),
);
@carlwiedemann
Copy link

I have some comments with this implementation.

In my view, the notion of context would be information about the theme callback internals and not supplemented "information that alters the flow of logic".

These internals may include:

  • The name of the invoked theme hook
  • The name of the parent theme hook (if different than the original)
  • The theme hook suggestions being used
  • Etc

All of this information is internal to theme() and thus would be created immediately before invoking any of the prepare hooks.

$context = array(
  'theme_id' => $hook,
  'original_theme_id' => $original_hook,
  'suggestions' => $suggestions,
);

foreach ($prepare_hooks as $prepare_hook) {
  foreach (\Drupal::moduleHandler()->getImplementations($prepare_hook) as $module) {
    $prepare_function = $module . '_' . $prepare_hook;
    if (function_exists($prepare_function)) {
      call_user_func_array($prepare_function, array(
        &$variables,
        $context,
      ));
    }
  }
}

Instead, what is suggested in markcarver's code above, is that $context should be user-supplied to contain anything really, with the distinction that things in context are non-printable whilst things in $variables should be printable directly. From a practical standpoint, this means the following:

  • We'd have to rewrite every render array in core, debating what is "printable" and what is "non-printable."

  • Certain theme callbacks, such as array('#theme' => 'node') receive a 'render element', i.e., nothing in the realm of "printable" exists explicitly at the time of invocation. So would this look like the following?

    return array(
      '#theme' => 'node',
      '#context' => array(
        'node' => $node,
      ),
    );
    
  • Other theme callbacks may have information that is ambiguous whether it is printed explicitly or not. That is, for array('#theme' => 'item_list'), should $type live in $variables or $context? What about $view_mode for entities?

I am concerned that by adding more rules about what should be $variables and what should be $context is actually more confusing since we having two different places to put/look for information.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment