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;
}
@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