Passed
Push — master ( 3b9ff0...8f9852 )
by Julito
09:21
created

Message::getFirstReceiver()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
cc 2
eloc 3
c 1
b 1
f 0
nc 2
nop 0
dl 0
loc 7
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
/* For licensing terms, see /license.txt */
6
7
namespace Chamilo\CoreBundle\Entity;
8
9
use ApiPlatform\Core\Annotation\ApiFilter;
10
use ApiPlatform\Core\Annotation\ApiProperty;
11
use ApiPlatform\Core\Annotation\ApiResource;
12
use ApiPlatform\Core\Annotation\ApiSubresource;
13
use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\OrderFilter;
14
use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\SearchFilter;
15
use Chamilo\CourseBundle\Entity\CGroup;
16
use DateTime;
17
use Doctrine\Common\Collections\ArrayCollection;
18
use Doctrine\Common\Collections\Collection;
19
use Doctrine\Common\Collections\Criteria;
20
use Doctrine\ORM\Mapping as ORM;
21
use Gedmo\Mapping\Annotation as Gedmo;
22
use Symfony\Component\Serializer\Annotation\Groups;
23
use Symfony\Component\Validator\Constraints as Assert;
24
25
/**
26
 * Message.
27
 *
28
 * @ORM\Table(name="message", indexes={
29
 *     @ORM\Index(name="idx_message_user_sender", columns={"user_sender_id"}),
30
 *     @ORM\Index(name="idx_message_group", columns={"group_id"}),
31
 *     @ORM\Index(name="idx_message_type", columns={"msg_type"})
32
 * })
33
 * @ORM\Entity(repositoryClass="Chamilo\CoreBundle\Repository\MessageRepository")
34
 * @ORM\EntityListeners({"Chamilo\CoreBundle\Entity\Listener\MessageListener"})
35
 */
36
#[ApiResource(
37
    collectionOperations: [
38
        'get' => [
39
            'security' => "is_granted('ROLE_USER')",  // the get collection is also filtered by MessageExtension.php
40
        ],
41
        'post' => [
42
            //'security' => "is_granted('ROLE_USER')",
43
            /*'messenger' => true,
44
            'output' => false,
45
            'status' => 202,*/
46
            'security_post_denormalize' => "is_granted('CREATE', object)",
47
            //            'deserialize' => false,
48
            //            'controller' => Create::class,
49
            //            'openapi_context' => [
50
            //                'requestBody' => [
51
            //                    'content' => [
52
            //                        'multipart/form-data' => [
53
            //                            'schema' => [
54
            //                                'type' => 'object',
55
            //                                'properties' => [
56
            //                                    'title' => [
57
            //                                        'type' => 'string',
58
            //                                    ],
59
            //                                    'content' => [
60
            //                                        'type' => 'string',
61
            //                                    ],
62
            //                                ],
63
            //                            ],
64
            //                        ],
65
            //                    ],
66
            //                ],
67
            //            ],
68
        ],
69
    ],
70
    itemOperations: [
71
        'get' => [
72
            'security' => "is_granted('VIEW', object)",
73
        ],
74
        'put' => [
75
            'security' => "is_granted('EDIT', object)",
76
        ],
77
        'delete' => [
78
            'security' => "is_granted('DELETE', object)",
79
        ],
80
    ],
81
    attributes: [
82
        'security' => "is_granted('ROLE_USER')",
83
    ],
84
    denormalizationContext: [
85
        'groups' => ['message:write'],
86
    ],
87
    normalizationContext: [
88
        'groups' => ['message:read'],
89
    ],
90
)]
91
#[ApiFilter(OrderFilter::class, properties: ['title', 'sendDate'])]
92
#[ApiFilter(SearchFilter::class, properties: [
93
    'msgType' => 'exact',
94
    'status' => 'exact',
95
    'sender' => 'exact',
96
    'receivers.receiver' => 'exact',
97
    'receivers.tags.tag' => 'exact',
98
])]
99
class Message
100
{
101
    public const MESSAGE_TYPE_INBOX = 1;
102
    public const MESSAGE_TYPE_OUTBOX = 2;
103
    public const MESSAGE_TYPE_PROMOTED = 3;
104
    public const MESSAGE_TYPE_WALL = 4;
105
    public const MESSAGE_TYPE_GROUP = 5;
106
    public const MESSAGE_TYPE_INVITATION = 6;
107
    public const MESSAGE_TYPE_CONVERSATION = 7;
108
109
    // status
110
    public const MESSAGE_STATUS_DELETED = 3;
111
    public const MESSAGE_STATUS_DRAFT = 4;
112
    public const MESSAGE_STATUS_INVITATION_PENDING = 5;
113
    public const MESSAGE_STATUS_INVITATION_ACCEPTED = 6;
114
    public const MESSAGE_STATUS_INVITATION_DENIED = 7;
115
    public const MESSAGE_STATUS_PROMOTED = 13;
116
117
    /**
118
     * @ORM\Column(name="id", type="bigint")
119
     * @ORM\Id
120
     * @ORM\GeneratedValue()
121
     */
122
    #[ApiProperty(identifier: true)]
123
    #[Groups(['message:read'])]
124
    protected ?int $id = null;
125
126
    /**
127
     * @ORM\ManyToOne(targetEntity="User", inversedBy="sentMessages")
128
     * @ORM\JoinColumn(name="user_sender_id", referencedColumnName="id", nullable=false)
129
     */
130
    #[Assert\NotBlank]
131
    #[Groups(['message:read', 'message:write'])]
132
    protected User $sender;
133
134
    /**
135
     * @var Collection|MessageRelUser[]
136
     *
137
     * @ORM\OneToMany(targetEntity="MessageRelUser", mappedBy="message", cascade={"persist", "remove"})
138
     */
139
    #[Assert\Valid]
140
    #[Groups(['message:read', 'message:write'])]
141
    #[ApiSubresource]
142
    protected array | null | Collection $receivers;
143
144
    /**
145
     * @ORM\Column(name="msg_type", type="smallint", nullable=false)
146
     */
147
    #[Assert\NotBlank]
148
    // @todo use enums with PHP 8.1
149
    /*#[Assert\Choice([
150
        self::MESSAGE_TYPE_INBOX,
151
        self::MESSAGE_TYPE_OUTBOX,
152
        self::MESSAGE_TYPE_PROMOTED,
153
    ])]*/
154
    /*#[ApiProperty(attributes: [
155
        'openapi_context' => [
156
            'type' => 'int',
157
            'enum' => [self::MESSAGE_TYPE_INBOX, self::MESSAGE_TYPE_OUTBOX],
158
        ],
159
    ])]*/
160
    #[Groups(['message:read', 'message:write'])]
161
    protected int $msgType;
162
163
    /**
164
     * @ORM\Column(name="status", type="smallint", nullable=false)
165
     */
166
    #[Assert\NotBlank]
167
    #[Groups(['message:read', 'message:write'])]
168
    protected int $status;
169
170
    /**
171
     * @ORM\Column(name="send_date", type="datetime", nullable=false)
172
     */
173
    #[Groups(['message:read'])]
174
    protected DateTime $sendDate;
175
176
    /**
177
     * @ORM\Column(name="title", type="string", length=255, nullable=false)
178
     */
179
    #[Assert\NotBlank]
180
    #[Groups(['message:read', 'message:write'])]
181
    protected string $title;
182
183
    /**
184
     * @ORM\Column(name="content", type="text", nullable=false)
185
     */
186
    #[Assert\NotBlank]
187
    #[Groups(['message:read', 'message:write'])]
188
    protected string $content;
189
190
    #[Groups(['message:read', 'message:write'])]
191
    protected string $firstReceiver;
192
193
    /**
194
     * @ORM\ManyToOne(targetEntity="Chamilo\CourseBundle\Entity\CGroup")
195
     * @ORM\JoinColumn(name="group_id", referencedColumnName="iid", nullable=true, onDelete="CASCADE")
196
     */
197
    protected ?CGroup $group = null;
198
199
    /**
200
     * @var Collection|Message[]
201
     * @ORM\OneToMany(targetEntity="Message", mappedBy="parent")
202
     */
203
    protected Collection $children;
204
205
    /**
206
     * @ORM\ManyToOne(targetEntity="Message", inversedBy="children")
207
     * @ORM\JoinColumn(name="parent_id", referencedColumnName="id")
208
     */
209
    protected ?Message $parent = null;
210
211
    /**
212
     * @Gedmo\Timestampable(on="update")
213
     * @ORM\Column(name="update_date", type="datetime", nullable=true)
214
     */
215
    protected ?DateTime $updateDate;
216
217
    /**
218
     * @ORM\Column(name="votes", type="integer", nullable=true)
219
     */
220
    protected ?int $votes;
221
222
    /**
223
     * @var Collection|MessageAttachment[]
224
     *
225
     * @ORM\OneToMany(targetEntity="MessageAttachment", mappedBy="message")
226
     */
227
    protected Collection $attachments;
228
229
    /**
230
     * @var Collection|MessageFeedback[]
231
     *
232
     * @ORM\OneToMany(targetEntity="MessageFeedback", mappedBy="message", orphanRemoval=true)
233
     */
234
    protected Collection $likes;
235
236
    public function __construct()
237
    {
238
        $this->sendDate = new DateTime('now');
239
        $this->updateDate = $this->sendDate;
240
        $this->content = '';
241
        $this->attachments = new ArrayCollection();
242
        $this->children = new ArrayCollection();
243
        $this->likes = new ArrayCollection();
244
        $this->receivers = new ArrayCollection();
245
        $this->votes = 0;
246
        $this->status = 0;
247
    }
248
249
    /**
250
     * @return null|Collection|MessageRelUser[]
251
     */
252
    public function getReceivers()
253
    {
254
        return $this->receivers;
255
    }
256
257
    public function getFirstReceiver(): ?MessageRelUser
258
    {
259
        if ($this->receivers->count() > 0) {
260
            return $this->receivers->first();
261
        }
262
263
        return null;
264
    }
265
266
    public function hasReceiver(User $receiver)
267
    {
268
        if ($this->receivers->count()) {
269
            $criteria = Criteria::create()->where(
270
                Criteria::expr()->eq('receiver', $receiver),
271
            )->andWhere(
272
                Criteria::expr()->eq('message', $this),
273
            );
274
275
            return $this->receivers->matching($criteria)->count() > 0;
276
        }
277
278
        return false;
279
    }
280
281
    public function addReceiver(User $receiver): self
282
    {
283
        $messageRelUser = (new MessageRelUser())
284
            ->setReceiver($receiver)
285
            ->setMessage($this)
286
        ;
287
        if (!$this->receivers->contains($messageRelUser)) {
288
            $this->receivers->add($messageRelUser);
289
        }
290
291
        return $this;
292
    }
293
294
    /**
295
     * @param Collection|MessageRelUser $receivers
296
     */
297
    public function setReceivers($receivers): self
298
    {
299
        /** @var MessageRelUser $receiver */
300
        foreach ($receivers as $receiver) {
301
            $receiver->setMessage($this);
302
        }
303
        $this->receivers = $receivers;
0 ignored issues
show
Documentation Bug introduced by
It seems like $receivers can also be of type Chamilo\CoreBundle\Entity\MessageRelUser. However, the property $receivers is declared as type Chamilo\CoreBundle\Entit...\Collections\Collection. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
304
305
        return $this;
306
    }
307
308
    public function setSender(User $sender): self
309
    {
310
        $this->sender = $sender;
311
312
        return $this;
313
    }
314
315
    public function getSender(): User
316
    {
317
        return $this->sender;
318
    }
319
320
    public function setMsgType(int $msgType): self
321
    {
322
        $this->msgType = $msgType;
323
324
        return $this;
325
    }
326
327
    public function getMsgType(): int
328
    {
329
        return $this->msgType;
330
    }
331
332
    public function setSendDate(DateTime $sendDate): self
333
    {
334
        $this->sendDate = $sendDate;
335
336
        return $this;
337
    }
338
339
    /**
340
     * Get sendDate.
341
     *
342
     * @return DateTime
343
     */
344
    public function getSendDate()
345
    {
346
        return $this->sendDate;
347
    }
348
349
    public function setTitle(string $title): self
350
    {
351
        $this->title = $title;
352
353
        return $this;
354
    }
355
356
    public function getTitle(): string
357
    {
358
        return $this->title;
359
    }
360
361
    public function setContent(string $content): self
362
    {
363
        $this->content = $content;
364
365
        return $this;
366
    }
367
368
    public function getContent(): string
369
    {
370
        return $this->content;
371
    }
372
373
    public function setUpdateDate(DateTime $updateDate): self
374
    {
375
        $this->updateDate = $updateDate;
376
377
        return $this;
378
    }
379
380
    /**
381
     * Get updateDate.
382
     *
383
     * @return DateTime
384
     */
385
    public function getUpdateDate()
386
    {
387
        return $this->updateDate;
388
    }
389
390
    /**
391
     * Get id.
392
     *
393
     * @return int
394
     */
395
    public function getId()
396
    {
397
        return $this->id;
398
    }
399
400
    public function setVotes(int $votes): self
401
    {
402
        $this->votes = $votes;
403
404
        return $this;
405
    }
406
407
    public function getVotes(): int
408
    {
409
        return $this->votes;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->votes could return the type null which is incompatible with the type-hinted return integer. Consider adding an additional type-check to rule them out.
Loading history...
410
    }
411
412
    /**
413
     * Get attachments.
414
     *
415
     * @return Collection|MessageAttachment[]
416
     */
417
    public function getAttachments()
418
    {
419
        return $this->attachments;
420
    }
421
422
    public function addAttachment(MessageAttachment $attachment): self
423
    {
424
        $this->attachments->add($attachment);
425
        $attachment->setMessage($this);
426
427
        return $this;
428
    }
429
430
    public function getParent(): ?self
431
    {
432
        return $this->parent;
433
    }
434
435
    /**
436
     * @return Collection|Message[]
437
     */
438
    public function getChildren()
439
    {
440
        return $this->children;
441
    }
442
443
    public function addChild(self $child): self
444
    {
445
        $this->children[] = $child;
446
        $child->setParent($this);
447
448
        return $this;
449
    }
450
451
    public function setParent(self $parent = null): self
452
    {
453
        $this->parent = $parent;
454
455
        return $this;
456
    }
457
458
    /**
459
     * @return MessageFeedback[]|Collection
460
     */
461
    public function getLikes()
462
    {
463
        return $this->likes;
464
    }
465
466
    public function getGroup(): ?CGroup
467
    {
468
        return $this->group;
469
    }
470
471
    public function setGroup(?CGroup $group): self
472
    {
473
        $this->msgType = self::MESSAGE_TYPE_GROUP;
474
        $this->group = $group;
475
476
        return $this;
477
    }
478
479
    public function getStatus(): int
480
    {
481
        return $this->status;
482
    }
483
484
    public function setStatus(int $status): self
485
    {
486
        $this->status = $status;
487
488
        return $this;
489
    }
490
}
491