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

PayumController::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 19
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 19
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 17
nc 1
nop 8

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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