Completed
Pull Request — 1.x (#352)
by Akihito
01:20
created

ScanClass::__invoke()   A

Complexity

Conditions 5
Paths 5

Size

Total Lines 29

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 29
rs 9.1448
c 0
b 0
f 0
cc 5
nc 5
nop 3
1
<?php
2
3
declare(strict_types=1);
4
5
namespace BEAR\Package\Compiler;
6
7
use BEAR\Resource\Exception\ParameterException;
8
use BEAR\Resource\NamedParameterInterface;
9
use Doctrine\Common\Annotations\Reader;
10
use ReflectionClass;
11
12
use function in_array;
13
use function is_callable;
14
use function sprintf;
15
use function substr;
16
17
/**
18
 * Compiler Component
19
 */
20
final class ScanClass
21
{
22
    /**
23
     * Save annotation and method meta information
24
     *
25
     * @param class-string<T> $className
0 ignored issues
show
Documentation introduced by
The doc-type class-string<T> could not be parsed: Unknown type name "class-string" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
26
     *
27
     * @template T
28
     */
29
    public function __invoke(Reader $reader, NamedParameterInterface $namedParams, string $className): void
30
    {
31
        $class = new ReflectionClass($className);
32
        $instance = $class->newInstanceWithoutConstructor();
33
        if (! $instance instanceof $className) {
34
            return; // @codeCoverageIgnore
35
        }
36
37
        $reader->getClassAnnotations($class);
38
        $methods = $class->getMethods();
39
        $log = sprintf('M %s:', $className);
40
        foreach ($methods as $method) {
41
            $methodName = $method->getName();
0 ignored issues
show
Bug introduced by
Consider using $method->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
42
            if ($this->isMagicMethod($methodName)) {
43
                continue;
44
            }
45
46
            if (substr($methodName, 0, 2) === 'on') {
47
                $log .= sprintf(' %s', $methodName);
48
                $this->saveNamedParam($namedParams, $instance, $methodName);
49
            }
50
51
            // method annotation
52
            $reader->getMethodAnnotations($method);
53
            $log .= sprintf('@ %s', $methodName);
54
        }
55
56
//        echo $log . PHP_EOL;
57
    }
58
59
    private function isMagicMethod(string $method): bool
60
    {
61
        return in_array($method, ['__sleep', '__wakeup', 'offsetGet', 'offsetSet', 'offsetExists', 'offsetUnset', 'count', 'ksort', 'asort', 'jsonSerialize'], true);
62
    }
63
64
    private function saveNamedParam(NamedParameterInterface $namedParameter, object $instance, string $method): void
65
    {
66
        // named parameter
67
        if (! in_array($method, ['onGet', 'onPost', 'onPut', 'onPatch', 'onDelete', 'onHead'], true)) {
68
            return;  // @codeCoverageIgnore
69
        }
70
71
        $callable = [$instance, $method];
72
        if (! is_callable($callable)) {
73
            return;  // @codeCoverageIgnore
74
        }
75
76
        try {
77
            $namedParameter->getParameters($callable, []);
78
        } catch (ParameterException $e) {
79
            return;
80
        }
81
    }
82
}
83