Completed
Push — master ( 7fbbb0...53f538 )
by Oleg
03:37
created

ConfigGenerator   A

Complexity

Total Complexity 20

Size/Duplication

Total Lines 112
Duplicated Lines 0 %

Test Coverage

Coverage 97.96%

Importance

Changes 0
Metric Value
eloc 45
dl 0
loc 112
rs 10
c 0
b 0
f 0
ccs 48
cts 49
cp 0.9796
wmc 20

8 Methods

Rating   Name   Duplication   Size   Complexity  
A getCurrentConfig() 0 13 3
A addUses() 0 8 3
A generate() 0 20 2
A getClassName() 0 3 1
A __construct() 0 8 1
A getConfigNamespace() 0 3 1
A getFileName() 0 3 1
B checkRecord() 0 14 8
1
<?php
2
declare(strict_types=1);
3
4
namespace SlayerBirden\DFCodeGeneration\Generator\Config;
5
6
use Nette\PhpGenerator\ClassType;
7
use Nette\PhpGenerator\PhpFile;
8
use Nette\PhpGenerator\PhpLiteral;
9
use Nette\PhpGenerator\PhpNamespace;
10
use Nette\PhpGenerator\PsrPrinter;
11
use SlayerBirden\DFCodeGeneration\Code\Printer\NsArrayPrinter;
12
use SlayerBirden\DFCodeGeneration\Generator\Config\Code\CodeFeederInterface;
13
use SlayerBirden\DFCodeGeneration\Generator\DataProvider\DataProviderInterface;
14
use SlayerBirden\DFCodeGeneration\Generator\GeneratorInterface;
15
use SlayerBirden\DFCodeGeneration\Util\ArrayUtils;
16
17
final class ConfigGenerator implements GeneratorInterface
18
{
19
    /**
20
     * @var DataProviderInterface
21
     */
22
    private $dataProvider;
23
    /**
24
     * @var ConfigPartInterface[]
25
     */
26
    private $parts;
27
    /**
28
     * @var array
29
     */
30
    private $currentConfig;
31
    /**
32
     * @var CodeFeederInterface
33
     */
34
    private $codeFeeder;
35
36 6
    public function __construct(
37
        DataProviderInterface $dataProvider,
38
        CodeFeederInterface $codeFeeder,
39
        ConfigPartInterface ...$parts
40
    ) {
41 6
        $this->dataProvider = $dataProvider;
42 6
        $this->parts = $parts;
43 6
        $this->codeFeeder = $codeFeeder;
44 6
    }
45
46 6
    public function generate(): string
47
    {
48 6
        $invoke = [];
49
50 6
        $file = new PhpFile();
51 6
        $file->setStrictTypes();
52 6
        $file->addComment('This file is generated by SlayerBirden\DFCodeGeneration');
53 6
        $namespace = $file->addNamespace($this->getConfigNamespace());
54 6
        $class = $namespace->addClass('ConfigProvider');
55 6
        $class->setFinal();
56
57 6
        foreach ($this->parts as $configPart) {
58 6
            $invoke[$configPart->getCode()] = $configPart->getConfig();
59
        }
60
61 6
        $invoke = ArrayUtils::merge($this->getCurrentConfig(), $invoke);
62 6
        $this->addUses($invoke, $namespace);
63 6
        $this->codeFeeder->feed($invoke, $class, $namespace);
64
65 6
        return (new PsrPrinter())->printFile($file);
66
    }
67
68 6
    public function getClassName(): string
69
    {
70 6
        return $this->getConfigNamespace() . '\\ConfigProvider';
71
    }
72
73 6
    private function getConfigNamespace(): string
74
    {
75 6
        return $this->dataProvider->provide()['config_namespace'];
76
    }
77
78 6
    private function getCurrentConfig(): array
79
    {
80 6
        if ($this->currentConfig === null) {
81 6
            $config = $this->getClassName();
82
83 6
            if (class_exists($config)) {
84
                $this->currentConfig = (new $config())();
85
            } else {
86 6
                $this->currentConfig = [];
87
            }
88
        }
89
90 6
        return $this->currentConfig;
91
    }
92
93 6
    private function addUses(array $config, PhpNamespace $phpNamespace): void
94
    {
95 6
        foreach ($config as $key => $value) {
96 6
            $this->checkRecord($key, $phpNamespace);
97 6
            if (is_array($value)) {
98 6
                $this->addUses($value, $phpNamespace);
99
            } else {
100 6
                $this->checkRecord($value, $phpNamespace);
101
            }
102
        }
103 6
    }
104
105
    /**
106
     * @param mixed $record
107
     * @param PhpNamespace $phpNamespace
108
     */
109 6
    private function checkRecord($record, PhpNamespace $phpNamespace): void
110
    {
111
        // order is important - first check records with ::class
112
        // only after that records just with backslash
113 6
        if (is_string($record) && (strpos($record, '::class') !== false)) {
114 6
            $phpNamespace->addUse(str_replace('::class', '', $record));
115 6
        } elseif (is_string($record) && (strpos($record, '\\') !== false)) {
116 6
            if (strpos($record, ':\\') !== false) {
117
                // don't add use if this is not a class name
118 4
                return;
119
            }
120 6
            $phpNamespace->addUse($record);
121 6
        } elseif (($record instanceof PhpLiteral) && (strpos((string)$record, '::class') !== false)) {
122 6
            $phpNamespace->addUse(str_replace('::class', '', (string)$record));
123
        }
124 6
    }
125
126 6
    public function getFileName(): string
127
    {
128 6
        return sprintf('src/%s/ConfigProvider.php', $this->dataProvider->provide()['moduleName']);
129
    }
130
}
131