Passed
Pull Request — master (#6257)
by
unknown
09:03
created

CStudentPublication::getResourceIdentifier()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
declare(strict_types=1);
6
7
namespace Chamilo\CourseBundle\Entity;
8
9
use ApiPlatform\Doctrine\Common\Filter\OrderFilterInterface;
10
use ApiPlatform\Doctrine\Orm\Filter\OrderFilter;
11
use ApiPlatform\Metadata\ApiFilter;
12
use ApiPlatform\Metadata\ApiResource;
13
use ApiPlatform\Metadata\Delete;
14
use ApiPlatform\Metadata\Get;
15
use ApiPlatform\Metadata\GetCollection;
16
use ApiPlatform\Metadata\Post;
17
use ApiPlatform\Metadata\Put;
18
use Chamilo\CoreBundle\Controller\Api\CreateStudentPublicationFileAction;
19
use Chamilo\CoreBundle\Entity\AbstractResource;
20
use Chamilo\CoreBundle\Entity\ResourceInterface;
21
use Chamilo\CoreBundle\Entity\ResourceNode;
22
use Chamilo\CoreBundle\Entity\Session;
23
use Chamilo\CoreBundle\Entity\User;
24
use Chamilo\CoreBundle\Filter\CidFilter;
25
use Chamilo\CoreBundle\Filter\ParentNullFilter;
26
use Chamilo\CoreBundle\Filter\SidFilter;
27
use Chamilo\CoreBundle\State\CStudentPublicationPostStateProcessor;
28
use Chamilo\CourseBundle\Repository\CStudentPublicationRepository;
29
use DateTime;
30
use Doctrine\Common\Collections\ArrayCollection;
31
use Doctrine\Common\Collections\Collection;
32
use Doctrine\ORM\Mapping as ORM;
33
use Stringable;
34
use Symfony\Component\Serializer\Annotation\Groups;
35
use Symfony\Component\Validator\Constraints as Assert;
36
37
#[ORM\Table(name: 'c_student_publication')]
38
#[ORM\Entity(repositoryClass: CStudentPublicationRepository::class)]
39
#[ApiResource(
40
    operations: [
41
        new Put(security: "is_granted('EDIT', object.resourceNode)"),
42
        new Get(
43
            normalizationContext: [
44
                'groups' => ['student_publication:read', 'student_publication:item:get'],
45
            ],
46
            security: "is_granted('VIEW', object.resourceNode)",
47
        ),
48
        new GetCollection(),
49
        new Delete(security: "is_granted('DELETE', object.resourceNode)"),
50
        new Post(
51
            security: "is_granted('ROLE_CURRENT_COURSE_TEACHER') or is_granted('ROLE_CURRENT_COURSE_SESSION_TEACHER') or is_granted('ROLE_TEACHER')",
52
            processor: CStudentPublicationPostStateProcessor::class
53
        ),
54
        new Post(
55
            uriTemplate: '/c_student_publications/upload',
56
            controller: CreateStudentPublicationFileAction::class,
57
            security: "is_granted('ROLE_STUDENT') or is_granted('ROLE_STUDENT_BOSS')",
58
            validationContext: ['groups' => ['Default', 'c_student_publication:write']],
59
            deserialize: false
60
        ),
61
    ],
62
    normalizationContext: [
63
        'groups' => ['student_publication:read'],
64
    ],
65
    denormalizationContext: [
66
        'groups' => ['c_student_publication:write'],
67
    ],
68
    order: ['sentDate' => 'DESC'],
69
)]
70
#[ApiFilter(
71
    OrderFilter::class,
72
    properties: [
73
        'title',
74
        'sentDate' => ['nulls_comparison' => OrderFilterInterface::NULLS_SMALLEST],
75
        'assignment.expiresOn' => ['nulls_comparison' => OrderFilterInterface::NULLS_SMALLEST],
76
        'assingment.endsOn' => ['nulls_comparison' => OrderFilterInterface::NULLS_SMALLEST],
77
    ]
78
)]
79
#[ApiFilter(ParentNullFilter::class, properties: ['publicationParent.iid' => null])]
80
#[ApiFilter(filterClass: CidFilter::class)]
81
#[ApiFilter(filterClass: SidFilter::class)]
82
class CStudentPublication extends AbstractResource implements ResourceInterface, Stringable
83
{
84
    #[Groups(['c_student_publication:write', 'student_publication:read'])]
85
    public bool $addToGradebook = false;
86
87
    #[Groups(['c_student_publication:write'])]
88
    public int $gradebookCategoryId = 0;
89
90
    #[Groups(['c_student_publication:write', 'student_publication:read'])]
91
    public bool $addToCalendar = false;
92
    #[ORM\Column(name: 'iid', type: 'integer')]
93
    #[ORM\Id]
94
    #[ORM\GeneratedValue]
95
    protected ?int $iid = null;
96
97
    #[Assert\NotBlank]
98
    #[ORM\Column(name: 'title', type: 'string', length: 255, nullable: false)]
99
    #[Groups(['c_student_publication:write', 'student_publication:read'])]
100
    protected string $title;
101
102
    #[ORM\Column(name: 'description', type: 'text', nullable: true)]
103
    #[Groups(['c_student_publication:write', 'student_publication:item:get', 'student_publication:read'])]
104
    protected ?string $description;
105
106
    #[ORM\Column(name: 'author', type: 'string', length: 255, nullable: true)]
107
    protected ?string $author = null;
108
109
    #[ORM\Column(name: 'active', type: 'integer', nullable: true)]
110
    protected ?int $active = null;
111
112
    #[ORM\Column(name: 'accepted', type: 'boolean', nullable: true)]
113
    protected ?bool $accepted = null;
114
115
    #[ORM\Column(name: 'post_group_id', type: 'integer', nullable: false)]
116
    protected int $postGroupId;
117
118
    #[ORM\Column(name: 'sent_date', type: 'datetime', nullable: true)]
119
    #[Groups(['student_publication:read'])]
120
    protected ?DateTime $sentDate;
121
122
    #[Assert\NotBlank]
123
    #[Assert\Choice(callback: 'getFileTypes')]
124
    #[ORM\Column(name: 'filetype', type: 'string', length: 10, nullable: false)]
125
    protected string $filetype;
126
127
    #[ORM\Column(name: 'has_properties', type: 'integer', nullable: false)]
128
    protected int $hasProperties;
129
130
    #[ORM\Column(name: 'view_properties', type: 'boolean', nullable: true)]
131
    protected ?bool $viewProperties = null;
132
133
    #[ORM\Column(name: 'qualification', type: 'float', precision: 6, scale: 2, nullable: false)]
134
    #[Groups(['c_student_publication:write', 'student_publication:read'])]
135
    protected float $qualification;
136
137
    #[ORM\Column(name: 'date_of_qualification', type: 'datetime', nullable: true)]
138
    protected ?DateTime $dateOfQualification = null;
139
140
    /**
141
     * @var Collection<int, CStudentPublication>
142
     */
143
    #[ORM\OneToMany(mappedBy: 'publicationParent', targetEntity: self::class)]
144
    protected Collection $children;
145
146
    /**
147
     * @var Collection<int, CStudentPublicationComment>
148
     */
149
    #[ORM\OneToMany(mappedBy: 'publication', targetEntity: CStudentPublicationComment::class)]
150
    #[Groups(['student_publication:read'])]
151
    protected Collection $comments;
152
153
    #[Groups(['c_student_publication:write', 'student_publication:read', 'student_publication_comment:read'])]
154
    #[ORM\ManyToOne(targetEntity: self::class, inversedBy: 'children')]
155
    #[ORM\JoinColumn(name: 'parent_id', referencedColumnName: 'iid')]
156
    protected ?CStudentPublication $publicationParent;
157
158
    #[Groups(['student_publication:read', 'student_publication_comment:read'])]
159
    #[ORM\ManyToOne(targetEntity: User::class)]
160
    #[ORM\JoinColumn(name: 'user_id', referencedColumnName: 'id', onDelete: 'CASCADE')]
161
    protected User $user;
162
163
    #[Groups(['c_student_publication:write', 'student_publication:read'])]
164
    #[ORM\OneToOne(mappedBy: 'publication', targetEntity: CStudentPublicationAssignment::class, cascade: ['persist'])]
165
    #[Assert\Valid]
166
    protected ?CStudentPublicationAssignment $assignment = null;
167
168
    #[ORM\Column(name: 'qualificator_id', type: 'integer', nullable: false)]
169
    protected int $qualificatorId;
170
171
    #[Assert\NotBlank]
172
    #[ORM\Column(name: 'weight', type: 'float', precision: 6, scale: 2, nullable: false)]
173
    #[Groups(['c_student_publication:write', 'student_publication:read'])]
174
    protected float $weight = 0;
175
176
    #[ORM\Column(name: 'allow_text_assignment', type: 'integer', nullable: false)]
177
    #[Groups(['c_student_publication:write', 'student_publication:item:get'])]
178
    protected int $allowTextAssignment;
179
180
    #[ORM\Column(name: 'contains_file', type: 'integer', nullable: false)]
181
    protected int $containsFile;
182
183
    #[ORM\Column(name: 'document_id', type: 'integer', nullable: false)]
184
    protected int $documentId;
185
186
    #[ORM\Column(name: 'filesize', type: 'integer', nullable: true)]
187
    protected ?int $fileSize = null;
188
189
    #[ORM\Column(name: 'duration', type: 'integer', nullable: true)]
190
    protected ?int $duration = null;
191
192
    #[ORM\ManyToOne(targetEntity: CGroupCategory::class)]
193
    #[ORM\JoinColumn(name: 'group_category_id', referencedColumnName: 'iid', nullable: true)]
194
    protected ?CGroupCategory $groupCategory = null;
195
196
    #[ORM\Column(name: 'student_delete_own_publication', type: 'boolean', nullable: true, options: ['default' => 0])]
197
    protected ?bool $studentDeleteOwnPublication = null;
198
199
    #[ORM\Column(name: 'default_visibility', type: 'boolean', nullable: true, options: ['default' => 0])]
200
    protected ?bool $defaultVisibility = null;
201
202
    #[ORM\Column(name: 'extensions', type: 'text', nullable: true)]
203
    protected ?string $extensions = null;
204
205
    #[ORM\Column(name: 'group_category_work_id', type: 'integer', nullable: false, options: ['default' => 0])]
206
    #[Groups(['c_student_publication:write', 'student_publication:read'])]
207
    protected int $groupCategoryWorkId = 0;
208
209
    public function __construct()
210
    {
211
        $this->description = '';
212
        $this->documentId = 0;
213
        $this->active = 1;
214
        $this->hasProperties = 0;
215
        $this->containsFile = 0;
216
        $this->publicationParent = null;
217
        $this->qualificatorId = 0;
218
        $this->qualification = 0;
219
        $this->assignment = null;
220
        $this->postGroupId = 0;
221
        $this->allowTextAssignment = 0;
222
        $this->filetype = 'folder';
223
        $this->sentDate = new DateTime();
224
        $this->children = new ArrayCollection();
225
        $this->comments = new ArrayCollection();
226
    }
227
228
    public function __toString(): string
229
    {
230
        return $this->getTitle();
231
    }
232
233
    public function getTitle(): string
234
    {
235
        return $this->title;
236
    }
237
238
    public function setTitle(string $title): self
239
    {
240
        $this->title = $title;
241
242
        return $this;
243
    }
244
245
    public function getFileTypes(): array
246
    {
247
        return ['file', 'folder'];
248
    }
249
250
    public function getDescription(): ?string
251
    {
252
        return $this->description;
253
    }
254
255
    public function setDescription(string $description): self
256
    {
257
        $this->description = $description;
258
259
        return $this;
260
    }
261
262
    public function getAuthor(): ?string
263
    {
264
        return $this->author;
265
    }
266
267
    public function setAuthor(string $author): self
268
    {
269
        $this->author = $author;
270
271
        return $this;
272
    }
273
274
    public function getActive(): ?int
275
    {
276
        return $this->active;
277
    }
278
279
    public function setActive(int $active): self
280
    {
281
        $this->active = $active;
282
283
        return $this;
284
    }
285
286
    public function getAccepted(): ?bool
287
    {
288
        return $this->accepted;
289
    }
290
291
    public function setAccepted(bool $accepted): self
292
    {
293
        $this->accepted = $accepted;
294
295
        return $this;
296
    }
297
298
    public function getPostGroupId(): int
299
    {
300
        return $this->postGroupId;
301
    }
302
303
    public function setPostGroupId(int $postGroupId): static
304
    {
305
        $this->postGroupId = $postGroupId;
306
307
        return $this;
308
    }
309
310
    public function getSentDate(): ?DateTime
311
    {
312
        return $this->sentDate;
313
    }
314
315
    public function setSentDate(DateTime $sentDate): self
316
    {
317
        $this->sentDate = $sentDate;
318
319
        return $this;
320
    }
321
322
    public function getFiletype(): string
323
    {
324
        return $this->filetype;
325
    }
326
327
    public function setFiletype(string $filetype): self
328
    {
329
        $this->filetype = $filetype;
330
331
        return $this;
332
    }
333
334
    public function getHasProperties(): int
335
    {
336
        return $this->hasProperties;
337
    }
338
339
    public function setHasProperties(int $hasProperties): self
340
    {
341
        $this->hasProperties = $hasProperties;
342
343
        return $this;
344
    }
345
346
    public function getViewProperties(): ?bool
347
    {
348
        return $this->viewProperties;
349
    }
350
351
    public function setViewProperties(bool $viewProperties): self
352
    {
353
        $this->viewProperties = $viewProperties;
354
355
        return $this;
356
    }
357
358
    public function getQualification(): float
359
    {
360
        return $this->qualification;
361
    }
362
363
    public function setQualification(float $qualification): self
364
    {
365
        $this->qualification = $qualification;
366
367
        return $this;
368
    }
369
370
    public function getDateOfQualification(): ?DateTime
371
    {
372
        return $this->dateOfQualification;
373
    }
374
375
    public function setDateOfQualification(DateTime $dateOfQualification): self
376
    {
377
        $this->dateOfQualification = $dateOfQualification;
378
379
        return $this;
380
    }
381
382
    public function getQualificatorId(): int
383
    {
384
        return $this->qualificatorId;
385
    }
386
387
    public function setQualificatorId(int $qualificatorId): static
388
    {
389
        $this->qualificatorId = $qualificatorId;
390
391
        return $this;
392
    }
393
394
    public function getWeight(): float
395
    {
396
        return $this->weight;
397
    }
398
399
    public function setWeight(float $weight): self
400
    {
401
        $this->weight = $weight;
402
403
        return $this;
404
    }
405
406
    public function getAllowTextAssignment(): int
407
    {
408
        return $this->allowTextAssignment;
409
    }
410
411
    public function setAllowTextAssignment(int $allowTextAssignment): self
412
    {
413
        $this->allowTextAssignment = $allowTextAssignment;
414
415
        return $this;
416
    }
417
418
    public function getContainsFile(): int
419
    {
420
        return $this->containsFile;
421
    }
422
423
    public function setContainsFile(int $containsFile): self
424
    {
425
        $this->containsFile = $containsFile;
426
427
        return $this;
428
    }
429
430
    public function getDocumentId(): int
431
    {
432
        return $this->documentId;
433
    }
434
435
    public function setDocumentId(int $documentId): self
436
    {
437
        $this->documentId = $documentId;
438
439
        return $this;
440
    }
441
442
    public function getFileSize(): int
443
    {
444
        return $this->fileSize;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->fileSize 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...
445
    }
446
447
    public function setFileSize(int $fileSize): self
448
    {
449
        $this->fileSize = $fileSize;
450
451
        return $this;
452
    }
453
454
    #[Groups(['student_publication:read'])]
455
    public function getCorrection(): ?ResourceNode
456
    {
457
        if (!$this->hasResourceNode()) {
458
            return null;
459
        }
460
461
        $expectedTitle = $this->getExtensions();
462
        $children = $this->getResourceNode()->getChildren();
463
464
        foreach ($children as $child) {
465
            $name = $child->getResourceType()->getTitle();
466
467
            if ('student_publications_corrections' === $name) {
468
                if ($child->getTitle() === $expectedTitle) {
469
                    return $child;
470
                }
471
            }
472
        }
473
474
        return null;
475
    }
476
477
    #[Groups(['student_publication:read'])]
478
    public function getCorrectionTitle(): ?string
479
    {
480
        return $this->getExtensions();
481
    }
482
483
    #[Groups(['student_publication:read'])]
484
    public function getChildFileCount(): int
485
    {
486
        return $this->children
487
            ->filter(fn (self $child) => $child->getFiletype() === 'file' && $child->getActive() !== 2)
488
            ->count();
489
    }
490
491
    /**
492
     * @return Collection<int, CStudentPublication>
493
     */
494
    public function getChildren(): Collection
495
    {
496
        return $this->children;
497
    }
498
499
    public function setChildren(Collection $children): self
500
    {
501
        $this->children = $children;
502
503
        return $this;
504
    }
505
506
    public function getAssignment(): ?CStudentPublicationAssignment
507
    {
508
        return $this->assignment;
509
    }
510
511
    public function setAssignment(?CStudentPublicationAssignment $assignment): self
512
    {
513
        $this->assignment = $assignment;
514
515
        if ($assignment) {
516
            $assignment->setPublication($this);
517
        }
518
519
        return $this;
520
    }
521
522
    public function getPublicationParent(): ?self
523
    {
524
        return $this->publicationParent;
525
    }
526
527
    public function setPublicationParent(?self $publicationParent): self
528
    {
529
        $this->publicationParent = $publicationParent;
530
531
        return $this;
532
    }
533
534
    public function getUser(): User
535
    {
536
        return $this->user;
537
    }
538
539
    public function setUser(User $user): self
540
    {
541
        $this->user = $user;
542
543
        return $this;
544
    }
545
546
    /**
547
     * @return Collection<int, CStudentPublicationComment>
548
     */
549
    public function getComments(): Collection
550
    {
551
        return $this->comments;
552
    }
553
554
    public function setComments(Collection $comments): self
555
    {
556
        $this->comments = $comments;
557
558
        return $this;
559
    }
560
561
    public function getDuration(): ?int
562
    {
563
        return $this->duration;
564
    }
565
566
    public function setDuration(?int $duration): self
567
    {
568
        $this->duration = $duration;
569
570
        return $this;
571
    }
572
573
    public function getGroupCategory(): ?CGroupCategory
574
    {
575
        return $this->groupCategory;
576
    }
577
578
    public function setGroupCategory(?CGroupCategory $groupCategory): self
579
    {
580
        $this->groupCategory = $groupCategory;
581
582
        return $this;
583
    }
584
585
    public function getStudentDeleteOwnPublication(): ?bool
586
    {
587
        return $this->studentDeleteOwnPublication;
588
    }
589
590
    public function setStudentDeleteOwnPublication(?bool $studentDeleteOwnPublication): self
591
    {
592
        $this->studentDeleteOwnPublication = $studentDeleteOwnPublication;
593
594
        return $this;
595
    }
596
597
    public function getDefaultVisibility(): ?bool
598
    {
599
        return $this->defaultVisibility;
600
    }
601
602
    public function setDefaultVisibility(?bool $defaultVisibility): self
603
    {
604
        $this->defaultVisibility = $defaultVisibility;
605
606
        return $this;
607
    }
608
609
    public function getExtensions(): ?string
610
    {
611
        return $this->extensions;
612
    }
613
614
    public function setExtensions(?string $extensions): self
615
    {
616
        $this->extensions = $extensions;
617
618
        return $this;
619
    }
620
621
    public function getResourceIdentifier(): int
622
    {
623
        return $this->getIid();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->getIid() 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...
624
    }
625
626
    #[Groups(['student_publication:read'])]
627
    public function getIid(): ?int
628
    {
629
        return $this->iid;
630
    }
631
632
    public function getResourceName(): string
633
    {
634
        return $this->getTitle();
635
    }
636
637
    public function setResourceName(string $name): self
638
    {
639
        return $this->setTitle($name);
640
    }
641
642
    #[Groups(['student_publication:read'])]
643
    public function getUniqueStudentAttemptsTotal(): int
644
    {
645
        $userIdList = [];
646
647
        $reduce = $this->children
648
            ->filter(function (self $child) {
649
                return $child->postGroupId === $this->postGroupId;
650
            })
651
            ->reduce(function (int $accumulator, self $child) use (&$userIdList): int {
652
                $user = $child->getUser();
653
654
                if (!\in_array($user->getId(), $userIdList, true)) {
655
                    $userIdList[] = $user->getId();
656
657
                    return $accumulator + 1;
658
                }
659
660
                return $accumulator;
661
            }, 0);
662
663
        return $reduce ?: 0;
664
    }
665
666
    #[Groups(['student_publication:read'])]
667
    public function getStudentSubscribedToWork(): int
668
    {
669
        $firstLink = $this->getFirstResourceLink();
670
671
        $course = $firstLink->getCourse();
672
        $session = $firstLink->getSession();
673
        $group = $firstLink->getGroup();
674
675
        if ($group) {
676
            return $group->getMembers()->count();
677
        }
678
679
        if ($session) {
680
            return $session->getSessionRelCourseRelUsersByStatus($course, Session::STUDENT)->count();
681
        }
682
683
        if ($course) {
684
            return $course->getStudentSubscriptions()->count();
685
        }
686
687
        return 0;
688
    }
689
690
    #[Groups(['student_publication:read'])]
691
    public function getCorrectionDownloadUrl(): ?string
692
    {
693
        $correctionNode = $this->getCorrection();
694
        if ($correctionNode && $correctionNode->getFirstResourceFile()) {
695
            $uuid = $correctionNode->getUuid();
696
            if ($uuid) {
697
                return '/r/student_publication/student_publications_corrections/'.$uuid.'/download';
698
            }
699
        }
700
701
        return null;
702
    }
703
704
    public function getGroupCategoryWorkId(): int
705
    {
706
        return $this->groupCategoryWorkId;
707
    }
708
709
    public function setGroupCategoryWorkId(int $groupCategoryWorkId): self
710
    {
711
        $this->groupCategoryWorkId = $groupCategoryWorkId;
712
713
        return $this;
714
    }
715
}
716