Passed
Push — master ( 2c780f...8e874c )
by butschster
06:09 queued 21s
created

ScaffolderConfig::getDeclarations()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 2
c 0
b 0
f 0
dl 0
loc 4
ccs 3
cts 3
cp 1
rs 10
cc 1
nc 1
nop 0
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Spiral\Scaffolder\Config;
6
7
use Doctrine\Inflector\Rules\English\InflectorFactory;
8
use Spiral\Core\InjectableConfig;
9
use Spiral\Scaffolder\Exception\ScaffolderException;
10
11
/**
12
 * Configuration for default scaffolder namespaces and other rendering options.
13
 */
14
class ScaffolderConfig extends InjectableConfig
15
{
16
    public const CONFIG = 'scaffolder';
17
18
    protected array $config = [
19
        'header' => [],
20
        'directory' => '',
21
        'namespace' => '',
22
        'declarations' => [],
23
        'defaults' => [
24
            'declarations' => [],
25
        ],
26
    ];
27
28 34
    public function headerLines(): array
29
    {
30 34
        return $this->config['header'];
31
    }
32
33
    /**
34
     * @deprecated since v3.8.0.
35
     */
36
    public function baseDirectory(): string
37
    {
38
        return $this->config['directory'];
39
    }
40
41
    /**
42
     * @return non-empty-string[]
0 ignored issues
show
Documentation Bug introduced by
The doc comment non-empty-string[] at position 0 could not be parsed: Unknown type name 'non-empty-string' at position 0 in non-empty-string[].
Loading history...
43
     */
44 1
    public function getDeclarations(): array
45
    {
46 1
        return \array_keys($this->config['defaults']['declarations'] ?? []) + \array_keys(
47 1
            $this->config['declarations'],
48 1
        );
49
    }
50
51
    /**
52
     * @param non-empty-string $element
0 ignored issues
show
Documentation Bug introduced by
The doc comment non-empty-string at position 0 could not be parsed: Unknown type name 'non-empty-string' at position 0 in non-empty-string.
Loading history...
53
     */
54 49
    public function declarationDirectory(string $element): string
55
    {
56 49
        $declaration = $this->getDeclaration($element);
57
58 49
        return !empty($declaration['directory']) ? $declaration['directory'] : $this->config['directory'];
59
    }
60
61
    /**
62
     * @param non-empty-string $element
0 ignored issues
show
Documentation Bug introduced by
The doc comment non-empty-string at position 0 could not be parsed: Unknown type name 'non-empty-string' at position 0 in non-empty-string.
Loading history...
63
     */
64 39
    public function className(string $element, string $name): string
65
    {
66 39
        ['name' => $name] = $this->parseName($name);
67
68 39
        $class = $this->classify($name);
69 39
        $postfix = $this->elementPostfix($element);
70
71 39
        return \str_ends_with($class, $postfix) ? $class : $class . $postfix;
72
    }
73
74
    /**
75
     * @param non-empty-string $element
0 ignored issues
show
Documentation Bug introduced by
The doc comment non-empty-string at position 0 could not be parsed: Unknown type name 'non-empty-string' at position 0 in non-empty-string.
Loading history...
76
     */
77 27
    public function classNamespace(string $element, string $name = ''): string
78
    {
79 27
        $localNamespace = \trim($this->getOption($element, 'namespace', ''), '\\');
80 27
        ['namespace' => $namespace] = $this->parseName($name);
81
82 27
        if (!empty($namespace)) {
83 1
            $localNamespace .= '\\' . $this->classify($namespace);
84
        }
85
86 27
        if (empty($this->baseNamespace($element))) {
87
            return $localNamespace;
88
        }
89
90 27
        return \trim($this->baseNamespace($element) . '\\' . $localNamespace, '\\');
91
    }
92
93
    /**
94
     * @param non-empty-string $element
0 ignored issues
show
Documentation Bug introduced by
The doc comment non-empty-string at position 0 could not be parsed: Unknown type name 'non-empty-string' at position 0 in non-empty-string.
Loading history...
95
     * @param non-empty-string $name
96
     *
97
     * @return non-empty-string
0 ignored issues
show
Documentation Bug introduced by
The doc comment non-empty-string at position 0 could not be parsed: Unknown type name 'non-empty-string' at position 0 in non-empty-string.
Loading history...
98
     */
99 39
    public function classFilename(string $element, string $name, ?string $namespace = null): string
100
    {
101 39
        $elementNamespace = $namespace ?? $this->classNamespace($element, $name);
102 39
        $elementNamespace = \substr($elementNamespace, \strlen($this->baseNamespace($element)));
103
104 39
        return $this->joinPathChunks([
105 39
            $this->declarationDirectory($element),
106 39
            \str_replace('\\', '/', $elementNamespace),
107 39
            $this->className($element, $name) . '.php',
108 39
        ], '/');
109
    }
110
111
    /**
112
     * @param non-empty-string $element
0 ignored issues
show
Documentation Bug introduced by
The doc comment non-empty-string at position 0 could not be parsed: Unknown type name 'non-empty-string' at position 0 in non-empty-string.
Loading history...
113
     *
114
     * @throws ScaffolderException
115
     */
116
    public function declarationClass(string $element): string
117
    {
118
        $class = $this->getOption($element, 'class');
119
120
        if (empty($class)) {
121
            throw new ScaffolderException(
122
                \sprintf("Unable to scaffold '%s', no declaration class found", $element),
123
            );
124
        }
125
126
        return $class;
127
    }
128
129
    /**
130
     * Declaration options.
131
     *
132
     * @param non-empty-string $element
0 ignored issues
show
Documentation Bug introduced by
The doc comment non-empty-string at position 0 could not be parsed: Unknown type name 'non-empty-string' at position 0 in non-empty-string.
Loading history...
133
     */
134 37
    public function declarationOptions(string $element): array
135
    {
136 37
        return $this->getOption($element, 'options', []);
137
    }
138
139
    /**
140
     * Get declaration options by element name.
141
     *
142
     * @param non-empty-string $element
0 ignored issues
show
Documentation Bug introduced by
The doc comment non-empty-string at position 0 could not be parsed: Unknown type name 'non-empty-string' at position 0 in non-empty-string.
Loading history...
143
     */
144 57
    public function getDeclaration(string $element): array
145
    {
146 57
        $default = $this->config['defaults']['declarations'][$element] ?? [];
147 57
        $declaration = $this->config['declarations'][$element] ?? [];
148
149 57
        return $declaration + $default;
150
    }
151
152
    /**
153
     * @param non-empty-string $element
0 ignored issues
show
Documentation Bug introduced by
The doc comment non-empty-string at position 0 could not be parsed: Unknown type name 'non-empty-string' at position 0 in non-empty-string.
Loading history...
154
     */
155 39
    private function elementPostfix(string $element): string
156
    {
157 39
        return $this->getOption($element, 'postfix', '');
158
    }
159
160
    /**
161
     * @param non-empty-string $element
0 ignored issues
show
Documentation Bug introduced by
The doc comment non-empty-string at position 0 could not be parsed: Unknown type name 'non-empty-string' at position 0 in non-empty-string.
Loading history...
162
     * @param non-empty-string $section
163
     */
164 46
    private function getOption(string $element, string $section, mixed $default = null): mixed
165
    {
166 46
        $declaration = $this->getDeclaration($element);
167
168 46
        if ($declaration === []) {
169 1
            throw new ScaffolderException(\sprintf("Undefined declaration '%s'.", $element));
170
        }
171
172 45
        if (\array_key_exists($section, $declaration)) {
173 41
            return $declaration[$section];
174
        }
175
176 30
        return $default;
177
    }
178
179
    /**
180
     * Split user name into namespace and class name.
181
     *
182
     * @param non-empty-string $name
0 ignored issues
show
Documentation Bug introduced by
The doc comment non-empty-string at position 0 could not be parsed: Unknown type name 'non-empty-string' at position 0 in non-empty-string.
Loading history...
183
     *
184
     * @return array{namespace: string, name: non-empty-string}
0 ignored issues
show
Documentation Bug introduced by
The doc comment array{namespace: string, name: non-empty-string} at position 8 could not be parsed: Unknown type name 'non-empty-string' at position 8 in array{namespace: string, name: non-empty-string}.
Loading history...
185
     */
186 39
    private function parseName(string $name): array
187
    {
188 39
        $name = \str_replace('/', '\\', $name);
189
190 39
        if (str_contains($name, '\\')) {
191 1
            $names = \explode('\\', $name);
192 1
            $class = \array_pop($names);
193
194 1
            return ['namespace' => \implode('\\', $names), 'name' => $class];
195
        }
196
197
        //No user namespace
198 38
        return ['namespace' => '', 'name' => $name];
199
    }
200
201
    /**
202
     * @param non-empty-string $element
0 ignored issues
show
Documentation Bug introduced by
The doc comment non-empty-string at position 0 could not be parsed: Unknown type name 'non-empty-string' at position 0 in non-empty-string.
Loading history...
203
     */
204 41
    private function baseNamespace(string $element): string
205
    {
206 41
        $declaration = $this->getDeclaration($element);
207
208 41
        if (\array_key_exists('baseNamespace', $declaration)) {
209 1
            return \trim((string)$this->getOption($element, 'baseNamespace', ''), '\\');
210
        }
211
212 40
        return \trim($this->config['namespace'], '\\');
213
    }
214
215 39
    private function joinPathChunks(array $chunks, string $joint): string
216
    {
217 39
        $firstChunkIterated = false;
218 39
        $joinedPath = '';
219 39
        foreach ($chunks as $chunk) {
220 39
            if (!$firstChunkIterated) {
221 39
                $firstChunkIterated = true;
222 39
                $joinedPath = $chunk;
223
            } else {
224 39
                $joinedPath = \rtrim($joinedPath, $joint) . $joint . \ltrim($chunk, $joint);
225
            }
226
        }
227
228 39
        return $joinedPath;
229
    }
230
231 39
    private function classify(string $name): string
232
    {
233 39
        return (new InflectorFactory())
234 39
            ->build()
235 39
            ->classify($name);
236
    }
237
}
238