LTI Integration Library 4.10.3
PHP class library for building LTI integrations
 
Loading...
Searching...
No Matches
Membership.php
1<?php
2
3namespace ceLTIc\LTI\Service;
4
5use ceLTIc\LTI;
8
16class Membership extends Service
17{
18
22 const MEDIA_TYPE_MEMBERSHIPS_V1 = 'application/vnd.ims.lis.v2.membershipcontainer+json';
23
27 const MEDIA_TYPE_MEMBERSHIPS_NRPS = 'application/vnd.ims.lti-nrps.v2.membershipcontainer+json';
28
32 public static $SCOPE = 'https://purl.imsglobal.org/spec/lti-nrps/scope/contextmembership.readonly';
33
37 public static $defaultLimit = 100;
38
44 private $source = null;
45
53 private $limit;
54
62 private $pagingMode;
63
73 public function __construct($source, $endpoint, $format = self::MEDIA_TYPE_MEMBERSHIPS_V1, $limit = null, $pagingMode = false)
74 {
75 $platform = $source->getPlatform();
76 parent::__construct($platform, $endpoint);
77 $this->scope = self::$SCOPE;
78 $this->mediaType = $format;
79 $this->source = $source;
80 $this->limit = $limit;
81 $this->pagingMode = $pagingMode;
82 }
83
92 public function get($role = null, $limit = null)
93 {
94 return $this->getMembers(false, $role, $limit);
95 }
96
105 public function getWithGroups($role = null, $limit = null)
106 {
107 return $this->getMembers(true, $role, $limit);
108 }
109
119 private function getMembers($withGroups, $role = null, $limit = null)
120 {
121 $isLink = is_a($this->source, 'ceLTIc\LTI\ResourceLink');
122 $parameters = array();
123 if (!empty($role)) {
124 $parameters['role'] = $role;
125 }
126 if (is_null($limit)) {
127 $limit = $this->limit;
128 }
129 if (is_null($limit)) {
130 $limit = self::$defaultLimit;
131 }
132 if (!empty($limit)) {
133 $parameters['limit'] = strval($limit);
134 }
135 if ($isLink) {
136 $context = $this->source->getContext();
137 if (!empty($this->source->getId())) {
138 $parameters['rlid'] = $this->source->getId();
139 }
140 if ($withGroups && ($this->mediaType === self::MEDIA_TYPE_MEMBERSHIPS_NRPS) && !empty($context)) {
141 $context->getGroups();
142 $this->source->groupSets = $context->groupSets;
143 $this->source->groups = $context->groups;
144 $parameters['groups'] = 'true';
145 }
146 } elseif ($withGroups && ($this->mediaType === self::MEDIA_TYPE_MEMBERSHIPS_NRPS)) {
147 $this->source->getGroups();
148 $parameters['groups'] = 'true';
149 }
150 $userResults = array();
151 $memberships = array();
153 do {
154 $http = $this->send('GET', $parameters);
155 $url = '';
156 if (!empty($http) && $http->ok) {
157 $isjsonld = false;
158 if (isset($http->responseJson->pageOf) && isset($http->responseJson->pageOf->membershipSubject) &&
159 isset($http->responseJson->pageOf->membershipSubject->membership)) {
160 $isjsonld = true;
161 $memberships = array_merge($memberships, $http->responseJson->pageOf->membershipSubject->membership);
162 if (!empty($http->responseJson->nextPage) && !empty($http->responseJson->pageOf->membershipSubject->membership)) {
163 $http->relativeLinks['next'] = $http->responseJson->nextPage;
164 }
165 } elseif (isset($http->responseJson->members)) {
166 $memberships = array_merge($memberships, $http->responseJson->members);
167 }
168 if (!$this->pagingMode && $http->hasRelativeLink('next')) {
169 $url = $http->getRelativeLink('next');
170 $this->endpoint = $url;
171 $parameters = array();
172 }
173 } else {
174 $userResults = false;
175 }
176 } while ($url);
177 $this->endpoint = $endpoint;
178 if ($userResults !== false) {
179 if ($isLink) {
180 $oldUsers = $this->source->getUserResultSourcedIDs(true, LTI\Tool::ID_SCOPE_RESOURCE);
181 }
182 foreach ($memberships as $membership) {
183 if ($isjsonld) {
184 $member = $membership->member;
185 if ($isLink) {
186 $userresult = LTI\UserResult::fromResourceLink($this->source, $member->userId);
187 } else {
188 $userresult = new LTI\UserResult();
189 $userresult->ltiUserId = $member->userId;
190 }
191
192// Set the user name
193 $firstname = (isset($member->givenName)) ? $member->givenName : '';
194 $middlename = (isset($member->middleName)) ? $member->middleName : '';
195 $lastname = (isset($member->familyName)) ? $member->familyName : '';
196 $fullname = (isset($member->name)) ? $member->name : '';
197 $userresult->setNames($firstname, $lastname, $fullname);
198
199// Set the sourcedId
200 if (isset($member->sourcedId)) {
201 $userresult->sourcedId = $member->sourcedId;
202 }
203
204// Set the username
205 if (isset($member->ext_username)) {
206 $userresult->username = $member->ext_username;
207 } elseif (isset($member->ext_user_username)) {
208 $userresult->username = $member->ext_user_username;
209 } elseif (isset($member->custom_username)) {
210 $userresult->username = $member->custom_username;
211 } elseif (isset($member->custom_user_username)) {
212 $userresult->username = $member->custom_user_username;
213 }
214
215// Set the user email
216 $email = (isset($member->email)) ? $member->email : '';
217 $userresult->setEmail($email, $this->source->getPlatform()->defaultEmail);
218
219// Set the user roles
220 if (isset($membership->role)) {
221 $roles = $this->parseContextsInArray($http->responseJson->{'@context'}, $membership->role);
222 $userresult->roles = LTI\Tool::parseRoles($roles, $this->getPlatform()->ltiVersion);
223 }
224
225// If a result sourcedid is provided save the user
226 if ($isLink) {
227 $doSave = false;
228 if (isset($membership->message)) {
229 foreach ($membership->message as $message) {
230 if (isset($message->message_type) && (($message->message_type === 'basic-lti-launch-request') || ($message->message_type) === 'LtiResourceLinkRequest')) {
231 if (isset($message->lis_result_sourcedid)) {
232 if (empty($userresult->ltiResultSourcedId) || ($userresult->ltiResultSourcedId !== $message->lis_result_sourcedid)) {
233 $userresult->ltiResultSourcedId = $message->lis_result_sourcedid;
234 $doSave = true;
235 }
236 } elseif ($userresult->isLearner() && empty($userresult->created)) { // Ensure all learners are recorded in case Assignment and Grade services are used
237 $userresult->ltiResultSourcedId = '';
238 $doSave = true;
239 }
240 if (isset($message->ext)) {
241 if (empty($userresult->username)) {
242 if (!empty($message->ext->username)) {
243 $userresult->username = $message->ext->username;
244 } elseif (!empty($message->ext->user_username)) {
245 $userresult->username = $message->ext->user_username;
246 }
247 }
248 }
249 if (isset($message->custom)) {
250 if (empty($userresult->username)) {
251 if (!empty($message->custom->username)) {
252 $userresult->username = $message->custom->username;
253 } elseif (!empty($message->custom->user_username)) {
254 $userresult->username = $message->custom->user_username;
255 }
256 }
257 }
258 break;
259 }
260 }
261 } elseif ($userresult->isLearner() && empty($userresult->created)) { // Ensure all learners are recorded in case Assignment and Grade services are used
262 $userresult->ltiResultSourcedId = '';
263 $doSave = true;
264 }
265 if (!$doSave && isset($member->resultSourcedId)) {
266 $userresult->setResourceLinkId($this->source->getId());
267 $userresult->ltiResultSourcedId = $member->resultSourcedId;
268 $doSave = true;
269 }
270 if ($doSave) {
271 $userresult->save();
272 }
273 }
274 $userResults[] = $userresult;
275
276// Remove old user (if it exists)
277 if ($isLink) {
278 unset($oldUsers[$userresult->getId(LTI\Tool::ID_SCOPE_RESOURCE)]);
279 }
280 } else { // Version 2
281 $member = $membership;
282 if ($isLink) {
283 $userresult = LTI\UserResult::fromResourceLink($this->source, $member->user_id);
284 } else {
285 $userresult = new LTI\UserResult();
286 $userresult->ltiUserId = $member->user_id;
287 }
288
289// Set the user name
290 $firstname = (isset($member->given_name)) ? $member->given_name : '';
291 $middlename = (isset($member->middle_name)) ? $member->middle_name : '';
292 $lastname = (isset($member->family_name)) ? $member->family_name : '';
293 $fullname = (isset($member->name)) ? $member->name : '';
294 $userresult->setNames($firstname, $lastname, $fullname);
295
296// Set the sourcedId
297 if (isset($member->lis_person_sourcedid)) {
298 $userresult->sourcedId = $member->lis_person_sourcedid;
299 }
300
301// Set the user email
302 $email = (isset($member->email)) ? $member->email : '';
303 $userresult->setEmail($email, $this->source->getPlatform()->defaultEmail);
304
305// Set the user roles
306 if (isset($member->roles)) {
307 $userresult->roles = LTI\Tool::parseRoles($member->roles, $this->getPlatform()->ltiVersion);
308 }
309
310// If a result sourcedid is provided save the user
311 if ($isLink) {
312 $doSave = false;
313 if (isset($member->message)) {
314 $messages = $member->message;
315 if (!is_array($messages)) {
316 $messages = array($member->message);
317 }
318 foreach ($messages as $message) {
319 if (isset($message->{'https://purl.imsglobal.org/spec/lti/claim/message_type'}) && (($message->{'https://purl.imsglobal.org/spec/lti/claim/message_type'} === 'basic-lti-launch-request') || ($message->{'https://purl.imsglobal.org/spec/lti/claim/message_type'}) === 'LtiResourceLinkRequest')) {
320 if (isset($message->{'https://purl.imsglobal.org/spec/lti-bo/claim/basicoutcome'}) &&
321 isset($message->{'https://purl.imsglobal.org/spec/lti-bo/claim/basicoutcome'}->lis_result_sourcedid)) {
322 $userresult->ltiResultSourcedId = $message->{'https://purl.imsglobal.org/spec/lti-bo/claim/basicoutcome'}->lis_result_sourcedid;
323 $doSave = true;
324 } elseif ($userresult->isLearner() && empty($userresult->created)) { // Ensure all learners are recorded in case Assignment and Grade services are used
325 $userresult->ltiResultSourcedId = '';
326 $doSave = true;
327 }
328 if (isset($message->{'https://purl.imsglobal.org/spec/lti/claim/ext'})) {
329 if (empty($userresult->username)) {
330 if (!empty($message->{'https://purl.imsglobal.org/spec/lti/claim/ext'}->username)) {
331 $userresult->username = $message->{'https://purl.imsglobal.org/spec/lti/claim/ext'}->username;
332 } elseif (!empty($message->{'https://purl.imsglobal.org/spec/lti/claim/ext'}->user_username)) {
333 $userresult->username = $message->{'https://purl.imsglobal.org/spec/lti/claim/ext'}->user_username;
334 }
335 }
336 }
337 if (isset($message->{'https://purl.imsglobal.org/spec/lti/claim/custom'})) {
338 if (empty($userresult->username)) {
339 if (!empty($message->{'https://purl.imsglobal.org/spec/lti/claim/custom'}->username)) {
340 $userresult->username = $message->{'https://purl.imsglobal.org/spec/lti/claim/custom'}->username;
341 } elseif (!empty($message->{'https://purl.imsglobal.org/spec/lti/claim/custom'}->user_username)) {
342 $userresult->username = $message->{'https://purl.imsglobal.org/spec/lti/claim/custom'}->user_username;
343 }
344 }
345 }
346 break;
347 }
348 }
349 } elseif ($userresult->isLearner() && empty($userresult->created)) { // Ensure all learners are recorded in case Assignment and Grade services are used
350 $userresult->ltiResultSourcedId = '';
351 $doSave = true;
352 }
353 if ($doSave) {
354 $userresult->save();
355 }
356 }
357 $userResults[] = $userresult;
358 if (isset($member->group_enrollments)) {
359 $userresult->groups = array();
360 foreach ($member->group_enrollments as $group) {
361 $groupId = $group->group_id;
362 if (empty($this->source->groups) || !array_key_exists($groupId, $this->source->groups)) {
363 $this->source->groups[$groupId] = array('title' => "Group {$groupId}");
364 }
365 if (!empty($this->source->groups[$groupId]['set'])) {
366 $this->source->groupSets[$this->source->groups[$groupId]['set']]['num_members']++;
367 if ($userresult->isStaff()) {
368 $this->source->groupSets[$this->source->groups[$groupId]['set']]['num_staff']++;
369 }
370 if ($userresult->isLearner()) {
371 $this->source->groupSets[$this->source->groups[$groupId]['set']]['num_learners']++;
372 }
373 }
374 $userresult->groups[] = $groupId;
375 }
376 }
377
378// Remove old user (if it exists)
379 if ($isLink) {
380 unset($oldUsers[$userresult->getId(LTI\Tool::ID_SCOPE_RESOURCE)]);
381 }
382 }
383 }
384
386 if ($isLink && !$this->pagingMode) {
387 foreach ($oldUsers as $id => $userresult) {
388 $userresult->delete();
389 }
390 }
391 }
392
393 return $userResults;
394 }
395
396}
Class to represent a platform context.
Definition Context.php:18
Class to implement the Membership service.
static $defaultLimit
Default limit on size of container to be returned from requests.
getWithGroups($role=null, $limit=null)
Get the memberships.
__construct($source, $endpoint, $format=self::MEDIA_TYPE_MEMBERSHIPS_V1, $limit=null, $pagingMode=false)
Class constructor.
const MEDIA_TYPE_MEMBERSHIPS_V1
Media type for version 1 of Memberships service.
static $SCOPE
Access scope.
const MEDIA_TYPE_MEMBERSHIPS_NRPS
Media type for Names and Role Provisioning service.
Class to implement a service.
Definition Service.php:19
send($method, $parameters=array(), $body=null)
Send a service request.
Definition Service.php:119
getPlatform()
Get platform.
Definition Service.php:95
$endpoint
Service endpoint.
Definition Service.php:33
parseContextsInArray($contexts, $arr)
Parse the JSON for context references.
Definition Service.php:210
const ID_SCOPE_RESOURCE
Prefix the ID with the consumer key and resource ID.
Definition Tool.php:49