Passed
Push — master ( 9d7682...92bbd7 )
by Andreas
18:14
created

org_openpsa_qbpager::count()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
cc 3
eloc 5
c 0
b 0
f 0
nc 2
nop 0
dl 0
loc 8
ccs 0
cts 6
cp 0
crap 12
rs 10
1
<?php
2
/**
3
 * @package org.openpsa.qbpager
4
 */
5
6
/**
7
 * Pages QB resultsets
8
 *
9
 * @package org.openpsa.qbpager
10
 */
11
class org_openpsa_qbpager
12
{
13
    use midcom_baseclasses_components_base;
0 ignored issues
show
introduced by
The trait midcom_baseclasses_components_base requires some properties which are not provided by org_openpsa_qbpager: $i18n, $head
Loading history...
14
15
    public $results_per_page = 25;
16
    public $display_pages = 10;
17
    public $string_next = 'next';
18
    public $string_previous = 'previous';
19
    protected $_midcom_qb;
20
    protected $_midcom_qb_count;
21
    protected $_pager_id;
22
    protected $_prefix = '';
23
    private $_offset = 0;
24
    private $count;
25
    private $_count_mode;
26
    private $_current_page = 1;
27
28 14
    public function __construct(string $classname, string $pager_id)
29
    {
30 14
        $this->_component = 'org.openpsa.qbpager';
31 14
        if (empty($pager_id)) {
32
            throw new midcom_error('pager_id is not set (needed for distinguishing different instances on same request)');
33
        }
34
35 14
        $this->_pager_id = $pager_id;
36 14
        $this->_prefix = 'org_openpsa_qbpager_' . $pager_id . '_';
37 14
        $this->_prepare_qbs($classname);
38 14
    }
39
40 13
    protected function _prepare_qbs(string $classname)
41
    {
42 13
        $this->_midcom_qb = midcom::get()->dbfactory->new_query_builder($classname);
43
        // Make another QB for counting, we need to do this to avoid trouble with core internal references system
44 13
        $this->_midcom_qb_count = midcom::get()->dbfactory->new_query_builder($classname);
45 13
    }
46
47
    /**
48
     * Check $_REQUEST for variables and sets internal status accordingly
49
     */
50
    private function _check_page_vars()
0 ignored issues
show
Unused Code introduced by
The method _check_page_vars() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
51
    {
52
    }
53
54
    /**
55
     * Get the current page number
56
     */
57 5
    public function get_current_page() : int
58
    {
59 5
        return $this->_current_page;
60
    }
61
62
    /**
63
     * Fetch all $_GET variables
64
     */
65
    private function _get_query_string(string $page_var, int $page_number) : string
66
    {
67
        $query = [$page_var => $page_number];
68
69
        foreach ($_GET as $key => $value) {
70
            if (!in_array($key, [$page_var, ''])) {
71
                $query[$key] = $value;
72
            }
73
        }
74
75
        return '?' . http_build_query($query);
76
    }
77
78
    /**
79
     * Displays previous/next selector
80
     */
81 5
    function show_previousnext()
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
82
    {
83 5
        $page_count = $this->count_pages();
84
        //Skip the header in case we only have one page
85 5
        if ($page_count <= 1) {
86 5
            return;
87
        }
88
        //@todo Move to style element
89
        //TODO: "showing results (offset)-(offset+limit)
90
        $page_var = $this->_prefix . 'page';
91
        echo '<div class="org_openpsa_qbpager_previousnext">';
92
93
        if ($this->_current_page > 1) {
94
            $previous = $this->_current_page - 1;
95
            echo "\n<a class=\"previous_page\" href=\"" . $this->_get_query_string($page_var, $previous) . "\" rel=\"prev\">" . $this->_l10n->get($this->string_previous) . "</a>";
96
        }
97
98
        if ($this->_current_page < $page_count) {
99
            $next = $this->_current_page + 1;
100
            echo "\n<a class=\"next_page\" href=\"" . $this->_get_query_string($page_var, $next) . "\" rel=\"next\">" . $this->_l10n->get($this->string_next) . "</a>";
101
        }
102
103
        echo "\n</div>\n";
104
    }
105
106 1
    public function get_pages() : array
107
    {
108 1
        $pages = [];
109 1
        $page_count = $this->count_pages();
110
111 1
        if ($page_count < 1) {
112
            return $pages;
113
        }
114
115 1
        $page_var = $this->_prefix . 'page';
116 1
        $display_start = max(($this->_current_page - ceil($this->display_pages / 2)), 1);
117 1
        $display_end = min(($this->_current_page + ceil($this->display_pages / 2)), $page_count);
118
119 1
        if ($this->_current_page > 1) {
120
            $previous = $this->_current_page - 1;
121
            if ($previous > 1) {
122
                $pages[] = [
123
                    'class' => 'first',
124
                    'href' => $this->_get_query_string($page_var, 1),
125
                    'rel' => 'prev',
126
                    'label' => $this->_l10n->get('first'),
127
                    'number' => 1
128
                ];
129
            }
130
            $pages[] = [
131
                'class' => 'previous',
132
                'href' => $this->_get_query_string($page_var, $previous),
133
                'rel' => 'prev',
134
                'label' => $this->_l10n->get($this->string_previous),
135
                'number' => $previous
136
            ];
137
        }
138 1
        $page = $display_start - 1;
139 1
        while ($page++ < $display_end) {
140 1
            $href = false;
141 1
            if ($page != $this->_current_page) {
142
                $href = $this->_get_query_string($page_var, $page);
143
            }
144 1
            $pages[] = [
145 1
                'class' => 'current',
146 1
                'href' => $href,
147
                'rel' => false,
148 1
                'label' => $page,
149 1
                'number' => $page
150
            ];
151
        }
152
153 1
        if ($this->_current_page < $page_count) {
154
            $next = $this->_current_page + 1;
155
            $pages[] = [
156
                'class' => 'next',
157
                'href' => $this->_get_query_string($page_var, $next),
158
                'rel' => 'next',
159
                'label' => $this->_l10n->get($this->string_next),
160
                'number' => $next
161
            ];
162
163
            if ($next < $page_count) {
164
                $pages[] = [
165
                    'class' => 'last',
166
                    'href' => $this->_get_query_string($page_var, $page_count),
0 ignored issues
show
Bug introduced by
$page_count of type double is incompatible with the type integer expected by parameter $page_number of org_openpsa_qbpager::_get_query_string(). ( Ignorable by Annotation )

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

166
                    'href' => $this->_get_query_string($page_var, /** @scrutinizer ignore-type */ $page_count),
Loading history...
167
                    'rel' => 'next',
168
                    'label' => $this->_l10n->get('last'),
169
                    'number' => $page_count
170
                ];
171
            }
172
        }
173
174 1
        return $pages;
175
    }
176
177 1
    private function show(string $name, array $data)
178
    {
179 1
        $context = midcom_core_context::enter();
180 1
        $context->set_custom_key('request_data', $data);
181 1
        midcom::get()->style->prepend_component_styledir($this->_component);
182 1
        midcom::get()->style->enter_context($context);
183 1
        midcom_show_style('show_' . $name);
184 1
        midcom::get()->style->leave_context();
185 1
        midcom_core_context::leave();
186 1
    }
187
188
    /**
189
     * Displays page selector
190
     */
191 1
    public function show_pages()
192
    {
193 1
        $this->show('pages', ['pages' => $this->get_pages()]);
194 1
    }
195
196
    /**
197
     * Displays page selector as list
198
     */
199
    function show_pages_as_list()
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
200
    {
201
        $this->show('pages_as_list', ['pages' => $this->get_pages()]);
202
    }
203
204
    /**
205
     * sets LIMIT and OFFSET for requested page
206
     */
207 14
    protected function _qb_limits($qb)
208
    {
209 14
        $page_var = $this->_prefix . 'page';
210 14
        if (!empty($_REQUEST[$page_var])) {
211
            debug_add("{$page_var} has value: {$_REQUEST[$page_var]}");
212
            $this->_current_page = max(1, (int) $_REQUEST[$page_var]);
213
        }
214 14
        if ($this->_current_page == 'all') {
215
            debug_add("displaying all results");
216
            return;
217
        }
218 14
        $results_var = $this->_prefix . 'results';
219 14
        if (!empty($_REQUEST[$results_var])) {
220
            debug_add("{$results_var} has value: {$_REQUEST[$results_var]}");
221
            $this->results_per_page = max(1, (int) $_REQUEST[$results_var]);
222
        }
223 14
        if ($this->results_per_page < 1) {
224
            throw new LogicException('results_per_page is set to ' . $this->results_per_page);
225
        }
226 14
        $this->_offset = ($this->_current_page - 1) * $this->results_per_page;
227 14
        $qb->set_limit($this->results_per_page);
228 14
        $qb->set_offset($this->_offset);
229 14
        debug_add("set offset to {$this->_offset} and limit to {$this->results_per_page}");
230 14
    }
231
232 14
    public function execute() : array
233
    {
234 14
        $this->_qb_limits($this->_midcom_qb);
235 14
        return $this->_midcom_qb->execute();
236
    }
237
238
    public function execute_unchecked() : array
239
    {
240
        $this->_qb_limits($this->_midcom_qb);
241
        return $this->_midcom_qb->execute_unchecked();
242
    }
243
244
    /**
245
     * Returns number of total pages for query
246
     *
247
     * By default returns a number of pages without any ACL checks
248
     */
249 6
    public function count_pages()
250
    {
251 6
        $this->count_unchecked();
252 6
        return ceil($this->count / $this->results_per_page);
253
    }
254
255
    //Rest of supported methods wrapped with extra sanity check
256 14
    public function add_constraint(string $param, string $op, $val) : bool
257
    {
258 14
        $this->_midcom_qb_count->add_constraint($param, $op, $val);
259 14
        return $this->_midcom_qb->add_constraint($param, $op, $val);
260
    }
261
262 13
    public function add_order(string $param, string $sort = 'ASC') : bool
263
    {
264 13
        return $this->_midcom_qb->add_order($param, $sort);
265
    }
266
267 2
    public function begin_group(string $type)
268
    {
269 2
        $this->_midcom_qb_count->begin_group($type);
270 2
        $this->_midcom_qb->begin_group($type);
271 2
    }
272
273 2
    public function end_group()
274
    {
275 2
        $this->_midcom_qb_count->end_group();
276 2
        $this->_midcom_qb->end_group();
277 2
    }
278
279 1
    public function include_deleted()
280
    {
281 1
        $this->_midcom_qb_count->include_deleted();
282 1
        $this->_midcom_qb->include_deleted();
283 1
    }
284
285
    public function count() : int
286
    {
287
        if (   !$this->count
288
            || $this->_count_mode != 'count') {
289
            $this->count = $this->_midcom_qb_count->count();
290
        }
291
        $this->_count_mode = 'count';
292
        return $this->count;
293
    }
294
295 6
    public function count_unchecked() : int
296
    {
297 6
        if (   !$this->count
298 6
            || $this->_count_mode != 'count_unchecked') {
299 6
            $this->count = $this->_midcom_qb_count->count_unchecked();
300
        }
301 6
        $this->_count_mode = 'count_unchecked';
302 6
        return $this->count;
303
    }
304
}
305