Stash::rebuild_list PHP Method

rebuild_list() public method

Retrieve and rebuild list, or optionally part of a list
public rebuild_list ( mixed $params = '', string $type = 'variable', string $scope = 'user' ) : array
$params mixed The name of the variable to retrieve, or an array of key => value pairs
$type string The type of variable
$scope string The scope of the variable
return array
    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;
    }