Issues (105)

src/AutoMapper/RestRequestMapper.php (2 issues)

1
<?php
2
declare(strict_types = 1);
3
/**
4
 * /src/AutoMapper/RestRequestMapper.php
5
 *
6
 * @author TLe, Tarmo Leppänen <[email protected]>
7
 */
8
9
namespace App\AutoMapper;
10
11
use App\DTO\RestDtoInterface;
12
use AutoMapperPlus\MapperInterface;
13
use InvalidArgumentException;
14
use LengthException;
15
use ReflectionClass;
16
use ReflectionNamedType;
17
use Symfony\Component\HttpFoundation\Request;
18
use function array_filter;
19
use function gettype;
20
use function is_object;
21
use function method_exists;
22
use function sprintf;
23
use function ucfirst;
24
25
/**
26
 * Class RestRequestMapper
27
 *
28
 * @package App\AutoMapper
29
 * @author TLe, Tarmo Leppänen <[email protected]>
30
 */
31
abstract class RestRequestMapper implements MapperInterface
32
{
33
    /**
34
     * Properties to map to destination object.
35
     *
36
     * @var array<int, non-empty-string>
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<int, non-empty-string> at position 4 could not be parsed: Unknown type name 'non-empty-string' at position 4 in array<int, non-empty-string>.
Loading history...
37
     */
38
    protected static array $properties = [];
39
40
    /**
41
     * {@inheritdoc}
42
     *
43
     * @psalm-param array<array-key, mixed>|object $source
44
     * @psalm-param array<int, mixed> $context
45
     */
46 86
    public function map($source, string $targetClass, array $context = []): RestDtoInterface
47
    {
48
        /** @psalm-var class-string $targetClass */
49 86
        $destination = new $targetClass();
50
51 86
        return $this->mapToObject($source, $destination, $context);
52
    }
53
54
    /**
55
     * {@inheritdoc}
56
     *
57
     * @psalm-param array<array-key, mixed>|object $source
58
     * @psalm-param object $destination
59
     * @psalm-param array<int, mixed> $context
60
     */
61 123
    public function mapToObject($source, $destination, array $context = []): RestDtoInterface
62
    {
63 123
        if (!is_object($source)) {
64 1
            throw new InvalidArgumentException(
65 1
                sprintf(
66 1
                    'RestRequestMapper expects that $source is Request object, "%s" provided',
67 1
                    gettype($source),
68 1
                )
69 1
            );
70
        }
71
72 122
        if (!$source instanceof Request) {
73 1
            throw new InvalidArgumentException(
74 1
                sprintf(
75 1
                    'RestRequestMapper expects that $source is Request object, "%s" provided',
76 1
                    $source::class,
77 1
                )
78 1
            );
79
        }
80
81 121
        if (!$destination instanceof RestDtoInterface) {
82 1
            throw new InvalidArgumentException(
83 1
                sprintf(
84 1
                    'RestRequestMapper expects that $destination is instance of RestDtoInterface object, "%s" provided',
85 1
                    $destination::class,
86 1
                )
87 1
            );
88
        }
89
90 120
        if (static::$properties === []) {
91 1
            throw new LengthException(
92 1
                sprintf(
93 1
                    'RestRequestMapper expects that mapper "%s::$properties" contains properties to convert',
94 1
                    static::class,
95 1
                )
96 1
            );
97
        }
98
99 119
        return $this->getObject($source, $destination);
100
    }
101
102 119
    private function getObject(Request $request, RestDtoInterface $restDto): RestDtoInterface
103
    {
104 119
        $reflectionClass = new ReflectionClass($restDto::class);
105
106 119
        foreach ($this->getValidProperties($request) as $property) {
107 32
            $setter = 'set' . ucfirst($property);
108 32
            $transformer = 'transform' . ucfirst($property);
109 32
            $type = $reflectionClass->getProperty($property)->getType();
110
111 32
            $value = $type instanceof ReflectionNamedType && $type->getName() === 'array'
112 8
                ? $request->request->all($property)
113 24
                : $request->request->get($property);
114
115 32
            if (method_exists($this, $transformer)) {
116
                /** @var int|string|object|array<mixed>|null $value */
117 24
                $value = $this->{$transformer}($value);
118
            }
119
120 32
            $restDto->{$setter}($value);
121
        }
122
123 119
        return $restDto;
124
    }
125
126
    /**
127
     * @return array<int, non-empty-string>
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<int, non-empty-string> at position 4 could not be parsed: Unknown type name 'non-empty-string' at position 4 in array<int, non-empty-string>.
Loading history...
128
     */
129 119
    private function getValidProperties(Request $request): array
130
    {
131 119
        return array_filter(static::$properties, static fn ($property) => $request->request->has($property));
132
    }
133
}
134