Completed
Push — develop ( 15ec3c...8b62a8 )
by Baptiste
02:19
created

Compile::__invoke()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 21
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 2.0023

Importance

Changes 0
Metric Value
cc 2
eloc 11
nc 2
nop 3
dl 0
loc 21
ccs 11
cts 12
cp 0.9167
crap 2.0023
rs 9.3142
c 0
b 0
f 0
1
<?php
2
declare(strict_types = 1);
3
4
namespace Innmind\Compose;
5
6
use Innmind\Compose\{
7
    Services,
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, Innmind\Compose\Services. 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...
8
    Loader
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, Innmind\Compose\Loader. 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 Innmind\Url\PathInterface;
11
use Innmind\Immutable\{
12
    MapInterface,
13
    Set,
14
    Str
15
};
16
use Symfony\Component\Config\{
17
    ConfigCache,
18
    Resource\FileResource
19
};
20
use Psr\Container\ContainerInterface;
21
22
final class Compile
23
{
24
    private $cache;
25
26 1
    public function __construct(PathInterface $cache)
27
    {
28 1
        $this->cache = Str::of((string) $cache)->rightTrim('/');
29 1
    }
30
31
    /**
32
     * @param MapInterface<string, mixed> $arguments
33
     */
34 1
    public function __invoke(
35
        Loader $load,
36
        PathInterface $path,
37
        MapInterface $arguments
38
    ): ContainerInterface {
39 1
        $cachePath = sprintf(
40 1
            '%s/%s.php',
41 1
            $this->cache,
42 1
            md5((string) $path)
43
        );
44 1
        $cache = new ConfigCache($cachePath, false);
45
46 1
        if ($cache->isFresh()) {
47
            return require $cachePath;
48
        }
49
50 1
        $services = $load($path);
51 1
        $code = $this->generateCode($services);
52 1
        $cache->write($code, [new FileResource((string) $path)]);
53
54 1
        return require $cachePath;
55
    }
56
57 1
    private function generateCode(Services $services): string
58
    {
59 1
        $compiled = $services->compile();
60
61
        return <<<PHP
62
<?php
63
declare(strict_types = 1);
64
65
use Innmind\Compose\Exception\NotFound;
66
use Innmind\Immutable\MapInterface;
67
use Psr\Container\ContainerInterface;
68
69
return new class(\$arguments) implements ContainerInterface {
70
    private \$container;
71
72
    public function __construct(MapInterface \$arguments)
73
    {
74
        //wrapping is used to avoid access to public method of the real
75
        //compiled container, methods to build services are public so we
76
        //can access tunnelled arguments between dependencies
77 1
        \$this->container = $compiled
78
    }
79
80
    public function get(\$id): object
81
    {
82
        return \$this->container->get(\$id);
83
    }
84
85
    public function has(\$id): bool
86
    {
87
        return \$this->container->has(\$id);
88
    }
89
};
90
91
PHP;
92
    }
93
}
94