Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 137
0.00% covered (danger)
0.00%
0 / 8
CRAP
0.00% covered (danger)
0.00%
0 / 1
FeedbackController
0.00% covered (danger)
0.00%
0 / 137
0.00% covered (danger)
0.00%
0 / 8
756
0.00% covered (danger)
0.00%
0 / 1
 getParam
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
12
 homeAction
0.00% covered (danger)
0.00%
0 / 19
0.00% covered (danger)
0.00%
0 / 1
2
 deleteAction
0.00% covered (danger)
0.00%
0 / 33
0.00% covered (danger)
0.00%
0 / 1
90
 confirmDelete
0.00% covered (danger)
0.00%
0 / 16
0.00% covered (danger)
0.00%
0 / 1
2
 getConfirmDeleteMessages
0.00% covered (danger)
0.00%
0 / 24
0.00% covered (danger)
0.00%
0 / 1
30
 updateStatusAction
0.00% covered (danger)
0.00%
0 / 32
0.00% covered (danger)
0.00%
0 / 1
20
 convertFilter
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
12
 getStatuses
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3/**
4 * Class FeedbackController
5 *
6 * PHP version 8
7 *
8 * Copyright (C) Moravian Library 2023.
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  VuFindAdmin\Controller
25 * @author   Josef Moravec <moravec@mzk.cz>
26 * @license  https://opensource.org/licenses/gpl-2.0.php GNU General Public License
27 * @link     https://vufind.org/wiki/development:plugins:controllers Wiki
28 */
29
30declare(strict_types=1);
31
32namespace VuFindAdmin\Controller;
33
34use VuFind\Db\Service\FeedbackServiceInterface;
35
36use function count;
37use function intval;
38use function is_array;
39
40/**
41 * Class FeedbackController
42 *
43 * @category VuFind
44 * @package  VuFindAdmin\Controller
45 * @author   Josef Moravec <moravec@mzk.cz>
46 * @license  https://opensource.org/licenses/gpl-2.0.php GNU General Public License
47 * @link     https://vufind.org/wiki/development:plugins:controllers Wiki
48 */
49class FeedbackController extends AbstractAdmin
50{
51    /**
52     * Get the url parameters
53     *
54     * @param string $param          A key to check the url params for
55     * @param bool   $prioritizePost If true, check the POST params first
56     * @param mixed  $default        Default value if no value found
57     *
58     * @return string|string[]
59     */
60    protected function getParam($param, $prioritizePost = false, $default = null)
61    {
62        $primary = $prioritizePost ? 'fromPost' : 'fromQuery';
63        $secondary = $prioritizePost ? 'fromQuery' : 'fromPost';
64        return $this->params()->$primary($param)
65            ?? $this->params()->$secondary($param, $default);
66    }
67
68    /**
69     * Home action
70     *
71     * @return \Laminas\View\Model\ViewModel
72     */
73    public function homeAction()
74    {
75        $feedbackService = $this->getDbService(FeedbackServiceInterface::class);
76        $feedback = $feedbackService->getFeedbackPaginator(
77            $this->convertFilter($this->getParam('form_name')),
78            $this->convertFilter($this->getParam('site_url')),
79            $this->convertFilter($this->getParam('status')),
80            intval($this->getParam('page', default: '1'))
81        );
82        $view = $this->createViewModel(
83            [
84                'feedback' => $feedback,
85                'statuses' => $this->getStatuses(),
86                'uniqueForms' => $feedbackService->getUniqueColumn('form_name'),
87                'uniqueSites' => $feedbackService->getUniqueColumn('site_url'),
88                'params'
89                    => $this->params()->fromQuery() + $this->params()->fromPost(),
90            ]
91        );
92        $view->setTemplate('admin/feedback/home');
93        return $view;
94    }
95
96    /**
97     * Delete action
98     *
99     * @return \Laminas\Http\Response
100     */
101    public function deleteAction()
102    {
103        $confirm = $this->getParam('confirm', true);
104        $originUrl = $this->url()->fromRoute('admin/feedback');
105        $formName = $this->getParam('form_name', true);
106        $siteUrl = $this->getParam('site_url', true);
107        $status = $this->getParam('status', true);
108        $originUrl .= '?' . http_build_query(
109            [
110                'form_name' => empty($formName) ? 'ALL' : $formName,
111                'site_url' => empty($siteUrl) ? 'ALL' : $siteUrl,
112                'status' => empty($status) ? 'ALL' : $status,
113            ]
114        );
115        $newUrl = $this->url()->fromRoute('admin/feedback', ['action' => 'Delete']);
116
117        $ids = null === $this->getParam('deletePage', true)
118            ? $this->getParam('ids', true)
119            : $this->getParam('idsAll', true);
120
121        if (!is_array($ids) || empty($ids)) {
122            $this->flashMessenger()->addMessage('bulk_noitems_advice', 'error');
123            return $this->redirect()->toUrl($originUrl);
124        }
125        if (!$confirm) {
126            return $this->confirmDelete($ids, $originUrl, $newUrl);
127        }
128        $delete = $this->getDbService(FeedbackServiceInterface::class)->deleteByIdArray($ids);
129        if (0 == $delete) {
130            $this->flashMessenger()->addMessage('feedback_delete_failure', 'error');
131            return $this->redirect()->toUrl($originUrl);
132        }
133        $this->flashMessenger()->addMessage(
134            [
135                'msg' => 'feedback_delete_success',
136                'tokens' => ['%%count%%' => $delete],
137            ],
138            'success'
139        );
140        return $this->redirect()->toUrl($originUrl);
141    }
142
143    /**
144     * Confirm delete feedback messages
145     *
146     * @param array  $ids       IDs of feedback messages to delete
147     * @param string $originUrl URL to redirect to after cancel
148     * @param string $newUrl    URL to redirect to after confirm
149     *
150     * @return mixed
151     */
152    protected function confirmDelete(array $ids, string $originUrl, string $newUrl)
153    {
154        $data = [
155            'data' => [
156                'confirm' => $newUrl,
157                'cancel' => $originUrl,
158                'title' => 'confirm_delete_feedback',
159                'messages' => $this->getConfirmDeleteMessages(count($ids)),
160                'ids' => $ids,
161                'extras' => [
162                    'form_name' => $this->getParam('form_name', true),
163                    'site_url' => $this->getParam('site_url', true),
164                    'status' => $this->getParam('status', true),
165                    'ids' => $ids,
166                ],
167            ],
168        ];
169        return $this->forwardTo('Confirm', 'Confirm', $data);
170    }
171
172    /**
173     * Get messages for confirm delete
174     *
175     * @param int $count Count of feedback messages to delete
176     *
177     * @return array[]
178     */
179    protected function getConfirmDeleteMessages(int $count): array
180    {
181        // Default all messages to "All"; we'll make them more specific as needed:
182        $allMessage = $this->translate('All');
183
184        $params = ['form_name', 'site_url', 'status'];
185        $paramMessages = [];
186        foreach ($params as $param) {
187            $value = $this->getParam($param, true);
188            $message = $value ?: $allMessage;
189            $message = $message === 'ALL' ? $allMessage : $message;
190            $paramMessages[$param] = $message;
191        }
192
193        $messages = [];
194        $messages[] = [
195            'msg' => 'feedback_delete_warning',
196            'tokens' => ['%%count%%' => $count],
197        ];
198
199        if (array_filter(array_map([$this, 'getParam'], $params))) {
200            $messages[] = [
201                'msg' => 'feedback_delete_filter',
202                'tokens' => [
203                    '%%formname%%' => $paramMessages['form_name'],
204                    '%%siteurl%%' => $paramMessages['site_url'],
205                    '%%status%%' => $paramMessages['status'],
206                ],
207            ];
208        }
209        $messages[] = ['msg' => 'confirm_delete'];
210        return $messages;
211    }
212
213    /**
214     * Update status field of feedback message
215     *
216     * @return \Laminas\Http\Response
217     */
218    public function updateStatusAction()
219    {
220        $newStatus = $this->getParam('new_status', true);
221        $id = intval($this->getParam('id', true));
222        $success = false;
223        $feedbackService = $this->getDbService(FeedbackServiceInterface::class);
224        try {
225            $feedback = $feedbackService->getFeedbackById($id);
226            if ($feedback) {
227                $feedback->setStatus($newStatus);
228                $feedbackService->persistEntity($feedback);
229                $success = true;
230            }
231        } catch (\Exception $e) {
232        }
233        if ($success) {
234            $this->flashMessenger()->addMessage(
235                'feedback_status_update_success',
236                'success'
237            );
238        } else {
239            $this->flashMessenger()->addMessage(
240                'feedback_status_update_failure',
241                'error'
242            );
243        }
244        return $this->redirect()->toRoute(
245            'admin/feedback',
246            [],
247            [
248                'query' => array_filter(
249                    [
250                        'form_name' => $this->getParam('form_name'),
251                        'site_url' => $this->getParam('site_url'),
252                        'status' => $this->getParam('status'),
253                    ]
254                ),
255            ]
256        );
257    }
258
259    /**
260     * Converts null and "ALL" params to null
261     *
262     * @param string|null $value A parameter to check
263     *
264     * @return string|null A modified parameter
265     */
266    protected function convertFilter(?string $value): ?string
267    {
268        return ('ALL' !== $value && null !== $value)
269            ? $value : null;
270    }
271
272    /**
273     * Get available feedback statuses
274     *
275     * @return array
276     */
277    protected function getStatuses(): array
278    {
279        return [
280            'open',
281            'in progress',
282            'pending',
283            'answered',
284            'closed',
285        ];
286    }
287}