Skip to content

Instantly share code, notes, and snippets.

@dvessel
Created February 5, 2011 22:37
Show Gist options
  • Save dvessel/812873 to your computer and use it in GitHub Desktop.
Save dvessel/812873 to your computer and use it in GitHub Desktop.
drupal_render + CSS simple selectors
<?php
/**
* @file
* Functions related to Drupal 7 render arrays.
*/
/**
* Prints out a Drupal render array filtered by a simple selection.
*
* ren(): Possible uses:
*
* same as the core render() function: - no performance penalty.
* <?php ren($page['content']); ?>
*
* simple selector: - slightly slower, use example above for shallow elements.
* <?php ren($page, 'content'); ?>
*
* descendent selector: - node comment form inside the content region.
* <?php ren($page, 'content nodes comment_form'); ?>
*
* simple selector deep in the tree: - comment_form wherever it is.
* <?php ren($page, 'comment_form'); ?>
*
* if the above was done with core's render() it would look similar to this:
* <?php print render($page['content']['system_main']['nodes'][nid]['comments']['comment_form']); ?>
*
* comma separated groups: - output each element in a specific order.
* <?php ren($content, 'links, body, comment_form, comments'); ?>
*
* @see http://api.drupal.org/api/search/7/render
*
* @param $elements
* The raw drupal render array.
* @param $select
* This works similar in concept to selecting a single id or id's grouped into
* a descendent selector in CSS.
*/
function ren(&$elements, $select = '') {
print implode("\n", ns_elements($elements, $select, 'render'));
}
/**
* Forms a reference to an inner element based on the select string then
* applies a callback function.
*
* @param $elements
* The raw drupal render array.
* @param $select
* This works similar in concept to selecting a single id or id's grouped into
* a descendent selector in CSS.
* @param $callback
* The function callback. Known callbacks: 'render', 'show' or 'hide'.
*/
function ns_elements(&$elements, $select = '', $callback) {
if (!$select) {
return array($callback($elements));
}
$output = array();
foreach (ns_search_keys($select) as $search_keys) {
if ($inner_elements = &ns_ref_inner_element($elements, $search_keys)) {
$output[] = $callback($inner_elements);
}
}
return $output;
}
/**
* Converts a simple search string into a multiple search sets.
*/
function ns_search_keys($search) {
$search_array = array();
foreach (explode(',', $search) as $i => $set) {
foreach (preg_split("/[\s]+/", $set, -1, PREG_SPLIT_NO_EMPTY) as $sub_set) {
$search_array[$i][] = is_numeric($sub_set) ? (int) $sub_set : $sub_set;
}
}
return $search_array;
}
/**
* Forms a reference to an inner element targeted by a search.
*
* @param $elements
* The parent element.
* @param $search
* An array of search keys pointing to a key member of the $elements.
*/
function &ns_ref_inner_element(&$elements, $search = array()) {
$indexes = ns_path_finder($elements, $search);
if ($indexes && end($search) == end($indexes)) {
$inner_elements = &$elements;
for ($index = reset($indexes); $index !== FALSE; $index = next($indexes)) {
$inner_elements = &$inner_elements[$index];
}
}
else {
$inner_elements = NULL;
}
return $inner_elements;
}
/**
* Returns a flat array mapping the traversed tree of the targeted search.
*
* @param $elements
* The typically large haystack.
* @param $search
* An array of paths to search by key.
* @param $found
* For internal use while in recursion.
*/
function ns_path_finder($elements, $search, $found = array()) {
$find = current($search);
foreach ($elements as $path => $sub_elements) {
// Ignore hash keys.
if ($path[0] === '#') {
continue;
}
// Increment if found.
if ($path === $find) {
next($search);
}
// Apply recursion and merge as it pulls out.
if ($inner_found = ns_path_finder($sub_elements, $search, $found)) {
$found = array_merge($found, array($path), $inner_found);
return $found;
}
// Found.
elseif ($path === $find) {
$found[] = $path;
return $found;
}
}
return FALSE;
}
@johnvsc
Copy link

johnvsc commented Feb 8, 2011

You know what, I wrote this function for my RUNVSC theme to automate the ns() function:

function runvsc_build_main_classes(& $variables, $addclass = "") {
  $left = $variables['left'];
  $left_layout = $variables['layouts']['left']['grid'];
  $right = $variables['right'];
  $right_layout = $variables['layouts']['right']['grid'];
  $main_layout = $variables['layouts']['default']['container'];
  $container = "container-" . $main_layout ;

  if ($left && $right) {
    $value = $main_layout - $right_layout - $left_layout ;
    $grid = "grid-" . $value ;
    $classes = array($container, $grid) ;
  }
  else
    if ($left) {
      $value = $main_layout - $left_layout ;
      $grid = "grid-" . $value ;
      $classes = array($container, $grid) ;
    }
    else
      if ($right) {
        $value = $main_layout - $right_layout ;
        $grid = "grid-" . $value ;
        $classes = array($container, $grid) ;
      }
      else {
        $classes[] = runvsc_build_layout_classes($variables['layouts']) ;
  }
  $classes[] = $addclass ;
  $output = 'class="' . runvsc_implode_array($classes) . '"' ;
  return $output ;
}

But for the D7 version of RUNVSC, I want to make a layout manager -> where you can swap out CSS classes to control layout. I need to look at this (and you code above) in order to figure out a way to make this happen -> seems like we are thinking in the same direction!

@dvessel
Copy link
Author

dvessel commented Feb 8, 2011

I'm not sure exactly what that function is doing since I haven't seen the theme but one thing you can do dig into any element in the $page array and push classes into individual elements. I did a few simple experiments and it's possible to push grid classes from the page.tpl.php or "page" scope into any inner elements. Might be possible to have a massive layout manager from one place like a THEME_preprocess_page() shoving grid classes into individual nodes, blocks, etc…

I'll leave that to the smarter folks out there though. The though of any sort of 'manager' gives me a headache. :)

@dvessel
Copy link
Author

dvessel commented Mar 3, 2011

I got something better going on here: https://gist.github.com/852446

Similar idea but far more powerful using a class.

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