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

findStudentProgressByCourse()   B

Complexity

Conditions 7
Paths 14

Size

Total Lines 72
Code Lines 49

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 7
eloc 49
nc 14
nop 2
dl 0
loc 72
rs 8.1793
c 1
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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\CourseRelUser;
11
use Chamilo\CoreBundle\Entity\ResourceLink;
12
use Chamilo\CoreBundle\Entity\Session;
13
use Chamilo\CoreBundle\Entity\SessionRelCourseRelUser;
14
use Chamilo\CoreBundle\Entity\User;
15
use Chamilo\CoreBundle\Repository\ResourceRepository;
16
use Chamilo\CourseBundle\Entity\CGroup;
17
use Chamilo\CourseBundle\Entity\CStudentPublication;
18
use Chamilo\CourseBundle\Entity\CStudentPublicationComment;
19
use Chamilo\CourseBundle\Entity\CStudentPublicationRelUser;
20
use Doctrine\Common\Collections\Criteria;
21
use Doctrine\ORM\QueryBuilder;
22
use Doctrine\ORM\Tools\Pagination\Paginator;
23
use Doctrine\Persistence\ManagerRegistry;
24
25
final class CStudentPublicationRepository extends ResourceRepository
26
{
27
    public function __construct(ManagerRegistry $registry)
28
    {
29
        parent::__construct($registry, CStudentPublication::class);
30
    }
31
32
    public function findAllByCourse(
33
        Course $course,
34
        ?Session $session = null,
35
        ?string $title = null,
36
        ?int $active = null,
37
        ?string $fileType = null
38
    ): QueryBuilder {
39
        $qb = $this->getResourcesByCourse($course, $session);
40
41
        $this->addTitleQueryBuilder($title, $qb);
42
        $this->addActiveQueryBuilder($active, $qb);
43
        $this->addFileTypeQueryBuilder($fileType, $qb);
44
45
        return $qb;
46
    }
47
48
    public function getStudentAssignments(
49
        CStudentPublication $publication,
50
        Course $course,
51
        ?Session $session = null,
52
        ?CGroup $group = null,
53
        ?User $user = null
54
    ): QueryBuilder {
55
        $qb = $this->getResourcesByCourse($course, $session, $group);
56
57
        $this->addNotDeletedPublicationQueryBuilder($qb);
58
        $qb
59
            ->andWhere('resource.publicationParent =:publicationParent')
60
            ->setParameter('publicationParent', $publication)
61
        ;
62
63
        return $qb;
64
    }
65
66
    public function getStudentPublicationByUser(User $user, Course $course, ?Session $session = null): array
67
    {
68
        $qb = $this->findAllByCourse($course, $session);
69
70
        /** @var CStudentPublication[] $works */
71
        $works = $qb->getQuery()->getResult();
72
        $list = [];
73
        foreach ($works as $work) {
74
            $qb = $this->getStudentAssignments($work, $course, $session, null, $user);
75
            $results = $qb->getQuery()->getResult();
76
            $list[$work->getIid()]['work'] = $work;
77
            $list[$work->getIid()]['results'] = $results;
78
        }
79
80
        return $list;
81
    }
82
83
    public function countUserPublications(
84
        User $user,
85
        Course $course,
86
        ?Session $session = null,
87
        ?CGroup $group = null
88
    ): int {
89
        $qb = $this->getResourcesByCourseLinkedToUser($user, $course, $session);
90
        $qb->andWhere('resource.publicationParent IS NOT NULL');
91
92
        return $this->getCount($qb);
93
    }
94
95
    public function countCoursePublications(Course $course, ?Session $session = null, ?CGroup $group = null): int
96
    {
97
        $qb = $this->getResourcesByCourse($course, $session, $group);
98
99
        $this->addNotDeletedPublicationQueryBuilder($qb);
100
101
        return $this->getCount($qb);
102
    }
103
104
    /**
105
     * Find all the works registered by a teacher.
106
     */
107
    public function findWorksByTeacher(User $user, Course $course, ?Session $session = null): array
108
    {
109
        $qb = $this->getResourcesByCourseLinkedToUser($user, $course, $session);
110
        $qb->andWhere('resource.publicationParent IS NOT NULL');
111
112
        return $qb
113
            ->orderBy('resource.sentDate', Criteria::ASC)
114
            ->getQuery()
115
            ->getResult()
116
        ;
117
    }
118
119
    private function addActiveQueryBuilder(?int $active = null, ?QueryBuilder $qb = null): void
120
    {
121
        $qb = $this->getOrCreateQueryBuilder($qb);
122
123
        if (null !== $active) {
124
            $qb
125
                ->andWhere('resource.active = :active')
126
                ->setParameter('active', $active)
127
            ;
128
        }
129
    }
130
131
    private function addNotDeletedPublicationQueryBuilder(?QueryBuilder $qb = null): void
132
    {
133
        $qb = $this->getOrCreateQueryBuilder($qb);
134
        $qb
135
            ->andWhere('resource.active <> 2')
136
        ;
137
    }
138
139
    private function addFileTypeQueryBuilder(?string $fileType, ?QueryBuilder $qb = null): void
140
    {
141
        $qb = $this->getOrCreateQueryBuilder($qb);
142
        if (null === $fileType) {
143
            return;
144
        }
145
146
        $qb
147
            ->andWhere('resource.filetype = :filetype')
148
            ->setParameter('filetype', $fileType)
149
        ;
150
    }
151
152
    public function findVisibleAssignmentsForStudent(Course $course, ?Session $session = null): array
153
    {
154
        $userId = api_get_user_id();
155
156
        $qb = $this->createQueryBuilder('resource')
157
            ->select('resource')
158
            ->addSelect('(SELECT COUNT(comment.iid) FROM ' . CStudentPublicationComment::class . ' comment WHERE comment.publication = resource) AS commentsCount')
159
            ->addSelect('(SELECT COUNT(c1.iid) FROM ' . CStudentPublication::class . ' c1 WHERE c1.publicationParent = resource AND c1.extensions IS NOT NULL AND c1.extensions <> \'\') AS correctionsCount')
160
            ->addSelect('(SELECT MAX(c2.sentDate) FROM ' . CStudentPublication::class . ' c2 WHERE c2.publicationParent = resource) AS lastUpload')
161
            ->join('resource.resourceNode', 'rn')
162
            ->join('rn.resourceLinks', 'rl')
163
            ->leftJoin(CStudentPublicationRelUser::class, 'rel', 'WITH', 'rel.publication = resource AND rel.user = :userId')
164
            ->where('resource.publicationParent IS NULL')
165
            ->andWhere('resource.active IN (0, 1)')
166
            ->andWhere('resource.filetype = :filetype')
167
            ->setParameter('filetype', 'folder')
168
            ->andWhere('rl.visibility = 2')
169
            ->andWhere('rl.course = :course')
170
            ->setParameter('course', $course)
171
            ->setParameter('userId', $userId)
172
            ->orderBy('resource.sentDate', 'DESC');
173
174
        if ($session) {
175
            $qb->andWhere('rl.session = :session')
176
                ->setParameter('session', $session);
177
        } else {
178
            $qb->andWhere('rl.session IS NULL');
179
        }
180
181
        $qb->andWhere('
182
            NOT EXISTS (
183
                SELECT 1 FROM '.CStudentPublicationRelUser::class.' rel_all
184
                WHERE rel_all.publication = resource
185
            )
186
            OR rel.iid IS NOT NULL
187
        ');
188
189
        return $qb->getQuery()->getResult();
190
    }
191
192
    public function findStudentProgressByCourse(Course $course, ?Session $session): array
193
    {
194
        $em = $this->getEntityManager();
195
196
        $qb = $em->createQueryBuilder();
197
        $qb->select('sp')
198
            ->from(CStudentPublication::class, 'sp')
199
            ->join('sp.resourceNode', 'rn')
200
            ->join(ResourceLink::class, 'rl', 'WITH', 'rl.resourceNode = rn')
201
            ->where('rl.course = :course')
202
            ->andWhere($session ? 'rl.session = :session' : 'rl.session IS NULL')
203
            ->andWhere('sp.active IN (0, 1)')
204
            ->andWhere('sp.filetype = :filetype')
205
            ->andWhere('sp.publicationParent IS NULL')
206
            ->setParameter('course', $course)
207
            ->setParameter('filetype', 'folder');
208
209
        if ($session) {
210
            $qb->setParameter('session', $session);
211
        }
212
213
        $workFolders = $qb->getQuery()->getResult();
214
215
        if (empty($workFolders)) {
216
            return [];
217
        }
218
219
        $workIds = array_map(fn (CStudentPublication $sp) => $sp->getIid(), $workFolders);
220
221
        if ($session) {
222
            $students = $em->getRepository(SessionRelCourseRelUser::class)->findBy([
223
                'session' => $session,
224
                'course' => $course,
225
                'status' => Session::STUDENT,
226
            ]);
227
        } else {
228
            $students = $em->getRepository(CourseRelUser::class)->findBy([
229
                'course' => $course,
230
                'status' => CourseRelUser::STUDENT,
231
            ]);
232
        }
233
234
        if (empty($students)) {
235
            return [];
236
        }
237
238
        $studentProgress = [];
239
240
        foreach ($students as $studentRel) {
241
            $user = $studentRel->getUser();
242
243
            $qb = $em->createQueryBuilder();
244
            $qb->select('COUNT(DISTINCT sp.publicationParent)')
245
                ->from(CStudentPublication::class, 'sp')
246
                ->where('sp.user = :user')
247
                ->andWhere('sp.publicationParent IN (:workIds)')
248
                ->andWhere('sp.active IN (0, 1)')
249
                ->setParameter('user', $user)
250
                ->setParameter('workIds', $workIds);
251
252
            $submissionCount = (int) $qb->getQuery()->getSingleScalarResult();
253
254
            $studentProgress[] = [
255
                'id' => $user->getId(),
256
                'firstname' => $user->getFirstname(),
257
                'lastname' => $user->getLastname(),
258
                'submissions' => $submissionCount,
259
                'totalAssignments' => count($workIds),
260
            ];
261
        }
262
263
        return $studentProgress;
264
    }
265
266
    public function findAssignmentSubmissionsPaginated(
267
        int $assignmentId,
268
        User $user,
269
        int $page,
270
        int $itemsPerPage,
271
        array $order = []
272
    ): array {
273
        $qb = $this->createQueryBuilder('submission')
274
            ->leftJoin('submission.resourceNode', 'resourceNode')
275
            ->join('resourceNode.resourceLinks', 'resourceLink')
276
            ->leftJoin('submission.comments', 'comments')
277
            ->addSelect('comments')
278
            ->leftJoin('submission.publicationParent', 'assignment')
279
            ->addSelect('assignment')
280
            ->where('submission.publicationParent = :assignmentId')
281
            ->andWhere('submission.filetype = :filetype')
282
            ->andWhere('resourceLink.visibility = :publishedVisibility')
283
            ->setParameter('assignmentId', $assignmentId)
284
            ->setParameter('filetype', 'file')
285
            ->setParameter('publishedVisibility', 2);
286
287
        foreach ($order as $field => $direction) {
288
            $qb->addOrderBy('submission.' . $field, $direction);
289
        }
290
291
        $qb->setFirstResult(($page - 1) * $itemsPerPage)
292
            ->setMaxResults($itemsPerPage);
293
294
        $paginator = new Paginator($qb);
295
296
        return [
297
            iterator_to_array($paginator),
298
            count($paginator),
299
        ];
300
    }
301
302
    public function findAllSubmissionsByAssignment(
303
        int $assignmentId,
304
        int $page,
305
        int $itemsPerPage,
306
        array $order = []
307
    ): array {
308
        $qb = $this->createQueryBuilder('submission')
309
            ->leftJoin('submission.user', 'user')
310
            ->addSelect('user')
311
            ->leftJoin('submission.comments', 'comments')
312
            ->addSelect('comments')
313
            ->where('submission.publicationParent = :assignmentId')
314
            ->andWhere('submission.filetype = :filetype')
315
            ->setParameter('assignmentId', $assignmentId)
316
            ->setParameter('filetype', 'file');
317
318
        foreach ($order as $field => $direction) {
319
            $qb->addOrderBy('submission.' . $field, $direction);
320
        }
321
322
        $qb->setFirstResult(($page - 1) * $itemsPerPage)
323
            ->setMaxResults($itemsPerPage);
324
325
        $paginator = new Paginator($qb);
326
327
        return [
328
            iterator_to_array($paginator),
329
            count($paginator),
330
        ];
331
    }
332
333
    public function findUserIdsWithSubmissions(int $assignmentId): array
334
    {
335
        $qb = $this->createQueryBuilder('sp')
336
            ->select('DISTINCT u.id')
337
            ->join('sp.user', 'u')
338
            ->where('sp.publicationParent = :assignmentId')
339
            ->andWhere('sp.active IN (0,1)')
340
            ->setParameter('assignmentId', $assignmentId);
341
342
        return array_column($qb->getQuery()->getArrayResult(), 'id');
343
    }
344
}
345