Passed
Pull Request — 1.x (#321)
by Akihito
02:42
created

InputParamEnumHandler::createEnum()   B

Complexity

Conditions 9
Paths 7

Size

Total Lines 39
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 9
eloc 17
nc 7
nop 5
dl 0
loc 39
rs 8.0555
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace BEAR\Resource\Input;
6
7
use BackedEnum;
8
use BEAR\Resource\Exception\NotBackedEnumException;
9
use BEAR\Resource\Exception\ParameterEnumTypeException;
10
use BEAR\Resource\Exception\ParameterException;
11
use BEAR\Resource\Exception\ParameterInvalidEnumException;
12
use ReflectionEnum;
0 ignored issues
show
Bug introduced by
The type ReflectionEnum was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
13
use ReflectionNamedType;
14
use UnitEnum;
15
16
use function assert;
17
use function enum_exists;
0 ignored issues
show
introduced by
The function enum_exists was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
18
use function is_a;
19
use function is_int;
20
use function is_string;
21
use function ltrim;
22
use function preg_replace;
23
use function strtolower;
24
25
final class InputParamEnumHandler
26
{
27
    /** @param array<string, mixed> $query */
28
    public function createEnum(
29
        string $type,
30
        string $varName,
31
        array $query,
32
        bool $isDefaultAvailable,
33
        mixed $defaultValue,
34
    ): mixed {
35
        $props = $this->getPropsForClassParam($varName, $query, $isDefaultAvailable, $defaultValue);
36
37
        /** @var class-string<UnitEnum> $type */
38
        $refEnum = new ReflectionEnum($type);
39
        assert(enum_exists($type));
0 ignored issues
show
Bug introduced by
The function enum_exists was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

39
        assert(/** @scrutinizer ignore-call */ enum_exists($type));
Loading history...
40
41
        if (! $refEnum->isBacked()) {
42
            throw new NotBackedEnumException($type);
43
        }
44
45
        assert(is_a($type, BackedEnum::class, true));
46
        if (! (is_int($props) || is_string($props))) {
47
            if ($isDefaultAvailable) {
0 ignored issues
show
introduced by
The condition $isDefaultAvailable is always true.
Loading history...
48
                return $defaultValue;
49
            }
50
51
            throw new ParameterEnumTypeException($varName);
52
        }
53
54
        // Get the backing type of the enum
55
        $backingType = $refEnum->getBackingType();
56
        if ($backingType instanceof ReflectionNamedType && $backingType->getName() === 'int' && is_string($props)) {
57
            $props = (int) $props;
58
        }
59
60
        /** @psalm-suppress MixedAssignment */
61
        $value = $type::tryFrom($props);
62
        if ($value === null) {
63
            throw new ParameterInvalidEnumException($varName);
64
        }
65
66
        return $value;
67
    }
68
69
    /** @param array<string, mixed> $query */
70
    private function getPropsForClassParam(
71
        string $varName,
72
        array $query,
73
        bool $isDefaultAvailable,
74
        mixed $defaultValue,
75
    ): mixed {
76
        if (isset($query[$varName])) {
77
            return $query[$varName];
78
        }
79
80
        $snakeName = ltrim(strtolower((string) preg_replace('/[A-Z]/', '_\0', $varName)), '_');
81
        if (isset($query[$snakeName])) {
82
            return $query[$snakeName];
83
        }
84
85
        if ($isDefaultAvailable) {
86
            return $defaultValue;
87
        }
88
89
        throw new ParameterException($varName);
90
    }
91
}
92