Passed
Push — develop ( 7c6c89...89f4d5 )
by Daniel
06:08
created

AbstractComponent::getComponentName()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 4
ccs 0
cts 3
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Silverback\ApiComponentBundle\Entity\Component;
4
5
use ApiPlatform\Core\Annotation\ApiProperty;
6
use Doctrine\Common\Collections\ArrayCollection;
7
use Doctrine\Common\Collections\Collection;
8
use Doctrine\ORM\Mapping as ORM;
9
use Ramsey\Uuid\Uuid;
10
use Silverback\ApiComponentBundle\Entity\Content\AbstractContent;
11
use Silverback\ApiComponentBundle\Entity\Content\ComponentGroup;
12
use Silverback\ApiComponentBundle\Entity\Content\ComponentLocation;
13
use Silverback\ApiComponentBundle\Entity\Content\ContentInterface;
14
use Silverback\ApiComponentBundle\Entity\DeleteCascadeInterface;
15
use Silverback\ApiComponentBundle\Entity\ValidComponentTrait;
16
use Symfony\Component\Serializer\Annotation\Groups;
17
18
/**
19
 * Class AbstractComponent
20
 * @package Silverback\ApiComponentBundle\Entity\Component
21
 * @author Daniel West <[email protected]>
22
 * @ORM\Entity()
23
 * @ORM\Table(name="component")
24
 * @ORM\InheritanceType("SINGLE_TABLE")
25
 * @ORM\DiscriminatorColumn(name="type", type="string")
26
 * @ORM\DiscriminatorMap({
27
 *     "content" = "Silverback\ApiComponentBundle\Entity\Component\Content\Content",
28
 *     "form" = "Silverback\ApiComponentBundle\Entity\Component\Form\Form",
29
 *     "gallery" = "Silverback\ApiComponentBundle\Entity\Component\Gallery\Gallery",
30
 *     "gallery_item" = "Silverback\ApiComponentBundle\Entity\Component\Gallery\GalleryItem",
31
 *     "hero" = "Silverback\ApiComponentBundle\Entity\Component\Hero\Hero",
32
 *     "feature_columns" = "Silverback\ApiComponentBundle\Entity\Component\Feature\Columns\FeatureColumns",
33
 *     "feature_columns_item" = "Silverback\ApiComponentBundle\Entity\Component\Feature\Columns\FeatureColumnsItem",
34
 *     "feature_stacked" = "Silverback\ApiComponentBundle\Entity\Component\Feature\Stacked\FeatureStacked",
35
 *     "feature_stacked_item" = "Silverback\ApiComponentBundle\Entity\Component\Feature\Stacked\FeatureStackedItem",
36
 *     "feature_text_list" = "Silverback\ApiComponentBundle\Entity\Component\Feature\TextList\FeatureTextList",
37
 *     "feature_text_list_item" = "Silverback\ApiComponentBundle\Entity\Component\Feature\TextList\FeatureTextListItem",
38
 *     "article" = "Silverback\ApiComponentBundle\Entity\Component\Article\Article"
39
 * })
40
 * @ORM\EntityListeners({"Silverback\ApiComponentBundle\EntityListener\ComponentListener"})
41
 */
42
abstract class AbstractComponent implements ComponentInterface, DeleteCascadeInterface
43
{
44
    use ValidComponentTrait;
45
46
    /**
47
     * @ORM\Id()
48
     * @ORM\Column(type="string")
49
     * @var string
50
     */
51
    private $id;
52
53
    /**
54
     * @ORM\Column(nullable=true)
55
     * @Groups({"component", "content"})
56
     * @var null|string
57
     */
58
    private $className;
59
60
    /**
61
     * @ORM\OneToMany(targetEntity="Silverback\ApiComponentBundle\Entity\Content\ComponentLocation", mappedBy="component")
62
     * @var ArrayCollection|ComponentLocation[]
63
     */
64
    protected $locations;
65
66
    /**
67
     * @ORM\OneToMany(targetEntity="Silverback\ApiComponentBundle\Entity\Content\ComponentGroup", mappedBy="parent", cascade={"persist"})
68
     * @ApiProperty(attributes={"fetchEager": false})
69
     * @Groups({"component", "content"})
70
     * @var ArrayCollection|ComponentGroup[]
71
     */
72
    protected $componentGroups;
73
74
    /**
75
     * @Groups({"component_write"})
76
     * @var AbstractComponent|null
77
     */
78
    private $parent;
79
80
    /**
81
     * AbstractComponent constructor.
82
     */
83 17
    public function __construct()
84
    {
85 17
        $this->id = Uuid::uuid4()->getHex();
86 17
        $this->locations = new ArrayCollection;
87 17
        $this->componentGroups = new ArrayCollection;
88 17
        $this->validComponents = new ArrayCollection;
89 17
    }
90
91
    /**
92
     * @return string
93
     */
94
    public function getId(): string
95
    {
96
        return $this->id;
97
    }
98
99
    /**
100
     * @return null|string
101
     */
102 1
    public function getClassName(): ?string
103
    {
104 1
        return $this->className;
105
    }
106
107
    /**
108
     * @param null|string $className
109
     * @return AbstractComponent
110
     */
111 6
    public function setClassName(?string $className): AbstractComponent
112
    {
113 6
        $this->className = $className;
114 6
        return $this;
115
    }
116
117
    /**
118
     * @param ContentInterface $content
119
     * @param bool|null $sortLast
120
     * @return AbstractComponent
121
     */
122
    public function addLocation(ContentInterface $content, ?bool $sortLast = null): AbstractComponent
123
    {
124
        $this->locations->add($content);
125
        return $this;
126
    }
127
128
    /**
129
     * @param ContentInterface $content
130
     * @return AbstractComponent
131
     */
132
    public function removeLocation(ContentInterface $content): AbstractComponent
133
    {
134
        $this->locations->removeElement($content);
135
        return $this;
136
    }
137
138
    /**
139
     * @param array $componentGroups
140
     * @return AbstractComponent
141
     */
142
    public function setComponentGroups(array $componentGroups): AbstractComponent
143
    {
144
        $this->componentGroups = new ArrayCollection;
145
        foreach ($componentGroups as $componentGroup) {
146
            $this->addComponentGroup($componentGroup);
147
        }
148
        return $this;
149
    }
150
151
    /**
152
     * @param ComponentGroup $componentGroup
153
     * @return AbstractComponent
154
     */
155
    public function addComponentGroup(ComponentGroup $componentGroup): AbstractComponent
156
    {
157
        $componentGroup->setParent($this);
158
        $this->componentGroups->add($componentGroup);
159
        return $this;
160
    }
161
162
    /**
163
     * @param ComponentGroup $componentGroup
164
     * @return AbstractComponent
165
     */
166
    public function removeComponentGroup(ComponentGroup $componentGroup): AbstractComponent
167
    {
168
        $this->componentGroups->removeElement($componentGroup);
169
        return $this;
170
    }
171
172
    /**
173
     * @return ArrayCollection|ComponentGroup[]
174
     */
175
    public function getComponentGroups(): Collection
176
    {
177
        return $this->componentGroups;
178
    }
179
180
    /**
181
     * @Groups({"component"})
182
     * @return string
183
     */
184
    public static function getComponentName(): string
185
    {
186
        $explodedClass = explode('\\', static::class);
187
        return array_pop($explodedClass);
188
    }
189
190
    /**
191
     * @param AbstractComponent $component
192
     * @param int $componentGroupOffset
193
     * @return ComponentGroup
194
     * @throws \InvalidArgumentException
195
     */
196
    private function getComponentComponentGroup(AbstractComponent $component, int $componentGroupOffset = 0): ComponentGroup
197
    {
198
        /** @var ComponentGroup $componentGroup */
199
        $componentGroup = $component->getComponentGroups()->get($componentGroupOffset);
200
        if (null === $componentGroup) {
201
            throw new \InvalidArgumentException(sprintf('There is no component group child of this component with the offset %d', $componentGroupOffset));
202
        }
203
        return $componentGroup;
204
    }
205
206
    /**
207
     * @param AbstractComponent $child
208
     * @param int $componentGroupOffset
209
     * @return AbstractComponent
210
     * @throws \InvalidArgumentException
211
     */
212
    public function addChildComponent(AbstractComponent $child, int $componentGroupOffset = 0): AbstractComponent
213
    {
214
        $componentGroup = $this->getComponentComponentGroup($this, $componentGroupOffset);
215
        $componentGroup->addComponent(new ComponentLocation($componentGroup, $child));
216
        return $this;
217
    }
218
219
    /**
220
     * @param AbstractComponent $parent
221
     * @param int $componentGroupOffset
222
     * @return AbstractComponent
223
     * @throws \InvalidArgumentException
224
     */
225
    public function addToParentComponent(AbstractComponent $parent, int $componentGroupOffset = 0): AbstractComponent
226
    {
227
        if (!\in_array($parent, $this->getParentComponents(), true)) {
228
            $componentGroup = $this->getComponentComponentGroup($parent, $componentGroupOffset);
229
            $componentGroup->addComponent(new ComponentLocation($componentGroup, $this));
230
        }
231
        return $this;
232
    }
233
234
    /**
235
     * @return AbstractComponent[]
236
     */
237
    private function getParentComponents(): array
238
    {
239
        $parentContent = $this->getParentContent();
240
        return array_unique(
241
            array_filter(
242
                array_map(
243
                    function ($content) {
244
                        if ($content instanceof ComponentGroup) {
245
                            return $content->getParent();
246
                        }
247
                    },
248
                    $parentContent
249
                )
250
            )
251
        );
252
    }
253
254
    /**
255
     * @return AbstractContent[]
256
     */
257
    private function getParentContent(): array
258
    {
259
        return array_unique(
260
            array_filter(
261
                array_map(
262
                    function (ComponentLocation $loc) {
263
                        return $loc->getContent();
264
                    },
265
                    $this->locations->toArray()
266
                )
267
            )
268
        );
269
    }
270
271
    /**
272
     * @return bool
273
     */
274
    public function onDeleteCascade(): bool
275
    {
276
        return false;
277
    }
278
279
    /**
280
     * @return AbstractComponent|null
281
     */
282
    public function getParent(): ?AbstractComponent
283
    {
284
        return $this->parent;
285
    }
286
287
    /**
288
     * @param AbstractComponent|null $parent
289
     */
290
    public function setParent(?AbstractComponent $parent): void
291
    {
292
        $this->parent = $parent;
293
    }
294
}
295