Topic::setName()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
c 0
b 0
f 0
dl 0
loc 3
rs 10
cc 1
nc 1
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace ProjetNormandie\ForumBundle\Entity;
6
7
use ApiPlatform\Metadata\ApiResource;
8
use ApiPlatform\Metadata\ApiFilter;
9
use ApiPlatform\Doctrine\Orm\Filter\BooleanFilter;
10
use ApiPlatform\Doctrine\Orm\Filter\OrderFilter;
11
use ApiPlatform\Doctrine\Orm\Filter\SearchFilter;
12
use ApiPlatform\Metadata\Get;
13
use ApiPlatform\Metadata\GetCollection;
14
use ApiPlatform\Metadata\Link;
15
use ApiPlatform\Metadata\Patch;
16
use ApiPlatform\Metadata\Post;
17
use ApiPlatform\Metadata\Put;
18
use Doctrine\Common\Collections\Collection;
19
use Doctrine\ORM\Mapping as ORM;
20
use Gedmo\Timestampable\Traits\TimestampableEntity;
21
use Gedmo\Mapping\Annotation as Gedmo;
22
use ProjetNormandie\ForumBundle\Controller\Topic\GetRecentActivity;
23
use ProjetNormandie\ForumBundle\Controller\Topic\MarkAsRead;
24
use ProjetNormandie\ForumBundle\Controller\Topic\ToggleNotification;
25
use ProjetNormandie\ForumBundle\Repository\TopicRepository;
26
use Doctrine\Common\Collections\ArrayCollection;
27
use Symfony\Component\Serializer\Annotation\Groups;
28
use Symfony\Component\Validator\Constraints as Assert;
29
30
#[ORM\Table(name:'pnf_topic')]
31
#[ORM\Entity(repositoryClass: TopicRepository::class)]
32
#[ORM\EntityListeners(["ProjetNormandie\ForumBundle\EventListener\Entity\TopicListener"])]
33
#[ORM\Index(name: "idx_name", columns: ["name"])]
34
#[ApiResource(
35
    shortName: 'ForumTopic',
36
    order: ['type.position' => 'ASC', 'lastMessage.id' => 'DESC'],
37
    operations: [
38
        new GetCollection(
39
            normalizationContext: ['groups' =>
40
                [
41
                    'topic:read',
42
                    'topic:last-message',
43
                    'message:read',
44
                    'topic:forum',
45
                    'forum:read',
46
                    'topic:type',
47
                    'topic-type:read'
48
                ]
49
            ]
50
        ),
51
        new GetCollection(
52
            uriTemplate: '/forum_topics/recent-activity',
53
            controller: GetRecentActivity::class,
54
            normalizationContext: ['groups' =>
55
                [
56
                    'topic:read',
57
                    'topic:last-message',
58
                    'message:read',
59
                    'topic:forum',
60
                    'forum:read',
61
                    'topic:type',
62
                    'topic-type:read',
63
                    'message:user',
64
                    'user:read',
65
                ]
66
            ]
67
        ),
68
        new Get(),
69
        new Post(
70
            denormalizationContext: ['groups' => ['topic:insert', 'message:insert']],
71
            normalizationContext: ['groups' =>
72
                ['topic:read', 'topic:forum', 'forum:read']
73
            ],
74
            security: 'is_granted("ROLE_USER")',
75
        ),
76
        new Put(
77
            security: 'is_granted("ROLE_USER") and object.getUser() == user',
78
        ),
79
        new Get(
80
            uriTemplate: '/forum_topics/{id}/toggle-notification',
81
            controller: ToggleNotification::class,
82
            security: 'is_granted("ROLE_USER")',
83
            read: false,
84
        ),
85
        new Get(
86
            uriTemplate: '/forum_topics/{id}/mark-as-read',
87
            controller: MarkAsRead::class,
88
            security: 'is_granted("ROLE_USER")',
89
            read: false,
90
        )
91
    ],
92
    normalizationContext: ['groups' => ['topic:read', 'topic:type', 'topic-type:read']],
93
)]
94
#[ApiResource(
95
    shortName: 'ForumTopic',
96
    uriTemplate: '/forum_forums/{id}/topics',
97
    uriVariables: [
98
        'id' => new Link(fromClass: Forum::class, toProperty: 'forum'),
99
    ],
100
    operations: [
101
        new GetCollection(
102
            order: ['type.position' => 'ASC', 'lastMessage.id' => 'DESC']
103
        )
104
    ],
105
    normalizationContext: ['groups' => [
106
        'topic:read',
107
        'topic:last-message',
108
        'message:read',
109
        'message:user',
110
        'topic:type',
111
        'topic-type:read']
112
    ],
113
)]
114
#[ApiFilter(
115
    SearchFilter::class,
116
    properties: [
117
        'name' => 'partial',
118
        'forum' => 'exact',
119
        'forum.status' => 'exact',
120
        'topicUser.user' => 'exact',
121
        'topicUser.boolNotif' => 'exact'
122
    ]
123
)]
124
#[ApiFilter(
125
    OrderFilter::class,
126
    properties: [
127
        'lastMessage.id' => 'DESC',
128
    ]
129
)]
130
#[ApiFilter(BooleanFilter::class, properties: ['boolArchive'])]
131
class Topic
132
{
133
    use TimestampableEntity;
134
135
    #[Groups(['topic:read'])]
136
    #[ORM\Id, ORM\Column, ORM\GeneratedValue]
137
    private ?int $id = null;
138
139
    #[Groups(['topic:read', 'topic:insert'])]
140
    #[Assert\NotNull]
141
    #[Assert\NotBlank]
142
    #[Assert\Length(min:3, max: 255)]
143
    #[ORM\Column(length: 255, nullable: false)]
144
    private string $name;
145
146
    #[Groups(['topic:read'])]
147
    #[ORM\Column(nullable: false, options: ['default' => 0])]
148
    private int $nbMessage = 0;
149
150
    #[Groups(['topic:forum', 'topic:insert'])]
151
    #[ORM\ManyToOne(targetEntity: Forum::class, inversedBy: 'topics')]
152
    #[ORM\JoinColumn(name:'forum_id', referencedColumnName:'id', nullable:false)]
153
    private Forum $forum;
154
155
    #[Groups(['topic:user'])]
156
    #[ORM\ManyToOne(targetEntity: UserInterface::class)]
157
    #[ORM\JoinColumn(name:'user_id', referencedColumnName:'id', nullable:false)]
158
    private $user;
159
160
    #[Groups(['topic:read'])]
161
    #[ORM\Column(length: 255)]
162
    #[Gedmo\Slug(fields: ['name'])]
163
    protected string $slug;
164
165
    #[Groups(['topic:type', 'topic:insert'])]
166
    #[ORM\ManyToOne(targetEntity: TopicType::class)]
167
    #[ORM\JoinColumn(name:'type_id', referencedColumnName:'id', nullable:false)]
168
    private TopicType $type;
169
170
    #[Groups(['topic:insert'])]
171
    #[ORM\OneToMany(targetEntity: Message::class, mappedBy: 'topic', cascade: ['persist'])]
172
    private Collection $messages;
173
174
    #[Groups(['topic:last-message'])]
175
    #[ORM\ManyToOne(targetEntity: Message::class, cascade: ['persist'])]
176
    #[ORM\JoinColumn(name:'max_message_id', referencedColumnName:'id', nullable:true, onDelete: 'SET NULL')]
177
    private ?Message $lastMessage;
178
179
    #[ORM\Column(nullable: false, options: ['default' => false])]
180
    private bool $boolArchive = false;
181
182
    #[ORM\OneToMany(targetEntity: TopicUserLastVisit::class, mappedBy: 'topic')]
183
    private Collection $userLastVisits;
184
185
186
    public function __toString()
187
    {
188
        return sprintf('%s [%s]', $this->getName(), $this->getId());
189
    }
190
191
192
    public function __construct()
193
    {
194
        $this->messages = new ArrayCollection();
195
        $this->userLastVisits = new ArrayCollection();
196
    }
197
198
    public function setId(int $id): void
199
    {
200
        $this->id = $id;
201
    }
202
203
    public function getId(): ?int
204
    {
205
        return $this->id;
206
    }
207
208
    public function setName(string $name): void
209
    {
210
        $this->name = $name;
211
    }
212
213
    public function getName(): string
214
    {
215
        return $this->name;
216
    }
217
218
    public function setNbMessage(int $nbMessage): void
219
    {
220
        $this->nbMessage = $nbMessage;
221
    }
222
223
    public function getNbMessage(): int
224
    {
225
        return $this->nbMessage;
226
    }
227
228
    public function setForum(Forum $forum): void
229
    {
230
        $this->forum = $forum;
231
    }
232
233
    public function getForum(): Forum
234
    {
235
        return $this->forum;
236
    }
237
238
    public function setUser($user): void
239
    {
240
        $this->user = $user;
241
    }
242
243
    public function getUser()
244
    {
245
        return $this->user;
246
    }
247
248
    public function getSlug(): string
249
    {
250
        return $this->slug;
251
    }
252
253
    public function setType(TopicType $type): void
254
    {
255
        $this->type = $type;
256
    }
257
258
    public function getType(): TopicType
259
    {
260
        return $this->type;
261
    }
262
263
    public function setMessages(array $messages): void
264
    {
265
        foreach ($messages as $message) {
266
            $this->addMessage($message);
267
        }
268
    }
269
270
    public function addMessage(Message $message): void
271
    {
272
        $message->setTopic($this);
273
        $this->messages[] = $message;
274
    }
275
276
    public function getMessages(): Collection
277
    {
278
        return $this->messages;
279
    }
280
281
    public function setLastMessage(?Message $message = null): void
282
    {
283
        $this->lastMessage = $message;
284
    }
285
286
    public function getLastMessage(): ?Message
287
    {
288
        return $this->lastMessage;
289
    }
290
291
    public function setBoolArchive(bool $boolArchive): void
292
    {
293
        $this->boolArchive = $boolArchive;
294
    }
295
296
    public function getBoolArchive(): bool
297
    {
298
        return $this->boolArchive;
299
    }
300
301
    public function getLastVisitData(): ?TopicUserLastVisit
302
    {
303
        if ($this->userLastVisits->first()) {
304
            return $this->userLastVisits->first();
305
        }
306
        return null;
307
    }
308
309
    #[Groups(['topic:read-status'])]
310
    public function getIsRead(): ?bool
311
    {
312
        $topicVisit = $this->getLastVisitData();
313
        if ($topicVisit && $this->getLastMessage()) {
314
            return $topicVisit->getLastVisitedAt() >= $this->getLastMessage()->getCreatedAt();
315
        } else {
316
            return $this->getLastMessage() === null;
317
        }
318
    }
319
320
    #[Groups(['topic:read-status'])]
321
    public function hasNewContent(): ?bool
322
    {
323
        $topicVisit = $this->getLastVisitData();
324
        if ($topicVisit && $this->getLastMessage()) {
325
            return !$this->getIsRead();
326
        } else {
327
            return $this->getLastMessage() !== null;
328
        }
329
    }
330
331
    #[Groups(['topic:read-status'])]
332
    public function getHasBeenVisited(): ?bool
333
    {
334
        $topicVisit = $this->getLastVisitData();
335
        return $topicVisit !== null;
336
    }
337
338
    #[Groups(['topic:read-status'])]
339
    public function getLastVisitedAt(): ?\DateTime
340
    {
341
        $topicVisit = $this->getLastVisitData();
342
        return $topicVisit?->getLastVisitedAt();
343
    }
344
345
    #[Groups(['topic:read-status'])]
346
    public function getIsNotify(): ?bool
347
    {
348
        $topicVisit = $this->getLastVisitData();
349
        return $topicVisit && $topicVisit->getIsNotify();
350
    }
351
352
353
    public function getUrl(): string
354
    {
355
        return sprintf(
356
            '%s-forum-f%d/%s-topic-t%d/index',
357
            $this->getForum()->getSlug(),
358
            $this->getForum()->getId(),
359
            $this->getSlug(),
360
            $this->getId()
361
        );
362
    }
363
}
364