Passed
Push — master ( af41cd...8dcf4e )
by Gerrit
01:54
created

GenericServiceInvokeController::callService()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 45

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 23
CRAP Score 4

Importance

Changes 0
Metric Value
dl 0
loc 45
ccs 23
cts 23
cp 1
rs 9.2
c 0
b 0
f 0
cc 4
nc 6
nop 1
crap 4
1
<?php
2
/**
3
 * Copyright (C) 2018 Gerrit Addiks.
4
 * This package (including this file) was released under the terms of the GPL-3.0.
5
 * You should have received a copy of the GNU General Public License along with this program.
6
 * If not, see <http://www.gnu.org/licenses/> or send me a mail so i can send you a copy.
7
 *
8
 * @license GPL-3.0
9
 *
10
 * @author Gerrit Addiks <[email protected]>
11
 */
12
13
namespace Addiks\SymfonyGenerics\Controllers\API;
14
15
use Addiks\SymfonyGenerics\Controllers\ControllerHelperInterface;
16
use Webmozart\Assert\Assert;
17
use Psr\Container\ContainerInterface;
18
use Addiks\SymfonyGenerics\Services\ArgumentCompilerInterface;
19
use Symfony\Component\HttpFoundation\Response;
20
use Symfony\Component\HttpFoundation\Request;
21
use ErrorException;
22
use ReflectionObject;
23
use ReflectionMethod;
24
25
final class GenericServiceInvokeController
26
{
27
28
    /**
29
     * @var ControllerHelperInterface
30
     */
31
    private $controllerHelper;
32
33
    /**
34
     * @var ArgumentCompilerInterface
35
     */
36
    private $argumentCompiler;
37
38
    /**
39
     * @var ContainerInterface
40
     */
41
    private $container;
42
43
    /**
44
     * @var string
45
     */
46
    private $serviceId;
47
48
    /**
49
     * @var string
50
     */
51
    private $method;
52
53
    /**
54
     * @var array
55
     */
56
    private $arguments;
57
58
    /**
59
     * @var string|null
60
     */
61
    private $authorizationAttribute;
62
63
    /**
64
     * @var string|null
65
     */
66
    private $successRedirectRoute;
67
68
    /**
69
     * @var array
70
     */
71
    private $successRedirectArguments;
72
73
    /**
74
     * @var integer
75
     */
76
    private $successRedirectStatus;
77
78 9
    public function __construct(
79
        ControllerHelperInterface $controllerHelper,
80
        ArgumentCompilerInterface $argumentCompiler,
81
        ContainerInterface $container,
82
        array $options
83
    ) {
84 9
        Assert::null($this->controllerHelper);
85 9
        Assert::keyExists($options, 'service');
86 8
        Assert::keyExists($options, 'method');
87
88
        /** @var int $defaultRedirectStatus */
89 7
        $defaultRedirectStatus = 303;
90
91 7
        $options = array_merge([
92 7
            'arguments' => [],
93
            'authorization-attributes' => null,
94
            'success-redirect' => null,
95
            'success-redirect-arguments' => [],
96 7
            'success-redirect-status' => $defaultRedirectStatus,
97 7
        ], $options);
98
99 7
        $this->controllerHelper = $controllerHelper;
100 7
        $this->argumentCompiler = $argumentCompiler;
101 7
        $this->container = $container;
102 7
        $this->serviceId = $options['service'];
103 7
        $this->method = $options['method'];
104 7
        $this->arguments = $options['arguments'];
105 7
        $this->authorizationAttribute = $options['authorization-attributes'];
106 7
        $this->successRedirectRoute = $options['success-redirect'];
107 7
        $this->successRedirectArguments = $options['success-redirect-arguments'];
108 7
        $this->successRedirectStatus = $options['success-redirect-status'];
109 7
    }
110
111 2 View Code Duplication
    public function __invoke(): Response
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
112
    {
113
        /** @var Request $request */
114 2
        $request = $this->controllerHelper->getCurrentRequest();
115
116 2
        Assert::isInstanceOf($request, Request::class, "Cannot use controller outside of request-scope!");
117
118 1
        return $this->callService($request);
119
    }
120
121 5
    public function callService(Request $request): Response
122
    {
123 5
        if (!is_null($this->authorizationAttribute)) {
124 1
            $this->controllerHelper->denyAccessUnlessGranted($this->authorizationAttribute, $request);
125
        }
126
127
        /** @var object|null $service */
128 4
        $service = $this->container->get($this->serviceId);
129
130 4
        if (is_null($service)) {
131 1
            throw new ErrorException(sprintf(
132 1
                "Could not find service '%s'!",
133 1
                $this->serviceId
134
            ));
135
        }
136
137 3
        $reflectionObject = new ReflectionObject($service);
138
139
        /** @var ReflectionMethod $reflectionMethod */
140 3
        $reflectionMethod = $reflectionObject->getMethod($this->method);
141
142
        /** @var array $arguments */
143 3
        $arguments = $this->argumentCompiler->buildCallArguments(
144 3
            $reflectionMethod,
145 3
            $this->arguments,
146 3
            $request
147
        );
148
149 3
        $reflectionMethod->invokeArgs($service, $arguments);
150
151 3
        $this->controllerHelper->flushORM();
152
153 3
        if (!empty($this->successRedirectRoute)) {
154
            /** @var array $redirectArguments */
155 1
            $redirectArguments = $this->argumentCompiler->buildArguments($this->successRedirectArguments, $request);
156
157 1
            return $this->controllerHelper->redirectToRoute(
158 1
                $this->successRedirectRoute,
159 1
                $redirectArguments,
160 1
                $this->successRedirectStatus
161
            );
162
        }
163
164 2
        return new Response("Service call completed");
165
    }
166
167
}
168