Passed
Pull Request — master (#1181)
by Tarmo
06:39 queued 03:09
created

RestDtoValueResolver::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 0

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 0
c 0
b 0
f 0
nc 1
nop 2
dl 0
loc 4
ccs 1
cts 1
cp 1
crap 1
rs 10
1
<?php
2
declare(strict_types = 1);
3
/**
4
 * /src/ArgumentResolver/RestDtoValueResolver.php
5
 *
6
 * @author TLe, Tarmo Leppänen <[email protected]>
7
 */
8
9
namespace App\ArgumentResolver;
10
11
use App\DTO\RestDtoInterface;
12
use App\Rest\Controller;
13
use App\Rest\ControllerCollection;
14
use AutoMapperPlus\AutoMapperInterface;
15
use BadMethodCallException;
16
use Generator;
17
use Symfony\Component\HttpFoundation\Request;
18
use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
19
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
20
use Throwable;
21
use function count;
22
use function explode;
23
use function in_array;
24
25
/**
26
 * Class RestDtoValueResolver
27
 *
28
 * @package App\ArgumentResolver
29
 * @author TLe, Tarmo Leppänen <[email protected]>
30
 */
31
class RestDtoValueResolver implements ArgumentValueResolverInterface
32
{
33
    private const CONTROLLER_KEY = '_controller';
34
35
    /**
36
     * @var array<int, string>
37
     */
38
    private array $supportedActions = [
39
        Controller::ACTION_CREATE,
40
        Controller::ACTION_UPDATE,
41
        Controller::ACTION_PATCH,
42
    ];
43
44
    /**
45
     * @var array<string, string>
46
     */
47
    private array $actionMethodMap = [
48
        Controller::ACTION_CREATE => Controller::METHOD_CREATE,
49
        Controller::ACTION_UPDATE => Controller::METHOD_UPDATE,
50
        Controller::ACTION_PATCH => Controller::METHOD_PATCH,
51
    ];
52
53
    private ?string $controllerName = null;
54
    private ?string $actionName = null;
55
56 44
    public function __construct(
57
        private ControllerCollection $controllerCollection,
58
        private AutoMapperInterface $autoMapper,
59
    ) {
60 44
    }
61
62 43
    public function supports(Request $request, ArgumentMetadata $argument): bool
63
    {
64 43
        $bits = explode('::', (string)$request->attributes->get(self::CONTROLLER_KEY, ''));
65
66 43
        if (count($bits) !== 2) {
67 2
            return false;
68
        }
69
70 41
        [$controllerName, $actionName] = $bits;
71
72 41
        $output = $argument->getType() === RestDtoInterface::class
73 41
            && in_array($actionName, $this->supportedActions, true)
74 41
            && $this->controllerCollection->has($controllerName);
75
76 41
        if ($output === true) {
77 41
            $this->controllerName = $controllerName;
78 41
            $this->actionName = $actionName;
79
        }
80
81 41
        return $output;
82
    }
83
84
    /**
85
     * @throws Throwable
86
     *
87
     * @return Generator<RestDtoInterface>
88
     */
89 42
    public function resolve(Request $request, ArgumentMetadata $argument): Generator
90
    {
91 42
        if ($this->controllerName === null || $this->actionName === null) {
92 1
            $message = sprintf(
93 1
                'You cannot call `%1$s::resolve(...)` method without calling `%1$s::supports(...)` first',
94 1
                self::class,
95
            );
96
97 1
            throw new BadMethodCallException($message);
98
        }
99
100 41
        $dtoClass = $this->controllerCollection
101 41
            ->get($this->controllerName)
102 41
            ->getDtoClass($this->actionMethodMap[$this->actionName] ?? null);
103
104 41
        yield $this->autoMapper->map($request, $dtoClass);
105 41
    }
106
}
107