Completed
Branch master (3b8125)
by
unknown
01:25
created

generateAndFillInterfaceMethods()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 22

Duplication

Lines 13
Ratio 59.09 %

Importance

Changes 0
Metric Value
dl 13
loc 22
rs 9.568
c 0
b 0
f 0
cc 3
nc 3
nop 1
1
<?php
2
3
namespace HelloWordPl\SimpleEntityGeneratorBundle\Lib;
4
5
use Doctrine\Common\Collections\ArrayCollection;
6
use HelloWordPl\SimpleEntityGeneratorBundle\Lib\ClassConfig;
7
use HelloWordPl\SimpleEntityGeneratorBundle\Lib\Items\ClassConstructorManager;
8
use HelloWordPl\SimpleEntityGeneratorBundle\Lib\Items\ClassManager;
9
use HelloWordPl\SimpleEntityGeneratorBundle\Lib\Items\InitPropertyManager;
10
use HelloWordPl\SimpleEntityGeneratorBundle\Lib\Items\InterfaceManager;
11
use HelloWordPl\SimpleEntityGeneratorBundle\Lib\Items\MethodGetterBooleanInterfaceManager;
12
use HelloWordPl\SimpleEntityGeneratorBundle\Lib\Items\MethodGetterBooleanManager;
13
use HelloWordPl\SimpleEntityGeneratorBundle\Lib\Items\MethodGetterInterfaceManager;
14
use HelloWordPl\SimpleEntityGeneratorBundle\Lib\Items\MethodGetterManager;
15
use HelloWordPl\SimpleEntityGeneratorBundle\Lib\Items\MethodSetterInterfaceManager;
16
use HelloWordPl\SimpleEntityGeneratorBundle\Lib\Items\MethodSetterManager;
17
use HelloWordPl\SimpleEntityGeneratorBundle\Lib\Items\TestClassManager;
18
use HelloWordPl\SimpleEntityGeneratorBundle\Lib\Items\TestMethodManager;
19
use JMS\Serializer\SerializerBuilder;
20
use JMS\Serializer\SerializerInterface;
21
use Symfony\Component\Yaml\Parser;
22
23
/**
24
 * GeneratorEntity Manager
25
 *
26
 * @author Sławomir Kania <[email protected]>
27
 */
28
class StructureGenerator
29
{
30
31
    /**
32
     * Namespace for Serializer
33
     *
34
     * @var string
35
     */
36
    const CLASS_MANAGER_NAMESPACE = "HelloWordPl\SimpleEntityGeneratorBundle\Lib\Items\ClassManager";
37
38
    /**
39
     * @var SerializerInterface
40
     */
41
    private $serializer = null;
42
43
    /**
44
     * @var Parser
45
     */
46
    private $parser = null;
47
48
    /**
49
     * CONSTR
50
     *
51
     * @param Parser $parser
52
     */
53
    public function __construct(Parser $parser)
54
    {
55
        $this->parser = $parser;
56
        $this->serializer = SerializerBuilder::create()->build();
57
    }
58
59
    /**
60
     * Parse yaml string to array of JSONs
61
     *
62
     * @param string $fileContent
63
     * @return ArrayCollection
64
     */
65
    public function parseToArray($fileContent)
66
    {
67
        $parser = $this->getParser();
68
        $entitiesDataArray = $parser->parse($fileContent);
69
        $entitiesData = new ArrayCollection();
70
        foreach ($entitiesDataArray as $entityDataArray) {
0 ignored issues
show
Bug introduced by
The expression $entitiesDataArray of type null|object<Symfony\Comp...|array|object<stdClass> is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
71
            $entitiesData->add(json_encode($entityDataArray, true));
72
        }
73
74
        return $entitiesData;
75
    }
76
77
    /**
78
     * Build Entities Class Structures from array array('{"data":"data"}', '{"data":"data"}')
79
     *
80
     * @param ArrayCollection $entitiesData
81
     * @param ClassConfig $classConfig
82
     * @return ArrayCollection
83
     */
84
    public function buildEntitiesClassStructure(ArrayCollection $entitiesData, ClassConfig $classConfig = null)
85
    {
86
        $classConfig = $this->getDefaultClassConfigIfNeed($classConfig);
87
        $classesManagers = new ArrayCollection();
88
        foreach ($entitiesData->toArray() as $jsonData) {
89
            $classesManagers->add($this->deserializeJsonDataToClassManager($jsonData));
90
        }
91
92
        // building class environment
93
        foreach ($classesManagers->toArray() as $classManager) {
94
            $this->preapareClassManager($classManager, $classConfig); // reference
95
        }
96
97
        return $classesManagers;
98
    }
99
100
    /**
101
     * Generate class components
102
     *
103
     * @param ClassManager $classManager
104
     * @param ClassConfig $classConfig
105
     * @return ClassManager
106
     */
107
    public function preapareClassManager(ClassManager $classManager, ClassConfig $classConfig = null)
108
    {
109
        $inClassConfiguration = $classManager->getConfiguration();
110
        $defaultClassConfiguration = $this->getDefaultClassConfigIfNeed($classConfig);
111
        $constructor = new ClassConstructorManager($classManager);
112
        $this->generateAndFillClassMethods($classManager);
113
        $this->prepareAndFillInitProperties($constructor);
114
        $classManager->setConstructor($constructor);
115
116
        // inline config is more important
117
        $canAddInterface = true;
0 ignored issues
show
Unused Code introduced by
$canAddInterface is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
118
        $canPHPUnitClass = true;
0 ignored issues
show
Unused Code introduced by
$canPHPUnitClass is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
119
        if ($inClassConfiguration instanceof ClassConfig) {
120
            $canAddInterface = !$inClassConfiguration->isNoInterface();
121
            $canPHPUnitClass = !$inClassConfiguration->isNoPHPUnitClass();
122
        } else {
123
            $canAddInterface = !$defaultClassConfiguration->isNoInterface();
124
            $canPHPUnitClass = !$defaultClassConfiguration->isNoPHPUnitClass();
125
        }
126
127
        if ($canAddInterface) {
128
            $interface = new InterfaceManager($classManager);
129
            $this->generateAndFillInterfaceMethods($interface);
130
            $classManager->setInterface($interface);
131
        }
132
        if ($canPHPUnitClass) {
133
            $testClass = new TestClassManager($classManager);
134
            $this->generateAndFillTestClassMethods($testClass);
135
            $classManager->setTestClass($testClass);
136
        }
137
138
        return $classManager;
139
    }
140
141
    /**
142
     * Generate class components
143
     * - setters and getters for Class and Interface (optional)
144
     * - method with prefix is for boolean properties
145
     *
146
     * @param \HelloWordPl\SimpleEntityGeneratorBundle\Lib\ClassManager $classManager
147
     */
148
    protected function generateAndFillClassMethods(ClassManager $classManager)
149
    {
150
        $methodsForClass = new ArrayCollection();
151
152
        // fix - jms serializer does not call ClassManager constructor during deserialization
153
        if (false === ($classManager->getProperties() instanceof ArrayCollection)) {
154
            $classManager->setProperties(new ArrayCollection());
155
        }
156
157 View Code Duplication
        foreach ($classManager->getProperties() as $property) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
158
            if ($property->isTypeBoolean()) {
159
                $methodsForClass->add((new MethodGetterBooleanManager($classManager))->setProperty($property));
160
            }
161
162
            $methodSetterManager = new MethodSetterManager($classManager);
163
            $methodSetterManager->setProperty($property);
164
            $methodGetterManager = new MethodGetterManager($classManager);
165
            $methodGetterManager->setProperty($property);
166
167
            $methodsForClass->add($methodSetterManager);
168
            $methodsForClass->add($methodGetterManager);
169
        }
170
171
        $classManager->setMethods($methodsForClass);
172
173
        return $classManager;
174
    }
175
176
    /**
177
     * Generate methods for interface
178
     *
179
     * @param InterfaceManager $interface
180
     * @return ArrayCollection
181
     */
182
    protected function generateAndFillInterfaceMethods(InterfaceManager $interface)
183
    {
184
        $methodsForInterface = new ArrayCollection();
185
        $classManager = $interface->getClassManager();
186 View Code Duplication
        foreach ($classManager->getProperties() as $property) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
187
            if ($property->isTypeBoolean()) {
188
                $methodsForInterface->add((new MethodGetterBooleanInterfaceManager($classManager))->setProperty($property));
189
            }
190
191
            $methodSetterInterfaceManager = new MethodSetterInterfaceManager($classManager);
192
            $methodSetterInterfaceManager->setProperty($property);
193
            $methodGetterInterfaceManager = new MethodGetterInterfaceManager($classManager);
194
            $methodGetterInterfaceManager->setProperty($property);
195
196
            $methodsForInterface->add($methodSetterInterfaceManager);
197
            $methodsForInterface->add($methodGetterInterfaceManager);
198
        }
199
200
        $interface->setMethods($methodsForInterface);
201
202
        return $interface;
203
    }
204
205
    /**
206
     * Prepare list of init properties for constructor
207
     *
208
     * @param ClassConstructorManager $classConstructor
209
     * @return ClassConstructorManager
210
     */
211
    protected function prepareAndFillInitProperties(ClassConstructorManager $classConstructor)
212
    {
213
        $initProperties = new ArrayCollection();
214
        foreach ($classConstructor->getClassManager()->getProperties() as $property) {
215
            if (false === $property->isTypeArrayCollection()) {
216
                continue;
217
            }
218
219
            $initProperty = new InitPropertyManager();
220
            $initProperty->setProperty($property);
221
222
            $initProperties->add($initProperty);
223
        }
224
225
        $classConstructor->setInitProperties($initProperties);
226
227
        return $classConstructor;
228
    }
229
230
    /**
231
     * init test class for entity
232
     *
233
     * @param TestClassManager $testClassManager
234
     * @return TestClassManager
235
     */
236
    protected function generateAndFillTestClassMethods(TestClassManager $testClassManager)
237
    {
238
        $testMethods = new ArrayCollection();
239
        foreach ($testClassManager->getClassManager()->getMethods() as $method) {
240
            $testMethod = new TestMethodManager();
241
            $testMethod->setMethod($method);
242
            $testMethods->add($testMethod);
243
        }
244
245
        $testClassManager->setMethods($testMethods);
246
247
        return $testClassManager;
248
    }
249
250
    /**
251
     * Deserialize JSON data to class manager
252
     *
253
     * @param string $jsonClassToDeserialize
254
     * @return ClassManager
255
     */
256
    protected function deserializeJsonDataToClassManager($jsonClassToDeserialize)
257
    {
258
        return $this->getSerializer()->deserialize($jsonClassToDeserialize, self::CLASS_MANAGER_NAMESPACE, 'json');
259
    }
260
261
    /**
262
     * @return SerializerInterface
263
     */
264
    protected function getSerializer()
265
    {
266
        return $this->serializer;
267
    }
268
269
    /**
270
     * @return Parser
271
     */
272
    protected function getParser()
273
    {
274
        return $this->parser;
275
    }
276
277
    /**
278
     * @param mixed $classConfig
279
     * @return ClassConfig
280
     */
281
    private function getDefaultClassConfigIfNeed($classConfig)
282
    {
283
        if (false === ($classConfig instanceof ClassConfig)) {
284
            $classConfig = new ClassConfig();
285
        }
286
287
        return $classConfig;
288
    }
289
}
290