Passed
Pull Request — master (#6287)
by
unknown
08:55
created

CToolStateProvider   A

Complexity

Total Complexity 28

Size/Duplication

Total Lines 135
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 66
c 1
b 0
f 0
dl 0
loc 135
rs 10
wmc 28

3 Methods

Rating   Name   Duplication   Size   Complexity  
F provide() 0 71 18
B shouldRestrictToPositioningOnly() 0 40 9
A __construct() 0 13 1
1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
declare(strict_types=1);
6
7
namespace Chamilo\CoreBundle\State;
8
9
use ApiPlatform\Doctrine\Orm\State\CollectionProvider;
10
use ApiPlatform\Metadata\Operation;
11
use ApiPlatform\State\Pagination\PartialPaginatorInterface;
12
use ApiPlatform\State\ProviderInterface;
13
use Chamilo\CoreBundle\DataTransformer\CourseToolDataTranformer;
14
use Chamilo\CoreBundle\Entity\ResourceLink;
15
use Chamilo\CoreBundle\Entity\User;
16
use Chamilo\CoreBundle\ServiceHelper\PluginServiceHelper;
17
use Chamilo\CoreBundle\Settings\SettingsManager;
18
use Chamilo\CoreBundle\Tool\AbstractPlugin;
19
use Chamilo\CoreBundle\Tool\ToolChain;
20
use Chamilo\CoreBundle\Traits\CourseFromRequestTrait;
21
use Chamilo\CourseBundle\Entity\CTool;
22
use Doctrine\ORM\EntityManagerInterface;
23
use Symfony\Bundle\SecurityBundle\Security;
24
use Symfony\Component\HttpFoundation\RequestStack;
25
26
/**
27
 * @template-implements ProviderInterface<CTool>
28
 */
29
final class CToolStateProvider implements ProviderInterface
30
{
31
    use CourseFromRequestTrait;
32
33
    private CourseToolDataTranformer $transformer;
34
35
    public function __construct(
36
        private readonly CollectionProvider $provider,
37
        protected EntityManagerInterface $entityManager,
38
        private readonly SettingsManager $settingsManager,
39
        private readonly Security $security,
40
        private readonly ToolChain $toolChain,
41
        protected RequestStack $requestStack,
42
        private readonly PluginServiceHelper $pluginServiceHelper,
43
    ) {
44
        $this->transformer = new CourseToolDataTranformer(
45
            $this->requestStack,
46
            $this->entityManager,
47
            $this->toolChain
48
        );
49
    }
50
51
    public function provide(Operation $operation, array $uriVariables = [], array $context = []): array
52
    {
53
        /** @var PartialPaginatorInterface $result */
54
        $result = $this->provider->provide($operation, $uriVariables, $context);
55
56
        $request = $this->requestStack->getMainRequest();
57
        $studentView = $request ? $request->getSession()->get('studentview') : 'studentview';
58
59
        /** @var User|null $user */
60
        $user = $this->security->getUser();
61
62
        $isAllowToEdit = $user && ($user->hasRole('ROLE_ADMIN') || $user->hasRole('ROLE_CURRENT_COURSE_TEACHER'));
63
        $isAllowToEditBack = $isAllowToEdit;
64
        $isAllowToSessionEdit = $user && (
65
                $user->hasRole('ROLE_ADMIN') ||
66
                $user->hasRole('ROLE_CURRENT_COURSE_TEACHER') ||
67
                $user->hasRole('ROLE_CURRENT_COURSE_SESSION_TEACHER')
68
            );
69
70
        $allowVisibilityInSession = $this->settingsManager->getSetting('course.allow_edit_tool_visibility_in_session');
71
        $session = $this->getSession();
72
        $course = $this->getCourse();
73
74
        [$restrictToPositioning, $allowedToolName] = $this->shouldRestrictToPositioningOnly($user, $course->getId(), $session?->getId());
75
76
        $results = [];
77
78
        /** @var CTool $cTool */
79
        foreach ($result as $cTool) {
80
            if ($restrictToPositioning && $cTool->getTool()->getTitle() !== $allowedToolName) {
81
                continue;
82
            }
83
84
            $toolModel = $this->toolChain->getToolFromName(
85
                $cTool->getTool()->getTitle()
86
            );
87
88
            if (!$isAllowToEdit && 'admin' === $toolModel->getCategory()) {
0 ignored issues
show
Bug introduced by
The method getCategory() does not exist on Chamilo\CoreBundle\Tool\AbstractTool. It seems like you code against a sub-type of said class. However, the method does not exist in Chamilo\CoreBundle\Tool\AbstractCourseTool. Are you sure you never get one of those? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

88
            if (!$isAllowToEdit && 'admin' === $toolModel->/** @scrutinizer ignore-call */ getCategory()) {
Loading history...
89
                continue;
90
            }
91
92
            $resourceLinks = $cTool->getResourceNode()->getResourceLinks();
93
94
            if ($session && $allowVisibilityInSession) {
95
                $sessionLink = $resourceLinks->findFirst(
96
                    fn (int $key, ResourceLink $resourceLink): bool => $resourceLink->getSession()?->getId() === $session->getId()
97
                );
98
99
                if ($sessionLink) {
100
                    // Set the session link as unique to include in repsonse
101
                    $resourceLinks->clear();
102
                    $resourceLinks->add($sessionLink);
103
104
                    $isAllowToEdit = $isAllowToSessionEdit;
105
                } else {
106
                    $isAllowToEdit = $isAllowToEditBack;
107
                }
108
            }
109
110
            if (!$isAllowToEdit || 'studentview' === $studentView) {
111
                $notPublishedLink = ResourceLink::VISIBILITY_PUBLISHED !== $resourceLinks->first()->getVisibility();
112
113
                if ($notPublishedLink) {
114
                    continue;
115
                }
116
            }
117
118
            $results[] = $this->transformer->transform($cTool);
119
        }
120
121
        return $results;
122
    }
123
124
    private function shouldRestrictToPositioningOnly(?User $user, int $courseId, ?int $sessionId): array
125
    {
126
        if (!$user || !$user->hasRole('ROLE_STUDENT')) {
127
            return [false, null];
128
        }
129
130
        $tool = $this->toolChain->getToolFromName('positioning');
131
132
        if (!$tool instanceof AbstractPlugin) {
133
            return [false, null];
134
        }
135
136
        if (!$this->pluginServiceHelper->isPluginEnabled('positioning')) {
137
            return [false, null];
138
        }
139
140
        $pluginInstance = $this->pluginServiceHelper->loadLegacyPlugin('Positioning');
141
142
        if (!$pluginInstance || 'true' !== $pluginInstance->get('block_course_if_initial_exercise_not_attempted')) {
143
            return [false, null];
144
        }
145
146
        $initialData = $pluginInstance->getInitialExercise($courseId, $sessionId);
147
148
        if (!isset($initialData['exercise_id'])) {
149
            return [false, null];
150
        }
151
152
        $results = \Event::getExerciseResultsByUser(
0 ignored issues
show
Bug introduced by
The method getExerciseResultsByUser() does not exist on Event. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

152
        /** @scrutinizer ignore-call */ 
153
        $results = \Event::getExerciseResultsByUser(

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
153
            $user->getId(),
154
            (int) $initialData['exercise_id'],
155
            $courseId,
156
            $sessionId
157
        );
158
159
        if (empty($results)) {
160
            return [true, 'positioning'];
161
        }
162
163
        return [false, null];
164
    }
165
}
166