1<?php
2
3namespace dokuwiki\plugin\struct\meta;
4
5/**
6 * Manage dynamic parameters for aggregations
7 *
8 * @package dokuwiki\plugin\struct\meta
9 */
10class SearchConfigParameters
11{
12    /** @var string parameter name to pass filters */
13    public static $PARAM_FILTER = 'flt';
14    /** @var string parameter name to pass offset */
15    public static $PARAM_OFFSET = 'ofs';
16    /** @var string parameter name to pass srt */
17    public static $PARAM_SORT = 'srt';
18
19    /** @var SearchConfig */
20    protected $searchConfig;
21
22    /** @var null|array */
23    protected $sort = null;
24    /** @var int */
25    protected $offset = 0;
26    /** @var  array */
27    protected $filters = array();
28
29    /**
30     * Initializes the dynamic parameters from $INPUT
31     *
32     * @param SearchConfig $searchConfig
33     */
34    public function __construct(SearchConfig $searchConfig)
35    {
36        global $INPUT;
37        $this->searchConfig = $searchConfig;
38        /** @var \helper_plugin_struct_config $confHlp */
39        $confHlp = plugin_load('helper', 'struct_config');
40
41        if ($INPUT->has(self::$PARAM_SORT)) {
42            list($colname, $sort) = $confHlp->parseSort($INPUT->str(self::$PARAM_SORT));
43            $this->setSort($colname, $sort);
44        }
45
46        if ($INPUT->has(self::$PARAM_FILTER)) {
47            foreach ($INPUT->arr(self::$PARAM_FILTER) as $colcomp => $filter) {
48                list($colname, $comp, $value,) = $confHlp->parseFilterLine('AND', $colcomp . $filter);
49                $this->addFilter($colname, $comp, $value);
50            }
51        }
52
53        if ($INPUT->has(self::$PARAM_OFFSET)) {
54            $this->setOffset($INPUT->int(self::$PARAM_OFFSET));
55        }
56    }
57
58    /**
59     * Returns the full qualified name for a given column
60     *
61     * @param string|Column $column
62     * @return bool|string
63     */
64    protected function resolveColumn($column)
65    {
66        if (!is_a($column, '\dokuwiki\plugin\struct\meta\Column')) {
67            $column = $this->searchConfig->findColumn($column);
68            if (!$column) return false;
69        }
70        /** @var Column $column */
71        return $column->getFullQualifiedLabel();
72    }
73
74    /**
75     * Sets the sorting column
76     *
77     * @param string|Column $column
78     * @param bool $asc
79     */
80    public function setSort($column, $asc = true)
81    {
82        $column = $this->resolveColumn($column);
83        if (!$column) return;
84        $this->sort = array($column, $asc);
85    }
86
87    /**
88     * Remove the sorting column
89     */
90    public function removeSort()
91    {
92        $this->sort = null;
93    }
94
95    /**
96     * Set the offset
97     *
98     * @param int $offset
99     */
100    public function setOffset($offset)
101    {
102        $this->offset = $offset;
103    }
104
105    /**
106     * Removes the offset
107     */
108    public function removeOffset()
109    {
110        $this->offset = 0;
111    }
112
113    /**
114     * Adds another filter
115     *
116     * When there is a filter for that column already, the new filter overwrites it. Setting a
117     * blank value is the same as calling @param string|Column $column
118     * @param string $comp the comparator
119     * @param string $value the value to compare against
120     * @see removeFilter()
121     *
122     */
123    public function addFilter($column, $comp, $value)
124    {
125        $column = $this->resolveColumn($column);
126        if (!$column) return;
127
128        if (trim($value) === '') {
129            $this->removeFilter($column);
130        } else {
131            $this->filters[$column] = array($comp, $value);
132        }
133    }
134
135    /**
136     * Removes the filter for the given column
137     *
138     * @param $column
139     */
140    public function removeFilter($column)
141    {
142        $column = $this->resolveColumn($column);
143        if (!$column) return;
144        if (isset($this->filters[$column])) unset($this->filters[$column]);
145    }
146
147    /**
148     * Remove all filter
149     */
150    public function clearFilters()
151    {
152        $this->filters = array();
153    }
154
155    /**
156     * @return array the current filters
157     */
158    public function getFilters()
159    {
160        return $this->filters;
161    }
162
163    /**
164     * Get the current parameters
165     *
166     * It creates a flat key value in a form that can be used to
167     * create URLs or Form parameters
168     *
169     *
170     * @return array
171     */
172    public function getURLParameters()
173    {
174        $params = array();
175        if ($this->offset) {
176            $params[self::$PARAM_OFFSET] = $this->offset;
177        }
178
179        if ($this->sort) {
180            list($column, $asc) = $this->sort;
181            if (!$asc) $column = "^$column";
182            $params[self::$PARAM_SORT] = $column;
183        }
184
185        if ($this->filters) {
186            foreach ($this->filters as $column => $filter) {
187                list($comp, $value) = $filter;
188                $key = self::$PARAM_FILTER . '[' . $column . $comp . ']';
189                $params[$key] = $value;
190            }
191        }
192
193        return $params;
194    }
195
196    /**
197     * Updates the given config array with the values currently set
198     *
199     * This should only be called once at the initialization
200     *
201     * @param array $config
202     * @return array
203     */
204    public function updateConfig($config)
205    {
206        if ($this->offset) {
207            $config['offset'] = $this->offset;
208        }
209
210        if ($this->sort) {
211            list($column, $asc) = $this->sort;
212            $config['sort'] = array(
213                array($column, $asc)
214            );
215        }
216
217        if ($this->filters) {
218            if (empty($config['filter'])) $config['filter'] = array();
219            foreach ($this->filters as $column => $filter) {
220                list($comp, $value) = $filter;
221                $config['filter'][] = array($column, $comp, $value, 'AND');
222            }
223        }
224
225        return $config;
226    }
227}
228