CompileAttributesProcessor   A
last analyzed

Complexity

Total Complexity 10

Size/Duplication

Total Lines 107
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 24
dl 0
loc 107
ccs 29
cts 29
cp 1
rs 10
c 1
b 0
f 0
wmc 10

5 Methods

Rating   Name   Duplication   Size   Complexity  
A configureBuilder() 0 13 2
A __construct() 0 17 1
A generateProcessor() 0 16 2
A generate() 0 7 1
A loadProcessor() 0 12 4
1
<?php
2
3
namespace Bdf\Form\Attribute\Processor;
4
5
use Bdf\Form\Aggregate\FormBuilder;
6
use Bdf\Form\Aggregate\FormBuilderInterface;
7
use Bdf\Form\Attribute\AttributeForm;
8
use LogicException;
9
10
/**
11
 * Processor for compile attributes to native PHP code for build the form
12
 *
13
 * - Resolve the class name of the generated processor
14
 * - If the class do not exist, resolve its file name
15
 * - If the file do not exist, generate the processor class
16
 * - Include the processor class file
17
 * - Instantiate the generated processor
18
 * - Delegate the form configuration to the generated processor
19
 */
20
final class CompileAttributesProcessor implements AttributesProcessorInterface
21
{
22 5
    public function __construct(
23
        /**
24
         * Resolve the class name of the generated processor class
25
         * Takes as parameter the form instance, and should return the generated class name
26
         *
27
         * The class name must be contained into a namespace
28
         *
29
         * @var callable(AttributeForm):non-empty-string
30
         */
31
        private $classNameResolver,
32
        /**
33
         * Resolve the file name from the generated processor class name
34
         *
35
         * @var callable(class-string<AttributesProcessorInterface>):non-empty-string
36
         */
37
        private $fileNameResolver,
38
    ) {
39 5
    }
40
41
    /**
42
     * {@inheritdoc}
43
     */
44 49
    public function configureBuilder(AttributeForm $form, FormBuilderInterface $builder): PostConfigureInterface
45
    {
46
        /** @var class-string<AttributesProcessorInterface&PostConfigureInterface> $className */
47 49
        $className = ($this->classNameResolver)($form);
48
49 49
        if (!class_exists($className)) {
50 49
            $this->loadProcessor($className, $form, $builder);
51
        }
52
53 47
        $generated = new $className();
54 47
        $generated->configureBuilder($form, $builder);
55
56 47
        return $generated;
57
    }
58
59
    /**
60
     * Generate the configurator for the given form
61
     * Unlike `configureBuilder()` process, the class will be regenerated if already exists,
62
     * and the class will not be included
63
     *
64
     * @param AttributeForm $form Form to generate
65
     *
66
     * @return void
67
     */
68 1
    public function generate(AttributeForm $form): void
69
    {
70
        /** @var class-string<AttributesProcessorInterface&PostConfigureInterface> $className */
71 1
        $className = ($this->classNameResolver)($form);
72 1
        $fileName = ($this->fileNameResolver)($className);
73
74 1
        $this->generateProcessor($fileName, $className, $form, new FormBuilder());
75
    }
76
77
    /**
78
     * Try to load the processor from its file
79
     *
80
     * @param class-string<AttributesProcessorInterface&PostConfigureInterface> $className Generated processor class name
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string<AttributesP...PostConfigureInterface> at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string<AttributesProcessorInterface&PostConfigureInterface>.
Loading history...
81
     * @param AttributeForm $form Form to build
82
     * @param FormBuilderInterface $builder Builder to configure
83
     *
84
     * @return void
85
     */
86 49
    private function loadProcessor(string $className, AttributeForm $form, FormBuilderInterface $builder): void
87
    {
88 49
        $fileName = ($this->fileNameResolver)($className);
89
90 49
        if (!file_exists($fileName)) {
91 46
            $this->generateProcessor($fileName, $className, $form, $builder);
92
        }
93
94 49
        require_once $fileName;
95
96 49
        if (!class_exists($className) || !is_subclass_of($className, AttributesProcessorInterface::class)) {
97 2
            throw new LogicException('Invalid generated class "' . $className . '" in file "' . $fileName . '"');
98
        }
99
    }
100
101
    /**
102
     * Generate the processor class and save it into the given file
103
     *
104
     * @param string $fileName Target file
105
     * @param class-string<AttributesProcessorInterface&PostConfigureInterface> $className Generated processor class name
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string<AttributesP...PostConfigureInterface> at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string<AttributesProcessorInterface&PostConfigureInterface>.
Loading history...
106
     * @param AttributeForm $form Form to build
107
     * @param FormBuilderInterface $builder Builder to configure
108
     *
109
     * @return void
110
     */
111 47
    private function generateProcessor(string $fileName, string $className, AttributeForm $form, FormBuilderInterface $builder): void
112
    {
113 47
        $generator = new GenerateConfiguratorStrategy($className);
114 47
        $processor = new ReflectionProcessor($generator);
115
116 47
        $processor->configureBuilder($form, $builder);
117
118 47
        $code = $generator->code();
119
120 47
        $dirname = dirname($fileName);
121
122 47
        if (!is_dir($dirname)) {
123 1
            mkdir($dirname, 0777, true);
124
        }
125
126 47
        file_put_contents($fileName, '<?php' . PHP_EOL . $code);
127
    }
128
}
129