Passed
Push — master ( b0b4c3...57268f )
by Yannick
09:19 queued 13s
created

LtiContextMembershipResource::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
c 0
b 0
f 0
nc 1
nop 3
dl 0
loc 5
rs 10
1
<?php
2
/* For licensing terms, see /license.txt */
3
4
use Chamilo\CoreBundle\Entity\CourseRelUser;
5
use Chamilo\CoreBundle\Entity\Session;
6
use Chamilo\CoreBundle\Entity\SessionRelCourseRelUser;
7
use Chamilo\UserBundle\Entity\User;
8
use Doctrine\Common\Collections\Criteria;
9
use Symfony\Component\HttpFoundation\Request;
10
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
11
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
12
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
13
use Symfony\Component\HttpKernel\Exception\UnsupportedMediaTypeHttpException;
14
15
/**
16
 * Class LtiContextMembershipResource.
17
 */
18
class LtiContextMembershipResource extends LtiAdvantageServiceResource
19
{
20
    const URL_TEMPLATE = '/context_id/memberships';
21
22
    /**
23
     * @var bool
24
     */
25
    private $inSession = false;
26
    /**
27
     * @var Session
28
     */
29
    private $session;
30
31
    /**
32
     * LtiContextMembershipResorce constructor.
33
     *
34
     * @param int $toolId
35
     * @param int $courseId
36
     * @param int $sessionId
37
     *
38
     * @throws \Doctrine\ORM\ORMException
39
     * @throws \Doctrine\ORM\OptimisticLockException
40
     * @throws \Doctrine\ORM\TransactionRequiredException
41
     */
42
    public function __construct($toolId, $courseId, $sessionId = 0)
43
    {
44
        $this->session = api_get_session_entity($sessionId);
45
46
        parent::__construct($toolId, $courseId);
47
    }
48
49
    /**
50
     * {@inheritDoc}
51
     */
52
    public function validate()
53
    {
54
        if ($this->request->server->get('HTTP_ACCEPT') !== LtiNamesRoleProvisioningService::TYPE_MEMBERSHIP_CONTAINER) {
55
            throw new UnsupportedMediaTypeHttpException('Unsupported media type.');
56
        }
57
58
        if (!$this->course) {
59
            throw new BadRequestHttpException('Course not found.');
60
        }
61
62
        if (!$this->tool) {
63
            throw new BadRequestHttpException('Tool not found.');
64
        }
65
66
        if (null === $this->tool->getCourse()) {
67
            throw new BadRequestHttpException('Tool not enabled.');
68
        }
69
70
        if ($this->tool->getCourse()->getId() !== $this->course->getId()) {
71
            throw new AccessDeniedHttpException('Tool not found in course.');
72
        }
73
74
        $sessionId = (int) $this->request->query->get('s');
75
        $this->inSession = $sessionId > 0;
76
77
        if ($this->inSession && !$this->session) {
78
            throw new BadRequestHttpException('Session not found');
79
        }
80
    }
81
82
    /**
83
     * {@inheritDoc}
84
     */
85
    public function process()
86
    {
87
        switch ($this->request->getMethod()) {
88
            case Request::METHOD_GET:
89
                $this->validateToken(
90
                    [LtiNamesRoleProvisioningService::SCOPE_CONTEXT_MEMBERSHIP_READ]
91
                );
92
                $this->processGet();
93
                break;
94
            default:
95
                throw new MethodNotAllowedHttpException([Request::METHOD_GET]);
96
        }
97
    }
98
99
    private function processGet()
100
    {
101
        $role = str_replace(
102
            'http://purl.imsglobal.org/vocab/lis/v2/membership#',
103
            '',
104
            $this->request->query->get('role')
105
        );
106
        $limit = $this->request->query->getInt('limit');
107
        $page = $this->request->query->getInt('page');
108
        $status = -1;
109
110
        if ('Instructor' === $role) {
111
            $status = $this->session ? Session::COACH : User::COURSE_MANAGER;
0 ignored issues
show
Bug introduced by
The constant Chamilo\CoreBundle\Entity\Session::COACH was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
112
        } elseif ('Learner' === $role) {
113
            $status = $this->session ? Session::STUDENT : User::STUDENT;
114
        }
115
116
        $members = $this->getMembers($status, $limit, $page);
117
118
        $data = $this->getGetData($members);
119
120
        $this->setLinkHeaderToGet($status, $limit, $page);
121
122
        $this->response->headers->set('Content-Type', LtiNamesRoleProvisioningService::TYPE_MEMBERSHIP_CONTAINER);
123
        $this->response->setData($data);
124
    }
125
126
    /**
127
     * @param int $status If $status = -1 then get all statuses.
128
     * @param int $limit
129
     * @param int $page
130
     *
131
     * @return array
132
     */
133
    private function getMembers($status, $limit, $page = 0)
134
    {
135
        if ($this->session) {
136
            $subscriptions = $this->session->getUsersSubscriptionsInCourse($this->course);
0 ignored issues
show
Bug introduced by
The method getUsersSubscriptionsInCourse() does not exist on Chamilo\CoreBundle\Entity\Session. Did you maybe mean getUsers()? ( Ignorable by Annotation )

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

136
            /** @scrutinizer ignore-call */ 
137
            $subscriptions = $this->session->getUsersSubscriptionsInCourse($this->course);

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...
137
138
            // Add session admin as teacher in course
139
            $adminSubscription = new SessionRelCourseRelUser();
140
            $adminSubscription->setCourse($this->course);
141
            $adminSubscription->setSession($this->session);
142
            $adminSubscription->setStatus(Session::COACH);
0 ignored issues
show
Bug introduced by
The constant Chamilo\CoreBundle\Entity\Session::COACH was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
143
            $adminSubscription->setUser(
144
                api_get_user_entity($this->session->getSessionAdminId())
0 ignored issues
show
Bug introduced by
The method getSessionAdminId() does not exist on Chamilo\CoreBundle\Entity\Session. Did you maybe mean getSessionAdmins()? ( Ignorable by Annotation )

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

144
                api_get_user_entity($this->session->/** @scrutinizer ignore-call */ getSessionAdminId())

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...
145
            );
146
147
            $subscriptions->add($adminSubscription);
148
        } else {
149
            $subscriptions = $this->course->getUsers();
150
        }
151
152
        $criteria = Criteria::create();
153
154
        if ($status > -1) {
155
            $criteria->where(
156
                Criteria::expr()->eq('status', $status)
157
            );
158
        }
159
160
        if ($limit > 0) {
161
            $criteria->setMaxResults($limit);
162
163
            if ($page > 0) {
164
                $criteria->setFirstResult($page * $limit);
165
            }
166
        }
167
168
        return $subscriptions->matching($criteria)->toArray();
169
    }
170
171
    /**
172
     * @return array
173
     */
174
    private function getGetData(array $members)
175
    {
176
        $platformDomain = str_replace(['https://', 'http://'], '', api_get_setting('InstitutionUrl'));
177
        $dataMembers = [];
178
179
        $isSharingName = $this->tool->isSharingName();
180
        $isSharingEmail = $this->tool->isSharingEmail();
181
        $isSharingPicture = $this->tool->isSharingPicture();
182
183
        foreach ($members as $member) {
184
            /** @var User $user */
185
            $user = $member->getUser();
186
187
            $dataMember = [
188
                'status' => $user->isActive()
189
                    ? LtiNamesRoleProvisioningService::USER_STATUS_ACTIVE
190
                    : LtiNamesRoleProvisioningService::USER_STATUS_INACTIVE,
191
                'user_id' => ImsLtiPlugin::getLaunchUserIdClaim($this->tool, $user),
192
                'lis_person_sourcedid' => ImsLti::getPersonSourcedId($platformDomain, $user),
193
                'lti11_legacy_user_id' => ImsLtiPlugin::generateToolUserId($user->getId()),
194
            ];
195
196
            if ($isSharingName) {
197
                $dataMember['name'] = $user->getFullname();
198
                $dataMember['given_name'] = $user->getFirstname();
199
                $dataMember['family_name'] = $user->getLastname();
200
            }
201
202
            if ($isSharingEmail) {
203
                $dataMember['email'] = $user->getEmail();
204
            }
205
206
            if ($isSharingPicture) {
207
                $dataMember['picture'] = UserManager::getUserPicture($user->getId());
208
            }
209
210
            if ($member instanceof CourseRelUser) {
211
                $dataMember['roles'] = $member->getStatus() === User::COURSE_MANAGER
212
                    ? ['http://purl.imsglobal.org/vocab/lis/v2/membership#Instructor']
213
                    : ['http://purl.imsglobal.org/vocab/lis/v2/membership#Learner'];
214
            } elseif ($member instanceof SessionRelCourseRelUser) {
215
                $dataMember['roles'] = $member->getStatus() === Session::STUDENT
216
                    ? ['http://purl.imsglobal.org/vocab/lis/v2/membership#Learner']
217
                    : ['http://purl.imsglobal.org/vocab/lis/v2/membership#Instructor'];
218
            }
219
220
            $dataMembers[] = $dataMember;
221
        }
222
223
        return [
224
            'id' => api_get_path(WEB_PLUGIN_PATH)
225
                ."ims_lti/nrps2.php/{$this->course->getId()}/memberships?"
226
                .http_build_query(
227
                    [
228
                        't' => $this->tool->getId(),
229
                        's' => $this->session ? $this->session->getId() : null,
230
                    ]
231
                ),
232
            'context' => [
233
                'id' => (string) $this->course->getId(),
234
                'label' => $this->course->getCode(),
235
                'title' => $this->course->getTitle(),
236
            ],
237
            'members' => $dataMembers,
238
        ];
239
    }
240
241
    /**
242
     * @param int $status
243
     * @param int $limit
244
     * @param int $page
245
     */
246
    private function setLinkHeaderToGet($status, $limit, $page = 0)
247
    {
248
        if (!$limit) {
249
            return;
250
        }
251
252
        if ($this->session) {
253
            $subscriptions = $this->session->getUsersSubscriptionsInCourse($this->course);
254
        } else {
255
            $subscriptions = $this->course->getUsers();
256
        }
257
258
        $criteria = Criteria::create();
259
260
        if ($status > -1) {
261
            $criteria->where(
262
                Criteria::expr()->eq('status', $status)
263
            );
264
        }
265
266
        $count = $subscriptions->matching($criteria)->count();
267
268
        if ($this->session) {
269
            // +1 for session admin
270
            $count++;
271
        }
272
273
        if ($page + 1 < ceil($count / $limit)) {
274
            $url = LtiNamesRoleProvisioningService::getUrl(
275
                $this->tool->getId(),
276
                $this->course->getId(),
277
                $this->session ? $this->session->getId() : 0,
278
                [
279
                    'role' => $this->request->query->get('role'),
280
                    'limit' => $limit,
281
                    'page' => $page + 1,
282
                ]
283
            );
284
285
            $this->response->headers->set(
286
                'Link',
287
                '<'.$url.'>; rel="next"'
288
            );
289
        }
290
    }
291
}
292