Passed
Push — develop ( c8e85b...83a19a )
by Daniel
05:18
created

AbstractComponent::getLocations()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 0
cts 2
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\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 Collection|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 Collection|ComponentGroup[]
76
     */
77
    protected $componentGroups;
78
79
    /**
80
     * AbstractComponent constructor.
81
     */
82 43
    public function __construct()
83
    {
84 43
        $this->id = Uuid::uuid4()->getHex();
85 43
        $this->locations = new ArrayCollection;
86 43
        $this->componentGroups = new ArrayCollection;
87 43
        $this->validComponents = new ArrayCollection;
88 43
    }
89
90
    /**
91
     * @return string
92
     */
93 2
    public function getId(): string
94
    {
95 2
        return $this->id;
96
    }
97
98
    /**
99
     * @return null|string
100
     */
101 1
    public function getClassName(): ?string
102
    {
103 1
        return $this->className;
104
    }
105
106
    /**
107
     * @param null|string $className
108
     * @return AbstractComponent
109
     */
110 2
    public function setClassName(?string $className): AbstractComponent
111
    {
112 2
        $this->className = $className;
113 2
        return $this;
114
    }
115
116
    /**
117
     * @return Collection|ComponentLocation[]
118
     */
119
    public function getLocations()
120
    {
121
        return $this->locations;
122
    }
123
124
    /**
125
     * @param ContentInterface $content
126
     * @return AbstractComponent
127
     */
128
    public function addLocation(ContentInterface $content): AbstractComponent
129
    {
130
        $this->locations->add($content);
131
        return $this;
132
    }
133
134
    /**
135
     * @param ContentInterface $content
136
     * @return AbstractComponent
137
     */
138
    public function removeLocation(ContentInterface $content): AbstractComponent
139
    {
140
        $this->locations->removeElement($content);
141
        return $this;
142
    }
143
144
    /**
145
     * @param array $componentGroups
146
     * @return AbstractComponent
147
     */
148
    public function setComponentGroups(array $componentGroups): AbstractComponent
149
    {
150
        $this->componentGroups = new ArrayCollection;
151
        foreach ($componentGroups as $componentGroup) {
152
            $this->addComponentGroup($componentGroup);
153
        }
154
        return $this;
155
    }
156
157
    /**
158
     * @param ComponentGroup $componentGroup
159
     * @return AbstractComponent
160
     */
161 12
    public function addComponentGroup(ComponentGroup $componentGroup): AbstractComponent
162
    {
163 12
        $componentGroup->setParent($this);
164 12
        $this->componentGroups->add($componentGroup);
165 12
        return $this;
166
    }
167
168
    /**
169
     * @param ComponentGroup $componentGroup
170
     * @return AbstractComponent
171
     */
172
    public function removeComponentGroup(ComponentGroup $componentGroup): AbstractComponent
173
    {
174
        $this->componentGroups->removeElement($componentGroup);
175
        return $this;
176
    }
177
178
    /**
179
     * @return Collection|ComponentGroup[]
180
     */
181 2
    public function getComponentGroups(): Collection
182
    {
183 2
        return $this->componentGroups;
184
    }
185
186
    /**
187
     * Return the component name for front-end to decipher
188
     * @Groups({"content", "component"})
189
     * @return string
190
     */
191
    public static function getComponentName(): string
192
    {
193
        $explodedClass = explode('\\', static::class);
194
        return array_pop($explodedClass);
195
    }
196
197
    /**
198
     * @return bool
199
     */
200
    public function onDeleteCascade(): bool
201
    {
202
        return false;
203
    }
204
205
    /**
206
     * @param AbstractComponent $component
207
     * @param int $componentGroupOffset
208
     * @return ComponentGroup
209
     * @throws \InvalidArgumentException
210
     */
211 1
    private function getComponentComponentGroup(AbstractComponent $component, int $componentGroupOffset = 0): ComponentGroup
212
    {
213
        /** @var ComponentGroup $componentGroup */
214 1
        $componentGroup = $component->getComponentGroups()->get($componentGroupOffset);
215 1
        if (null === $componentGroup) {
216
            throw new \InvalidArgumentException(sprintf('There is no component group child of this component with the offset %d', $componentGroupOffset));
217
        }
218 1
        return $componentGroup;
219
    }
220
221
    /**
222
     * @Groups({"component_write"})
223
     * @param AbstractComponent $parent
224
     * @param int $componentGroupOffset
225
     * @return AbstractComponent
226
     * @throws \InvalidArgumentException
227
     */
228 1
    public function setParent(AbstractComponent $parent, int $componentGroupOffset = 0): AbstractComponent
229
    {
230 1
        if (!\in_array($parent, $this->getParentComponents(), true)) {
231 1
            $componentGroup = $this->getComponentComponentGroup($parent, $componentGroupOffset);
232 1
            if (!$componentGroup->hasComponent($this)) {
233 1
                $componentGroup->addComponent(new ComponentLocation($componentGroup, $this));
234
            }
235
        }
236 1
        return $this;
237
    }
238
239
    /**
240
     * @return AbstractComponent[]
241
     */
242 1
    private function getParentComponents(): array
243
    {
244 1
        $parentContent = $this->getParentContent();
245 1
        return array_unique(
246 1
            array_filter(
247 1
                array_map(
248 1
                    function ($content) {
249
                        if ($content instanceof ComponentGroup) {
250
                            return $content->getParent();
251
                        }
252 1
                    },
253 1
                    $parentContent
254
                )
255
            )
256
        );
257
    }
258
259
    /**
260
     * @return AbstractContent[]
261
     */
262 1
    private function getParentContent(): array
263
    {
264 1
        return array_unique(
265 1
            array_filter(
266 1
                array_map(
267 1
                    function (ComponentLocation $loc) {
268
                        return $loc->getContent();
269 1
                    },
270 1
                    $this->locations->toArray()
271
                )
272
            )
273
        );
274
    }
275
}
276