Completed
Pull Request — master (#68)
by Cristiano
05:36
created

CodeGeneratorConfig::configureOptions()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 31

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 22
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 31
ccs 22
cts 22
cp 1
rs 9.424
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 1
1
<?php declare(strict_types=1);
2
/*
3
 * This file is part of the php-code-generator package.
4
 * For the full copyright and license information, please view the LICENSE
5
 * file that was distributed with this source code.
6
 *
7
 * @license Apache-2.0
8
 */
9
10
namespace gossi\codegen\config;
11
12
use gossi\codegen\generator\CodeGenerator;
13
use gossi\docblock\Docblock;
14
use phootwork\lang\Comparator;
15
use Stringable;
16
use Symfony\Component\OptionsResolver\Options;
17
use Symfony\Component\OptionsResolver\OptionsResolver;
18
19
/**
20
 * Configuration for code generation
21
 *
22
 * @author Thomas Gossmann
23
 */
24
class CodeGeneratorConfig {
25
	protected array $options;
0 ignored issues
show
Bug introduced by
This code did not parse for me. Apparently, there is an error somewhere around this line:

Syntax error, unexpected T_ARRAY, expecting T_FUNCTION or T_CONST
Loading history...
26
27
	/**
28
	 * Creates a new configuration for code generator
29
	 *
30 49
	 * @see https://php-code-generator.readthedocs.org/en/latest/generator.html
31 49
	 *
32 49
	 * @param array $options
33 49
	 */
34 49
	public function __construct(array $options = []) {
35 49
		$resolver = new OptionsResolver();
36
		$this->configureOptions($resolver);
37 49
		$this->options = $resolver->resolve($options);
38 49
	}
39 49
40
	protected function configureOptions(OptionsResolver $resolver): void {
41
		$resolver->setDefaults([
42 47
			'generateDocblock' => true,
43 49
			'generateEmptyDocblock' => fn (Options $options) => $options['generateDocblock'],
44
			'generateTypeHints' => fn (Options $options) => $options['declareStrictTypes'],
45
			'generateReturnTypeHints' => fn (Options $options) => $options['declareStrictTypes'],
46
			'generatePropertyTypes' => fn (Options $options) => $options['declareStrictTypes'],
47
			'minPhpVersion' => '8.0',
48
			'enableSorting' => true,
49 49
			'useStatementSorting' => CodeGenerator::SORT_USESTATEMENTS_DEFAULT,
50 49
			'constantSorting' => CodeGenerator::SORT_CONSTANTS_DEFAULT,
51 49
			'propertySorting' => CodeGenerator::SORT_PROPERTIES_DEFAULT,
52 49
			'methodSorting' => CodeGenerator::SORT_METHODS_DEFAULT,
53
			'headerComment' => '',
54
			'headerDocblock' => '',
55 49
			'declareStrictTypes' => true,
56 49
			'codeStyle' => 'default',
57 49
			'templatesDirs' => []
58 49
		]);
59 49
60 49
		$resolver->setAllowedTypes('generateDocblock', 'bool');
61 49
		$resolver->setAllowedTypes('generateEmptyDocblock', 'bool');
62 49
		$resolver->setAllowedTypes('generateTypeHints', 'bool');
63 49
		$resolver->setAllowedTypes('generateReturnTypeHints', 'bool');
64 49
		$resolver->setAllowedTypes('generatePropertyTypes', 'bool');
65 49
		$resolver->setAllowedTypes('minPhpVersion', 'string');
66 49
		$resolver->setAllowedTypes('enableSorting', 'bool');
67 49
		$resolver->setAllowedTypes('useStatementSorting', ['bool', 'string', '\Closure', Comparator::class]);
68
		$resolver->setAllowedTypes('constantSorting', ['bool', 'string', '\Closure', Comparator::class]);
69
		$resolver->setAllowedTypes('propertySorting', ['bool', 'string', '\Closure', Comparator::class]);
70
		$resolver->setAllowedTypes('methodSorting', ['bool', 'string', '\Closure', Comparator::class]);
71
		$resolver->setAllowedTypes('headerComment', ['string', Docblock::class]);
72
		$resolver->setAllowedTypes('headerDocblock', ['string', Docblock::class]);
73
		$resolver->setAllowedTypes('declareStrictTypes', 'bool');
74 45
		$resolver->setAllowedTypes('codeStyle', 'string');
75 45
		$resolver->setAllowedTypes('templatesDirs', 'string[]');
76
77
		/** All templates directories must exists */
78
		$resolver->setAllowedValues('templatesDirs',
79
			fn (array $dirs): bool => count(array_filter($dirs, 'is_dir')) === count($dirs)
80
		);
81
		$resolver->setAllowedValues('codeStyle',
82
			fn (string $value): bool => in_array(strtolower($value), ['default', 'phootwork', 'psr-12'])
83
		);
84 1
		$resolver->setAllowedValues('minPhpVersion', fn (string $value): bool => in_array($value, ['7.4', '8.0']));
85 1
86 1
		$resolver->setNormalizer('headerComment',
87
			fn (Options $options, Docblock|string $value): Docblock => is_string($value) ? new Docblock(str_replace('/*', '/**', $value)) : $value
88 1
		);
89 1
		$resolver->setNormalizer('headerDocblock',
90
			fn (Options $options, Docblock|string $value): Docblock => is_string($value) ? new Docblock($value) : $value
91
		);
92
93
		$resolver->setNormalizer('codeStyle', function (Options $options, string $value): string {
94
			$value = strtolower($value);
95
96
			return $value === 'phootwork' ? 'default' : $value;
97 38
		}
98 38
		);
99
100
		$resolver->setNormalizer('templatesDirs', function (Options $options, array $value): array {
101
			$value[] = realpath(__DIR__ . '/../../resources/templates/' . $options['codeStyle']);
102
103
			return $value;
104
		}
105
		);
106
	}
107 1
108 1
	/**
109 1
	 * Returns whether docblocks should be generated
110 1
	 *
111
	 * @return bool `true` if they will be generated and `false` if not
112 1
	 */
113
	public function getGenerateDocblock(): bool {
114
		return $this->options['generateDocblock'];
115
	}
116
117
	/**
118
	 * Sets whether docblocks should be generated
119
	 *
120 38
	 * @param bool $generate `true` if they will be generated and `false` if not
121 38
	 *
122
	 * @return $this
123
	 */
124
	public function setGenerateDocblock(bool $generate): self {
125
		$this->options['generateDocblock'] = $generate;
126
		if (!$generate) {
127
			$this->options['generateEmptyDocblock'] = $generate;
128
		}
129
130 1
		return $this;
131 1
	}
132 1
133 1
	/**
134
	 * Returns whether empty docblocks are generated
135 1
	 *
136
	 * @return bool `true` if they will be generated and `false` if not
137
	 */
138
	public function getGenerateEmptyDocblock(): bool {
139
		return $this->options['generateEmptyDocblock'];
140
	}
141
142
	/**
143 15
	 * Sets whether empty docblocks are generated
144 15
	 *
145
	 * @param bool $generate `true` if they will be generated and `false` if not
146
	 *
147
	 * @return $this
148
	 */
149
	public function setGenerateEmptyDocblock(bool $generate): self {
150
		$this->options['generateEmptyDocblock'] = $generate;
151
		if ($generate) {
152 18
			$this->options['generateDocblock'] = $generate;
153 18
		}
154
155
		return $this;
156
	}
157
158
	/**
159
	 * Returns whether type hints will be generated for method parameters
160
	 *
161 43
	 * @return bool `true` if they will be generated and `false` if not
162 43
	 */
163
	public function getGenerateTypeHints(): bool {
164
		return $this->options['generateTypeHints'];
165
	}
166
167
	/**
168
	 * Returns whether sorting is enabled
169
	 *
170 18
	 * @return bool `true` if it is enabled and `false` if not
171 18
	 */
172
	public function isSortingEnabled(): bool {
173
		return $this->options['enableSorting'];
174
	}
175
176
	/**
177
	 * Returns whether formatting is enalbed
178
	 *
179 17
	 * @return bool `true` if it is enabled and `false` if not
180 17
	 */
181
	public function isFormattingEnabled(): bool {
182
		return $this->options['enableFormatting'];
183
	}
184
185
	/**
186
	 * Sets whether sorting is enabled
187
	 *
188 16
	 * @param $enabled bool `true` if it is enabled and `false` if not
189 16
	 *
190
	 * @return $this
191
	 */
192
	public function setSortingEnabled(bool $enabled): self {
193
		$this->options['enableSorting'] = $enabled;
194
195
		return $this;
196
	}
197 18
198 18
	/**
199
	 * Sets whether formatting is enabled
200
	 *
201
	 * @param $enabled bool `true` if it is enabled and `false` if not
202
	 *
203
	 * @return $this
204
	 */
205
	public function setFormattingEnabled(bool $enabled): self {
206
		$this->options['enableFormatting'] = $enabled;
207 1
208 1
		return $this;
209 1
	}
210
211
	/**
212
	 * Returns the use statement sorting
213
	 *
214
	 * @return string|bool|Comparator|\Closure
215
	 */
216
	public function getUseStatementSorting(): string|bool|Comparator|\Closure {
217 20
		return $this->options['useStatementSorting'];
218 20
	}
219
220
	/**
221
	 * Returns the constant sorting
222
	 *
223
	 * @return string|bool|Comparator|\Closure
224
	 */
225
	public function getConstantSorting(): string|bool|Comparator|\Closure {
226
		return $this->options['constantSorting'];
227 1
	}
228 1
229 1
	/**
230
	 * Returns the property sorting
231
	 *
232
	 * @return string|bool|Comparator|\Closure
233
	 */
234
	public function getPropertySorting(): string|bool|Comparator|\Closure {
235
		return $this->options['propertySorting'];
236
	}
237 23
238 23
	/**
239
	 * Returns the method sorting
240
	 *
241
	 * @return string|bool|Comparator|\Closure
242
	 */
243
	public function getMethodSorting(): string|bool|Comparator|\Closure {
244
		return $this->options['methodSorting'];
245
	}
246
247 1
	/**
248 1
	 * Sets whether scalar type hints will be generated for method parameters
249 1
	 *
250
	 * @param bool $generate `true` if they will be generated and `false` if not
251
	 *
252
	 * @return $this
253
	 */
254
	public function setGenerateTypeHints(bool $generate): self {
255
		$this->options['generateTypeHints'] = $generate;
256
257
		return $this;
258 1
	}
259 1
260 1
	/**
261
	 * Returns whether return type hints will be generated for method parameters
262
	 *
263
	 * @return bool `true` if they will be generated and `false` if not
264
	 */
265
	public function getGenerateReturnTypeHints(): bool {
266
		return $this->options['generateReturnTypeHints'];
267
	}
268
269 1
	/**
270 1
	 * Sets whether return type hints will be generated for method parameters
271 1
	 *
272
	 * @param bool $generate `true` if they will be generated and `false` if not
273
	 *
274
	 * @return $this
275
	 */
276
	public function setGenerateReturnTypeHints(bool $generate): self {
277
		$this->options['generateReturnTypeHints'] = $generate;
278
279
		return $this;
280 1
	}
281 1
282 1
	/**
283
	 * Returns the use statement sorting
284
	 *
285
	 * @param $sorting string|bool|Comparator|\Closure
286
	 *
287
	 * @return $this
288
	 */
289
	public function setUseStatementSorting(string|bool|Comparator|\Closure $sorting): self {
290
		$this->options['useStatementSorting'] = $sorting;
291 1
292 1
		return $this;
293 1
	}
294
295
	/**
296
	 * Returns the constant sorting
297
	 *
298
	 * @param $sorting string|bool|Comparator|\Closure
299
	 *
300
	 * @return $this
301
	 */
302 1
	public function setConstantSorting(string|bool|Comparator|\Closure $sorting): self {
303 1
		$this->options['constantSorting'] = $sorting;
304 1
305
		return $this;
306
	}
307
308
	/**
309
	 * Returns the property sorting
310
	 *
311
	 * @param $sorting string|bool|Comparator|\Closure
312
	 *
313 1
	 * @return $this
314 1
	 */
315 1
	public function setPropertySorting(string|bool|Comparator|\Closure $sorting): self {
316
		$this->options['propertySorting'] = $sorting;
317
318
		return $this;
319
	}
320
321
	/**
322
	 * Returns the method sorting
323
	 *
324
	 * @param $sorting string|bool|Comparator|\Closure
325
	 *
326
	 * @return $this
327
	 */
328
	public function setMethodSorting(string|bool|Comparator|\Closure $sorting): self {
329
		$this->options['methodSorting'] = $sorting;
330
331
		return $this;
332
	}
333
334
	/**
335
	 * Returns the file header comment
336
	 *
337
	 * @return Docblock|null the header comment
338
	 */
339
	public function getHeaderComment(): ?Docblock {
340
		return $this->options['headerComment'];
341
	}
342
343
	/**
344
	 * Sets the file header comment
345
	 *
346
	 * @param string|Stringable|Docblock $comment the header comment
347
	 *
348
	 * @return $this
349
	 */
350
	public function setHeaderComment(string|Stringable|Docblock $comment): self {
351
		$this->options['headerComment'] = $comment instanceof Docblock ? $comment :
352
			new Docblock((string) $comment);
353
354
		return $this;
355
	}
356
357
	/**
358
	 * Returns the file header docblock
359
	 *
360
	 * @return Docblock|null the docblock
361
	 */
362
	public function getHeaderDocblock(): ?Docblock {
363
		return $this->options['headerDocblock'];
364
	}
365
366
	/**
367
	 * Sets the file header docblock
368
	 *
369
	 * @param string|Stringable|Docblock $docblock the docblock
370
	 *
371
	 * @return $this
372
	 */
373
	public function setHeaderDocblock(string|Stringable|Docblock $docblock): self {
374
		$this->options['headerDocblock'] = $docblock instanceof Docblock ? $docblock :
375
			new Docblock((string) $docblock);
376
377
		return $this;
378
	}
379
380
	/**
381
	 * Returns whether a `declare(strict_types=1);` statement should be printed
382
	 * as the very first instruction
383
	 *
384
	 * @return bool `true` if it will be printed and `false` if not
385
	 */
386
	public function getDeclareStrictTypes(): bool {
387
		return $this->options['declareStrictTypes'];
388
	}
389
390
	/**
391
	 * Sets whether a `declare(strict_types=1);` statement should be printed
392
	 * below the header comments
393
	 *
394
	 * @param bool $strict `true` if it will be printed and `false` if not
395
	 *
396
	 * @return $this
397
	 */
398
	public function setDeclareStrictTypes(bool $strict): self {
399
		$this->options['declareStrictTypes'] = $strict;
400
401
		$this->options['generateReturnTypeHints'] = $strict;
402
		$this->options['generateTypeHints'] = $strict;
403
		$this->options['generatePropertyTypes'] = $strict;
404
405
		return $this;
406
	}
407
408
	public function getCodeStyle(): string {
409
		return $this->options['codeStyle'];
410
	}
411
412
	public function setCodeStyle(string $style): self {
413
		$style = strtolower($style);
414
		if (in_array($style, ['default', 'phootwork', 'psr-12'])) {
415
			$this->options['codeStyle'] = $style;
416
		}
417
418
		return $this;
419
	}
420
421
	/**
422
	 * @return string[]
423
	 */
424
	public function getTemplatesDirs(): array {
425
		return $this->options['templatesDirs'];
426
	}
427
428
	/**
429
	 * Prepend one or more directories, where templates reside.
430
	 * The order of the directories is mandatory to correctly find overridden templates.
431
	 *
432
	 * @param string ...$dirs
433
	 *
434
	 * @return $this
435
	 */
436
	public function addTemplatesDirs(string ...$dirs): self {
437
		$dirs = array_reverse($dirs);
438
		foreach ($dirs as $dir) {
439
			if (is_dir($dir)) {
440
				array_unshift($this->options['templatesDirs'], $dir);
441
			}
442
		}
443
444
		return $this;
445
	}
446
447
	public function getGeneratePropertyTypes(): bool {
448
		return $this->options['generatePropertyTypes'];
449
	}
450
451
	public function setGeneratePropertyTypes(bool $types): self {
452
		$this->options['generatePropertyTypes'] = $types;
453
454
		return $this;
455
	}
456
457
	public function getMinPhpVersion(): string {
458
		return $this->options['minPhpVersion'];
459
	}
460
461
	public function setMinPhpVersion(string $version): self {
462
		if (in_array($version, ['7.4', '8.0'])) {
463
			$this->options['minPhpVersion'] = $version;
464
		}
465
466
		return $this;
467
	}
468
}
469