Passed
Push — feature/second-release ( 176745...89fc3a )
by Andrea Marco
02:27
created

MethodAnnotation::forTranslation()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 3
c 1
b 0
f 0
nc 1
nop 2
dl 0
loc 7
ccs 4
cts 4
cp 1
crap 1
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Cerbero\LaravelEnum\Data;
6
7
use BackedEnum;
0 ignored issues
show
Bug introduced by
The type BackedEnum 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...
8
use Cerbero\LaravelEnum\Services\CacheKey;
9
use ReflectionMethod;
10
use Stringable;
11
use UnitEnum;
0 ignored issues
show
Bug introduced by
The type UnitEnum 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
13
use function Cerbero\LaravelEnum\namespaceExists;
14
15
/**
16
 * The method annotation.
17
 */
18
final class MethodAnnotation implements Stringable
19
{
20
    /**
21
     * The regular expression to extract the explicit arguments.
22
     */
23
    public const RE_ARGUMENTS = '~{([a-z]+\s+\$[^}]+)}~';
24
25
    /**
26
     * The regular expression to extract the translation placeholders.
27
     */
28
    public const RE_PLACEHOLDER = '~:([a-zA-Z0-9_]+)~';
29
30
    /**
31
     * Whether the method is static.
32
     */
33
    public readonly bool $isStatic;
34
35
    /**
36
     * Retrieve the method annotation for the given case.
37
     */
38 1
    public static function forCase(UnitEnum $case): self
39
    {
40 1
        $returnType = is_int($case->value ?? null) ? 'int' : 'string';
41
42 1
        return new self($case->name, "static {$returnType} {$case->name}()");
43
    }
44
45
    /**
46
     * Retrieve the method annotation for the given cache case.
47
     */
48 1
    public static function forCacheCase(BackedEnum $case): self
49
    {
50 1
        preg_match_all(self::RE_ARGUMENTS, (string) $case->value, $matches);
51
52 1
        $arguments = implode(', ', array_map('trim', $matches[1]));
53
54 1
        return new self($case->name, "static CacheKey {$case->name}({$arguments})", [CacheKey::class]);
55
    }
56
57
    /**
58
     * Retrieve the method annotation for the given invokable class.
59
     *
60
     * @param class-string $class
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string.
Loading history...
61
     */
62 1
    public static function forInvokable(string $name, string $class): self
63
    {
64 1
        $parameters = $namespaces = [];
65 1
        $reflection = new ReflectionMethod($class, '__invoke');
66
67 1
        if (namespaceExists($returnType = (string) $reflection->getReturnType() ?: 'mixed')) {
68
            /** @var class-string $returnType */
69 1
            $namespaces[] = $returnType;
70
71 1
            $returnType = class_basename($returnType);
72
        }
73
74 1
        foreach ($reflection->getParameters() as $parameter) {
75 1
            if (namespaceExists($type = (string) $parameter->getType() ?: 'mixed')) {
76
                /** @var class-string $type */
77 1
                $namespaces[] = $type;
78
79 1
                $type = class_basename($type);
80
            }
81
82 1
            $parameters[] = "{$type} \${$parameter->getName()}";
83
        }
84
85 1
        return new self($name, sprintf('%s %s(%s)', $returnType, $name, implode(', ', $parameters)), $namespaces);
86
    }
87
88
    /**
89
     * Retrieve the method annotation for an instance method.
90
     */
91 1
    public static function instance(string $name, string $returnType): self
92
    {
93 1
        $namespaces = [];
94 1
        $null = str_starts_with($returnType, '?') ? '?' : '';
95 1
        $returnType = ltrim($returnType, '?');
96
97 1
        if (namespaceExists($returnType)) {
98
            /** @var class-string $returnType */
99 1
            $namespaces[] = $returnType;
100
101 1
            $returnType = class_basename($returnType);
102
        }
103
104 1
        return new self($name, "{$null}{$returnType} {$name}()", $namespaces);
105
    }
106
107
    /**
108
     * Retrieve the method annotation for the given translation.
109
     */
110 1
    public static function forTranslation(string $name, string $translation): self
111
    {
112 1
        preg_match_all(self::RE_PLACEHOLDER, $translation, $matches);
113
114 1
        $parameters = array_map(fn(string $name) => "mixed \${$name}", $matches[1]);
115
116 1
        return new self($name, sprintf('string %s(%s)', $name, implode(', ', $parameters)));
117
    }
118
119
    /**
120
     * Instantiate the class.
121
     *
122
     * @param list<class-string> $namespaces
0 ignored issues
show
Bug introduced by
The type Cerbero\LaravelEnum\Data\list 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...
123
     */
124 1
    public function __construct(
125
        public readonly string $name,
126
        public readonly string $annotation,
127
        public readonly array $namespaces = [],
128
    ) {
129 1
        $this->isStatic = str_starts_with($annotation, 'static');
0 ignored issues
show
Bug introduced by
The property isStatic is declared read-only in Cerbero\LaravelEnum\Data\MethodAnnotation.
Loading history...
130
    }
131
132
    /**
133
     * Retrieve the method annotation string.
134
     */
135 1
    public function __toString(): string
136
    {
137 1
        return "@method {$this->annotation}";
138
    }
139
}
140