Passed
Push — master ( 289469...3cf8a9 )
by Gerrit
03:42
created

GenericEntityInvokeController   A

Complexity

Total Complexity 8

Size/Duplication

Total Lines 188
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 6

Test Coverage

Coverage 94.03%

Importance

Changes 0
Metric Value
dl 0
loc 188
ccs 63
cts 67
cp 0.9403
rs 10
c 0
b 0
f 0
wmc 8
lcom 1
cbo 6

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 35 1
A __invoke() 0 23 2
B invokeEntityMethod() 0 68 5
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 Addiks\SymfonyGenerics\Services\ArgumentCompilerInterface;
17
use Webmozart\Assert\Assert;
18
use InvalidArgumentException;
19
use ReflectionObject;
20
use ReflectionMethod;
21
use Symfony\Component\HttpFoundation\Request;
22
use Symfony\Component\HttpFoundation\Response;
23
use Addiks\SymfonyGenerics\Events\EntityInteractionEvent;
24
25
final class GenericEntityInvokeController
26
{
27
28
    /**
29
     * @var ControllerHelperInterface
30
     */
31
    private $controllerHelper;
32
33
    /**
34
     * @var ArgumentCompilerInterface
35
     */
36
    private $argumentCompiler;
37
38
    /**
39
     * @var string
40
     */
41
    private $entityClass;
42
43
    /**
44
     * @var string
45
     */
46
    private $entityIdKey;
47
48
    /**
49
     * @var string
50
     */
51
    private $methodName;
52
53
    /**
54
     * @var array
55
     */
56
    private $arguments;
57
58
    /**
59
     * @var string|null
60
     */
61
    private $denyAccessAttribute;
62
63
    /**
64
     * @var string
65
     */
66
    private $successMessage;
67
68
    /**
69
     * @var string|null
70
     */
71
    private $redirectRoute;
72
73
    /**
74
     * @var array
75
     */
76
    private $redirectRouteParameters;
77
78
    /**
79
     * @var bool
80
     */
81
    private $sendReturnValueInResponse = false;
82
83 12
    public function __construct(
84
        ControllerHelperInterface $controllerHelper,
85
        ArgumentCompilerInterface $argumentCompiler,
86
        array $options
87
    ) {
88 12
        Assert::null($this->controllerHelper);
89 12
        Assert::keyExists($options, 'entity-class');
90 11
        Assert::keyExists($options, 'method');
91
92 10
        $options = array_merge([
93 10
            'arguments' => [],
94
            'deny-access-attribute' => null,
95
            'success-message' => "Entity method invoked!",
96
            'redirect-route' => null,
97
            'redirect-route-parameters' => [],
98
            'entity-id-key' => 'entityId',
99
            'send-return-value-in-response' => false,
100 10
        ], $options);
101
102 10
        Assert::classExists($options['entity-class']);
103 9
        Assert::methodExists($options['entity-class'], $options['method']);
104 8
        Assert::isArray($options['arguments'], 'Method-arguments must be array!');
105
106 7
        $this->controllerHelper = $controllerHelper;
107 7
        $this->argumentCompiler = $argumentCompiler;
108 7
        $this->entityClass = $options['entity-class'];
109 7
        $this->entityIdKey = $options['entity-id-key'];
110 7
        $this->methodName = $options['method'];
111 7
        $this->arguments = $options['arguments'];
112 7
        $this->denyAccessAttribute = $options['deny-access-attribute'];
113 7
        $this->successMessage = $options['success-message'];
114 7
        $this->redirectRoute = $options['redirect-route'];
115 7
        $this->redirectRouteParameters = $options['redirect-route-parameters'];
116 7
        $this->sendReturnValueInResponse = $options['send-return-value-in-response'];
117 7
    }
118
119 2
    public function __invoke(): Response
120
    {
121
        /** @var Request $request */
122 2
        $request = $this->controllerHelper->getCurrentRequest();
123
124 2
        Assert::isInstanceOf($request, Request::class, "Cannot use controller outside of request-scope!");
125
126
        /** @var Response $response */
127 1
        $response = null;
0 ignored issues
show
Unused Code introduced by
$response is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
128
129 1
        if ($this->argumentCompiler->understandsArgumentString($this->entityIdKey)) {
130
            $response = $this->invokeEntityMethod('');
131
132
        } else {
133
            /** @var string $entityId */
134 1
            $entityId = $request->get($this->entityIdKey);
135
136 1
            $response = $this->invokeEntityMethod($entityId);
137
        }
138
139 1
        return $response;
140
141
    }
142
143 5
    public function invokeEntityMethod(string $entityId): Response
144
    {
145
        /** @var object|null $entity */
146 5
        $entity = null;
0 ignored issues
show
Unused Code introduced by
$entity is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
147
148 5
        if ($this->argumentCompiler->understandsArgumentString($this->entityIdKey)) {
149
            $entity = $this->argumentCompiler->buildArgument($this->entityIdKey);
150
            Assert::object($entity, "Entity not found!");
151
152
        } else {
153 5
            $entity = $this->controllerHelper->findEntity($this->entityClass, $entityId);
154 5
            Assert::object($entity, sprintf("Entity with id '%s' not found!", $entityId));
155
        }
156
157 4
        Assert::isInstanceOf($entity, $this->entityClass, sprintf(
158 4
            "Found entity is not of expected class '%s', but of class '%s' instead!",
159 4
            $this->entityClass,
160 4
            get_class($entity)
161
        ));
162
163 4
        if (!empty($this->denyAccessAttribute)) {
164 1
            $this->controllerHelper->denyAccessUnlessGranted($this->denyAccessAttribute, $entity);
165
        }
166
167 3
        $reflectionObject = new ReflectionObject($entity);
168
169
        /** @var ReflectionMethod $reflectionMethod */
170 3
        $reflectionMethod = $reflectionObject->getMethod($this->methodName);
171
172
        /** @var array $callArguments */
173 3
        $callArguments = $this->argumentCompiler->buildCallArguments(
174 3
            $reflectionMethod,
175 3
            $this->arguments
176
        );
177
178 3
        $this->controllerHelper->dispatchEvent("symfony_generics.entity_interaction", new EntityInteractionEvent(
179 3
            $this->entityClass,
180 3
            $entityId,
181 3
            $entity,
182 3
            $this->methodName,
183 3
            $callArguments
184
        ));
185
186
        /** @var mixed $result */
187 3
        $result = $reflectionMethod->invokeArgs($entity, $callArguments);
188
189 3
        $this->controllerHelper->flushORM();
190
191
        /** @var Response $response */
192 3
        $response = null;
0 ignored issues
show
Unused Code introduced by
$response is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
193
194 3
        if ($this->sendReturnValueInResponse) {
195
            return new Response((string)$result);
196
197 3
        } elseif (is_null($this->redirectRoute)) {
198 2
            $response = new Response($this->successMessage);
199
200
        } else {
201 1
            $response = $this->controllerHelper->redirectToRoute(
202 1
                $this->redirectRoute,
203 1
                $this->argumentCompiler->buildArguments($this->redirectRouteParameters, [
204 1
                    'result' => $result
205
                ])
206
            );
207
        }
208
209 3
        return $response;
210
    }
211
212
}
213