Passed
Push — master ( 179526...2874e4 )
by Andreas
28:11
created

provider   B

Complexity

Total Complexity 43

Size/Duplication

Total Lines 256
Duplicated Lines 0 %

Test Coverage

Coverage 85.45%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 104
dl 0
loc 256
ccs 94
cts 110
cp 0.8545
rs 8.96
c 2
b 0
f 0
wmc 43

18 Methods

Rating   Name   Duplication   Size   Complexity  
A set_query() 0 5 1
A get_query() 0 11 3
A get_grid() 0 11 3
A set_rows() 0 5 2
A __construct() 0 9 3
A get_rows() 0 6 2
A set_grid() 0 5 1
A add_order() 0 4 1
A setup_grid() 0 7 3
A count_rows() 0 4 1
A get_column_total() 0 10 3
A _prepare_query() 0 4 1
A _get_rows() 0 22 6
A render() 0 5 1
A _render_json() 0 14 1
A _convert_to_localdata() 0 3 1
A _get_grid_option() 0 6 2
B _parse_query() 0 19 8

How to fix   Complexity   

Complex Class

Complex classes like provider often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use provider, and based on these observations, apply Extract Interface, too.

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
        $this->_total_rows ??= $this->_prepare_query()->count();
163 27
        return $this->_total_rows;
164
    }
165
166 3
    public function get_column_total(string $column)
167
    {
168 3
        $ret = 0;
169 3
        $rows = $this->get_rows();
170 3
        foreach ($rows as $row) {
171 2
            if (array_key_exists($column, $row)) {
172 2
                $ret += $row[$column];
173
            }
174
        }
175 3
        return $ret;
176
    }
177
178 31
    public function setup_grid()
179
    {
180 31
        if ($this->_datatype == 'local') {
181 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

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