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;
24    /** @var int */
25    protected $offset = 0;
26    /** @var  array */
27    protected $filters = [];
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            [$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                [$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 false|string
63     */
64    protected function resolveColumn($column)
65    {
66        if (!is_a($column, Column::class)) {
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 = [$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 removeFilter()
118     *
119     * @param string|Column $column
120     * @param string $comp the comparator
121     * @param string $value the value to compare against
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] = [$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 = [];
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 = [];
175        if ($this->offset) {
176            $params[self::$PARAM_OFFSET] = $this->offset;
177        }
178
179        if ($this->sort) {
180            [$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                [$comp, $value] = $filter;
188                $key = self::$PARAM_FILTER . '[' . $column . $comp . ']';
189                $params[$key] = $value;
190            }
191        }
192
193        return $params;
194    }
195
196    /**
197     * Applies the dynamic filter settings to the SearchConfig
198     */
199    public function apply()
200    {
201        if ($this->offset) {
202            $this->searchConfig->setOffset($this->offset);
203        }
204
205        if ($this->sort) {
206            $this->searchConfig->clearSort(); // remove any existing sort
207            $this->searchConfig->addSort($this->sort[0], $this->sort[1]);
208        }
209
210        foreach ($this->filters as $colName => $filter) {
211            [$comp, $value] = $filter;
212            $this->searchConfig->addDynamicFilter($colName, $value, $comp, 'AND');
213        }
214    }
215}
216