Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 82
0.00% covered (danger)
0.00%
0 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
AlphabrowseController
0.00% covered (danger)
0.00%
0 / 82
0.00% covered (danger)
0.00%
0 / 5
600
0.00% covered (danger)
0.00%
0 / 1
 getTypes
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 getExtras
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 addResultsToView
0.00% covered (danger)
0.00%
0 / 36
0.00% covered (danger)
0.00%
0 / 1
156
 applyHighlighting
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
20
 homeAction
0.00% covered (danger)
0.00%
0 / 28
0.00% covered (danger)
0.00%
0 / 1
20
1<?php
2
3/**
4 * AlphaBrowse Module Controller
5 *
6 * PHP version 8
7 *
8 * Copyright (C) Villanova University 2011.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2,
12 * as published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.    See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22 *
23 * @category VuFind
24 * @package  Controller
25 * @author   Mark Triggs <vufind-tech@lists.sourceforge.net>
26 * @author   Chris Hallberg <challber@villanova.edu>
27 * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
28 * @link     https://vufind.org/wiki/indexing:alphabetical_heading_browse Wiki
29 */
30
31namespace VuFind\Controller;
32
33use Laminas\Config\Config;
34use Laminas\View\Model\ViewModel;
35use VuFind\Exception\BadRequest;
36use VuFindSearch\ParamBag;
37
38use function in_array;
39use function intval;
40
41/**
42 * AlphabrowseController Class
43 *
44 * Controls the alphabetical browsing feature
45 *
46 * @category VuFind
47 * @package  Controller
48 * @author   Mark Triggs <vufind-tech@lists.sourceforge.net>
49 * @author   Chris Hallberg <challber@villanova.edu>
50 * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
51 * @link     https://vufind.org/wiki/indexing:alphabetical_heading_browse Wiki
52 */
53class AlphabrowseController extends AbstractBase
54{
55    use Feature\AlphaBrowseTrait;
56
57    /**
58     * Default browse types
59     *
60     * @var array
61     */
62    protected $defaultTypes = [
63        'topic'  => 'By Topic',
64        'author' => 'By Author',
65        'title'  => 'By Title',
66        'lcc'    => 'By Call Number',
67    ];
68
69    /**
70     * Default extras
71     *
72     * @var array
73     */
74    protected $defaultExtras = [
75        'title' => 'author:format:publishDate',
76        'lcc' => 'title',
77        'dewey' => 'title',
78    ];
79
80    /**
81     * Get browse types from config file, or use defaults if unavailable.
82     *
83     * @param Config $config Configuration
84     *
85     * @return array
86     */
87    protected function getTypes(Config $config): array
88    {
89        return empty($config->AlphaBrowse_Types)
90            ? $this->defaultTypes
91            : $config->AlphaBrowse_Types->toArray();
92    }
93
94    /**
95     * Load any extras from config file, or use defaults if unavailable.
96     *
97     * @param Config $config Configuration
98     *
99     * @return array
100     */
101    protected function getExtras(Config $config): array
102    {
103        return isset($config->AlphaBrowse_Extras)
104            ? $config->AlphaBrowse_Extras->toArray()
105            : $this->defaultExtras;
106    }
107
108    /**
109     * Add alphabrowse results to the view model.
110     *
111     * @param ViewModel $view         View model (must already contain source and
112     * from values)
113     * @param int       $page         Results page to load
114     * @param int       $limit        Page size
115     * @param int       $rowsBefore   Number of rows to display before highlighted
116     * row
117     * @param bool      $highlighting Is row highlighting enabled?
118     * @param array     $extras       Extra fields to load in results
119     *
120     * @return void
121     */
122    protected function addResultsToView(
123        ViewModel $view,
124        int $page,
125        int $limit,
126        int $rowsBefore,
127        bool $highlighting,
128        array $extras
129    ): void {
130        $result = [];
131        if ($view->source && $view->from !== false) {
132            // Validate source parameter:
133            if (!in_array($view->source, array_keys($view->alphaBrowseTypes))) {
134                throw new BadRequest(
135                    "Unsupported alphabrowse type: {$view->source}"
136                );
137            }
138
139            // Set up extra params:
140            $extraParams = new ParamBag();
141            if (isset($extras[$view->source])) {
142                $extraParams->add('extras', $extras[$view->source]);
143            }
144
145            // Load Solr data or die trying:
146            $result = $this->alphabeticBrowse(
147                $view->source,
148                $view->from,
149                $page,
150                $limit,
151                $extraParams,
152                0 - $rowsBefore
153            );
154
155            // No results?    Try the previous page just in case we've gone past
156            // the end of the list....
157            if ($result['Browse']['totalCount'] == 0) {
158                $page--;
159                $result = $this->alphabeticBrowse(
160                    $view->source,
161                    $view->from,
162                    $page,
163                    $limit,
164                    $extraParams,
165                    0
166                );
167                if ($highlighting) {
168                    $view->highlight_end = true;
169                }
170            }
171
172            // Only display next/previous page links when applicable:
173            if ($result['Browse']['totalCount'] > $limit) {
174                $view->nextpage = $page + 1;
175            }
176            if ($result['Browse']['offset'] + $result['Browse']['startRow'] > 1) {
177                $view->prevpage = $page - 1;
178            }
179        }
180        $view->result = $result;
181
182        // set up highlighting: page 0 contains match location
183        if ($highlighting && $page == 0 && isset($view->result['Browse'])) {
184            $this->applyHighlighting($view, $rowsBefore);
185        }
186    }
187
188    /**
189     * Apply highlighting settings to the view based on the result set.
190     *
191     * @param ViewModel $view       View model to be updated (must already contain
192     * results)
193     * @param int       $rowsBefore Number of rows to display before highlighted row
194     *
195     * @return void
196     */
197    protected function applyHighlighting(ViewModel $view, int $rowsBefore): void
198    {
199        $startRow = $view->result['Browse']['startRow'];
200        // solr counts rows from 1; adjust to array position style
201        $startRow_adj = $startRow - 1;
202        $offset = $view->result['Browse']['offset'];
203        $totalRows = $view->result['Browse']['totalCount'];
204        $totalRows += $startRow + $offset > 0 ? $startRow_adj + $offset : 0;
205
206        // normal case: somewhere in the middle of the browse list
207        $highlight_row = $rowsBefore;
208        // special case: match row is < rowsBefore (i.e. at beginning of list)
209        if ($startRow_adj < $rowsBefore) {
210            $highlight_row = $startRow_adj;
211        }
212        // special case: we've gone past the end
213        // only the rowsBefore records will have been returned
214        if ($startRow > $totalRows) {
215            $view->highlight_end = true;
216        }
217        $view->highlight_row = $highlight_row;
218        $view->match_type = $view->result['Browse']['matchType'];
219    }
220
221    /**
222     * Gathers data for the view of the AlphaBrowser and does some initialization
223     *
224     * @return ViewModel
225     */
226    public function homeAction(): ViewModel
227    {
228        // Load config parameters
229        $config = $this->getConfig();
230        $rowsBefore = ctype_digit((string)($config->AlphaBrowse->rows_before ?? '-'))
231            ? (int)$config->AlphaBrowse->rows_before : 0;
232        $limit  = ctype_digit((string)($config->AlphaBrowse->page_size ?? '-'))
233            ? (int)$config->AlphaBrowse->page_size : 20;
234
235        // Process incoming parameters:
236        $source = $this->params()->fromQuery('source', false);
237        $from   = $this->params()->fromQuery('from', false);
238        $page   = intval($this->params()->fromQuery('page', 0));
239
240        // Load highlighting configuration while accounting for special case:
241        // highlighting is pointless if there's no user input:
242        $highlighting = empty($from)
243            ? false : $config->AlphaBrowse->highlighting ?? false;
244
245        // Set up any extra parameters to pass
246        $extras = $this->getExtras($config);
247
248        // Create view model:
249        $view = $this->createViewModel(
250            [
251                'alphaBrowseTypes' => $this->getTypes($config),
252                'from' => $from,
253                'source' => $source,
254                'extras' => array_filter(explode(':', $extras[$source] ?? '')),
255            ]
256        );
257
258        // If required parameters are present, load results:
259        $this->addResultsToView(
260            $view,
261            $page,
262            $limit,
263            $rowsBefore,
264            $highlighting,
265            $extras
266        );
267
268        return $view;
269    }
270}