ServiceAwareClassAnnotatorTask::_getUsedServices()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2.0185

Importance

Changes 0
Metric Value
cc 2
eloc 5
nc 2
nop 1
dl 0
loc 10
ccs 5
cts 6
cp 0.8333
crap 2.0185
rs 10
c 0
b 0
f 0
1
<?php
2
declare(strict_types=1);
3
4
namespace Burzum\CakeServiceLayer\Annotator\ClassAnnotatorTask;
5
6
use Cake\Core\App;
7
use IdeHelper\Annotation\AnnotationFactory;
8
use IdeHelper\Annotator\ClassAnnotatorTask\AbstractClassAnnotatorTask;
9
use IdeHelper\Annotator\ClassAnnotatorTask\ClassAnnotatorTaskInterface;
10
11
/**
12
 * Classes that use ServiceAwareTrait should automatically have used tables - via loadService() call - annotated.
13
 */
14
class ServiceAwareClassAnnotatorTask extends AbstractClassAnnotatorTask implements ClassAnnotatorTaskInterface
15
{
16
    /**
17
     * @param string $path Path
18
     * @param string $content Content
19
     * @return bool
20
     */
21
    public function shouldRun(string $path, string $content): bool
22
    {
23
        if (preg_match('#\buse ServiceAwareTrait\b#', $content)) {
24
            return true;
25
        }
26
27
        $className = $this->getClassName($path, $content);
28
        if (!$className) {
29
            return false;
30
        }
31
32
        try {
33
            $object = new $className();
34
            if (method_exists($object, 'loadService')) {
35
                return true;
36
            }
37
        } catch (\Throwable $exception) {
38
            // Do nothing
39
        }
40
41
        return false;
42
    }
43
44
    /**
45
     * @param string $path Path
46
     * @return bool
47
     */
48 1
    public function annotate(string $path): bool
49
    {
50 1
        $services = $this->_getUsedServices($this->content);
51
52 1
        $annotations = $this->_getServiceAnnotations($services);
53
54 1
        return $this->annotateContent($path, $this->content, $annotations);
55
    }
56
57
    /**
58
     * @param string $content Content
59
     * @return array
60
     */
61 1
    protected function _getUsedServices(string $content): array
62
    {
63 1
        preg_match_all('/\$this-\>loadService\(\'([a-z.\\/]+)\'/i', $content, $matches);
64 1
        if (empty($matches[1])) {
65
            return [];
66
        }
67
68 1
        $services = $matches[1];
69
70 1
        return array_unique($services);
71
    }
72
73
    /**
74
     * @param array $usedServices Used services
75
     * @return \IdeHelper\Annotation\AbstractAnnotation[]
76
     */
77 1
    protected function _getServiceAnnotations(array $usedServices): array
78
    {
79 1
        $annotations = [];
80
81 1
        foreach ($usedServices as $usedService) {
82 1
            $className = App::className($usedService, 'Service', 'Service');
83 1
            if (!$className) {
84
                continue;
85
            }
86 1
            [, $name] = pluginSplit($usedService);
87
88 1
            if (strpos($name, '/') !== false) {
89 1
                $name = substr($name, strrpos($name, '/') + 1);
90
            }
91
92 1
            $annotations[] = AnnotationFactory::createOrFail('@property', '\\' . $className, '$' . $name);
93
        }
94
95 1
        return $annotations;
96
    }
97
98
    /**
99
     * @param string $path Path to PHP class file
100
     * @param string $content Content of PHP class file
101
     * @return string|null
102
     */
103
    protected function getClassName(string $path, string $content): ?string
104
    {
105
        preg_match('#^namespace (.+)\b#m', $content, $matches);
106
        if (!$matches) {
107
            return null;
108
        }
109
110
        $className = pathinfo($path, PATHINFO_FILENAME);
111
112
        return $matches[1] . '\\' . $className;
113
    }
114
}
115