Passed
Pull Request — master (#7089)
by
unknown
10:12
created

findNextNotDoneAdvancesForCourse()   A

Complexity

Conditions 5
Paths 8

Size

Total Lines 29
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 13
c 1
b 0
f 0
nc 8
nop 3
dl 0
loc 29
rs 9.5222
1
<?php
2
3
declare(strict_types=1);
4
5
/* For licensing terms, see /license.txt */
6
7
namespace Chamilo\CourseBundle\Repository;
8
9
use Chamilo\CoreBundle\Entity\Course;
10
use Chamilo\CoreBundle\Entity\Session;
11
use Chamilo\CoreBundle\Repository\ResourceRepository;
12
use Chamilo\CourseBundle\Entity\CThematic;
13
use Chamilo\CourseBundle\Entity\CThematicAdvance;
14
use Doctrine\Persistence\ManagerRegistry;
15
16
/**
17
 * Repository for course thematics and related advances.
18
 */
19
final class CThematicRepository extends ResourceRepository
20
{
21
    public function __construct(ManagerRegistry $registry)
22
    {
23
        parent::__construct($registry, CThematic::class);
24
    }
25
26
    /**
27
     * Get all active thematics linked to a given course/session,
28
     * ordered by the same rules as other course resources.
29
     *
30
     * @return CThematic[]
31
     */
32
    public function getThematicListForCourse(Course $course, ?Session $session = null): array
33
    {
34
        $qb = $this->getResourcesByCourse($course, $session, null, null, true, true);
35
        $qb->andWhere('resource.active = 1');
36
37
        return $qb->getQuery()->getResult();
38
    }
39
40
    /**
41
     * Return the last done advance for the given course/session
42
     */
43
    public function findLastDoneAdvanceForCourse(Course $course, ?Session $session = null): ?CThematicAdvance
44
    {
45
        $thematics = $this->getThematicListForCourse($course, $session);
46
47
        /** @var CThematicAdvance[] $candidates */
48
        $candidates = [];
49
50
        foreach ($thematics as $thematic) {
51
            foreach ($thematic->getAdvances() as $advance) {
52
                if (true === $advance->getDoneAdvance()) {
53
                    $candidates[] = $advance;
54
                }
55
            }
56
        }
57
58
        if (empty($candidates)) {
59
            return null;
60
        }
61
62
        // Sort by start date ASC and return the last one
63
        usort(
64
            $candidates,
65
            static fn (CThematicAdvance $a, CThematicAdvance $b) =>
66
                $a->getStartDate() <=> $b->getStartDate()
67
        );
68
69
        return end($candidates) ?: null;
70
    }
71
72
    /**
73
     * Return the first $limit advances not done for the given course/session
74
     *
75
     * @return CThematicAdvance[]
76
     */
77
    public function findNextNotDoneAdvancesForCourse(
78
        Course $course,
79
        ?Session $session = null,
80
        int $limit = 1
81
    ): array {
82
        $thematics = $this->getThematicListForCourse($course, $session);
83
84
        /** @var CThematicAdvance[] $pending */
85
        $pending = [];
86
87
        foreach ($thematics as $thematic) {
88
            foreach ($thematic->getAdvances() as $advance) {
89
                if (false === $advance->getDoneAdvance()) {
90
                    $pending[] = $advance;
91
                }
92
            }
93
        }
94
95
        if (empty($pending)) {
96
            return [];
97
        }
98
99
        usort(
100
            $pending,
101
            static fn (CThematicAdvance $a, CThematicAdvance $b) =>
102
                $a->getStartDate() <=> $b->getStartDate()
103
        );
104
105
        return array_slice($pending, 0, $limit);
106
    }
107
108
    /**
109
     * Compute the global average of thematic advances for the given course/session
110
     */
111
    public function calculateTotalAverageForCourse(Course $course, ?Session $session = null): float
112
    {
113
        $thematics = $this->getThematicListForCourse($course, $session);
114
115
        if (empty($thematics)) {
116
            return 0.0;
117
        }
118
119
        $averages = [];
120
121
        foreach ($thematics as $thematic) {
122
            $advances = $thematic->getAdvances();
123
            $total = $advances->count();
124
125
            if (0 === $total) {
126
                continue;
127
            }
128
129
            $done = 0;
130
            foreach ($advances as $advance) {
131
                if (true === $advance->getDoneAdvance()) {
132
                    ++$done;
133
                }
134
            }
135
136
            $averages[] = round(($done * 100) / $total);
137
        }
138
139
        if (empty($averages)) {
140
            return 0.0;
141
        }
142
143
        return round(array_sum($averages) / count($thematics));
144
    }
145
}
146