public function rebuild_list($params = '', $type = 'variable', $scope = 'user')
{
// is this method being called directly?
if (func_num_args() > 0) {
if (!(isset($this) && get_class($this) == __CLASS__)) {
return self::_api_static_call(__FUNCTION__, $params, $type, $scope);
} else {
return $this->_api_call(__FUNCTION__, $params, $type, $scope);
}
}
$sort = strtolower($this->EE->TMPL->fetch_param('sort', FALSE));
$sort_type = strtolower($this->EE->TMPL->fetch_param('sort_type', FALSE));
// string || integer || lowercase
$orderby = $this->EE->TMPL->fetch_param('orderby', FALSE);
$match = $this->EE->TMPL->fetch_param('match', NULL);
// regular expression to each list item against
$against = $this->EE->TMPL->fetch_param('against', NULL);
// array key to test $match against
$unique = $this->EE->TMPL->fetch_param('unique', NULL);
$slice = $this->EE->TMPL->fetch_param('slice', NULL);
// e.g. "0, 2" - slice the list array before order/sort/limit
$in = $this->EE->TMPL->fetch_param('in', FALSE);
// compare column against a tracked value, e.g. list_column:tracked_column, and include if it matches
$not_in = $this->EE->TMPL->fetch_param('not_in', FALSE);
// compare column against a tracked value, and exclude if it matches
// make sure any parsing is done AFTER the list has been replaced in to the template
// not when it's still a serialized array
$this->parse_complete = TRUE;
// run get() with a safe list of parameters
$list = $this->_run_tag('get', array('name', 'type', 'scope', 'context'));
// reenable parsing
$this->parse_complete = FALSE;
if ($list !== '' && $list !== NULL) {
// explode the list
$list = explode($this->_list_delimiter, $list);
foreach ($list as $key => &$value) {
$value = $this->_list_row_explode($value);
}
unset($value);
// apply order/sort
if ($orderby) {
if ($orderby == 'random') {
// shuffle list order
shuffle($list);
} elseif (strncmp($orderby, 'random:', 7) == 0) {
// shuffle one or more keys in the list, but leave the overall list order unchanged
$keys_to_shuffle = explode(',', substr($orderby, 7));
foreach ($keys_to_shuffle as $key_shuffle) {
$list = $this->shuffle_list_key($list, $key_shuffle);
}
} else {
// here be dragons (array_multisort)
$orderby = explode('|', preg_replace('#\\s+#', '', $orderby));
$sort = explode('|', preg_replace('#\\s+#', '', $sort));
$sort_type = explode('|', preg_replace('#\\s+#', '', $sort_type));
// make columns out of rows needed for orderby
$columns = array();
foreach ($list as $key => $row) {
foreach ($orderby as $name) {
if (isset($list[$key][$name])) {
$columns[$name][$key] =& $list[$key][$name];
} else {
$columns[$name][$key] = null;
}
}
}
// create function arguments for multisort
$args = array();
foreach ($orderby as $i => $name) {
$args[] =& $columns[$name];
// column reference
// SORT_ASC is default, only change if desc
if (isset($sort[$i]) && $sort[$i] == "desc") {
$args[] = SORT_DESC;
}
// types string, integer, lowercase
if (isset($sort_type[$i])) {
switch ($sort_type[$i]) {
case 'string':
$args[] = SORT_STRING;
break;
case 'integer':
case 'numeric':
$args[] = SORT_NUMERIC;
break;
case 'lowercase':
$columns[$name] = array_map('strtolower', $columns[$name]);
$args[] = SORT_STRING;
break;
case 'normalize':
$columns[$name] = array_map(array($this, '_normalize'), $columns[$name]);
$args[] = SORT_STRING;
break;
default:
// $args[] = SORT_REGULAR;
break;
}
}
}
// last argument, array to sort
$args[] =& $list;
// sorted
call_user_func_array('array_multisort', $args);
unset($columns);
}
}
// apply sort direction
if (!is_array($sort) && $sort == 'desc') {
$list = array_values(array_reverse($list));
}
// slice before any filtering is applied
// note: offset/limit can be used to 'slice' after filters are applied
if (!is_null($slice)) {
$slice = array_map('intval', explode(',', $slice));
if (isset($slice[1])) {
$list = array_slice($list, $slice[0], $slice[1]);
} else {
$list = array_slice($list, $slice[0]);
}
}
// compare column values against a statically tracked value, and *exclude* the row if the value matches
if ($not_in) {
$col_local = $col_tracked = $not_in;
if (strstr($not_in, ':')) {
$not_in = explode(':', $not_in);
$col_local = $not_in[0];
if (isset($not_in[1])) {
$col_tracked = $not_in[1];
}
}
if (isset(self::$_cache['track'][$col_tracked])) {
foreach ($list as $key => $value) {
if (isset($value[$col_local]) && in_array($value[$col_local], self::$_cache['track'][$col_tracked])) {
unset($list[$key]);
}
}
}
}
// compare column values against a statically tracked value, and *include* the row only if the value matches
if ($in) {
$new_list = array();
$col_local = $col_tracked = $not_in;
if (strstr($in, ':')) {
$in = explode(':', $in);
$col_local = $in[0];
if (isset($in[1])) {
$col_tracked = $in[1];
}
}
if (isset(self::$_cache['track'][$col_tracked])) {
foreach ($list as $key => $value) {
if (isset($value[$col_local]) && in_array($value[$col_local], self::$_cache['track'][$col_tracked])) {
$new_list[] = $value;
}
}
}
$list = $new_list;
}
// match/against: match the value of one of the list keys (specified by the against param) against a regex
if (!is_null($match) && preg_match('/^#(.*)#$/', $match) && !is_null($against)) {
$new_list = array();
foreach ($list as $key => $value) {
if (isset($value[$against])) {
if ($this->_matches($match, $value[$against])) {
// match found
$new_list[] = $value;
}
}
}
$list = $new_list;
}
// re-index array
$list = array_values($list);
// ensure we have unique rows?
if ($unique !== NULL) {
if (FALSE === (bool) preg_match('/^(0|off|no|n)$/i', $unique)) {
if (FALSE === (bool) preg_match('/^(1|on|yes|y)$/i', $unique)) {
// unique across a single column
$unique_list = array();
$index = 0;
foreach ($list as $key => $value) {
if (isset($value[$unique])) {
$unique_list[$index] = array($unique => $value[$unique]);
}
++$index;
}
// make a unique list for the column
$unique_list = array_map('unserialize', array_unique(array_map('serialize', $unique_list)));
// restore original list values for the unique rows
$restored_list = array();
foreach ($unique_list as $key => $value) {
$restored_list[] = $list[$key];
}
$list = $restored_list;
} else {
// make a unique list
$list = array_map('unserialize', array_unique(array_map('serialize', $list)));
}
}
}
} else {
$list = array();
// make sure we always return an array
}
return $list;
}