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

InputParamEnumHandler::createEnum()   B

Complexity

Conditions 9
Paths 7

Size

Total Lines 39
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 9
eloc 17
c 1
b 0
f 0
nc 7
nop 5
dl 0
loc 39
rs 8.0555
1
<?php
2
3
declare(strict_types=1);
4
5
namespace BEAR\Resource;
6
7
use BackedEnum;
8
use BEAR\Resource\Exception\ParameterEnumTypeException;
9
use BEAR\Resource\Exception\ParameterException;
10
use BEAR\Resource\Exception\ParameterInvalidEnumException;
11
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...
12
use ReflectionNamedType;
13
use UnitEnum;
14
15
use function assert;
16
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...
17
use function is_a;
18
use function is_int;
19
use function is_string;
20
use function ltrim;
21
use function preg_replace;
22
use function strtolower;
23
24
final class InputParamEnumHandler
25
{
26
    /** @param array<string, mixed> $query */
27
    public function createEnum(
28
        string $type,
29
        string $varName,
30
        array $query,
31
        bool $isDefaultAvailable,
32
        mixed $defaultValue,
33
    ): mixed {
34
        $props = $this->getPropsForClassParam($varName, $query, $isDefaultAvailable, $defaultValue);
35
36
        /** @var class-string<UnitEnum> $type */
37
        $refEnum = new ReflectionEnum($type);
38
        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

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