Meta::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 4
rs 10
c 0
b 0
f 0
ccs 3
cts 3
cp 1
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace BEAR\Resource;
6
7
use LogicException;
8
use ReflectionClass;
9
use ReflectionMethod;
10
11
use function array_shift;
12
use function assert;
13
use function class_exists;
14
use function explode;
15
use function implode;
16
use function is_string;
17
use function str_starts_with;
18
use function strtolower;
19
use function substr;
20
21
/**
22
 * @psalm-import-type PackageMetadata from Types
23
 * @psalm-import-type ResourceClassName from Types
24
 */
25
final class Meta
26
{
27
    private const EXTRAS_VENDOR = 'vendor';
28 4
    private const EXTRAS_PACKAGE = 'package';
29
30 4
    /** @var string */
31 4
    public $uri;
32 4
33
    /** @var Options */
34 4
    public $options;
35
36 4
    /** @var PackageMetadata */
0 ignored issues
show
Bug introduced by
The type BEAR\Resource\PackageMetadata 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...
37
    public $extras = [];
38 4
39 4
    /** @param ResourceClassName $class */
0 ignored issues
show
Bug introduced by
The type BEAR\Resource\ResourceClassName 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...
40 4
    public function __construct(string $class)
41 4
    {
42
        $this->uri = $this->getUri($class);
43 4
        $this->options = $this->getOptions($class);
44
    }
45
46
    private function getUri(string $class): string
47
    {
48
        /** @var list<string> $classPath */
49 4
        $classPath = explode('\\', $class);
50
        // $class
51 4
        $vendor = array_shift($classPath);
0 ignored issues
show
Bug introduced by
$classPath of type BEAR\Resource\list is incompatible with the type array expected by parameter $array of array_shift(). ( Ignorable by Annotation )

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

51
        $vendor = array_shift(/** @scrutinizer ignore-type */ $classPath);
Loading history...
52 4
        assert(is_string($vendor));
53 4
        $this->extras[self::EXTRAS_VENDOR] = $vendor;
54 4
        $package = array_shift($classPath);
55 4
        assert(is_string($package));
56
        $this->extras[self::EXTRAS_PACKAGE] = $package;
57
        array_shift($classPath); // "/Resource/"
58 4
        $scheme = array_shift($classPath);
59
        assert(is_string($scheme));
60
61
        return strtolower("{$scheme}://self/" . implode('/', $classPath));
62
    }
63
64 4
    /**
65
     * Return available resource request method
66 4
     *
67 4
     * @param ResourceClassName $class
68 4
     */
69 4
    private function getOptions(string $class): Options
70 4
    {
71
        if (! class_exists($class)) {
72
            throw new LogicException(); // @codeCoverageIgnore
73
        }
74 4
75
        $ref = new ReflectionClass($class);
76
        $allows = $this->getAllows($ref->getMethods());
77 4
        $params = [];
78
        foreach ($allows as $method) {
79 4
            $params[] = $this->getParams($class, $method);
80 4
        }
81 4
82 4
        return new Options($allows, $params);
83 4
    }
84 4
85 3
    /**
86
     * @param ReflectionMethod[] $methods
87 3
     *
88
     * @return string[]
89 4
     * @psalm-return list<string>
90
     */
91
    private function getAllows(array $methods): array
92 4
    {
93
        $allows = [];
94
        foreach ($methods as $method) {
95
            $isRequestMethod = str_starts_with($method->name, 'on') && ! str_starts_with($method->name, 'onLink');
96
            if (! $isRequestMethod) {
97
                continue;
98
            }
99
100
            $allows[] = strtolower(substr($method->name, 2));
101
        }
102
103
        return $allows;
104
    }
105
106
    /** @param ResourceClassName $class */
107
    private function getParams(string $class, string $method): Params
108
    {
109
        $refMethod = new ReflectionMethod($class, 'on' . $method);
110
        $parameters = $refMethod->getParameters();
111
        $optionalParams = $requiredParams = [];
112
        foreach ($parameters as $parameter) {
113
            $name = $parameter->name;
114
            if ($parameter->isOptional()) {
115
                $optionalParams[] = $name;
116
117
                continue;
118
            }
119
120
            $requiredParams[] = $name;
121
        }
122
123
        return new Params($method, $requiredParams, $optionalParams);
124
    }
125
}
126