Completed
Pull Request — master (#14)
by
unknown
08:12
created

ClassManager::setImplements()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 5
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 1
1
<?php
2
3
namespace SimpleEntityGeneratorBundle\Lib\Items;
4
5
use Doctrine\Common\Collections\ArrayCollection;
6
use Exception;
7
use SimpleEntityGeneratorBundle\Lib\Interfaces\DumpableInterface;
8
use SimpleEntityGeneratorBundle\Lib\Interfaces\MultilineCommentableInterface;
9
use SimpleEntityGeneratorBundle\Lib\Interfaces\RenderableInterface;
10
use SimpleEntityGeneratorBundle\Lib\Interfaces\StructureWithMethodsInterface;
11
use SimpleEntityGeneratorBundle\Lib\Tools;
12
use SimpleEntityGeneratorBundle\Lib\Traits\MultilineCommentTrait;
13
use SimpleEntityGeneratorBundle\Lib\Traits\TemplateTrait;
14
use JMS\Serializer\Annotation\SerializedName;
15
use JMS\Serializer\Annotation\Type;
16
use Symfony\Component\Validator\Constraints as Assert;
17
18
/**
19
 * Manager of Class structure
20
 *
21
 * @author Sławomir Kania <[email protected]>
22
 */
23
class ClassManager implements RenderableInterface, DumpableInterface, StructureWithMethodsInterface, MultilineCommentableInterface
24
{
25
26
    use MultilineCommentTrait;
27
    use TemplateTrait;
28
29
    /**
30
     * Collection of MethodManager
31
     *
32
     * @var ArrayCollection
33
     * @Assert\NotNull(message="Properties Collection can not be empty!")
34
     * @Assert\Valid()
35
     */
36
    private $methods = null;
37
38
    /**
39
     * Collection of PropertyManager
40
     *
41
     * @Type("Doctrine\Common\Collections\ArrayCollection<SimpleEntityGeneratorBundle\Lib\Items\PropertyManager>")
42
     * @Assert\NotNull(message="Properties Collection can not be empty!")
43
     * @Assert\Valid()
44
     */
45
    private $properties = null;
46
47
    /**
48
     * Interface namespace
49
     *
50
     * @var InterfaceManager
51
     * @Assert\Valid()
52
     */
53
    private $interface = null;
54
55
    /**
56
     * Class constructor
57
     *
58
     * @var ClassConstructorManager
59
     * @Assert\NotNull(message="Constructor can not be null!")
60
     * @Assert\Valid()
61
     */
62
    private $constructor = null;
63
64
    /**
65
     * Test Class
66
     *
67
     * @var TestClassManager
68
     * @Assert\Valid()
69
     * @var TestClassManager
70
     */
71
    private $testClass = null;
72
73
    /**
74
     * namespace of class - class name is retrieved from namespace
75
     *
76
     * @Type("string")
77
     * @Assert\NotBlank(message="Namespace can not be blank!")
78
     */
79
    private $namespace = "";
80
81
    /**
82
     * Comment under class
83
     *
84
     * @Type("string")
85
     */
86
    private $comment = "";
87
88
    /**
89
     * Base class namespace
90
     *
91
     * @Type("string")
92
     */
93
    private $extends = "";
94
95
    /**
96
     * @SerializedName("class_manager_template_path")
97
     * @Type("string")
98
     * @Assert\Type("string")
99
     */
100
    private $classManagerTemplatePath = "";
101
102
    /**
103
     *
104
     * @SerializedName("class_constructor_manager_template_path")
105
     * @Type("string")
106
     * @Assert\Type("string")
107
     */
108
    private $classConstructorManagerTemplatePath = "";
109
110
    /**
111
     * @SerializedName("interface_manager_template_path")
112
     * @Type("string")
113
     * @Assert\Type("string")
114
     */
115
    private $interfaceManagerTemplatePath = "";
116
117
    /**
118
     * @SerializedName("test_class_manager_template_path")
119
     * @Type("string")
120
     * @Assert\Type("string")
121
     */
122
    private $testClassManagerTemplatePath = "";
123
124
    /**
125
     * @Type("SimpleEntityGeneratorBundle\Lib\ClassConfig")
126
     * @SerializedName("configuration")
127
     * @Assert\Valid()
128
     * @var \SimpleEntityGeneratorBundle\Lib\ClassConfig
129
     */
130
    private $configuration;
131
132
    /**
133
     * @SerializedName("implements")
134
     * @Type("Doctrine\Common\Collections\ArrayCollection<string>")
135
     * @Assert\Type("Doctrine\Common\Collections\ArrayCollection")
136
     * @var ArrayCollection
137
     */
138
    private $implements;
139
140
    /**
141
     * Construct
142
     */
143
    public function __construct()
144
    {
145
        $this->properties = new ArrayCollection();
146
        $this->methods = new ArrayCollection();
147
        $this->implements = new ArrayCollection();
148
    }
149
150
    /**
151
     * @Assert\IsTrue(message = "Duplicated properties names in entity, check yaml schema!")
152
     * @return boolean
153
     */
154
    public function hasUniquePropertiesNames()
155
    {
156
        $tmpPropertiesNames = [];
157
        foreach ($this->getProperties() as $property) {
158
            /* @var $property PropertyManager */
159
            $propertyName = $property->getName();
160
            if (in_array($propertyName, $tmpPropertiesNames)) {
161
                return false;
162
            }
163
164
            $tmpPropertiesNames[] = $propertyName;
165
        }
166
167
        return true;
168
    }
169
170
    /**
171
     * @Assert\IsTrue(message = "Invalid class namespace, check yaml schema! eg. \AppBundle\Vendor\Entity")
172
     * @return boolean
173
     */
174
    public function isValidNamespace()
175
    {
176
        return Tools::isNamespaceValid($this->getNamespace());
177
    }
178
179
    /**
180
     * @Assert\IsTrue(message = "Invalid base class namespace, check yaml schema! eg. \AppBundle\Vendor\Entity")
181
     * @return boolean
182
     */
183
    public function isValidExtends()
184
    {
185
        if (false === $this->hasExtends()) {
186
            return true;
187
        }
188
189
        if (false === Tools::isFirstCharBackslash($this->getExtends())) {
190
            return false;
191
        }
192
193
        if (class_exists($this->getExtends())) {
194
            return true;
195
        }
196
197
        return Tools::isNamespaceValid($this->getNamespace());
198
    }
199
200
    /**
201
     * @return ArrayCollection
202
     */
203
    public function getMethods()
204
    {
205
        return $this->methods;
206
    }
207
208
    /**
209
     * @param ArrayCollection $methods
210
     * @return InterfaceManager
211
     */
212
    public function setMethods(ArrayCollection $methods)
213
    {
214
        $this->methods = $methods;
215
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this; (SimpleEntityGeneratorBundle\Lib\Items\ClassManager) is incompatible with the return type declared by the interface SimpleEntityGeneratorBun...dsInterface::setMethods of type SimpleEntityGeneratorBun...rfaces\InterfaceManager.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
216
    }
217
218
    /**
219
     * @return ArrayCollection
220
     */
221
    public function getProperties()
222
    {
223
        return $this->properties;
224
    }
225
226
    /**
227
     * @param ArrayCollection $properties
228
     * @return ClassManager
229
     */
230
    public function setProperties(ArrayCollection $properties)
231
    {
232
        $this->properties = $properties;
233
        return $this;
234
    }
235
236
    /**
237
     * @return InterfaceManager
238
     */
239
    public function getInterface()
240
    {
241
        return $this->interface;
242
    }
243
244
    /**
245
     * @param InterfaceManager $interface
246
     * @return ClassManager
247
     */
248
    public function setInterface(InterfaceManager $interface)
249
    {
250
        $this->interface = $interface;
251
        return $this;
252
    }
253
254
    /**
255
     * @return ClassConstructorManager
256
     */
257
    public function getConstructor()
258
    {
259
        return $this->constructor;
260
    }
261
262
    /**
263
     * @param ClassConstructorManager $constructor
264
     * @return ClassManager
265
     */
266
    public function setConstructor(ClassConstructorManager $constructor)
267
    {
268
        $this->constructor = $constructor;
269
        return $this;
270
    }
271
272
    /**
273
     * @return string
274
     */
275
    public function getComment()
276
    {
277
        return $this->comment;
278
    }
279
280
    /**
281
     * @param string
282
     * @return ClassManager
283
     */
284
    public function setComment($comment)
285
    {
286
        $this->comment = $comment;
287
        return $this;
288
    }
289
290
    /**
291
     * @return TestClassManager
292
     */
293
    public function getTestClass()
294
    {
295
        return $this->testClass;
296
    }
297
298
    /**
299
     * @param TestClassManager $testClass
300
     * @return ClassManager
301
     */
302
    public function setTestClass(TestClassManager $testClass)
303
    {
304
        $this->testClass = $testClass;
305
        return $this;
306
    }
307
308
    /**
309
     * @return string
310
     */
311
    public function getNamespace()
312
    {
313
        return $this->namespace;
314
    }
315
316
    /**
317
     * @param string $namespace
318
     * @return ClassManager
319
     */
320
    public function setNamespace($namespace)
321
    {
322
        $this->namespace = $namespace;
323
        return $this;
324
    }
325
326
    /**
327
     * Return base class namespace
328
     *
329
     * @return string
330
     */
331
    public function getExtends()
332
    {
333
        return $this->extends;
334
    }
335
336
    /**
337
     * Set base class namespace
338
     *
339
     * @param string $extends
340
     */
341
    public function setExtends($extends)
342
    {
343
        $this->extends = $extends;
344
    }
345
346
    /**
347
     * has set base class namespace
348
     *
349
     * @return boolean
350
     */
351
    public function hasExtends()
352
    {
353
        return false === empty($this->getExtends());
354
    }
355
356
    /**
357
     * Check interface exists
358
     *
359
     * @return boolean
360
     */
361
    public function hasInterface()
362
    {
363
        return $this->getInterface() instanceof InterfaceManager;
364
    }
365
366
    /**
367
     * Check interface exists
368
     *
369
     * @return boolean
370
     */
371
    public function hasTestClass()
372
    {
373
        return $this->getTestClass() instanceof TestClassManager;
374
    }
375
376
    /**
377
     * Return namespace without name - for createing directory
378
     *
379
     * @return string
380
     */
381
    public function getDirectory()
382
    {
383
        return Tools::getDirectoryFromNamespace($this->getNamespace());
384
    }
385
386
    /**
387
     * Return name of class/interface from namespace
388
     *
389
     * @return string
390
     * @throws Exception
391
     */
392
    public function getName()
393
    {
394
        return Tools::getNameFromNamespace($this->getNamespace());
395
    }
396
397
    /**
398
     * Return namespace without name - for rendering namespace in class
399
     *
400
     * @return string
401
     * @throws Exception
402
     */
403
    public function getNamespaceWithoutName()
404
    {
405
        return Tools::getNamespaceWithoutName($this->getNamespace());
406
    }
407
408
    /**
409
     * Return namespace without name - for rendering namespace in class
410
     *
411
     * @return string
412
     * @throws Exception
413
     */
414
    public function getNamespaceWithoutNameAndBackslashPrefix()
415
    {
416
        return Tools::removeBackslashPrefixFromNamespace(Tools::getNamespaceWithoutName($this->getNamespace()));
417
    }
418
419
    /**
420
     * Return set of tags used in template
421
     *
422
     * @return array
423
     */
424
    public function getTemplateTags()
425
    {
426
        return [
427
            self::TAG_NAMESPACE,
428
            self::TAG_COMMENT,
429
            self::TAG_NAME,
430
            self::TAG_EXTENDS,
431
            self::TAG_INTERFACE,
432
            self::TAG_CONSTRUCTOR,
433
            self::TAG_PROPERTIES,
434
            self::TAG_METHODS,
435
            self::TAG_MULTILINE_COMMENT,
436
        ];
437
    }
438
439
    /**
440
     * @return string
441
     */
442
    public function getClassManagerTemplatePath()
443
    {
444
        return $this->classManagerTemplatePath;
445
    }
446
447
    /**
448
     * @return string
449
     */
450
    public function getClassConstructorManagerTemplatePath()
451
    {
452
        return $this->classConstructorManagerTemplatePath;
453
    }
454
455
    /**
456
     * @return string
457
     */
458
    public function getInterfaceManagerTemplatePath()
459
    {
460
        return $this->interfaceManagerTemplatePath;
461
    }
462
463
    /**
464
     * @return string
465
     */
466
    public function getTestClassManagerTemplatePath()
467
    {
468
        return $this->testClassManagerTemplatePath;
469
    }
470
471
    /**
472
     * @param string $classManagerTemplatePath
473
     * @return $this
474
     */
475
    public function setClassManagerTemplatePath($classManagerTemplatePath)
476
    {
477
        $this->classManagerTemplatePath = $classManagerTemplatePath;
478
        return $this;
479
    }
480
481
    /**
482
     * @param string $classConstructorManagerTemplatePath
483
     * @return $this
484
     */
485
    public function setClassConstructorManagerTemplatePath($classConstructorManagerTemplatePath)
486
    {
487
        $this->classConstructorManagerTemplatePath = $classConstructorManagerTemplatePath;
488
        return $this;
489
    }
490
491
    /**
492
     * @param string $interfaceManagerTemplatePath
493
     * @return $this
494
     */
495
    public function setInterfaceManagerTemplatePath($interfaceManagerTemplatePath)
496
    {
497
        $this->interfaceManagerTemplatePath = $interfaceManagerTemplatePath;
498
        return $this;
499
    }
500
501
    /**
502
     * @param string $testClassManagerTemplatePath
503
     * @return $this
504
     */
505
    public function setTestClassManagerTemplatePath($testClassManagerTemplatePath)
506
    {
507
        $this->testClassManagerTemplatePath = $testClassManagerTemplatePath;
508
        return $this;
509
    }
510
511
    /**
512
     * @return \SimpleEntityGeneratorBundle\Lib\ClassConfig
513
     */
514
    public function getConfiguration()
515
    {
516
        return $this->configuration;
517
    }
518
519
    /**
520
     * @param \SimpleEntityGeneratorBundle\Lib\ClassConfig $configuration
521
     * @return \SimpleEntityGeneratorBundle\Lib\Items\ClassManager
522
     */
523
    public function setConfiguration(\SimpleEntityGeneratorBundle\Lib\ClassConfig $configuration)
524
    {
525
        $this->configuration = $configuration;
526
        return $this;
527
    }
528
529
    /**
530
     * @return ArrayCollection
531
     */
532
    public function getImplements()
533
    {
534
        // TODO is it possible to deserialize to empty ArrayCollection, when property no provided in yml file?
535
        if (is_null($this->implements)) {
536
            $this->implements = new ArrayCollection();
537
        }
538
        return $this->implements;
539
    }
540
541
    /**
542
     * @param ArrayCollection $implements
543
     * @return ClassManager
544
     */
545
    public function setImplements(ArrayCollection $implements)
546
    {
547
        $this->implements = $implements;
548
        return $this;
549
    }
550
}
551