Completed
Push — master ( 70dfe1...a97a1c )
by Torben
04:18
created

PaymentController::cancelAction()   B

Complexity

Conditions 5
Paths 12

Size

Total Lines 44

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 6.0373

Importance

Changes 0
Metric Value
dl 0
loc 44
ccs 17
cts 26
cp 0.6538
rs 8.9048
c 0
b 0
f 0
cc 5
nc 12
nop 2
crap 6.0373
1
<?php
2
3
/*
4
 * This file is part of the Extension "sf_event_mgt" for TYPO3 CMS.
5
 *
6
 * For the full copyright and license information, please read the
7
 * LICENSE.txt file that was distributed with this source code.
8
 */
9
10
namespace DERHANSEN\SfEventMgt\Controller;
11
12
use DERHANSEN\SfEventMgt\Event\ProcessPaymentCancelEvent;
13
use DERHANSEN\SfEventMgt\Event\ProcessPaymentFailureEvent;
14
use DERHANSEN\SfEventMgt\Event\ProcessPaymentInitializeEvent;
15
use DERHANSEN\SfEventMgt\Event\ProcessPaymentNotifyEvent;
16
use DERHANSEN\SfEventMgt\Event\ProcessPaymentSuccessEvent;
17
use DERHANSEN\SfEventMgt\Payment\Exception\PaymentException;
18
use TYPO3\CMS\Core\Utility\GeneralUtility;
19
use TYPO3\CMS\Extbase\Mvc\RequestInterface;
20
use TYPO3\CMS\Extbase\Mvc\ResponseInterface;
21
use TYPO3\CMS\Extbase\Security\Exception\InvalidHashException;
22
use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
23
24
/**
25
 * PaymentController
26
 *
27
 * @author Torben Hansen <[email protected]>
28
 */
29
class PaymentController extends AbstractController
30
{
31
    /**
32
     * Catches all PaymentExceptions and sets the Exception message to the response content
33
     *
34
     * @param RequestInterface $request
35
     * @param ResponseInterface $response
36
     * @throws \TYPO3\CMS\Extbase\Mvc\Exception\UnsupportedRequestTypeException
37
     */
38
    public function processRequest(RequestInterface $request, ResponseInterface $response)
39
    {
40
        try {
41
            parent::processRequest($request, $response);
42
        } catch (\DERHANSEN\SfEventMgt\Exception $e) {
43
            $response->setContent('<div class="payment-error">' . $e->getMessage() . '</div>');
44
        } catch (\TYPO3\CMS\Extbase\Security\Exception\InvalidHashException $e) {
45
            $response->setContent('<div class="payment-error">' . $e->getMessage() . '</div>');
46
        }
47
    }
48
49
    /**
50
     * Redirect to payment provider
51
     *
52
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Registration $registration
53
     * @param string $hmac
54
     */
55
    public function redirectAction($registration, $hmac)
56
    {
57
        $this->validateHmacForAction($registration, $hmac, $this->actionMethodName);
58
        $this->proceedWithAction($registration, $this->actionMethodName);
59
60
        $variables = [
61
            'sfEventMgtSettings' => $this->settings,
62
            'successUrl' => $this->getPaymentUriForAction('success', $registration),
63
            'failureUrl' => $this->getPaymentUriForAction('failure', $registration),
64
            'cancelUrl' => $this->getPaymentUriForAction('cancel', $registration),
65
            'notifyUrl' => $this->getPaymentUriForAction('notify', $registration),
66
            'registration' => $registration,
67
            'html' => ''
68
        ];
69
70
        $paymentMethod = $registration->getPaymentmethod();
71
72
        /**
73
         * If true, the externally called BeforeRedirect method requested, that the registration should be updated
74
         */
75
        $updateRegistration = false;
76
77
        $processPaymentInitializeEvent = new ProcessPaymentInitializeEvent(
78
            $variables,
79 10
            $paymentMethod,
80
            $updateRegistration,
81 10
            $registration,
82 10
            $this
83
        );
84
        $this->eventDispatcher->dispatch($processPaymentInitializeEvent);
0 ignored issues
show
Documentation introduced by
$processPaymentInitializeEvent is of type object<DERHANSEN\SfEvent...PaymentInitializeEvent>, but the function expects a object<Psr\EventDispatcher\object>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
85
        $variables = $processPaymentInitializeEvent->getVariables();
86
        $updateRegistration = $processPaymentInitializeEvent->getUpdateRegistration();
87
88
        if ($updateRegistration) {
89
            $this->registrationRepository->update($registration);
90
        }
91
92
        $this->view->assign('result', $variables);
93
    }
94
95
    /**
96
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Registration $registration
97
     * @param string $hmac
98
     */
99
    public function successAction($registration, $hmac)
100
    {
101
        $this->validateHmacForAction($registration, $hmac, $this->actionMethodName);
102
        $this->proceedWithAction($registration, $this->actionMethodName);
103
104
        $variables = ['html' => ''];
105
106
        $paymentMethod = $registration->getPaymentmethod();
107
108
        /**
109
         * If true, the externally called ProcessSuccess method requested, that the registration should be updated
110
         */
111
        $updateRegistration = false;
112
113
        $getVariables = is_array(GeneralUtility::_GET()) ? GeneralUtility::_GET() : [];
114
        $processPaymentSuccessEvent = new ProcessPaymentSuccessEvent(
115
            $variables,
116
            $paymentMethod,
117
            $updateRegistration,
118
            $registration,
119
            $getVariables,
0 ignored issues
show
Bug introduced by
It seems like $getVariables defined by is_array(\TYPO3\CMS\Core...ility::_GET() : array() on line 113 can also be of type string; however, DERHANSEN\SfEventMgt\Eve...essEvent::__construct() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
120
            $this
121
        );
122
        $this->eventDispatcher->dispatch($processPaymentSuccessEvent);
0 ignored issues
show
Documentation introduced by
$processPaymentSuccessEvent is of type object<DERHANSEN\SfEvent...essPaymentSuccessEvent>, but the function expects a object<Psr\EventDispatcher\object>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
123
        $variables = $processPaymentSuccessEvent->getVariables();
124
        $updateRegistration = $processPaymentSuccessEvent->getUpdateRegistration();
125
126
        if ($updateRegistration) {
127
            $this->registrationRepository->update($registration);
128 2
        }
129
130 2
        $this->view->assign('result', $variables);
131 2
    }
132
133
    /**
134 2
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Registration $registration
135 2
     * @param string $hmac
136 2
     */
137 2
    public function failureAction($registration, $hmac)
138 2
    {
139 2
        $this->validateHmacForAction($registration, $hmac, $this->actionMethodName);
140
        $this->proceedWithAction($registration, $this->actionMethodName);
141 2
142
        $variables = ['html' => ''];
143 2
144
        $paymentMethod = $registration->getPaymentmethod();
145
146
        /**
147
         * Update- and remove flags
148 2
         */
149
        $updateRegistration = false;
150 2
        $removeRegistration = false;
151 2
152 2
        $getVariables = is_array(GeneralUtility::_GET()) ? GeneralUtility::_GET() : [];
153 2
        $processPaymentFailureEvent = new ProcessPaymentFailureEvent(
154 2
            $variables,
155
            $paymentMethod,
156 2
            $updateRegistration,
157
            $removeRegistration,
158
            $registration,
159
            $getVariables,
0 ignored issues
show
Bug introduced by
It seems like $getVariables defined by is_array(\TYPO3\CMS\Core...ility::_GET() : array() on line 152 can also be of type string; however, DERHANSEN\SfEventMgt\Eve...ureEvent::__construct() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
160 2
            $this
161 2
        );
162
        $this->eventDispatcher->dispatch($processPaymentFailureEvent);
0 ignored issues
show
Documentation introduced by
$processPaymentFailureEvent is of type object<DERHANSEN\SfEvent...essPaymentFailureEvent>, but the function expects a object<Psr\EventDispatcher\object>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
163
        $variables = $processPaymentFailureEvent->getVariables();
164
        $updateRegistration = $processPaymentFailureEvent->getUpdateRegistration();
165
        $removeRegistration = $processPaymentFailureEvent->getRemoveRegistration();
166
167 2
        if ($updateRegistration) {
168
            $this->registrationRepository->update($registration);
169 2
        }
170 2
171
        if ($removeRegistration) {
172 2
            // First cancel depending registrations
173
            if ($registration->getAmountOfRegistrations() > 1) {
174 2
                $this->registrationService->cancelDependingRegistrations($registration);
175
            }
176
            $this->registrationRepository->remove($registration);
177
        }
178
179 2
        $this->view->assign('result', $variables);
180
    }
181 2
182 2
    /**
183 2
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Registration $registration
184 2
     * @param string $hmac
185 2
     */
186
    public function cancelAction($registration, $hmac)
187 2
    {
188
        $this->validateHmacForAction($registration, $hmac, $this->actionMethodName);
189
        $this->proceedWithAction($registration, $this->actionMethodName);
190
191 2
        $variables = ['html' => ''];
192 2
193
        $paymentMethod = $registration->getPaymentmethod();
194
195
        /**
196
         * Update- and remove flags
197
         */
198 2
        $updateRegistration = false;
199
        $removeRegistration = false;
200 2
201 2
        $getVariables = is_array(GeneralUtility::_GET()) ? GeneralUtility::_GET() : [];
202
        $processPaymentCancelEvent = new ProcessPaymentCancelEvent(
203 2
            $variables,
204
            $paymentMethod,
205 2
            $updateRegistration,
206
            $removeRegistration,
207
            $registration,
208
            $getVariables,
0 ignored issues
show
Bug introduced by
It seems like $getVariables defined by is_array(\TYPO3\CMS\Core...ility::_GET() : array() on line 201 can also be of type string; however, DERHANSEN\SfEventMgt\Eve...celEvent::__construct() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
209
            $this
210 2
        );
211 2
        $this->eventDispatcher->dispatch($processPaymentCancelEvent);
0 ignored issues
show
Documentation introduced by
$processPaymentCancelEvent is of type object<DERHANSEN\SfEvent...cessPaymentCancelEvent>, but the function expects a object<Psr\EventDispatcher\object>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
212
        $variables = $processPaymentCancelEvent->getVariables();
213 2
        $updateRegistration = $processPaymentCancelEvent->getUpdateRegistration();
214 2
        $removeRegistration = $processPaymentCancelEvent->getRemoveRegistration();
215 2
216 2
        if ($updateRegistration) {
217 2
            $this->registrationRepository->update($registration);
218
        }
219 2
220
        if ($removeRegistration) {
221
            // First cancel depending registrations
222
            if ($registration->getAmountOfRegistrations() > 1) {
223 2
                $this->registrationService->cancelDependingRegistrations($registration);
224
            }
225
            $this->registrationRepository->remove($registration);
226
        }
227
228
        $this->view->assign('result', $variables);
229
    }
230
231 2
    /**
232 2
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Registration $registration
233
     * @param string $hmac
234
     */
235
    public function notifyAction($registration, $hmac)
236
    {
237
        $this->validateHmacForAction($registration, $hmac, $this->actionMethodName);
238 2
        $this->proceedWithAction($registration, $this->actionMethodName);
239
240 2
        $variables = ['html' => ''];
241 2
242
        $paymentMethod = $registration->getPaymentmethod();
243 2
244
        /**
245 2
         * Initialize update-flag
246
         *
247
         * If true, the externally called ProcessNotify method requested, that the registration should be updated
248
         */
249
        $updateRegistration = false;
250 2
251 2
        $getVariables = is_array(GeneralUtility::_GET()) ? GeneralUtility::_GET() : [];
252
        $processPaymentNotifyEvent = new ProcessPaymentNotifyEvent(
253 2
            $variables,
254 2
            $paymentMethod,
255 2
            $updateRegistration,
256 2
            $registration,
257 2
            $getVariables,
0 ignored issues
show
Bug introduced by
It seems like $getVariables defined by is_array(\TYPO3\CMS\Core...ility::_GET() : array() on line 251 can also be of type string; however, DERHANSEN\SfEventMgt\Eve...ifyEvent::__construct() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
258
            $this
259 2
        );
260
        $this->eventDispatcher->dispatch($processPaymentNotifyEvent);
0 ignored issues
show
Documentation introduced by
$processPaymentNotifyEvent is of type object<DERHANSEN\SfEvent...cessPaymentNotifyEvent>, but the function expects a object<Psr\EventDispatcher\object>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
261
        $variables = $processPaymentNotifyEvent->getVariables();
262
        $updateRegistration = $processPaymentNotifyEvent->getUpdateRegistration();
263 2
264
        if ($updateRegistration) {
265
            $this->registrationRepository->update($registration);
266
        }
267
268
        $this->view->assign('result', $variables);
269
    }
270
271 2
    /**
272 2
     * Checks if the given action can be called for the given registration / event and throws
273
     * an exception if action should not proceed
274
     *
275
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Registration $registration
276
     * @param string $actionName
277
     * @throws PaymentException
278 2
     */
279
    protected function proceedWithAction($registration, $actionName)
280 2
    {
281 2
        if ($registration->getEvent()->getEnablePayment() === false) {
282
            $message = LocalizationUtility::translate('payment.messages.paymentNotEnabled', 'sf_event_mgt');
283 2
            throw new PaymentException($message, 1899934881);
284
        }
285 2
286
        if ($this->paymentService->paymentActionEnabled($registration->getPaymentmethod(), $actionName) === false) {
287
            $message = LocalizationUtility::translate('payment.messages.actionNotEnabled', 'sf_event_mgt');
288
            throw new PaymentException($message, 1899934882);
289
        }
290
291
        if ($registration->getPaid()) {
292 2
            $message = LocalizationUtility::translate('payment.messages.paymentAlreadyProcessed', 'sf_event_mgt');
293
            throw new PaymentException($message, 1899934883);
294 2
        }
295 2
296 2
        if ($registration->getEvent()->getRestrictPaymentMethods()) {
297 2
            $selectedPaymentMethods = explode(',', $registration->getEvent()->getSelectedPaymentMethods());
298 2
            if (!in_array($registration->getPaymentmethod(), $selectedPaymentMethods)) {
299
                $message = LocalizationUtility::translate('payment.messages.paymentMethodNotAvailable', 'sf_event_mgt');
300 2
                throw new PaymentException($message, 1899934884);
301
            }
302
        }
303
    }
304 2
305 2
    /**
306
     * Checks the HMAC for the given action and registration
307
     *
308
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Registration $registration
309
     * @param string $hmac
310
     * @param string $action
311
     * @throws InvalidHashException
312
     */
313
    protected function validateHmacForAction($registration, $hmac, $action)
314
    {
315
        $result = $this->hashService->validateHmac($action . '-' . $registration->getUid(), $hmac);
316
        if (!$result) {
317
            $message = LocalizationUtility::translate('payment.messages.invalidHmac', 'sf_event_mgt');
318
            throw new InvalidHashException($message, 1899934890);
319
        }
320
    }
321
322
    /**
323
     * Returns the payment Uri for the given action and registration
324
     *
325
     * @param string $action
326
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Registration $registration
327
     * @throws \TYPO3\CMS\Extbase\Security\Exception\InvalidArgumentForHashGenerationException
328
     * @return string
329
     */
330
    protected function getPaymentUriForAction($action, $registration)
331
    {
332
        $this->uriBuilder
333
            ->setCreateAbsoluteUri(true);
334
335
        return $this->uriBuilder->uriFor(
336
            $action,
337
            [
338
                'registration' => $registration,
339
                'hmac' => $this->hashService->generateHmac($action . 'Action-' . $registration->getUid())
340
            ],
341
            'Payment',
342
            'sfeventmgt',
343
            'Pipayment'
344
        );
345
    }
346
}
347