Completed
Push — master ( 91f8d1...9dd64d )
by
unknown
01:55 queued 39s
created

DocumentCollectionStateProvider::provide()   F

Complexity

Conditions 24
Paths > 20000

Size

Total Lines 153
Code Lines 89

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 24
eloc 89
c 1
b 0
f 0
nc 31969
nop 3
dl 0
loc 153
rs 0

How to fix   Long Method    Complexity   

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\CoreBundle\State;
8
9
use ApiPlatform\Metadata\Operation;
10
use ApiPlatform\State\ProviderInterface;
11
use Chamilo\CoreBundle\Entity\Course;
12
use Chamilo\CoreBundle\Entity\ResourceLink;
13
use Chamilo\CoreBundle\Entity\ResourceNode;
14
use Chamilo\CoreBundle\Entity\Session;
15
use Chamilo\CoreBundle\Repository\ResourceLinkRepository;
16
use Chamilo\CourseBundle\Entity\CDocument;
17
use Chamilo\CourseBundle\Entity\CGroup;
18
use Doctrine\ORM\EntityManagerInterface;
19
use Symfony\Component\HttpFoundation\RequestStack;
20
21
/**
22
 * @implements ProviderInterface<CDocument>
23
 */
24
final class DocumentCollectionStateProvider implements ProviderInterface
25
{
26
    public function __construct(
27
        private readonly EntityManagerInterface $entityManager,
28
        private readonly RequestStack $requestStack,
29
    ) {}
30
31
    /**
32
     * @param array<string, mixed> $uriVariables
33
     * @param array<string, mixed> $context
34
     *
35
     * @return array<CDocument>|CDocument|null
36
     */
37
    public function provide(Operation $operation, array $uriVariables = [], array $context = []): array|object|null
38
    {
39
        $request = $this->requestStack->getCurrentRequest();
40
        if (null === $request) {
41
            return [];
42
        }
43
44
        $qb = $this->entityManager
45
            ->getRepository(CDocument::class)
46
            ->createQueryBuilder('d')
47
            ->innerJoin('d.resourceNode', 'rn')
48
            ->addSelect('rn');
49
50
        // Filetype filtering: filetype[]=file&filetype[]=folder&filetype[]=video OR filetype=folder
51
        $filetypes = $request->query->all('filetype');
52
53
        if (empty($filetypes)) {
54
            $singleFiletype = $request->query->get('filetype');
55
            if (null !== $singleFiletype && '' !== $singleFiletype) {
56
                $filetypes = [$singleFiletype];
57
            }
58
        }
59
60
        if (!empty($filetypes)) {
61
            if (!\is_array($filetypes)) {
62
                $filetypes = [$filetypes];
63
            }
64
65
            $qb
66
                ->andWhere($qb->expr()->in('d.filetype', ':filetypes'))
67
                ->setParameter('filetypes', $filetypes);
68
        }
69
70
        // Context (course / session / group)
71
        $cid = $request->query->getInt('cid', 0);
72
        $sid = $request->query->getInt('sid', 0);
73
        $gid = $request->query->getInt('gid', 0);
74
75
        $hasContext = $cid > 0 || $sid > 0 || $gid > 0;
76
77
        // loadNode=1 -> documents list wants children of a folder
78
        $loadNode = (bool) $request->query->get('loadNode', false);
79
80
        // Current folder node (comes from Vue as resourceNode.parent=XX)
81
        $parentNodeId = (int) $request->query->get('resourceNode.parent', 0);
82
        if (0 === $parentNodeId) {
83
            $parentNodeId = (int) $request->query->get('resourceNode_parent', 0);
84
        }
85
86
        if ($hasContext) {
87
            // Contextual hierarchy based on ResourceLink.parent
88
            $qb->innerJoin('rn.resourceLinks', 'rl');
89
90
            if ($cid > 0) {
91
                $qb
92
                    ->andWhere('rl.course = :cid')
93
                    ->setParameter('cid', $cid);
94
            }
95
96
            if ($sid > 0) {
97
                $qb
98
                    ->andWhere('rl.session = :sid')
99
                    ->setParameter('sid', $sid);
100
            }
101
102
            if ($gid > 0) {
103
                $qb
104
                    ->andWhere('rl.group = :gid')
105
                    ->setParameter('gid', $gid);
106
            }
107
108
            if ($loadNode) {
109
                // We are browsing "inside" a folder in this context
110
                if ($parentNodeId > 0) {
111
                    $resourceNode = $this->entityManager
112
                        ->getRepository(ResourceNode::class)
113
                        ->find($parentNodeId);
114
115
                    if (null === $resourceNode) {
116
                        // Folder node not found -> nothing to list
117
                        return [];
118
                    }
119
120
                    /** @var ResourceLinkRepository $linkRepo */
121
                    $linkRepo = $this->entityManager->getRepository(ResourceLink::class);
122
123
                    $courseEntity = $cid > 0
124
                        ? $this->entityManager->getRepository(Course::class)->find($cid)
125
                        : null;
126
127
                    $sessionEntity = $sid > 0
128
                        ? $this->entityManager->getRepository(Session::class)->find($sid)
129
                        : null;
130
131
                    $groupEntity = $gid > 0
132
                        ? $this->entityManager->getRepository(CGroup::class)->find($gid)
133
                        : null;
134
135
                    // Find the link of this folder in the current context
136
                    $parentLink = $linkRepo->findParentLinkForContext(
137
                        $resourceNode,
138
                        $courseEntity,
139
                        $sessionEntity,
140
                        $groupEntity,
141
                        null,
142
                        null
143
                    );
144
145
                    if (null === $parentLink) {
146
                        // No link for this node in this context:
147
                        // treat it as context root → children have rl.parent IS NULL
148
                        $qb->andWhere('rl.parent IS NULL');
149
                    } else {
150
                        // Children inside this folder in this context
151
                        $qb
152
                            ->andWhere('rl.parent = :parentLink')
153
                            ->setParameter('parentLink', $parentLink);
154
                    }
155
                } else {
156
                    // No parentNodeId -> root of the context (course root)
157
                    $qb->andWhere('rl.parent IS NULL');
158
                }
159
            }
160
161
            // When the same document is linked multiple times in this context
162
            $qb->distinct();
163
        } else {
164
            // No course / session / group context:
165
            // keep legacy behavior using resource_node.parent (global docs, if any)
166
            if ($parentNodeId > 0) {
167
                $qb
168
                    ->andWhere('rn.parent = :parentId')
169
                    ->setParameter('parentId', $parentNodeId);
170
            }
171
        }
172
173
        // Ordering & pagination
174
        $qb->orderBy('rn.title', 'ASC');
175
176
        $page = (int) $request->query->get('page', 1);
177
        $itemsPerPage = (int) $request->query->get('itemsPerPage', 20);
178
179
        if ($page < 1) {
180
            $page = 1;
181
        }
182
183
        if ($itemsPerPage > 0) {
184
            $qb
185
                ->setFirstResult(($page - 1) * $itemsPerPage)
186
                ->setMaxResults($itemsPerPage);
187
        }
188
189
        return $qb->getQuery()->getResult();
190
    }
191
}
192