Completed
Push — master ( aedaa6...d154ad )
by Valentin
06:14
created

FileMaterializer::materialize()   B

Complexity

Conditions 6
Paths 8

Size

Total Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 24
rs 8.9137
c 0
b 0
f 0
cc 6
nc 8
nop 2
1
<?php
2
declare(strict_types=1);
3
4
namespace Cycle\ORM\Promise\Materizalizer;
5
6
use Cycle\ORM\Promise\Declaration\Declaration;
7
use Cycle\ORM\Promise\MaterializerInterface;
8
use Cycle\ORM\Promise\Materizalizer\ClassLocator\Locator;
9
use Cycle\ORM\Promise\Materizalizer\ClassLocator\LocatorFactory;
10
use Cycle\ORM\Promise\PromiseInterface;
11
12
class FileMaterializer implements MaterializerInterface
13
{
14
    /** @var Locator */
15
    private $locator;
16
17
    /** @var string */
18
    private $directory;
19
20
    public function __construct(LocatorFactory $factory, string $directory)
21
    {
22
        $this->locator = $factory->create($directory);
23
        $this->directory = $directory;
24
    }
25
26
    /**
27
     * {@inheritdoc}
28
     */
29
    public function materialize(string $code, Declaration $declaration): void
30
    {
31
        if (class_exists($declaration->class->getNamespacesName())) {
32
            return;
33
        }
34
35
        $targets = $this->locator->getClasses($declaration->parent->getNamespacesName(), PromiseInterface::class);
36
        if (count($targets) === 0) {
37
            $this->create($code, $declaration);
38
        } else {
39
            $alreadyExists = false;
40
            foreach ($targets as $target) {
41
                if (!$this->isContentIdentical($target, $code, $declaration)) {
42
                    unlink($target->getFileName());
43
                } else {
44
                    $alreadyExists = true;
45
                }
46
            }
47
48
            if (!$alreadyExists) {
49
                $this->create($code, $declaration);
50
            }
51
        }
52
    }
53
54
    private function create(string $code, Declaration $declaration): void
55
    {
56
        file_put_contents($this->makeFilename($declaration), $code);
57
    }
58
59
    private function makeFilename(Declaration $declaration): string
60
    {
61
        return $this->directory . DIRECTORY_SEPARATOR . $this->convertName($declaration);
62
    }
63
64
    private function convertName(Declaration $declaration): string
65
    {
66
        return str_replace('\\', '', $declaration->class->getNamespacesName());
67
    }
68
69
    private function isContentIdentical(\ReflectionClass $target, string $code, Declaration $declaration): bool
70
    {
71
        return $this->prepareCode($code, $declaration) === $this->prepareCode(file_get_contents($target->getFileName()), $declaration);
72
    }
73
74
    private function prepareCode(string $code, Declaration $declaration): string
75
    {
76
        $regexp = sprintf('"/class\s(\S+)\sextends\s%s/', $declaration->parent->name);
77
78
        return preg_replace($regexp, '', $code);
79
    }
80
}