-
Notifications
You must be signed in to change notification settings - Fork 7.6k
Generatic List Generator
Title should be "Generic List Generator with templating"
After having rewritten the same function for different controllers and only changing minor things within the function itself, I finally got round to creating a helperfunction that does the trick. This helper should be able to generate just about any list you might want, whether it be a UL, OL, /, table or a Script.aculo.us inPlaceCollectionEditor list.
The helper is tested but not yet fully. I created a thread in the forums, and added some more advanced examples in the 3rd post.
This helper contains one function: string generate_list(array/object $resource, array $options, string $template)
array/object $resource Takes either an array or an object and uses it as the data for its list, it can contain arrays which it will either accept as an associative array (to create a single entry with multiple parameters) or just multiple values to create a sublist which will be nested.
array $options Takes the following values:
- int level (defaults to 0) Keeps track of the level, the toplist gets 0 and a nested list gets 1, a list nested in the nested list gets 2, etc...
- string indent (defaults to '') Takes a string that will be added $option['level'] times where you put {INDENT}
- string link (defaults to '') Will be added between items, but not before the first or after the last.
- array ignore (defaults to array()) Takes an associated array where the values may be arrays. It checks each key/value in the $resource against this list if it is set and ignores any key/value(s) that match (which also ignores the children of this node).
-
string template_head (defaults to '')
Will be added before each list (for example
- ), can be ignored for the top list.
- string template_foot (defaults to '') Will be added after each list (for example
The following example:
$this->load->helper('generate_list');
$resource_test = array(array('something'=>array('a','b','c')),'test','and something else');
$options = array(
'template_head'=>'<ul>',
'template_foot'=>'</ul>',
'alternate'=>array('color: blue;', 'color: red;')
);
echo generate_list($resource_test, $options, '<li style="{ALTERNATE}">{CONTENT}</li>');
Will generate (without the spaces/linebreaks):
<ul>
<li style="color: red;">something</li>
<ul>
<li style="color: red;">a</li>
<li style="color: blue;">b</li>
<li style="color: red;">c</li>
</ul>
<li style="color: blue;">test</li>
<li style="color: red;">and something else</li>
</ul>
The contents of"generate_list_helper.php" (updated december 10, 1:49 GMT) Bugfix (11/20): added a str_replace at the end that replaces any double added $option['link'], should be prevented but don't have the time to figure out a decent patch. Bugfix (12/10): moved the foreach loop for external functions within and outside classes, which now detects if the expected class is the current controller. Though it still wouldn't handle a class correctly for which the classname and the variablename within CI aren't the same. (for example: a library "Example" would be instantiated on $this->example)
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
function generate_list($resource, $options, $template)
{
if (is_object($resource)) $resource = get_object_vars($resource);
// Check options, and put to default if unset
if (!isset($options)) $options = array();
if (!isset($options['level'])) $options['level'] = 0;
if (!isset($options['indent'])) $options['indent'] = '';
if (!isset($options['link'])) $options['link'] = '';
if (!isset($options['ignore'])) $options['ignore'] = array();
if (!isset($options['selected'])) $options['selected'] = array();
if (!isset($options['template_head'])) $options['template_head'] = '';
if (!isset($options['template_foot'])) $options['template_foot'] = '';
if (!isset($options['use_top_wrapper'])) $options['use_top_wrapper'] = true;
if (!isset($options['alternate'])) $options['alternate'] = array();
if (!isset($options['current_alternate'])) $options['current_alternate'] = 0;
if (!isset($options['functions'])) $options['functions'] = array();
// create options for next level
$next_options = $options;
$next_options['level']++;
// instantiate output variable
$output = '';
// add the list header
if ($options['level'] > 0 or $options['use_top_wrapper']) $output = $options['template_head'];
// count the number of values in resource
$resource_count = count($resource);
// create the list
foreach($resource as $item)
{
// create a temporary variable for each item
$item_output = $template;
// if there are methods set, replace their tags
if (count($options['functions']) > 0)
{
foreach($options['functions'] as $function)
{
$ci =& get_instance();
if (method_exists($function[1], $function[0]))
{
if (get_class($ci) == $function[1])
$replace_value = $ci->$function[0]($options['level'], $options['current_alternate'], $item['id']);
else
$replace_value = $ci->$function[1]->$function[0]($options['level'], $options['current_alternate'], $item['id']);
$item_output = str_replace('{'.strtoupper($function[0]).'}', $replace_value, $item_output);
}
elseif (function_exists($function[1]))
{
$replace_value = $function[0]($options['level'], $options['current_alternate'], $item['id']);
$item_output = str_replace('{'.strtoupper($function[0]).'}', $replace_value, $item_output);
}
}
}
// place the values in the item variable
if (!is_array($item))
{
$item_output = str_replace('{CONTENT}', $item, $item_output);
}
else
{
// check the ignore values
if (count($options['ignore']) > 0)
{
foreach($options['ignore'] as $ignore => $ignore_value)
{
if (is_array($ignore_value))
{
foreach ($ignore_value as $ignore_val_val)
{
if ($item[$ignore] == $ignore_val_val)
{
$item_output = '';
}
}
}
else
{
if ($item[$ignore] == $ignore_value)
{
$item_output = '';
}
}
}
}
foreach ($item as $key => $value)
{
// if the value is an array, replace any instance of SUBS with a sublist
if (!is_array($value))
{
$item_output = str_replace('{'.strtoupper($key).'}', $value, $item_output);
}
else
{
if (empty($value)) $sublist = '';
else $sublist = generate_list($value, $next_options, $template);
if ($sublist != '') $sublist = $options['link'].$sublist;
$item_output = str_replace('{SUBS}', $sublist, $item_output);
}
}
}
// check if any values were replaced, if not assume sublist, generate and continue
if ($item_output == $template && is_array($item))
{
$item_output = generate_list($item, $next_options, $template);
if ($resource_count > 1 && $item_output != '')
{
$item_output .= $options['link'];
$resource_count--;
}
$output .= $item_output;
continue;
}
// place the indent
$item_output = str_replace('{INDENT}', str_repeat($options['indent'], $options['level']), $item_output);
// place the alternation
if (is_array($options['alternate']) && !empty($options['alternate']))
{
$alternate_max = count($options['alternate']);
$alternate = $alternate_max;
while($options['current_alternate'] % $alternate != 0 && $alternate > 0) $alternate--;
$item_output = str_replace('{ALTERNATE}', $options['alternate'][$alternate - 1], $item_output);
}
// link the items with the link only if it isn't the last item
if ($resource_count > 1 && $item_output != '')
{
$item_output .= $options['link'];
}
// update the counters before next iteration
$options['current_alternate']++;
$resource_count--;
// cleanup and replace any leftover tags
$item_output = preg_replace('/\{([a-zA-z0-9_]*)\}/', '', $item_output);
// place the new item at the end of the current list
$output .= $item_output;
unset($item_output);
}
// close the list with the list footer
if ($options['level'] > 0 or $options['use_top_wrapper']) $output .= $options['template_foot'];
// remove any double "link"-s -- IMPROVE THIS FIX, PREVENT FROM HAPPENING, happens at the end of a sublist when its ignored
$output = str_replace($options['link'].$options['link'], $options['link'], $output);
// ... and return the output
return $output;
}
/* End of file generate_list_helper.php */
/* Location: ./system/application/helpers/generate_list_helper.php */