12 Nov 2011

feeddrupal.org aggregator

Drupal core announcements: Core's directory structure reorganized

As of 2011-11-01, most files in Drupal core live in a 'core' subdirectory. We did this to make it easier to tell what's core vs. site-specific code (e.g. to discourage people from installing modules into the 'modules' subdirectory in the webroot) and to make it easier to upgrade to newer versions. See #22336: Move all core Drupal files under a /core folder to improve usability and upgrades for the full story and/or the API change record: Most Drupal core files now live in a "core" subdirectory.

One of the only drawbacks of this change is that bug fix patches for Drupal 7 no longer apply to Drupal 8 without being rerolled. However, generally it's easy re-roll a patch in this situation. xjm wrote up detailed instructions for re-rolling patches here: http://xjm.drupalgardens.com/blog/rerolling-drupal-8-core-patches

A more simple (but less effective in some cases) way to re-roll was written up by scor over at comment #306 of the original issue.

Please don't reopen the original issue with follow-up suggestions or bug reports -- those belong in new issues.

Core

12 Nov 2011 8:39am GMT

11 Nov 2011

feeddrupal.org aggregator

Morbus Iff: Achievements 7.x-1.4: Using print render($a) and render arrays

The Drupal Achievements module offers the ability to create achievements and badges similar to systems seen on Xbox 360, Playstation 3, Foursquare, Gowalla, GetGlue, and more. For a Drupal site, this could mean commenting a certain number of times, starting a forum topic, visiting the site every day of the week, or anything else that can be tracked and coded. The recently released 7.x-1.4 update focuses on changes that make theming easier.

In my first post about #theme_wrappers, we fixed up bad HTML in #prefix and #suffix to give themers an easier time. This post, about render arrays, is no different. In fact, most of the tweaks in Achievements 7.x-1.4 are not very obvious, or even useful, to module developers. It's only when you sit down with a themer who wants to change the entire look and feel that you realize your carefully-coded "looks good in Garland!" output is not as useful as you think.

Why render arrays are better

You've probably read about render arrays in the Drupal Developer's Handbook already, but the documentation doesn't really give a developer a decent reason why they should use them. It also doesn't talk about $content or splitting your variables into "data" and "presentation". I'll cover both below.

First, let's look at the wrong approach:

    $build['image'] = theme('image', array('path' => array('misc/druplicon.png')));

If this was passed to a theme file, the themer would simply print $image; and be done with it. The themer could even link the image if they wanted, but they wouldn't be able to add any classes or attributes to the image, since calling theme() directly always returns rendered HTML. Here's what the above looks like as a render array:

    $build['image'] = array(
      '#theme' => 'image',
      '#path' => 'misc/druplicon.png',
    );

To get this to display in the theme, we'd use print render($image); instead. In this case, the theme is telling Drupal to render the HTML, not your module. Why is this important? Ignoring the nebulous "I CAN'T ADD CSS CLASSES, SNIFF!" themer lament, consider the following small tweak to our original bad example:

    $image = theme('image', array('path' => array('misc/druplicon.png')));
    $build['image'] = l($image, 'node', array('html' => TRUE));

Here, we've simply added a link to our dummy image and the themer gets the fully rendered HTML to print out. Everything is toasty... unless the client or theme doesn't want or need the image to be linked. The themer now has no choice: they either have to use a regular expression to strip out the unwanted link or they have to recreate the $image variable in his own, well, image. Not only is that fragile (it's essentially copying module code to the theme and that code might change in a future version), but it also mixes too much logic with too little presentation. If the image's path isn't available to the theme as its own variable (it isn't, in the above example), the themer will still have to parse your rendered HTML to find the image's path first. Yuck.

Let's convert the above to a render array:

    $build['image'] = array(
      '#theme' => 'image_formatter',
      '#item' => array(
        'uri' => 'misc/druplicon.png',
      ),
      '#path' => array(
        'path' => 'node',
        'options' => array('html' => TRUE),
      ),
    );

Now, if the themer wants to remove the link, they can listen in a theme override, a preprocess, or even the dreaded hook_page_alter() and simply unset($variables['image']['#path'])'. No more link, without duplicating any upstream code or recreating things themselves. This is a real-life example, by the way - I just finished an optional submodule of Achievements which removes all links to the default leaderboards. I couldn't have easily done that if I used either of the link approaches below:

    $build['achievement_title'] = l($title, 'path/to/achievement');
    $build['achievement_title']['#markup'] = l($title, 'path/to/achievement');

But with the following render array:

    $build['achievement_title'] = array(
      '#type' => 'link',
      '#title' => $title,
      '#href' => 'path/to/achievemnt',
    );

I can make those links linkless:

  unset($variables['achievement_title']['#type']);
  $variables['achievement_title']['#markup'] = $variables['achievement_title']['#title'];

Data, presentation, and $content['a'] not $a

This doesn't mean that every single variable you pass to the theme should be a render array: there's clearly a difference between variables that represent data (an image path, the $node or $user object, a Unix timestamp, etc.) and variables that are meant for presentation (the linked image, the node's filtered teaser, a human-readable date, etc.).

There's a move afoot to more clearly indicate these two types by using a $content variable as a container for all the supplied render arrays. Drupal core does this in some places (node.tpl.php, for one), but not all, and it's slowly becoming a preferred practice in the theming world. Another benefit is the ability to use print render($content);, which says "render everything I haven't already rendered", allowing themes to display things that they, or the parent module, might not know about (new data added by a third party module in a preprocess, etc.). I've yet to implement this in Achievements, but I'll likely get there for the next release.

11 Nov 2011 6:57pm GMT

Trellon.com: Looking ahead to Drupalcon Denver

With each week that DrupalCon Denver is coming nearer, the excitement in the community grows. At Trellon, we're not immune to that excitement, and we're proud to be a Platinum sponsor of Drupalcon Denver. We're looking forward to seeing members of the Drupal community there, both old friends and new. We're excited about the opportunity that Drupalcons give us not only to learn more about the direction of Drupal, but to help shape it. We're eager to learn what new and exciting things people around the world have been doing with Drupal.

read more

11 Nov 2011 6:00pm GMT