CodeGen::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 3
c 1
b 0
f 0
dl 0
loc 8
ccs 0
cts 0
cp 0
rs 10
cc 1
nc 1
nop 3
crap 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Ray\Aop;
6
7
use PhpParser\BuilderFactory;
8
use ReflectionClass;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, Ray\Aop\ReflectionClass. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
9
10
use function array_merge;
11
use function implode;
12
13
final class CodeGen implements CodeGenInterface
14
{
15
    /** @var BuilderFactory */
16
    private $factory;
17
18
    /** @var VisitorFactory */
19
    private $visitoryFactory;
20
21
    /** @var AopClass  */
22
    private $aopClass;
23
24
    public function __construct(
25
        BuilderFactory $factory,
26
        VisitorFactory $visitorFactory,
27
        AopClass $aopClass
28
    ) {
29
        $this->factory = $factory;
30
        $this->visitoryFactory = $visitorFactory;
31
        $this->aopClass = $aopClass;
32
    }
33
34
    /**
35
     * {@inheritdoc}
36
     *
37
     * @param ReflectionClass<object> $sourceClass
38
     */
39
    public function generate(ReflectionClass $sourceClass, BindInterface $bind): Code
40
    {
41
        $visitor = ($this->visitoryFactory)($sourceClass);
42
        $classStm = ($this->aopClass)($visitor, $sourceClass, $bind);
43
        $ns = $this->getNamespace($visitor);
44
        $stmt = $this->factory->namespace($ns)
45
            ->addStmt($this->factory->use(WeavedInterface::class))
46
            ->addStmt($this->factory->use(ReflectiveMethodInvocation::class)->as('Invocation'))
47
            ->addStmts($visitor->use)
48
            ->addStmt($classStm)
49
            ->getNode();
50
51
        return new Code(array_merge($visitor->declare, [$stmt]));
52
    }
53
54 33
    /**
55
     * @return string|null
56
     */
57
    private function getNamespace(CodeVisitor $source)
58
    {
59 33
        $parts = $source->namespace->name->parts ?? [];
60 33
        $ns = implode('\\', $parts);
61 33
62 33
        return $ns ? $ns : null;
63 33
    }
64
}
65