Completed
Push — 1.0-adjust-cs ( dde5cf )
by Kamil
27:56
created

PayumController::provideTokenBasedOnPayment()   B

Complexity

Conditions 3
Paths 2

Size

Total Lines 27
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 27
c 0
b 0
f 0
rs 8.8571
cc 3
eloc 19
nc 2
nop 2
1
<?php
2
3
/*
4
 * This file is part of the Sylius package.
5
 *
6
 * (c) Paweł Jędrzejewski
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace Sylius\Bundle\PayumBundle\Controller;
15
16
use FOS\RestBundle\View\View;
17
use Payum\Core\Model\GatewayConfigInterface;
18
use Payum\Core\Payum;
19
use Payum\Core\Security\GenericTokenFactoryInterface;
20
use Payum\Core\Security\HttpRequestVerifierInterface;
21
use Payum\Core\Security\TokenInterface;
22
use Sylius\Bundle\PayumBundle\Factory\GetStatusFactoryInterface;
23
use Sylius\Bundle\PayumBundle\Factory\ResolveNextRouteFactoryInterface;
24
use Sylius\Bundle\ResourceBundle\Controller\RequestConfigurationFactoryInterface;
25
use Sylius\Bundle\ResourceBundle\Controller\ViewHandlerInterface;
26
use Sylius\Component\Core\Model\OrderInterface;
27
use Sylius\Component\Order\Repository\OrderRepositoryInterface;
28
use Sylius\Component\Payment\Model\PaymentInterface;
29
use Sylius\Component\Resource\Metadata\MetadataInterface;
30
use Symfony\Component\HttpFoundation\RedirectResponse;
31
use Symfony\Component\HttpFoundation\Request;
32
use Symfony\Component\HttpFoundation\Response;
33
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
34
use Symfony\Component\Routing\RouterInterface;
35
36
/**
37
 * @author Arkadiusz Krakowiak <[email protected]>
38
 */
39
final class PayumController
40
{
41
    /**
42
     * @var Payum
43
     */
44
    private $payum;
45
46
    /**
47
     * @var OrderRepositoryInterface
48
     */
49
    private $orderRepository;
50
51
    /**
52
     * @var MetadataInterface
53
     */
54
    private $orderMetadata;
55
56
    /**
57
     * @var RequestConfigurationFactoryInterface
58
     */
59
    private $requestConfigurationFactory;
60
61
    /**
62
     * @var ViewHandlerInterface
63
     */
64
    private $viewHandler;
65
66
    /**
67
     * @var RouterInterface
68
     */
69
    private $router;
70
71
    /** @var GetStatusFactoryInterface */
72
    private $getStatusRequestFactory;
73
74
    /** @var ResolveNextRouteFactoryInterface */
75
    private $resolveNextRouteRequestFacotry;
76
77
    public function __construct(
78
        Payum $payum,
79
        OrderRepositoryInterface $orderRepository,
80
        MetadataInterface $orderMetadata,
81
        RequestConfigurationFactoryInterface $requestConfigurationFactory,
82
        ViewHandlerInterface $viewHandler,
83
        RouterInterface $router,
84
        GetStatusFactoryInterface $getStatusFactory,
85
        ResolveNextRouteFactoryInterface $resolveNextRouteFactory
86
    ) {
87
        $this->payum = $payum;
88
        $this->orderRepository = $orderRepository;
89
        $this->orderMetadata = $orderMetadata;
90
        $this->requestConfigurationFactory = $requestConfigurationFactory;
91
        $this->viewHandler = $viewHandler;
92
        $this->router = $router;
93
        $this->getStatusRequestFactory = $getStatusFactory;
94
        $this->resolveNextRouteRequestFacotry = $resolveNextRouteFactory;
95
    }
96
97
    public function prepareCaptureAction(Request $request, $tokenValue): Response
98
    {
99
        $configuration = $this->requestConfigurationFactory->create($this->orderMetadata, $request);
100
101
        /** @var OrderInterface $order */
102
        $order = $this->orderRepository->findOneByTokenValue($tokenValue);
103
104
        if (null === $order) {
105
            throw new NotFoundHttpException(sprintf('Order with token "%s" does not exist.', $tokenValue));
106
        }
107
108
        $request->getSession()->set('sylius_order_id', $order->getId());
109
        $payment = $order->getLastPayment(PaymentInterface::STATE_NEW);
110
111
        if (null === $payment) {
112
            $url = $this->router->generate('sylius_shop_order_thank_you');
113
114
            return new RedirectResponse($url);
115
        }
116
117
        $token = $this->provideTokenBasedOnPayment($payment, $configuration->getParameters()->get('redirect'));
118
119
        $view = View::createRedirect($token->getTargetUrl());
120
121
        return $this->viewHandler->handle($configuration, $view);
122
    }
123
124
    public function afterCaptureAction(Request $request): Response
125
    {
126
        $configuration = $this->requestConfigurationFactory->create($this->orderMetadata, $request);
127
128
        $token = $this->getHttpRequestVerifier()->verify($request);
129
130
        $status = $this->getStatusRequestFactory->createNewWithModel($token);
131
        $this->payum->getGateway($token->getGatewayName())->execute($status);
132
        $resolveNextRoute = $this->resolveNextRouteRequestFacotry->createNewWithModel($status->getFirstModel());
133
        $this->payum->getGateway($token->getGatewayName())->execute($resolveNextRoute);
134
135
        $this->getHttpRequestVerifier()->invalidate($token);
136
137
        if (PaymentInterface::STATE_NEW !== $status->getValue()) {
138
            $request->getSession()->getBag('flashes')->add('info', sprintf('sylius.payment.%s', $status->getValue()));
139
        }
140
141
        return $this->viewHandler->handle(
142
            $configuration,
143
            View::createRouteRedirect($resolveNextRoute->getRouteName(), $resolveNextRoute->getRouteParameters())
144
        );
145
    }
146
147
    private function getTokenFactory(): GenericTokenFactoryInterface
148
    {
149
        return $this->payum->getTokenFactory();
150
    }
151
152
    private function getHttpRequestVerifier(): HttpRequestVerifierInterface
153
    {
154
        return $this->payum->getHttpRequestVerifier();
155
    }
156
157
    private function provideTokenBasedOnPayment(PaymentInterface $payment, array $redirectOptions): TokenInterface
158
    {
159
        /** @var GatewayConfigInterface $gatewayConfig */
160
        $gatewayConfig = $payment->getMethod()->getGatewayConfig();
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Sylius\Component\Payment...\PaymentMethodInterface as the method getGatewayConfig() does only exist in the following implementations of said interface: Sylius\Component\Core\Model\PaymentMethod.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
161
162
        if (isset($gatewayConfig->getConfig()['use_authorize']) && $gatewayConfig->getConfig()['use_authorize'] == true) {
163
            $token = $this->getTokenFactory()->createAuthorizeToken(
164
                $gatewayConfig->getGatewayName(),
165
                $payment,
166
                $redirectOptions['route']
167
                    ?? null,
168
                $redirectOptions['parameters']
169
                    ?? []
170
            );
171
        } else {
172
            $token = $this->getTokenFactory()->createCaptureToken(
173
                $gatewayConfig->getGatewayName(),
174
                $payment,
175
                $redirectOptions['route']
176
                    ?? null,
177
                $redirectOptions['parameters']
178
                    ?? []
179
            );
180
        }
181
182
        return $token;
183
    }
184
}
185