AutoRegisterCompilerPass::process()   A
last analyzed

Complexity

Conditions 5
Paths 5

Size

Total Lines 27
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 1
Metric Value
eloc 15
c 2
b 0
f 1
dl 0
loc 27
rs 9.4555
cc 5
nc 5
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace KunicMarko\SonataAnnotationBundle\DependencyInjection\Compiler;
6
7
use Doctrine\Common\Annotations\Reader;
8
use KunicMarko\SonataAnnotationBundle\Annotation\Admin;
9
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
10
use Symfony\Component\DependencyInjection\ContainerBuilder;
11
use Symfony\Component\DependencyInjection\Definition;
12
use Symfony\Component\Finder\Finder;
13
use Symfony\Component\Finder\SplFileInfo;
14
15
/**
16
 * @author Marko Kunic <[email protected]>
17
 */
18
final class AutoRegisterCompilerPass implements CompilerPassInterface
19
{
20
    private const DEFAULT_SERVICE_PREFIX = 'app.admin.';
21
22
    /**
23
     * @var Reader
24
     */
25
    private $annotationReader;
26
27
    public function process(ContainerBuilder $container): void
28
    {
29
        $this->annotationReader = $container->get('annotation_reader');
30
31
        foreach ($this->findFiles($container->getParameter('sonata_annotation.directory')) as $file) {
32
            if (!($className = $this->getFullyQualifiedClassName($file))) {
33
                continue;
34
            }
35
36
            if (!\class_exists($className)) {
37
                continue;
38
            }
39
40
            if (!($annotation = $this->getClassAnnotation($reflection = new \ReflectionClass($className)))) {
41
                continue;
42
            }
43
44
            $definition = new Definition(
45
                $annotation->admin,
46
                [$annotation->code, $className, $annotation->controller]
47
            );
48
49
            $definition->addTag('sonata.admin', $annotation->getTagOptions());
50
51
            $container->setDefinition(
52
                $serviceId = ($annotation->serviceId ?? $this->getServiceId($file)),
53
                $definition
54
            );
55
        }
56
    }
57
58
    private function findFiles(string $directory): \IteratorAggregate
59
    {
60
        return Finder::create()
61
            ->in($directory)
62
            ->files()
63
            ->name('*.php');
64
    }
65
66
    private function getFullyQualifiedClassName(SplFileInfo $file): ?string
67
    {
68
        if (!($namespace = $this->getNamespace($file->getPathname()))) {
69
            return null;
70
        }
71
72
        return $namespace . '\\' . $this->getClassName($file->getFilename());
73
    }
74
75
    private function getNamespace(string $filePath): ?string
76
    {
77
        $namespaceLine = preg_grep('/^namespace /', file($filePath));
0 ignored issues
show
Bug introduced by
It seems like file($filePath) can also be of type false; however, parameter $input of preg_grep() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

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

77
        $namespaceLine = preg_grep('/^namespace /', /** @scrutinizer ignore-type */ file($filePath));
Loading history...
78
79
        if (!$namespaceLine) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $namespaceLine of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
80
            return null;
81
        }
82
83
        preg_match('/namespace (.*);$/', trim(reset($namespaceLine)), $match);
84
85
        return array_pop($match);
86
    }
87
88
    private function getClassName(string $fileName): string
89
    {
90
        return str_replace('.php', '', $fileName);
91
    }
92
93
    private function getClassAnnotation(\ReflectionClass $class): ?Admin
94
    {
95
        return $this->annotationReader->getClassAnnotation(
96
            $class,
97
            Admin::class
98
        );
99
    }
100
101
    private function getServiceId(SplFileInfo $file): string
102
    {
103
        return self::DEFAULT_SERVICE_PREFIX . $this->getClassName($file->getFilename());
104
    }
105
}
106