Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 99 |
|
0.00% |
0 / 7 |
CRAP | |
0.00% |
0 / 1 |
CheckoutsController | |
0.00% |
0 / 99 |
|
0.00% |
0 / 7 |
756 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
2 | |||
historyAction | |
0.00% |
0 / 57 |
|
0.00% |
0 / 1 |
156 | |||
purgeHistoryAction | |
0.00% |
0 / 31 |
|
0.00% |
0 / 1 |
90 | |||
getRowIdContainer | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
resetValidRowIds | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
rememberValidRowId | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
validateRowIds | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | |
3 | /** |
4 | * Checkouts Controller |
5 | * |
6 | * PHP version 8 |
7 | * |
8 | * Copyright (C) Villanova University 2010. |
9 | * Copyright (C) The National Library of Finland 2023. |
10 | * |
11 | * This program is free software; you can redistribute it and/or modify |
12 | * it under the terms of the GNU General Public License version 2, |
13 | * as published by the Free Software Foundation. |
14 | * |
15 | * This program is distributed in the hope that it will be useful, |
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
18 | * GNU General Public License for more details. |
19 | * |
20 | * You should have received a copy of the GNU General Public License |
21 | * along with this program; if not, write to the Free Software |
22 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
23 | * |
24 | * @category VuFind |
25 | * @package Controller |
26 | * @author Demian Katz <demian.katz@villanova.edu> |
27 | * @author Ere Maijala <ere.maijala@helsinki.fi> |
28 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License |
29 | * @link https://vufind.org Main Site |
30 | */ |
31 | |
32 | namespace VuFind\Controller; |
33 | |
34 | use Laminas\ServiceManager\ServiceLocatorInterface; |
35 | use Laminas\Session\SessionManager; |
36 | use VuFind\ILS\PaginationHelper; |
37 | use VuFind\Validator\CsrfInterface; |
38 | |
39 | use function is_array; |
40 | |
41 | /** |
42 | * Controller for the user checkouts area. |
43 | * |
44 | * @category VuFind |
45 | * @package Controller |
46 | * @author Demian Katz <demian.katz@villanova.edu> |
47 | * @author Ere Maijala <ere.maijala@helsinki.fi> |
48 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License |
49 | * @link https://vufind.org Main Site |
50 | */ |
51 | class CheckoutsController extends AbstractBase |
52 | { |
53 | use Feature\CatchIlsExceptionsTrait; |
54 | |
55 | /** |
56 | * CSRF validator |
57 | * |
58 | * @var CsrfInterface |
59 | */ |
60 | protected $csrf; |
61 | |
62 | /** |
63 | * Session manager |
64 | * |
65 | * @var SessionManager |
66 | */ |
67 | protected $sessionManager; |
68 | |
69 | /** |
70 | * Session container |
71 | * |
72 | * @var \Laminas\Session\Container |
73 | */ |
74 | protected $sessionContainer = null; |
75 | |
76 | /** |
77 | * Pagination helper |
78 | * |
79 | * @var PaginationHelper |
80 | */ |
81 | protected $paginationHelper; |
82 | |
83 | /** |
84 | * Constructor |
85 | * |
86 | * @param ServiceLocatorInterface $sm Service locator |
87 | * @param CsrfInterface $csrf CSRF validator |
88 | * @param SessionManager $sessMgr Session manager |
89 | */ |
90 | public function __construct( |
91 | ServiceLocatorInterface $sm, |
92 | CsrfInterface $csrf, |
93 | SessionManager $sessMgr |
94 | ) { |
95 | parent::__construct($sm); |
96 | $this->csrf = $csrf; |
97 | $this->sessionManager = $sessMgr; |
98 | $this->paginationHelper = new PaginationHelper(); |
99 | } |
100 | |
101 | /** |
102 | * Send loan history to view |
103 | * |
104 | * @return mixed |
105 | */ |
106 | public function historyAction() |
107 | { |
108 | $this->resetValidRowIds(); |
109 | |
110 | // Stop now if the user does not have valid catalog credentials available: |
111 | if (!is_array($patron = $this->catalogLogin())) { |
112 | return $patron; |
113 | } |
114 | |
115 | // Connect to the ILS: |
116 | $catalog = $this->getILS(); |
117 | |
118 | // Check function config |
119 | $functionConfig = $catalog->checkFunction( |
120 | 'getMyTransactionHistory', |
121 | $patron |
122 | ); |
123 | if (false === $functionConfig) { |
124 | $this->flashMessenger()->addErrorMessage('ils_action_unavailable'); |
125 | return $this->createViewModel(); |
126 | } |
127 | $purgeSelectedAllowed = !empty($functionConfig['purge_selected']); |
128 | $purgeAllAllowed = !empty($functionConfig['purge_all']); |
129 | |
130 | // Get paging setup: |
131 | $config = $this->getConfig(); |
132 | $pageOptions = $this->paginationHelper->getOptions( |
133 | (int)$this->params()->fromQuery('page', 1), |
134 | $this->params()->fromQuery('sort'), |
135 | $config->Catalog->historic_loan_page_size ?? 50, |
136 | $functionConfig |
137 | ); |
138 | |
139 | // Get checked out item details: |
140 | $result |
141 | = $catalog->getMyTransactionHistory($patron, $pageOptions['ilsParams']); |
142 | |
143 | if (isset($result['success']) && !$result['success']) { |
144 | $this->flashMessenger()->addErrorMessage($result['status']); |
145 | return $this->createViewModel(); |
146 | } |
147 | |
148 | $paginator = $this->paginationHelper->getPaginator( |
149 | $pageOptions, |
150 | $result['count'], |
151 | $result['transactions'] |
152 | ); |
153 | if ($paginator) { |
154 | $pageStart = $paginator->getAbsoluteItemNumber(1) - 1; |
155 | $pageEnd = $paginator->getAbsoluteItemNumber($pageOptions['limit']) - 1; |
156 | } else { |
157 | $pageStart = 0; |
158 | $pageEnd = $result['count']; |
159 | } |
160 | |
161 | $driversNeeded = $hiddenTransactions = []; |
162 | foreach ($result['transactions'] as $i => $current) { |
163 | // Build record drivers (only for the current visible page): |
164 | if ($pageOptions['ilsPaging'] || ($i >= $pageStart && $i <= $pageEnd)) { |
165 | $driversNeeded[] = $current; |
166 | } else { |
167 | $hiddenTransactions[] = $current; |
168 | } |
169 | if ($purgeSelectedAllowed && isset($current['row_id'])) { |
170 | $this->rememberValidRowId($current['row_id']); |
171 | } |
172 | } |
173 | |
174 | $transactions = $this->ilsRecords()->getDrivers($driversNeeded); |
175 | $sortList = $pageOptions['sortList']; |
176 | $params = $pageOptions['ilsParams']; |
177 | return $this->createViewModel( |
178 | compact( |
179 | 'transactions', |
180 | 'paginator', |
181 | 'params', |
182 | 'hiddenTransactions', |
183 | 'sortList', |
184 | 'functionConfig', |
185 | 'purgeAllAllowed', |
186 | 'purgeSelectedAllowed' |
187 | ) |
188 | ); |
189 | } |
190 | |
191 | /** |
192 | * Purge loans from loan history |
193 | * |
194 | * @return mixed |
195 | */ |
196 | public function purgeHistoryAction() |
197 | { |
198 | $this->ilsExceptionResponse = $redirectResponse |
199 | = $this->redirect()->toRoute('checkouts-history'); |
200 | |
201 | // Stop now if the user does not have valid catalog credentials available: |
202 | if (!is_array($patron = $this->catalogLogin())) { |
203 | return $patron; |
204 | } |
205 | |
206 | $purgeSelected = $this->formWasSubmitted('purgeSelected', false); |
207 | $purgeAll = $this->formWasSubmitted('purgeAll', false); |
208 | if ($purgeSelected || $purgeAll) { |
209 | $csrfToken = $this->getRequest()->getPost()->get('csrf'); |
210 | if (!$this->csrf->isValid($csrfToken)) { |
211 | $this->flashMessenger() |
212 | ->addErrorMessage('error_inconsistent_parameters'); |
213 | return $redirectResponse; |
214 | } |
215 | // After successful token verification, clear list to shrink session: |
216 | $this->csrf->trimTokenList(0); |
217 | $catalog = $this->getILS(); |
218 | if ($purgeAll) { |
219 | $result = $catalog->purgeTransactionHistory($patron, null); |
220 | } else { |
221 | $ids = $this->getRequest()->getPost()->get('purgeSelectedIDs', []); |
222 | if (!$ids) { |
223 | $this->flashMessenger() |
224 | ->addErrorMessage('no_items_selected'); |
225 | return $redirectResponse; |
226 | } |
227 | if (!$this->validateRowIds($ids)) { |
228 | $this->flashMessenger() |
229 | ->addErrorMessage('error_inconsistent_parameters'); |
230 | return $redirectResponse; |
231 | } |
232 | $result = $catalog->purgeTransactionHistory($patron, $ids); |
233 | } |
234 | $this->flashMessenger()->addMessage( |
235 | $result['status'], |
236 | $result['success'] ? 'success' : 'error' |
237 | ); |
238 | } |
239 | return $redirectResponse; |
240 | } |
241 | |
242 | /** |
243 | * Return a session container for validating selected row ids. |
244 | * |
245 | * @return \Laminas\Session\Container |
246 | */ |
247 | protected function getRowIdContainer() |
248 | { |
249 | if (null === $this->sessionContainer) { |
250 | $this->sessionContainer |
251 | = new \Laminas\Session\Container('row_ids', $this->sessionManager); |
252 | } |
253 | return $this->sessionContainer; |
254 | } |
255 | |
256 | /** |
257 | * Reset the array of valid IDs in the session (used for form submission |
258 | * validation) |
259 | * |
260 | * @return void |
261 | */ |
262 | protected function resetValidRowIds(): void |
263 | { |
264 | $this->getRowIdContainer()->validIds = []; |
265 | } |
266 | |
267 | /** |
268 | * Add an ID to the validation array. |
269 | * |
270 | * @param string $id ID to remember |
271 | * |
272 | * @return void |
273 | */ |
274 | protected function rememberValidRowId($id): void |
275 | { |
276 | $this->getRowIdContainer()->validIds[] = $id; |
277 | } |
278 | |
279 | /** |
280 | * Validate supplied IDs against remembered IDs. Returns true if all supplied |
281 | * IDs are remembered, otherwise returns false. |
282 | * |
283 | * @param array $ids IDs to validate |
284 | * |
285 | * @return bool |
286 | */ |
287 | public function validateRowIds(array $ids): bool |
288 | { |
289 | return !(bool)array_diff($ids, $this->getRowIdContainer()->validIds ?? []); |
290 | } |
291 | } |