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