Completed
Push — develop ( a0b39d...6e6eeb )
by Tino
07:33
created

Action::setRedirectMessage()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 1
nop 3
dl 0
loc 6
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * Copyright (c) by the ACP3 Developers.
5
 * See the LICENSE file at the top-level module directory for licensing details.
6
 */
7
8
namespace ACP3\Core\Modules\Helper;
9
10
use ACP3\Core;
11
use Doctrine\DBAL\ConnectionException;
12
use Symfony\Component\HttpFoundation\JsonResponse;
13
use Symfony\Component\HttpFoundation\RedirectResponse;
14
use Symfony\Component\HttpFoundation\Response;
15
16
class Action
17
{
18
    /**
19
     * @var \ACP3\Core\I18n\Translator
20
     */
21
    protected $translator;
22
    /**
23
     * @var \ACP3\Core\Http\RequestInterface
24
     */
25
    protected $request;
26
    /**
27
     * @var \ACP3\Core\Router\RouterInterface
28
     */
29
    protected $router;
30
    /**
31
     * @var \ACP3\Core\Helpers\Alerts
32
     */
33
    protected $alerts;
34
    /**
35
     * @var \ACP3\Core\Helpers\RedirectMessages
36
     */
37
    protected $redirectMessages;
38
    /**
39
     * @var \ACP3\Core\Database\Connection
40
     */
41
    private $db;
42
43
    /**
44
     * Action constructor.
45
     *
46
     * @param \ACP3\Core\Database\Connection      $db
47
     * @param \ACP3\Core\I18n\Translator          $translator
48
     * @param \ACP3\Core\Http\RequestInterface    $request
49
     * @param \ACP3\Core\Router\RouterInterface   $router
50
     * @param \ACP3\Core\Helpers\Alerts           $alerts
51
     * @param \ACP3\Core\Helpers\RedirectMessages $redirectMessages
52
     */
53
    public function __construct(
54
        Core\Database\Connection $db,
55
        Core\I18n\Translator $translator,
56
        Core\Http\RequestInterface $request,
57
        Core\Router\RouterInterface $router,
58
        Core\Helpers\Alerts $alerts,
59
        Core\Helpers\RedirectMessages $redirectMessages
60
    ) {
61
        $this->translator = $translator;
62
        $this->request = $request;
63
        $this->router = $router;
64
        $this->alerts = $alerts;
65
        $this->redirectMessages = $redirectMessages;
66
        $this->db = $db;
67
    }
68
69
    /**
70
     * @param callable    $callback
71
     * @param null|string $path
72
     *
73
     * @return string|array|\Symfony\Component\HttpFoundation\JsonResponse|\Symfony\Component\HttpFoundation\RedirectResponse
74
     *
75
     * @throws \Doctrine\DBAL\ConnectionException
76
     * @throws \Doctrine\DBAL\DBALException
77
     */
78
    public function handlePostAction(callable $callback, ?string $path = null)
79
    {
80
        try {
81
            $this->db->getConnection()->beginTransaction();
82
83
            $result = $callback();
84
85
            $this->db->getConnection()->commit();
86
87
            return $result;
88
        } catch (Core\Validation\Exceptions\InvalidFormTokenException $e) {
89
            return $this->redirectMessages->setMessage(
90
                false,
91
                $this->translator->t('system', 'form_already_submitted'),
92
                $path
93
            );
94
        } catch (Core\Validation\Exceptions\ValidationFailedException $e) {
95
            return $this->renderErrorBoxOnFailedFormValidation($e);
96
        } catch (ConnectionException $e) {
97
            $this->db->getConnection()->rollBack();
98
99
            throw $e;
100
        }
101
    }
102
103
    /**
104
     * @param \Exception $exception
105
     *
106
     * @return array|Response
107
     */
108
    public function renderErrorBoxOnFailedFormValidation(\Exception $exception)
109
    {
110
        $errors = $this->alerts->errorBox($exception->getMessage());
111
        if ($this->request->isXmlHttpRequest()) {
112
            return new Response($errors, Response::HTTP_BAD_REQUEST);
113
        }
114
115
        return ['error_msg' => $errors];
116
    }
117
118
    /**
119
     * @param string      $action
120
     * @param callable    $callback
121
     * @param string|null $moduleConfirmUrl
122
     * @param string|null $moduleIndexUrl
123
     *
124
     * @return array|JsonResponse|RedirectResponse
125
     *
126
     * @throws \ACP3\Core\Controller\Exception\ResultNotExistsException
127
     */
128
    public function handleDeleteAction(
129
        string $action,
130
        callable $callback,
131
        ?string $moduleConfirmUrl = null,
132
        ?string $moduleIndexUrl = null
133
    ) {
134
        return $this->handleCustomDeleteAction(
135
            $action,
136
            function (array $items) use ($callback, $moduleIndexUrl) {
137
                $result = $callback($items);
138
139
                return $this->prepareRedirectMessageAfterPost($result, 'delete', $moduleIndexUrl);
140
            },
141
            $moduleConfirmUrl,
142
            $moduleIndexUrl
143
        );
144
    }
145
146
    /**
147
     * @param string      $action
148
     * @param callable    $callback
149
     * @param string|null $moduleConfirmUrl
150
     * @param string|null $moduleIndexUrl
151
     *
152
     * @return array|JsonResponse|RedirectResponse
153
     *
154
     * @throws \ACP3\Core\Controller\Exception\ResultNotExistsException
155
     */
156
    public function handleCustomDeleteAction(
157
        string $action,
158
        callable $callback,
159
        ?string $moduleConfirmUrl = null,
160
        ?string $moduleIndexUrl = null
161
    ) {
162
        list($moduleConfirmUrl, $moduleIndexUrl) = $this->generateDefaultConfirmationBoxUris(
163
            $moduleConfirmUrl,
164
            $moduleIndexUrl
165
        );
166
        $result = $this->deleteItem($action, $moduleConfirmUrl, $moduleIndexUrl);
167
168
        if ($result instanceof RedirectResponse) {
169
            return $result;
170
        } elseif (\is_array($result)) {
0 ignored issues
show
introduced by Tino Goratsch
The condition is_array($result) is always false.
Loading history...
171
            if ($action === 'confirmed') {
172
                return $callback($result);
173
            }
174
175
            return $result;
176
        }
177
178
        throw new Core\Controller\Exception\ResultNotExistsException();
179
    }
180
181
    /**
182
     * @param callable    $callback
183
     * @param null|string $path
184
     *
185
     * @return string|array|\Symfony\Component\HttpFoundation\JsonResponse|\Symfony\Component\HttpFoundation\RedirectResponse
186
     *
187
     * @throws \Doctrine\DBAL\ConnectionException
188
     * @throws \Doctrine\DBAL\DBALException
189
     */
190
    public function handleSettingsPostAction(callable $callback, ?string $path = null)
191
    {
192
        return $this->handlePostAction(function () use ($callback, $path) {
193
            $result = $callback();
194
195
            return $this->prepareRedirectMessageAfterPost($result, 'settings', $path);
196
        }, $path);
197
    }
198
199
    /**
200
     * @param callable    $callback
201
     * @param null|string $path
202
     *
203
     * @return array|string|JsonResponse|RedirectResponse
204
     *
205
     * @throws \Doctrine\DBAL\ConnectionException
206
     * @throws \Doctrine\DBAL\DBALException
207
     */
208
    public function handleSaveAction(callable $callback, ?string $path = null)
209
    {
210
        return $this->handlePostAction(function () use ($callback, $path) {
211
            $result = $callback();
212
213
            return $this->prepareRedirectMessageAfterPost($result, 'save', $path);
214
        });
215
    }
216
217
    /**
218
     * @param bool|int    $result
219
     * @param string      $phrase
220
     * @param null|string $path
221
     *
222
     * @return \Symfony\Component\HttpFoundation\JsonResponse|\Symfony\Component\HttpFoundation\RedirectResponse
223
     */
224
    private function prepareRedirectMessageAfterPost($result, string $phrase, ?string $path = null)
225
    {
226
        return $this->setRedirectMessage(
227
            $result,
228
            $this->translator->t('system', $phrase . ($result !== false ? '_success' : '_error')),
229
            $path
230
        );
231
    }
232
233
    /**
234
     * @param bool|int    $result
235
     * @param string      $translatedText
236
     * @param null|string $path
237
     *
238
     * @return \Symfony\Component\HttpFoundation\JsonResponse|\Symfony\Component\HttpFoundation\RedirectResponse
239
     */
240
    public function setRedirectMessage($result, string $translatedText, ?string $path = null)
241
    {
242
        return $this->redirectMessages->setMessage(
243
            $result,
0 ignored issues
show
Bug introduced by Tino Goratsch
It seems like $result can also be of type integer; however, parameter $isSuccess of ACP3\Core\Helpers\RedirectMessages::setMessage() does only seem to accept boolean, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

243
            /** @scrutinizer ignore-type */ $result,
Loading history...
244
            $translatedText,
245
            $this->request->getPost()->has('continue') ? $this->request->getPathInfo() : $path
246
        );
247
    }
248
249
    /**
250
     * @param string|null $moduleConfirmUrl
251
     * @param string|null $moduleIndexUrl
252
     *
253
     * @return array
254
     */
255
    private function generateDefaultConfirmationBoxUris(?string $moduleConfirmUrl, ?string $moduleIndexUrl)
256
    {
257
        if ($moduleConfirmUrl === null) {
258
            $moduleConfirmUrl = $this->request->getFullPath();
259
        }
260
261
        if ($moduleIndexUrl === null) {
262
            $moduleIndexUrl = $this->request->getModuleAndController();
263
        }
264
265
        return [$moduleConfirmUrl, $moduleIndexUrl];
266
    }
267
268
    /**
269
     * helper function for deleting a result set.
270
     *
271
     * @param string      $action
272
     * @param string|null $moduleConfirmUrl
273
     * @param string|null $moduleIndexUrl
274
     *
275
     * @return array|JsonResponse|\Symfony\Component\HttpFoundation\RedirectResponse
276
     */
277
    private function deleteItem(string $action, ?string $moduleConfirmUrl = null, ?string $moduleIndexUrl = null)
278
    {
279
        $entries = $this->prepareRequestData();
280
281
        if (empty($entries)) {
282
            return $this->redirectMessages->setMessage(
283
                false,
284
                $this->translator->t('system', 'no_entries_selected'),
285
                $moduleIndexUrl
286
            );
287
        } elseif ($action !== 'confirmed') {
288
            $data = [
289
                'action' => 'confirmed',
290
                'entries' => $entries,
291
            ];
292
293
            return $this->alerts->confirmBoxPost(
294
                $this->prepareConfirmationBoxText($entries),
295
                $data,
296
                $this->router->route($moduleConfirmUrl),
297
                $this->router->route($moduleIndexUrl)
298
            );
299
        }
300
301
        return $entries;
302
    }
303
304
    /**
305
     * @return array
306
     */
307
    private function prepareRequestData(): array
308
    {
309
        $entries = [];
310
        if (\is_array($this->request->getPost()->get('entries')) === true) {
311
            $entries = $this->request->getPost()->get('entries');
312
        } elseif ((bool) \preg_match('/^((\d+)\|)*(\d+)$/', $this->request->getParameters()->get('entries')) === true) {
313
            $entries = \explode('|', $this->request->getParameters()->get('entries'));
314
        }
315
316
        return $entries;
317
    }
318
319
    /**
320
     * @param array $entries
321
     *
322
     * @return string
323
     */
324
    private function prepareConfirmationBoxText(array $entries): string
325
    {
326
        $entriesCount = \count($entries);
327
        if ($entriesCount === 1) {
328
            return $this->translator->t('system', 'confirm_delete_single');
329
        }
330
331
        return $this->translator->t('system', 'confirm_delete_multiple', ['{items}' => $entriesCount]);
332
    }
333
}
334