Passed
Push — develop ( 75d1fe...ccc913 )
by Daniel
06:14
created

AbstractComponent::getComponentComponentGroup()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

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