-
-
Save dvessel/812873 to your computer and use it in GitHub Desktop.
<?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; | |
} |
These look awesome ! Bookmarking
Great! This is going to be part of the NineSixty theme. And don't forget to read Young Hahn's post on rules based theming. This bit of code isn't exactly rules based but imagine if we got to that point. We are about 10% there and I can already see how this can simplify things a good deal.
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!
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. :)
I got something better going on here: https://gist.github.com/852446
Similar idea but far more powerful using a class.
Updated ns_path_finder. It's about twice as fast without all the unneeded safety checks.