Passed
Push — master ( 409c3f...e5371a )
by Andreas
09:22
created

provider::render()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 12
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 4.125

Importance

Changes 0
Metric Value
cc 3
eloc 10
nc 3
nop 0
dl 0
loc 12
ccs 5
cts 10
cp 0.5
crap 4.125
rs 9.9332
c 0
b 0
f 0
1
<?php
2
/**
3
 * @package midcom.grid
4
 * @author CONTENT CONTROL http://www.contentcontrol-berlin.de/
5
 * @copyright CONTENT CONTROL http://www.contentcontrol-berlin.de/
6
 * @license http://www.gnu.org/licenses/gpl.html GNU General Public License
7
 */
8
9
namespace midcom\grid;
10
11
use midcom\grid\provider\client;
12
use midcom_core_query;
13
use midcom_error;
14
use midcom;
15
16
/**
17
 * Manager for retrieving grid data by AJAX
18
 *
19
 * @package midcom.grid
20
 */
21
class provider
22
{
23
    /**
24
     * The class responsible for getting and formatting rows
25
     */
26
    private client $_client;
27
28
    /**
29
     * The rows to show
30
     */
31
    private ?array $_rows = null;
32
33
    /**
34
     * The total number of rows
35
     */
36
    private ?int $_total_rows = null;
37
38
    /**
39
     * How many items should be shown per page
40
     */
41
    private int $_results_per_page = 20;
42
43
    /**
44
     * The current offset
45
     */
46
    private int $_offset = 0;
47
48
    /**
49
     * The field for sorting
50
     */
51
    private ?string $_sort_field = null;
52
53
    /**
54
     * The direction for sorting (ASC or DESC)
55
     */
56
    private string $_sort_direction = 'ASC';
57
58
    /**
59
     * The grid we're working with
60
     */
61
    private ?grid $_grid = null;
62
63
    /**
64
     * The datatype we're working with
65
     */
66
    private string $_datatype;
67
68
    /**
69
     * The midcom query object
70
     */
71
    private ?midcom_core_query $_query = null;
72
73
    /**
74
     * Search parameters
75
     */
76
    private array $_search = [];
77
78 41
    public function __construct($source, string $datatype = 'json')
79
    {
80 41
        $this->_datatype = $datatype;
81 41
        if ($source instanceof client) {
82 28
            $this->_client = $source;
83 13
        } elseif (is_array($source)) {
84 13
            $this->set_rows($source);
85
        } else {
86
            throw new midcom_error('Unknown source type');
87
        }
88
    }
89
90
    /**
91
     * Adds an initial order to the resultset.
92
     *
93
     * This can be overwritten by GET parameters
94
     */
95 5
    public function add_order(string $field, string $direction = 'ASC')
96
    {
97 5
        $this->_sort_field = $field;
98 5
        $this->_sort_direction = $direction;
99
    }
100
101 10
    public function set_grid(grid $grid)
102
    {
103 10
        $this->_grid = $grid;
104 10
        $this->_grid->set_provider($this);
105 10
        $this->_datatype = $grid->get_option('datatype');
106
    }
107
108 21
    public function get_grid(string $identifier = null) : grid
109
    {
110 21
        if (null !== $identifier) {
111 21
            $this->_grid = new grid($identifier, $this->_datatype);
112 21
            $this->_grid->set_provider($this);
113 21
            if (!empty($this->_sort_field)) {
114 4
                $this->_grid->set_option('sortname', $this->_sort_field);
115 4
                $this->_grid->set_option('sortorder', strtolower($this->_sort_direction));
116
            }
117
        }
118 21
        return $this->_grid;
119
    }
120
121 13
    public function set_rows(array $rows)
122
    {
123 13
        $this->_rows = $rows;
124 13
        if ($this->_datatype == 'local') {
125 12
            $this->_total_rows = count($this->_rows);
126
        }
127
    }
128
129 32
    public function get_rows() : array
130
    {
131 32
        if ($this->_rows === null) {
132 20
            $this->_get_rows();
133
        }
134 32
        return $this->_rows;
135
    }
136
137
    public function set_query(midcom_core_query $query)
138
    {
139
        $this->_rows = null;
140
        $this->_total_rows = null;
141
        $this->_query = $query;
142
    }
143
144
    /**
145
     * returns the query (uncached)
146
     */
147 22
    public function get_query() : midcom_core_query
148
    {
149 22
        if ($this->_datatype == 'json') {
150 8
            $this->_parse_query($_GET);
151
        }
152 22
        $field = $this->_sort_field;
153 22
        if ($field !== null) {
154 5
            $field = str_replace('index_', '', $field);
155
        }
156
157 22
        return $this->_client->get_qb($field, $this->_sort_direction, $this->_search);
158
    }
159
160 27
    public function count_rows() : int
161
    {
162 27
        if ($this->_total_rows === null) {
163 4
            $qb = $this->_prepare_query();
164 4
            $this->_total_rows = $qb->count();
165
        }
166 27
        return $this->_total_rows;
167
    }
168
169 3
    public function get_column_total(string $column)
170
    {
171 3
        $ret = 0;
172 3
        $rows = $this->get_rows();
173 3
        foreach ($rows as $row) {
174 2
            if (array_key_exists($column, $row)) {
175 2
                $ret += $row[$column];
176
            }
177
        }
178 3
        return $ret;
179
    }
180
181 31
    public function setup_grid()
182
    {
183 31
        if ($this->_datatype == 'local') {
184 25
            $this->_grid->prepend_js($this->_convert_to_localdata());
0 ignored issues
show
Bug introduced by
The method prepend_js() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

184
            $this->_grid->/** @scrutinizer ignore-call */ 
185
                          prepend_js($this->_convert_to_localdata());

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
185 25
            $this->_grid->set_option('data', $this->_grid->get_identifier() . '_entries', false);
186 25
            if (null === $this->_get_grid_option('rowNum')) {
187 25
                $this->_grid->set_option('rowNum', $this->count_rows());
188
            }
189
        }
190
    }
191
192 6
    public function render()
193
    {
194 6
        switch ($this->_datatype) {
195 6
            case 'json':
196 6
                $this->_render_json();
197 6
                break;
198
            case 'local':
199
                $this->get_grid()->render();
200
                break;
201
            default:
202
                debug_add('Datatype ' . $this->_get_grid_option('datatype', 'json') . ' is not supported', MIDCOM_LOG_ERROR);
203
                throw new midcom_error('Unsupported datatype');
204
        }
205
    }
206
207 25
    private function _get_grid_option(string $key, $default = null)
208
    {
209 25
        if (empty($this->_grid)) {
210
            return $default;
211
        }
212 25
        return $this->_grid->get_option($key);
213
    }
214
215 25
    private function _convert_to_localdata() : string
216
    {
217 25
        return "var " . $this->_grid->get_identifier() . '_entries = ' .  json_encode($this->get_rows()) . ";\n";
218
    }
219
220 6
    private function _render_json()
221
    {
222 6
        $rows = $this->get_rows();
223 6
        $this->_total_rows ??= count($rows);
224
225 6
        $response = [
226 6
            'total' => ceil($this->_total_rows / $this->_results_per_page),
227 6
            'page' => ($this->_offset / $this->_results_per_page) + 1,
228 6
            'records' => $this->_total_rows,
229 6
            'rows' => $rows
230 6
        ];
231 6
        midcom::get()->cache->content->content_type('application/json; charset=UTF-8');
232
233 6
        echo json_encode($response);
234
    }
235
236 8
    private function _parse_query(array $query)
237
    {
238 8
        if (!empty($query['rows'])) {
239
            $this->_results_per_page = (int) $query['rows'];
240
            if (!empty($query['page'])) {
241
                $this->_offset = ($this->_results_per_page * ($query['page'] - 1));
242
            }
243
        }
244 8
        if (!empty($query['sidx'])) {
245
            $this->_sort_field = $query['sidx'];
246
            $this->_sort_direction = strtoupper($query['sord'] ?? 'ASC');
247
        }
248 8
        if (   !empty($query['_search'])
249 8
            && $query['_search'] === 'true') {
250
            foreach ($query as $field => $value) {
251
                if (in_array($field, ['_search', 'nd', 'page', 'rows', 'sidx', 'sord'])) {
252
                    continue;
253
                }
254
                $this->_search[str_replace('index_', '', $field)] = $value;
255
            }
256
        }
257
    }
258
259 22
    private function _prepare_query() : midcom_core_query
260
    {
261 22
        if ($this->_query === null) {
262 22
            $this->_query = $this->get_query();
263
        }
264 22
        return $this->_query;
265
    }
266
267 20
    private function _get_rows()
268
    {
269 20
        $query = $this->_prepare_query();
270
271 20
        $this->_total_rows = $query->count();
272
273 20
        if (   $this->_datatype == 'json'
274 20
            && !empty($this->_results_per_page)) {
275 7
            $query->set_limit($this->_results_per_page);
276 7
            if (!empty($this->_offset)) {
277
                $query->set_offset($this->_offset);
278
            }
279
        }
280 20
        $this->_rows = [];
281
282 20
        if ($query instanceof \midcom_core_collector) {
283 6
            $items = $query->get_objects();
284
        } else {
285 14
            $items = $query->execute();
286
        }
287 20
        foreach ($items as $item) {
288 8
            $this->_rows[] = $this->_client->get_row($item);
289
        }
290
    }
291
}
292