Passed
Push — master ( 0083f3...057072 )
by Andreas
17:57
created

org_openpsa_qbpager::execute_unchecked()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 2
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 4
ccs 0
cts 3
cp 0
crap 2
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
    protected  $count;
25
    private $_current_page = 1;
26
27 14
    public function __construct(string $classname, string $pager_id)
28
    {
29 14
        $this->_component = 'org.openpsa.qbpager';
30 14
        if (empty($pager_id)) {
31
            throw new midcom_error('pager_id is not set (needed for distinguishing different instances on same request)');
32
        }
33
34 14
        $this->_pager_id = $pager_id;
35 14
        $this->_prefix = 'org_openpsa_qbpager_' . $pager_id . '_';
36 14
        $this->_prepare_qbs($classname);
37 14
    }
38
39 13
    protected function _prepare_qbs(string $classname)
40
    {
41 13
        $this->_midcom_qb = midcom::get()->dbfactory->new_query_builder($classname);
42
        // Make another QB for counting, we need to do this to avoid trouble with core internal references system
43 13
        $this->_midcom_qb_count = midcom::get()->dbfactory->new_query_builder($classname);
44 13
    }
45
46
    /**
47
     * Get the current page number
48
     */
49 5
    public function get_current_page() : int
50
    {
51 5
        return $this->_current_page;
52
    }
53
54
    /**
55
     * Fetch all $_GET variables
56
     */
57
    private function _get_query_string(string $page_var, int $page_number) : string
58
    {
59
        $query = [$page_var => $page_number];
60
61
        foreach ($_GET as $key => $value) {
62
            if (!in_array($key, [$page_var, ''])) {
63
                $query[$key] = $value;
64
            }
65
        }
66
67
        return '?' . http_build_query($query);
68
    }
69
70
    /**
71
     * Displays previous/next selector
72
     */
73 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...
74
    {
75 5
        $page_count = $this->count_pages();
76
        //Skip the header in case we only have one page
77 5
        if ($page_count <= 1) {
78 5
            return;
79
        }
80
        //@todo Move to style element
81
        //TODO: "showing results (offset)-(offset+limit)
82
        $page_var = $this->_prefix . 'page';
83
        echo '<div class="org_openpsa_qbpager_previousnext">';
84
85
        if ($this->_current_page > 1) {
86
            $previous = $this->_current_page - 1;
87
            echo "\n<a class=\"previous_page\" href=\"" . $this->_get_query_string($page_var, $previous) . "\" rel=\"prev\">" . $this->_l10n->get($this->string_previous) . "</a>";
88
        }
89
90
        if ($this->_current_page < $page_count) {
91
            $next = $this->_current_page + 1;
92
            echo "\n<a class=\"next_page\" href=\"" . $this->_get_query_string($page_var, $next) . "\" rel=\"next\">" . $this->_l10n->get($this->string_next) . "</a>";
93
        }
94
95
        echo "\n</div>\n";
96
    }
97
98 1
    public function get_pages() : array
99
    {
100 1
        $pages = [];
101 1
        $page_count = $this->count_pages();
102
103 1
        if ($page_count < 1) {
104
            return $pages;
105
        }
106
107 1
        $page_var = $this->_prefix . 'page';
108 1
        $display_start = max(($this->_current_page - ceil($this->display_pages / 2)), 1);
109 1
        $display_end = min(($this->_current_page + ceil($this->display_pages / 2)), $page_count);
110
111 1
        if ($this->_current_page > 1) {
112
            $previous = $this->_current_page - 1;
113
            if ($previous > 1) {
114
                $pages[] = [
115
                    'class' => 'first',
116
                    'href' => $this->_get_query_string($page_var, 1),
117
                    'rel' => 'prev',
118
                    'label' => $this->_l10n->get('first'),
119
                    'number' => 1
120
                ];
121
            }
122
            $pages[] = [
123
                'class' => 'previous',
124
                'href' => $this->_get_query_string($page_var, $previous),
125
                'rel' => 'prev',
126
                'label' => $this->_l10n->get($this->string_previous),
127
                'number' => $previous
128
            ];
129
        }
130 1
        $page = $display_start - 1;
131 1
        while ($page++ < $display_end) {
132 1
            $href = false;
133 1
            if ($page != $this->_current_page) {
134
                $href = $this->_get_query_string($page_var, $page);
135
            }
136 1
            $pages[] = [
137 1
                'class' => 'current',
138 1
                'href' => $href,
139
                'rel' => false,
140 1
                'label' => $page,
141 1
                'number' => $page
142
            ];
143
        }
144
145 1
        if ($this->_current_page < $page_count) {
146
            $next = $this->_current_page + 1;
147
            $pages[] = [
148
                'class' => 'next',
149
                'href' => $this->_get_query_string($page_var, $next),
150
                'rel' => 'next',
151
                'label' => $this->_l10n->get($this->string_next),
152
                'number' => $next
153
            ];
154
155
            if ($next < $page_count) {
156
                $pages[] = [
157
                    'class' => 'last',
158
                    '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

158
                    'href' => $this->_get_query_string($page_var, /** @scrutinizer ignore-type */ $page_count),
Loading history...
159
                    'rel' => 'next',
160
                    'label' => $this->_l10n->get('last'),
161
                    'number' => $page_count
162
                ];
163
            }
164
        }
165
166 1
        return $pages;
167
    }
168
169 1
    private function show(string $name, array $data)
170
    {
171 1
        $context = midcom_core_context::enter();
172 1
        $context->set_custom_key('request_data', $data);
173 1
        midcom::get()->style->prepend_component_styledir($this->_component);
174 1
        midcom::get()->style->enter_context($context);
175 1
        midcom_show_style('show_' . $name);
176 1
        midcom::get()->style->leave_context();
177 1
        midcom_core_context::leave();
178 1
    }
179
180
    /**
181
     * Displays page selector
182
     */
183 1
    public function show_pages()
184
    {
185 1
        $this->show('pages', ['pages' => $this->get_pages()]);
186 1
    }
187
188
    /**
189
     * Displays page selector as list
190
     */
191
    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...
192
    {
193
        $this->show('pages_as_list', ['pages' => $this->get_pages()]);
194
    }
195
196
    /**
197
     * Check $_REQUEST for variables and sets LIMIT and OFFSET for requested page
198
     */
199 14
    protected function _qb_limits($qb)
200
    {
201 14
        $page_var = $this->_prefix . 'page';
202 14
        if (!empty($_REQUEST[$page_var])) {
203
            debug_add("{$page_var} has value: {$_REQUEST[$page_var]}");
204
            $this->_current_page = max(1, (int) $_REQUEST[$page_var]);
205
        }
206 14
        if ($this->_current_page == 'all') {
207
            debug_add("displaying all results");
208
            return;
209
        }
210 14
        $results_var = $this->_prefix . 'results';
211 14
        if (!empty($_REQUEST[$results_var])) {
212
            debug_add("{$results_var} has value: {$_REQUEST[$results_var]}");
213
            $this->results_per_page = max(1, (int) $_REQUEST[$results_var]);
214
        }
215 14
        if ($this->results_per_page < 1) {
216
            throw new LogicException('results_per_page is set to ' . $this->results_per_page);
217
        }
218 14
        $this->_offset = ($this->_current_page - 1) * $this->results_per_page;
219 14
        $qb->set_limit($this->results_per_page);
220 14
        $qb->set_offset($this->_offset);
221 14
        debug_add("set offset to {$this->_offset} and limit to {$this->results_per_page}");
222 14
    }
223
224 14
    public function execute() : array
225
    {
226 14
        $this->_qb_limits($this->_midcom_qb);
227 14
        return $this->_midcom_qb->execute();
228
    }
229
230
    /**
231
     * Returns number of total pages for query
232
     *
233
     * By default returns a number of pages without any ACL checks
234
     */
235 6
    public function count_pages()
236
    {
237 6
        return ceil($this->count_unchecked() / $this->results_per_page);
238
    }
239
240
    //Rest of supported methods wrapped with extra sanity check
241 14
    public function add_constraint(string $param, string $op, $val) : bool
242
    {
243 14
        $this->_midcom_qb_count->add_constraint($param, $op, $val);
244 14
        return $this->_midcom_qb->add_constraint($param, $op, $val);
245
    }
246
247 13
    public function add_order(string $param, string $sort = 'ASC') : bool
248
    {
249 13
        return $this->_midcom_qb->add_order($param, $sort);
250
    }
251
252 2
    public function begin_group(string $type)
253
    {
254 2
        $this->_midcom_qb_count->begin_group($type);
255 2
        $this->_midcom_qb->begin_group($type);
256 2
    }
257
258 2
    public function end_group()
259
    {
260 2
        $this->_midcom_qb_count->end_group();
261 2
        $this->_midcom_qb->end_group();
262 2
    }
263
264 1
    public function include_deleted()
265
    {
266 1
        $this->_midcom_qb_count->include_deleted();
267 1
        $this->_midcom_qb->include_deleted();
268 1
    }
269
270 6
    public function count_unchecked() : int
271
    {
272 6
        if (!$this->count) {
273 6
            $this->count = $this->_midcom_qb_count->count_unchecked();
274
        }
275 6
        return $this->count;
276
    }
277
}
278