Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
63.04% covered (warning)
63.04%
29 / 46
25.00% covered (danger)
25.00%
1 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
PaginationHelper
63.04% covered (warning)
63.04%
29 / 46
25.00% covered (danger)
25.00%
1 / 4
43.26
0.00% covered (danger)
0.00%
0 / 1
 validateSort
85.71% covered (warning)
85.71%
6 / 7
0.00% covered (danger)
0.00%
0 / 1
4.05
 getSortList
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
3
 getOptions
82.35% covered (warning)
82.35%
14 / 17
0.00% covered (danger)
0.00%
0 / 1
7.27
 getPaginator
0.00% covered (danger)
0.00%
0 / 13
0.00% covered (danger)
0.00%
0 / 1
56
1<?php
2
3/**
4 * ILS Pagination Helper
5 *
6 * This class helps build paginators for ILS-provided data.
7 *
8 * PHP version 8
9 *
10 * Copyright (C) Villanova University 2018.
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2,
14 * as published by the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
24 *
25 * @category VuFind
26 * @package  ILS_Drivers
27 * @author   Andrew S. Nagy <vufind-tech@lists.sourceforge.net>
28 * @author   Demian Katz <demian.katz@villanova.edu>
29 * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
30 * @link     https://vufind.org/wiki/development:plugins:ils_drivers Wiki
31 */
32
33namespace VuFind\ILS;
34
35use function in_array;
36
37/**
38 * ILS Pagination Helper
39 *
40 * This class helps build paginators for ILS-provided data.
41 *
42 * @category VuFind
43 * @package  ILS_Drivers
44 * @author   Ere Maijala <ere.maijala@helsinki.fi>
45 * @author   Demian Katz <demian.katz@villanova.edu>
46 * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
47 * @link     https://vufind.org/wiki/development:plugins:ils_drivers Wiki
48 */
49class PaginationHelper
50{
51    /**
52     * Support method for getPagingSetup() -- validate the active sort option,
53     * returning either a valid sort method or false.
54     *
55     * @param array  $functionConfig Function config returned from the ILS
56     * @param string $sort           The unvalidated user sort parameter
57     *
58     * @return string|bool
59     */
60    protected function validateSort($functionConfig, $sort)
61    {
62        // If sort is disabled, all settings are invalid...
63        if (empty($functionConfig['sort'])) {
64            return false;
65        }
66        // If provided setting is valid, use it...
67        if (isset($functionConfig['sort'][$sort])) {
68            return $sort;
69        }
70        // At this point, we need to find a reasonable value, either the configured
71        // default or the first valid sort value...
72        if (isset($functionConfig['default_sort'])) {
73            return $functionConfig['default_sort'];
74        }
75        return array_key_first($functionConfig['sort']);
76    }
77
78    /**
79     * Support method for getPagingSetup() -- determine the list of sort options.
80     *
81     * @param array  $functionConfig Function config returned from the ILS
82     * @param string $sort           Currently active sort option
83     *
84     * @return array
85     */
86    protected function getSortList($functionConfig, $sort)
87    {
88        $sortList = [];
89        if (!empty($functionConfig['sort'])) {
90            foreach ($functionConfig['sort'] as $key => $value) {
91                $sortList[$key] = [
92                    'desc' => $value,
93                    'url' => '?sort=' . urlencode($key),
94                    'selected' => $sort == $key,
95                ];
96            }
97        }
98        return $sortList;
99    }
100
101    /**
102     * Get paging settings and request data for paged ILS requests.
103     *
104     * @param int    $page            Current page (1-based)
105     * @param string $sort            Current sort setting (null for none)
106     * @param int    $defaultPageSize Default page size
107     * @param array  $functionConfig  Function config returned from the ILS
108     *
109     * @return array
110     */
111    public function getOptions(
112        $page,
113        $sort,
114        $defaultPageSize,
115        $functionConfig
116    ) {
117        // Get page and page size:
118        $limit = $defaultPageSize;
119        $ilsPaging = true;
120        if (isset($functionConfig['max_results'])) {
121            $limit = min([$functionConfig['max_results'], $limit]);
122        } elseif (isset($functionConfig['page_size'])) {
123            if (!in_array($limit, $functionConfig['page_size'])) {
124                $limit = $functionConfig['default_page_size']
125                    ?? $functionConfig['page_size'][0];
126            }
127        } else {
128            $ilsPaging = false;
129        }
130        // Collect ILS call params
131        $ilsParams = [];
132        if ($sort = $this->validateSort($functionConfig, $sort)) {
133            $ilsParams['sort'] = $sort;
134        }
135        if ($ilsPaging) {
136            $ilsParams['page'] = $page >= 1 ? $page : 1;
137            $ilsParams['limit'] = $limit;
138        }
139        $sortList = $this->getSortList($functionConfig, $sort);
140        return compact('page', 'limit', 'ilsPaging', 'ilsParams', 'sortList');
141    }
142
143    /**
144     * Build a paginator with the paging options and ILS results if necessary
145     *
146     * @param array $pageOptions Paging options and parameters (returned by the
147     * getOptions method)
148     * @param int   $count       Result count
149     * @param array $records     Result records
150     *
151     * @return false|\Laminas\Paginator\Paginator
152     */
153    public function getPaginator($pageOptions, $count, $records)
154    {
155        $limit = $pageOptions['limit'];
156        $page = $pageOptions['page'];
157        if (($page - 1) * $limit >= $count && $page > 1) {
158            throw new \VuFind\Exception\BadRequest('Page number out of range.');
159        }
160        if ($pageOptions['ilsPaging'] && $limit < $count) {
161            $adapter = new \Laminas\Paginator\Adapter\NullFill($count);
162        } elseif ($limit > 0 && $limit < $count) {
163            $adapter = new \Laminas\Paginator\Adapter\ArrayAdapter($records);
164        } else {
165            return false;
166        }
167        $paginator = new \Laminas\Paginator\Paginator($adapter);
168        $paginator->setItemCountPerPage($limit);
169        $paginator->setCurrentPageNumber($page);
170        return $paginator;
171    }
172}