Passed
Pull Request — main (#140)
by Daniel
07:55 queued 02:24
created

Route::setPath()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
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 1
dl 0
loc 5
ccs 0
cts 3
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
/*
4
 * This file is part of the Silverback API Components Bundle Project
5
 *
6
 * (c) Daniel West <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace Silverback\ApiComponentsBundle\Entity\Core;
15
16
use ApiPlatform\Metadata\ApiResource;
17
use ApiPlatform\Metadata\Delete;
18
use ApiPlatform\Metadata\Get;
19
use ApiPlatform\Metadata\GetCollection;
20
use ApiPlatform\Metadata\Patch;
21
use ApiPlatform\Metadata\Post;
22
use ApiPlatform\Metadata\Put;
23
use Doctrine\Common\Collections\ArrayCollection;
24
use Doctrine\Common\Collections\Collection;
25
use Silverback\ApiComponentsBundle\Annotation as Silverback;
26
use Silverback\ApiComponentsBundle\DataProvider\StateProvider\RouteStateProvider;
27
use Silverback\ApiComponentsBundle\Entity\Utility\IdTrait;
28
use Silverback\ApiComponentsBundle\Entity\Utility\TimestampedTrait;
29
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
30
use Symfony\Component\Serializer\Annotation\Groups;
31
use Symfony\Component\Validator\Constraints as Assert;
32
33 1
const REQUIREMENTS = ['id' => '(.+)'];
34
const SECURITY = "is_granted('read_route', object)";
35
36
/**
37
 * Although a user will be able to get the routes and the tree of data down to getting the ID for a component
38
 * fetching a component will be restricted based on the route it is within.
39
 *
40
 * @author Daniel West <[email protected]>
41
 */
42
#[Assert\Expression(
43
    '!(this.getPage() == null & this.getPageData() == null & this.getRedirect() == null)',
44
    message: 'Please specify either page, pageData or redirect.',
45
    groups: ['Route:generate:write', 'Default']
46
)]
47
#[Assert\Expression(
48
    '!(this.getPage() != null & this.getPageData() != null)',
49
    message: 'Please specify either page or pageData, not both.',
50
    groups: ['Route:generate:write', 'Default']
51
)]
52
#[UniqueEntity('name', 'This route name is already in use.')]
53
#[UniqueEntity('path', 'This path is already in use.')]
54
#[ApiResource(
55
    mercure: true,
56
    provider: RouteStateProvider::class
57
)]
58
#[Post]
59
#[GetCollection]
60
#[Delete(requirements: REQUIREMENTS, security: SECURITY)]
61
#[Put(requirements: REQUIREMENTS, security: SECURITY)]
62
#[Patch(requirements: REQUIREMENTS, security: SECURITY)]
63
#[Get(requirements: ['id' => "(?!.+\/redirects$).+"], security: SECURITY)]
64
#[Post(uriTemplate: '/routes/generate.{_format}', validationContext: ['groups' => ['Route:generate:write']], name: 'generate')]
65
#[Get(uriTemplate: '/routes/{id}/redirects.{_format}', defaults: ['_api_item_operation_name' => 'route_redirects'], requirements: REQUIREMENTS, normalizationContext: ['groups' => ['Route:redirect:read']], security: SECURITY, name: 'redirects')]
66
#[Silverback\Timestamped]
67
class Route
68
{
69
    use IdTrait;
70
    use TimestampedTrait;
71
72
    #[Assert\NotBlank]
73
    #[Groups(['Route:redirect:read'])]
74
    private string $path = '';
75
76
    #[Assert\NotNull]
77
    private string $name;
78
79
    private ?Route $redirect = null;
80
81
    #[Groups(['Route:redirect:read'])]
82
    private Collection $redirectedFrom;
83
84
    private ?Page $page = null;
85
86
    private ?AbstractPageData $pageData = null;
87
88
    public function __construct()
89
    {
90
        $this->redirectedFrom = new ArrayCollection();
91
    }
92
93
    public function getPath(): string
94
    {
95
        return $this->path;
96
    }
97
98
    public function setPath(string $path): self
99
    {
100
        $this->path = $path;
101
102
        return $this;
103
    }
104
105
    public function getName(): string
106
    {
107
        return $this->name;
108
    }
109
110
    public function setName(string $name): self
111
    {
112
        $this->name = $name;
113
114
        return $this;
115
    }
116
117
    public function getRedirect(): ?self
118
    {
119
        return $this->redirect;
120
    }
121
122
    public function setRedirect(?self $redirect): self
123
    {
124
        $this->redirect = $redirect;
125
        if ($redirect) {
126
            $redirect->addRedirectedFrom($this);
127
        }
128
129
        return $this;
130
    }
131
132
    /**
133
     * @return Collection|Route[]
134
     */
135
    public function getRedirectedFrom()
136
    {
137
        return $this->redirectedFrom;
138
    }
139
140
    /**
141
     * @param array|Collection $redirectedFrom
142
     */
143
    public function setRedirectedFrom($redirectedFrom): self
144
    {
145
        $isArray = \is_array($redirectedFrom);
146
        if (!$isArray && !$redirectedFrom instanceof Collection) {
0 ignored issues
show
introduced by
$redirectedFrom is always a sub-type of Doctrine\Common\Collections\Collection.
Loading history...
147
            throw new \InvalidArgumentException('setRedirectedFrom requires an array or Collection');
148
        }
149
        $this->redirectedFrom = $isArray ? new ArrayCollection($redirectedFrom) : $redirectedFrom;
0 ignored issues
show
Bug introduced by
It seems like $redirectedFrom can also be of type Doctrine\Common\Collections\Collection; however, parameter $elements of Doctrine\Common\Collecti...llection::__construct() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

149
        $this->redirectedFrom = $isArray ? new ArrayCollection(/** @scrutinizer ignore-type */ $redirectedFrom) : $redirectedFrom;
Loading history...
150
151
        return $this;
152
    }
153
154
    public function addRedirectedFrom(self $redirectedFrom): self
155
    {
156
        if (!$this->redirectedFrom->contains($redirectedFrom)) {
157
            $this->redirectedFrom->add($redirectedFrom);
158
        }
159
160
        return $this;
161
    }
162
163
    public function getPage(): ?Page
164
    {
165
        return $this->page;
166
    }
167
168
    public function setPage(?Page $page): self
169
    {
170
        $this->page = $page;
171
        if ($this->page) {
172
            $this->page->setRoute($this);
173
        }
174
175
        return $this;
176
    }
177
178
    public function getPageData(): ?AbstractPageData
179
    {
180
        return $this->pageData;
181
    }
182
183
    public function setPageData(?AbstractPageData $pageData): self
184
    {
185
        $this->pageData = $pageData;
186
        if ($this->pageData) {
187
            $this->pageData->setRoute($this);
188
        }
189
190
        return $this;
191
    }
192
}
193