LTI Integration Library 4.10.3
PHP class library for building LTI integrations
 
Loading...
Searching...
No Matches
DataConnector_mysqli.php
1<?php
2
4
5use ceLTIc\LTI;
16
24###
25# NB This class assumes that a MySQLi connection has already been opened to the appropriate schema
26###
27
28
30{
31###
32### Platform methods
33###
34
42 public function loadPlatform($platform)
43 {
44 $allowMultiple = false;
45 $id = $platform->getRecordId();
46 if (!is_null($id)) {
47 $sql = 'SELECT consumer_pk, name, consumer_key, secret, ' .
48 'platform_id, client_id, deployment_id, public_key, ' .
49 'lti_version, signature_method, consumer_name, consumer_version, consumer_guid, ' .
50 'profile, tool_proxy, settings, protected, enabled, ' .
51 'enable_from, enable_until, last_access, created, updated ' .
52 "FROM {$this->dbTableNamePrefix}" . static::PLATFORM_TABLE_NAME . ' ' .
53 'WHERE consumer_pk = ?';
54 $stmt = $this->db->prepare($sql);
55 $stmt->bind_param('i', $id);
56 } elseif (!empty($platform->platformId)) {
57 if (empty($platform->clientId)) {
58 $allowMultiple = true;
59 $sql = 'SELECT consumer_pk, name, consumer_key, secret, ' .
60 'platform_id, client_id, deployment_id, public_key, ' .
61 'lti_version, signature_method, consumer_name, consumer_version, consumer_guid, ' .
62 'profile, tool_proxy, settings, protected, enabled, ' .
63 'enable_from, enable_until, last_access, created, updated ' .
64 "FROM {$this->dbTableNamePrefix}" . static::PLATFORM_TABLE_NAME . ' ' .
65 'WHERE (platform_id = ?)';
66 $stmt = $this->db->prepare($sql);
67 $stmt->bind_param('s', $platform->platformId);
68 } elseif (empty($platform->deploymentId)) {
69 $allowMultiple = true;
70 $sql = 'SELECT consumer_pk, name, consumer_key, secret, ' .
71 'platform_id, client_id, deployment_id, public_key, ' .
72 'lti_version, signature_method, consumer_name, consumer_version, consumer_guid, ' .
73 'profile, tool_proxy, settings, protected, enabled, ' .
74 'enable_from, enable_until, last_access, created, updated ' .
75 "FROM {$this->dbTableNamePrefix}" . static::PLATFORM_TABLE_NAME . ' ' .
76 'WHERE (platform_id = ?) AND (client_id = ?)';
77 $stmt = $this->db->prepare($sql);
78 $stmt->bind_param('ss', $platform->platformId, $platform->clientId);
79 } else {
80 $sql = 'SELECT consumer_pk, name, consumer_key, secret, ' .
81 'platform_id,client_id, deployment_id, public_key, ' .
82 'lti_version, signature_method, consumer_name, consumer_version, consumer_guid, ' .
83 'profile, tool_proxy, settings, protected, enabled, ' .
84 'enable_from, enable_until, last_access, created, updated ' .
85 "FROM {$this->dbTableNamePrefix}" . static::PLATFORM_TABLE_NAME . ' ' .
86 'WHERE (platform_id = ?) AND (client_id = ?) AND (deployment_id = ?)';
87 $stmt = $this->db->prepare($sql);
88 $stmt->bind_param('sss', $platform->platformId, $platform->clientId, $platform->deploymentId);
89 }
90 } else {
91 $key = $platform->getKey();
92 $sql = 'SELECT consumer_pk, name, consumer_key, secret, ' .
93 'platform_id, client_id, deployment_id, public_key, ' .
94 'lti_version, signature_method, consumer_name, consumer_version, consumer_guid, ' .
95 'profile, tool_proxy, settings, protected, enabled, ' .
96 'enable_from, enable_until, last_access, created, updated ' .
97 "FROM {$this->dbTableNamePrefix}" . static::PLATFORM_TABLE_NAME . ' ' .
98 'WHERE consumer_key = ?';
99 $stmt = $this->db->prepare($sql);
100 $stmt->bind_param('s', $key);
101 }
102 $ok = $this->executeQuery($sql, $stmt);
103 if ($ok) {
104 $rsConsumer = $stmt->get_result();
105 $ok = $rsConsumer !== false;
106 if ($ok) {
107 $row = $rsConsumer->fetch_object();
108 $ok = $row && ($allowMultiple || is_null($rsConsumer->fetch_object()));
109 }
110 }
111 if ($ok) {
112 $platform->setRecordId(intval($row->consumer_pk));
113 $platform->name = $row->name;
114 $platform->setkey($row->consumer_key);
115 $platform->secret = $row->secret;
116 $platform->platformId = $row->platform_id;
117 $platform->clientId = $row->client_id;
118 $platform->deploymentId = $row->deployment_id;
119 $platform->rsaKey = $row->public_key;
120 $platform->ltiVersion = $row->lti_version;
121 $platform->signatureMethod = $row->signature_method;
122 $platform->consumerName = $row->consumer_name;
123 $platform->consumerVersion = $row->consumer_version;
124 $platform->consumerGuid = $row->consumer_guid;
125 $platform->profile = Util::jsonDecode($row->profile);
126 $platform->toolProxy = $row->tool_proxy;
127 $settings = Util::jsonDecode($row->settings, true);
128 if (!is_array($settings)) {
129 $settings = @unserialize($row->settings); // check for old serialized setting
130 }
131 if (!is_array($settings)) {
132 $settings = array();
133 }
134 $platform->setSettings($settings);
135 $platform->protected = (intval($row->protected) === 1);
136 $platform->enabled = (intval($row->enabled) === 1);
137 $platform->enableFrom = null;
138 if (!is_null($row->enable_from)) {
139 $platform->enableFrom = strtotime($row->enable_from);
140 }
141 $platform->enableUntil = null;
142 if (!is_null($row->enable_until)) {
143 $platform->enableUntil = strtotime($row->enable_until);
144 }
145 $platform->lastAccess = null;
146 if (!is_null($row->last_access)) {
147 $platform->lastAccess = strtotime($row->last_access);
148 }
149 $platform->created = strtotime($row->created);
150 $platform->updated = strtotime($row->updated);
151 $this->fixPlatformSettings($platform, false);
152 }
153
154 return $ok;
155 }
156
164 public function savePlatform($platform)
165 {
166 $id = $platform->getRecordId();
167 $key = $platform->getKey();
168 $protected = ($platform->protected) ? 1 : 0;
169 $enabled = ($platform->enabled) ? 1 : 0;
170 $profile = (!empty($platform->profile)) ? json_encode($platform->profile) : null;
171 $this->fixPlatformSettings($platform, true);
172 $settingsValue = json_encode($platform->getSettings());
173 $this->fixPlatformSettings($platform, false);
174 $time = time();
175 $now = date("{$this->dateFormat} {$this->timeFormat}", $time);
176 $from = null;
177 if (!is_null($platform->enableFrom)) {
178 $from = date("{$this->dateFormat} {$this->timeFormat}", $platform->enableFrom);
179 }
180 $until = null;
181 if (!is_null($platform->enableUntil)) {
182 $until = date("{$this->dateFormat} {$this->timeFormat}", $platform->enableUntil);
183 }
184 $last = null;
185 if (!is_null($platform->lastAccess)) {
186 $last = date($this->dateFormat, $platform->lastAccess);
187 }
188 if (empty($id)) {
189 $sql = "INSERT INTO {$this->dbTableNamePrefix}" . static::PLATFORM_TABLE_NAME . ' (consumer_key, name, secret, ' .
190 'platform_id, client_id, deployment_id, public_key, ' .
191 'lti_version, signature_method, consumer_name, consumer_version, consumer_guid, ' .
192 'profile, tool_proxy, settings, protected, enabled, ' .
193 'enable_from, enable_until, last_access, created, updated) ' .
194 'VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)';
195 $stmt = $this->db->prepare($sql);
196 $stmt->bind_param('sssssssssssssssiisssss', $key, $platform->name, $platform->secret, $platform->platformId,
197 $platform->clientId, $platform->deploymentId, $platform->rsaKey, $platform->ltiVersion, $platform->signatureMethod,
198 $platform->consumerName, $platform->consumerVersion, $platform->consumerGuid, $profile, $platform->toolProxy,
199 $settingsValue, $protected, $enabled, $from, $until, $last, $now, $now);
200 } else {
201 $sql = "UPDATE {$this->dbTableNamePrefix}" . static::PLATFORM_TABLE_NAME . ' SET ' .
202 'consumer_key = ?, name = ?, secret= ?, ' .
203 'platform_id = ?, client_id = ?, deployment_id = ?, public_key = ?, ' .
204 'lti_version = ?, signature_method = ?, ' .
205 'consumer_name = ?, consumer_version = ?, consumer_guid = ?, ' .
206 'profile = ?, tool_proxy = ?, settings = ?, ' .
207 'protected = ?, enabled = ?, enable_from = ?, enable_until = ?, last_access = ?, updated = ? ' .
208 'WHERE consumer_pk = ?';
209 $stmt = $this->db->prepare($sql);
210 $stmt->bind_param('sssssssssssssssiissssi', $key, $platform->name, $platform->secret, $platform->platformId,
211 $platform->clientId, $platform->deploymentId, $platform->rsaKey, $platform->ltiVersion, $platform->signatureMethod,
212 $platform->consumerName, $platform->consumerVersion, $platform->consumerGuid, $profile, $platform->toolProxy,
213 $settingsValue, $protected, $enabled, $from, $until, $last, $now, $id);
214 }
215 $ok = $this->executeQuery($sql, $stmt);
216 if ($ok) {
217 if (empty($id)) {
218 $platform->setRecordId($this->db->insert_id);
219 $platform->created = $time;
220 }
221 $platform->updated = $time;
222 }
223
224 return $ok;
225 }
226
234 public function deletePlatform($platform)
235 {
236 $id = $platform->getRecordId();
237
238// Delete any access token value for this consumer
239 $sql = "DELETE FROM {$this->dbTableNamePrefix}" . static::ACCESS_TOKEN_TABLE_NAME . ' WHERE consumer_pk = ?';
240 $stmt = $this->db->prepare($sql);
241 $stmt->bind_param('i', $id);
242 $this->executeQuery($sql, $stmt);
243
244// Delete any nonce values for this consumer
245 $sql = "DELETE FROM {$this->dbTableNamePrefix}" . static::NONCE_TABLE_NAME . ' WHERE consumer_pk = ?';
246 $stmt = $this->db->prepare($sql);
247 $stmt->bind_param('i', $id);
248 $this->executeQuery($sql, $stmt);
249
250// Delete any outstanding share keys for resource links for this consumer
251 $sql = 'DELETE sk ' .
252 "FROM {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_SHARE_KEY_TABLE_NAME . ' sk ' .
253 "INNER JOIN {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' rl ON sk.resource_link_pk = rl.resource_link_pk ' .
254 'WHERE rl.consumer_pk = ?';
255 $stmt = $this->db->prepare($sql);
256 $stmt->bind_param('i', $id);
257 $this->executeQuery($sql, $stmt);
258
259// Delete any outstanding share keys for resource links for contexts in this consumer
260 $sql = 'DELETE sk ' .
261 "FROM {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_SHARE_KEY_TABLE_NAME . ' sk ' .
262 "INNER JOIN {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' rl ON sk.resource_link_pk = rl.resource_link_pk ' .
263 "INNER JOIN {$this->dbTableNamePrefix}" . static::CONTEXT_TABLE_NAME . ' c ON rl.context_pk = c.context_pk ' .
264 'WHERE c.consumer_pk = ?';
265 $stmt = $this->db->prepare($sql);
266 $stmt->bind_param('i', $id);
267 $this->executeQuery($sql, $stmt);
268
269// Delete any users in resource links for this consumer
270 $sql = 'DELETE u ' .
271 "FROM {$this->dbTableNamePrefix}" . static::USER_RESULT_TABLE_NAME . ' u ' .
272 "INNER JOIN {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' rl ON u.resource_link_pk = rl.resource_link_pk ' .
273 'WHERE rl.consumer_pk = ?';
274 $stmt = $this->db->prepare($sql);
275 $stmt->bind_param('i', $id);
276 $this->executeQuery($sql, $stmt);
277
278// Delete any users in resource links for contexts in this consumer
279 $sql = 'DELETE u ' .
280 "FROM {$this->dbTableNamePrefix}" . static::USER_RESULT_TABLE_NAME . ' u ' .
281 "INNER JOIN {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' rl ON u.resource_link_pk = rl.resource_link_pk ' .
282 "INNER JOIN {$this->dbTableNamePrefix}" . static::CONTEXT_TABLE_NAME . ' c ON rl.context_pk = c.context_pk ' .
283 'WHERE c.consumer_pk = ?';
284 $stmt = $this->db->prepare($sql);
285 $stmt->bind_param('i', $id);
286 $this->executeQuery($sql, $stmt);
287
288// Update any resource links for which this consumer is acting as a primary resource link
289 $sql = "UPDATE {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' prl ' .
290 "INNER JOIN {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' rl ON prl.primary_resource_link_pk = rl.resource_link_pk ' .
291 'SET prl.primary_resource_link_pk = NULL, prl.share_approved = NULL ' .
292 'WHERE rl.consumer_pk = ?';
293 $stmt = $this->db->prepare($sql);
294 $stmt->bind_param('i', $id);
295 $this->executeQuery($sql, $stmt);
296
297// Update any resource links for contexts in which this consumer is acting as a primary resource link
298 $sql = "UPDATE {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' prl ' .
299 "INNER JOIN {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' rl ON prl.primary_resource_link_pk = rl.resource_link_pk ' .
300 "INNER JOIN {$this->dbTableNamePrefix}" . static::CONTEXT_TABLE_NAME . ' c ON rl.context_pk = c.context_pk ' .
301 'SET prl.primary_resource_link_pk = NULL, prl.share_approved = NULL ' .
302 'WHERE c.consumer_pk = ?';
303 $stmt = $this->db->prepare($sql);
304 $stmt->bind_param('i', $id);
305 $this->executeQuery($sql, $stmt);
306
307// Delete any resource links for this consumer
308 $sql = 'DELETE rl ' .
309 "FROM {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' rl ' .
310 'WHERE rl.consumer_pk = ?';
311 $stmt = $this->db->prepare($sql);
312 $stmt->bind_param('i', $id);
313 $this->executeQuery($sql, $stmt);
314
315// Delete any resource links for contexts in this consumer
316 $sql = 'DELETE rl ' .
317 "FROM {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' rl ' .
318 "INNER JOIN {$this->dbTableNamePrefix}" . static::CONTEXT_TABLE_NAME . ' c ON rl.context_pk = c.context_pk ' .
319 'WHERE c.consumer_pk = ?';
320 $stmt = $this->db->prepare($sql);
321 $stmt->bind_param('i', $id);
322 $this->executeQuery($sql, $stmt);
323
324// Delete any contexts for this consumer
325 $sql = 'DELETE c ' .
326 "FROM {$this->dbTableNamePrefix}" . static::CONTEXT_TABLE_NAME . ' c ' .
327 'WHERE c.consumer_pk = ?';
328 $stmt = $this->db->prepare($sql);
329 $stmt->bind_param('i', $id);
330 $this->executeQuery($sql, $stmt);
331
332// Delete consumer
333 $sql = 'DELETE c ' .
334 "FROM {$this->dbTableNamePrefix}" . static::PLATFORM_TABLE_NAME . ' c ' .
335 'WHERE c.consumer_pk = ?';
336 $stmt = $this->db->prepare($sql);
337 $stmt->bind_param('i', $id);
338 $ok = $this->executeQuery($sql, $stmt);
339
340 if ($ok) {
341 $platform->initialize();
342 }
343
344 return $ok;
345 }
346
352 public function getPlatforms()
353 {
354 $platforms = array();
355
356 $sql = 'SELECT consumer_pk, consumer_key, name, secret, ' .
357 'platform_id, client_id, deployment_id, public_key, ' .
358 'lti_version, signature_method, consumer_name, consumer_version, consumer_guid, ' .
359 'profile, tool_proxy, settings, ' .
360 'protected, enabled, enable_from, enable_until, last_access, created, updated ' .
361 "FROM {$this->dbTableNamePrefix}" . static::PLATFORM_TABLE_NAME . ' ' .
362 'ORDER BY name';
363 $stmt = $this->db->prepare($sql);
364 if ($this->executeQuery($sql, $stmt)) {
365 $rsConsumers = $stmt->get_result();
366 while ($row = $rsConsumers->fetch_object()) {
367 $platform = new Platform($this);
368 $platform->setRecordId(intval($row->consumer_pk));
369 $platform->name = $row->name;
370 $platform->setKey($row->consumer_key);
371 $platform->secret = $row->secret;
372 $platform->platformId = $row->platform_id;
373 $platform->clientId = $row->client_id;
374 $platform->deploymentId = $row->deployment_id;
375 $platform->rsaKey = $row->public_key;
376 $platform->ltiVersion = $row->lti_version;
377 $platform->signatureMethod = $row->signature_method;
378 $platform->consumerName = $row->consumer_name;
379 $platform->consumerVersion = $row->consumer_version;
380 $platform->consumerGuid = $row->consumer_guid;
381 $platform->profile = Util::jsonDecode($row->profile);
382 $platform->toolProxy = $row->tool_proxy;
383 $settings = Util::jsonDecode($row->settings, true);
384 if (!is_array($settings)) {
385 $settings = @unserialize($row->settings); // check for old serialized setting
386 }
387 if (!is_array($settings)) {
388 $settings = array();
389 }
390 $platform->setSettings($settings);
391 $platform->protected = (intval($row->protected) === 1);
392 $platform->enabled = (intval($row->enabled) === 1);
393 $platform->enableFrom = null;
394 if (!is_null($row->enable_from)) {
395 $platform->enableFrom = strtotime($row->enable_from);
396 }
397 $platform->enableUntil = null;
398 if (!is_null($row->enable_until)) {
399 $platform->enableUntil = strtotime($row->enable_until);
400 }
401 $platform->lastAccess = null;
402 if (!is_null($row->last_access)) {
403 $platform->lastAccess = strtotime($row->last_access);
404 }
405 $platform->created = strtotime($row->created);
406 $platform->updated = strtotime($row->updated);
407 $this->fixPlatformSettings($platform, false);
408 $platforms[] = $platform;
409 }
410 $rsConsumers->free_result();
411 }
412
413 return $platforms;
414 }
415
416###
417### Context methods
418###
419
427 public function loadContext($context)
428 {
429 $id = $context->getRecordId();
430 if (!is_null($id)) {
431 $sql = 'SELECT context_pk, consumer_pk, title, lti_context_id, type, settings, created, updated ' .
432 "FROM {$this->dbTableNamePrefix}" . static::CONTEXT_TABLE_NAME . ' ' .
433 'WHERE (context_pk = ?)';
434 $stmt = $this->db->prepare($sql);
435 $stmt->bind_param('i', $id);
436 } else {
437 $id = $context->getPlatform()->getRecordId();
438 $sql = 'SELECT context_pk, consumer_pk, title, lti_context_id, type, settings, created, updated ' .
439 "FROM {$this->dbTableNamePrefix}" . static::CONTEXT_TABLE_NAME . ' ' .
440 'WHERE (consumer_pk = ?) AND (lti_context_id = ?)';
441 $stmt = $this->db->prepare($sql);
442 $stmt->bind_param('is', $id, $context->ltiContextId);
443 }
444 $ok = $this->executeQuery($sql, $stmt);
445 if ($ok) {
446 $rsContext = $stmt->get_result();
447 $row = $rsContext->fetch_object();
448 if ($row) {
449 $context->setRecordId(intval($row->context_pk));
450 $context->setPlatformId(intval($row->consumer_pk));
451 $context->title = $row->title;
452 $context->ltiContextId = $row->lti_context_id;
453 $context->type = $row->type;
454 $settings = Util::jsonDecode($row->settings, true);
455 if (!is_array($settings)) {
456 $settings = @unserialize($row->settings); // check for old serialized setting
457 }
458 if (!is_array($settings)) {
459 $settings = array();
460 }
461 $context->setSettings($settings);
462 $context->created = strtotime($row->created);
463 $context->updated = strtotime($row->updated);
464 } else {
465 $ok = false;
466 }
467 }
468
469 return $ok;
470 }
471
479 public function saveContext($context)
480 {
481 $time = time();
482 $now = date("{$this->dateFormat} {$this->timeFormat}", $time);
483 $settingsValue = json_encode($context->getSettings());
484 $id = $context->getRecordId();
485 $consumer_pk = $context->getPlatform()->getRecordId();
486 if (empty($id)) {
487 $sql = "INSERT INTO {$this->dbTableNamePrefix}" . static::CONTEXT_TABLE_NAME . ' (consumer_pk, title, ' .
488 'lti_context_id, type, settings, created, updated) ' .
489 'VALUES (?, ?, ?, ?, ?, ?, ?)';
490 $stmt = $this->db->prepare($sql);
491 $stmt->bind_param('issssss', $consumer_pk, $context->title, $context->ltiContextId, $context->type, $settingsValue,
492 $now, $now);
493 } else {
494 $sql = "UPDATE {$this->dbTableNamePrefix}" . static::CONTEXT_TABLE_NAME . ' SET ' .
495 'title = ?, lti_context_id = ?, type = ?, settings = ?, ' .
496 'updated = ? ' .
497 'WHERE (consumer_pk = ?) AND (context_pk = ?)';
498 $stmt = $this->db->prepare($sql);
499 $stmt->bind_param('sssssii', $context->title, $context->ltiContextId, $context->type, $settingsValue, $now,
500 $consumer_pk, $id);
501 }
502 $ok = $this->executeQuery($sql, $stmt);
503 if ($ok) {
504 if (empty($id)) {
505 $context->setRecordId($this->db->insert_id);
506 $context->created = $time;
507 }
508 $context->updated = $time;
509 }
510
511 return $ok;
512 }
513
521 public function deleteContext($context)
522 {
523 $id = $context->getRecordId();
524
525// Delete any outstanding share keys for resource links for this context
526 $sql = 'DELETE sk ' .
527 "FROM {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_SHARE_KEY_TABLE_NAME . ' sk ' .
528 "INNER JOIN {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' rl ON sk.resource_link_pk = rl.resource_link_pk ' .
529 'WHERE rl.context_pk = ?';
530 $stmt = $this->db->prepare($sql);
531 $stmt->bind_param('i', $id);
532 $this->executeQuery($sql, $stmt);
533
534// Delete any users in resource links for this context
535 $sql = 'DELETE u ' .
536 "FROM {$this->dbTableNamePrefix}" . static::USER_RESULT_TABLE_NAME . ' u ' .
537 "INNER JOIN {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' rl ON u.resource_link_pk = rl.resource_link_pk ' .
538 'WHERE rl.context_pk = ?';
539 $stmt = $this->db->prepare($sql);
540 $stmt->bind_param('i', $id);
541 $this->executeQuery($sql, $stmt);
542
543// Update any resource links for which this consumer is acting as a primary resource link
544 $sql = "UPDATE {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' prl ' .
545 "INNER JOIN {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' rl ON prl.primary_resource_link_pk = rl.resource_link_pk ' .
546 'SET prl.primary_resource_link_pk = null, prl.share_approved = null ' .
547 'WHERE rl.context_pk = ?';
548 $stmt = $this->db->prepare($sql);
549 $stmt->bind_param('i', $id);
550 $this->executeQuery($sql, $stmt);
551
552// Delete any resource links for this consumer
553 $sql = 'DELETE rl ' .
554 "FROM {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' rl ' .
555 'WHERE rl.context_pk = ?';
556 $stmt = $this->db->prepare($sql);
557 $stmt->bind_param('i', $id);
558 $this->executeQuery($sql, $stmt);
559
560// Delete context
561 $sql = 'DELETE c ' .
562 "FROM {$this->dbTableNamePrefix}" . static::CONTEXT_TABLE_NAME . ' c ' .
563 'WHERE c.context_pk = ?';
564 $stmt = $this->db->prepare($sql);
565 $stmt->bind_param('i', $id);
566 $ok = $this->executeQuery($sql, $stmt);
567 if ($ok) {
568 $context->initialize();
569 }
570
571 return $ok;
572 }
573
574###
575### ResourceLink methods
576###
577
585 public function loadResourceLink($resourceLink)
586 {
587 $id = $resourceLink->getRecordId();
588 if (!is_null($id)) {
589 $sql = 'SELECT resource_link_pk, context_pk, consumer_pk, title, lti_resource_link_id, settings, primary_resource_link_pk, share_approved, created, updated ' .
590 "FROM {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' ' .
591 'WHERE (resource_link_pk = ?)';
592 $stmt = $this->db->prepare($sql);
593 $stmt->bind_param('i', $id);
594 } elseif (!is_null($resourceLink->getContext())) {
595 $rid = $resourceLink->getId();
596 $cid = $resourceLink->getContext()->getRecordId();
597 $sql = 'SELECT r.resource_link_pk, r.context_pk, r.consumer_pk, r.title, r.lti_resource_link_id, r.settings, r.primary_resource_link_pk, r.share_approved, r.created, r.updated ' .
598 "FROM {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' r ' .
599 'WHERE (r.lti_resource_link_id = ?) AND ((r.context_pk = ?) OR (r.consumer_pk IN (' .
600 'SELECT c.consumer_pk ' .
601 "FROM {$this->dbTableNamePrefix}" . static::CONTEXT_TABLE_NAME . ' c ' .
602 'WHERE (c.context_pk = ?))))';
603 $stmt = $this->db->prepare($sql);
604 $stmt->bind_param('sii', $rid, $cid, $cid);
605 } else {
606 $id = $resourceLink->getPlatform()->getRecordId();
607 $rid = $resourceLink->getId();
608 $sql = 'SELECT r.resource_link_pk, r.context_pk, r.consumer_pk, r.title, r.lti_resource_link_id, r.settings, r.primary_resource_link_pk, r.share_approved, r.created, r.updated ' .
609 "FROM {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' r LEFT OUTER JOIN ' .
610 $this->dbTableNamePrefix . static::CONTEXT_TABLE_NAME . ' c ON r.context_pk = c.context_pk ' .
611 ' WHERE ((r.consumer_pk = ?) OR (c.consumer_pk = ?)) AND (lti_resource_link_id = ?)';
612 $stmt = $this->db->prepare($sql);
613 $stmt->bind_param('iis', $id, $id, $rid);
614 }
615 $ok = $this->executeQuery($sql, $stmt);
616 if ($ok) {
617 $rsResourceLink = $stmt->get_result();
618 $row = $rsResourceLink->fetch_object();
619 if ($row) {
620 $resourceLink->setRecordId(intval($row->resource_link_pk));
621 if (!is_null($row->context_pk)) {
622 $resourceLink->setContextId(intval($row->context_pk));
623 } else {
624 $resourceLink->setContextId(null);
625 }
626 if (!is_null($row->consumer_pk)) {
627 $resourceLink->setPlatformId(intval($row->consumer_pk));
628 } else {
629 $resourceLink->setPlatformId(null);
630 }
631 $resourceLink->title = $row->title;
632 $resourceLink->ltiResourceLinkId = $row->lti_resource_link_id;
633 $settings = Util::jsonDecode($row->settings, true);
634 if (!is_array($settings)) {
635 $settings = @unserialize($row->settings); // check for old serialized setting
636 }
637 if (!is_array($settings)) {
638 $settings = array();
639 }
640 $resourceLink->setSettings($settings);
641 if (!is_null($row->primary_resource_link_pk)) {
642 $resourceLink->primaryResourceLinkId = intval($row->primary_resource_link_pk);
643 } else {
644 $resourceLink->primaryResourceLinkId = null;
645 }
646 $resourceLink->shareApproved = (is_null($row->share_approved)) ? null : (intval($row->share_approved) === 1);
647 $resourceLink->created = strtotime($row->created);
648 $resourceLink->updated = strtotime($row->updated);
649 } else {
650 $ok = false;
651 }
652 }
653
654 return $ok;
655 }
656
664 public function saveResourceLink($resourceLink)
665 {
666 if (is_null($resourceLink->shareApproved)) {
667 $approved = null;
668 } elseif ($resourceLink->shareApproved) {
669 $approved = 1;
670 } else {
671 $approved = 0;
672 }
673 if (empty($resourceLink->primaryResourceLinkId)) {
674 $primaryResourceLinkId = null;
675 } else {
676 $primaryResourceLinkId = strval($resourceLink->primaryResourceLinkId);
677 }
678 $time = time();
679 $now = date("{$this->dateFormat} {$this->timeFormat}", $time);
680 $settingsValue = json_encode($resourceLink->getSettings());
681 if (!is_null($resourceLink->getContext())) {
682 $consumerId = null;
683 $contextId = $resourceLink->getContext()->getRecordId();
684 } elseif (!is_null($resourceLink->getContextId())) {
685 $consumerId = null;
686 $contextId = $resourceLink->getContextId();
687 } else {
688 $consumerId = $resourceLink->getPlatform()->getRecordId();
689 $contextId = null;
690 }
691 $id = $resourceLink->getRecordId();
692 $rid = $resourceLink->getId();
693 if (empty($id)) {
694 $sql = "INSERT INTO {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' (consumer_pk, context_pk, ' .
695 'title, lti_resource_link_id, settings, primary_resource_link_pk, share_approved, created, updated) ' .
696 'VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)';
697 $stmt = $this->db->prepare($sql);
698 $stmt->bind_param('ssssssiss', $consumerId, $contextId, $resourceLink->title, $rid, $settingsValue,
699 $primaryResourceLinkId, $approved, $now, $now);
700 } elseif (!is_null($contextId)) {
701 $sql = "UPDATE {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' SET ' .
702 'consumer_pk = ?, title = ?, lti_resource_link_id = ?, settings = ?, ' .
703 'primary_resource_link_pk = ?, share_approved = ?, updated = ? ' .
704 'WHERE (context_pk = ?) AND (resource_link_pk = ?)';
705 $stmt = $this->db->prepare($sql);
706 $stmt->bind_param('sssssisii', $consumerId, $resourceLink->title, $rid, $settingsValue, $primaryResourceLinkId,
707 $approved, $now, $contextId, $id);
708 } else {
709 $sql = "UPDATE {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' SET ' .
710 'context_pk = NULL, title = ?, lti_resource_link_id = ?, settings = ?, ' .
711 'primary_resource_link_pk = ?, share_approved = ?, updated = ? ' .
712 'WHERE (consumer_pk = ?) AND (resource_link_pk = ?)';
713 $stmt = $this->db->prepare($sql);
714 $stmt->bind_param('sssiisii', $resourceLink->title, $rid, $settingsValue, $primaryResourceLinkId, $approved, $now,
715 $consumerId, $id);
716 }
717 $ok = $this->executeQuery($sql, $stmt);
718 if ($ok) {
719 if (empty($id)) {
720 $resourceLink->setRecordId($this->db->insert_id);
721 $resourceLink->created = $time;
722 }
723 $resourceLink->updated = $time;
724 }
725
726 return $ok;
727 }
728
736 public function deleteResourceLink($resourceLink)
737 {
738 $id = $resourceLink->getRecordId();
739
740// Delete any outstanding share keys for resource links for this consumer
741 $sql = "DELETE FROM {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_SHARE_KEY_TABLE_NAME . ' ' .
742 'WHERE (resource_link_pk = ?)';
743 $stmt = $this->db->prepare($sql);
744 $stmt->bind_param('i', $id);
745 $ok = $this->executeQuery($sql, $stmt);
746
747// Delete users
748 if ($ok) {
749 $sql = "DELETE FROM {$this->dbTableNamePrefix}" . static::USER_RESULT_TABLE_NAME . ' ' .
750 'WHERE (resource_link_pk = ?)';
751 $stmt = $this->db->prepare($sql);
752 $stmt->bind_param('i', $id);
753 $ok = $this->executeQuery($sql, $stmt);
754 }
755
756// Update any resource links for which this is the primary resource link
757 if ($ok) {
758 $sql = "UPDATE {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' ' .
759 'SET primary_resource_link_pk = NULL ' .
760 'WHERE (primary_resource_link_pk = ?)';
761 $stmt = $this->db->prepare($sql);
762 $stmt->bind_param('i', $id);
763 $ok = $this->executeQuery($sql, $stmt);
764 }
765
766// Delete resource link
767 if ($ok) {
768 $sql = "DELETE FROM {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' ' .
769 'WHERE (resource_link_pk = ?)';
770 $stmt = $this->db->prepare($sql);
771 $stmt->bind_param('i', $id);
772 $ok = $this->executeQuery($sql, $stmt);
773 }
774
775 if ($ok) {
776 $resourceLink->initialize();
777 }
778
779 return $ok;
780 }
781
794 public function getUserResultSourcedIDsResourceLink($resourceLink, $localOnly, $idScope)
795 {
796 $userResults = array();
797
798 $id = $resourceLink->getRecordId();
799 if ($localOnly) {
800 $sql = 'SELECT u.user_result_pk, u.lti_result_sourcedid, u.lti_user_id, u.created, u.updated ' .
801 "FROM {$this->dbTableNamePrefix}" . static::USER_RESULT_TABLE_NAME . ' AS u ' .
802 "INNER JOIN {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' AS rl ' .
803 'ON u.resource_link_pk = rl.resource_link_pk ' .
804 "WHERE (rl.resource_link_pk = ?) AND (rl.primary_resource_link_pk IS NULL)";
805 $stmt = $this->db->prepare($sql);
806 $stmt->bind_param('i', $id);
807 } else {
808 $sql = 'SELECT u.user_result_pk, u.lti_result_sourcedid, u.lti_user_id, u.created, u.updated ' .
809 "FROM {$this->dbTableNamePrefix}" . static::USER_RESULT_TABLE_NAME . ' AS u ' .
810 "INNER JOIN {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' AS rl ' .
811 'ON u.resource_link_pk = rl.resource_link_pk ' .
812 'WHERE ((rl.resource_link_pk = ?) AND (rl.primary_resource_link_pk IS NULL)) OR ' .
813 '((rl.primary_resource_link_pk = ?) AND (share_approved = 1))';
814 $stmt = $this->db->prepare($sql);
815 $stmt->bind_param('ii', $id, $id);
816 }
817 if ($this->executeQuery($sql, $stmt)) {
818 $rsUser = $stmt->get_result();
819 while ($row = $rsUser->fetch_object()) {
820 $userresult = LTI\UserResult::fromResourceLink($resourceLink, $row->lti_user_id);
821 if (is_null($idScope)) {
822 $userResults[] = $userresult;
823 } else {
824 $userResults[$userresult->getId($idScope)] = $userresult;
825 }
826 }
827 $rsUser->free_result();
828 }
829
830 return $userResults;
831 }
832
840 public function getSharesResourceLink($resourceLink)
841 {
842 $shares = array();
843
844 $id = $resourceLink->getRecordId();
845 $sql = 'SELECT c.consumer_name, r.resource_link_pk, r.title, r.share_approved ' .
846 "FROM {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' AS r ' .
847 "INNER JOIN {$this->dbTableNamePrefix}" . static::PLATFORM_TABLE_NAME . ' AS c ON r.consumer_pk = c.consumer_pk ' .
848 'WHERE (r.primary_resource_link_pk = ?) ' .
849 'UNION ' .
850 'SELECT c2.consumer_name, r2.resource_link_pk, r2.title, r2.share_approved ' .
851 "FROM {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' AS r2 ' .
852 "INNER JOIN {$this->dbTableNamePrefix}" . static::CONTEXT_TABLE_NAME . ' AS x ON r2.context_pk = x.context_pk ' .
853 "INNER JOIN {$this->dbTableNamePrefix}" . static::PLATFORM_TABLE_NAME . ' AS c2 ON x.consumer_pk = c2.consumer_pk ' .
854 'WHERE (r2.primary_resource_link_pk = ?) ' .
855 'ORDER BY consumer_name, title';
856 $stmt = $this->db->prepare($sql);
857 $stmt->bind_param('ii', $id, $id);
858 if ($this->executeQuery($sql, $stmt)) {
859 $rsShare = $stmt->get_result();
860 while ($row = $rsShare->fetch_object()) {
861 $share = new LTI\ResourceLinkShare();
862 $share->consumerName = $row->consumer_name;
863 $share->resourceLinkId = intval($row->resource_link_pk);
864 $share->title = $row->title;
865 $share->approved = (intval($row->share_approved) === 1);
866 $shares[] = $share;
867 }
868 $rsShare->free_result();
869 }
870
871 return $shares;
872 }
873
874###
875### PlatformNonce methods
876###
877
885 public function loadPlatformNonce($nonce)
886 {
887 if (parent::useMemcache()) {
888 $ok = parent::loadPlatformNonce($nonce);
889 } else {
890// Delete any expired nonce values
891 $now = date("{$this->dateFormat} {$this->timeFormat}", time());
892 $sql = "DELETE FROM {$this->dbTableNamePrefix}" . static::NONCE_TABLE_NAME . " WHERE expires <= ?";
893 $stmt = $this->db->prepare($sql);
894 $stmt->bind_param('s', $now);
895 $this->executeQuery($sql, $stmt);
896
897// Load the nonce
898 $id = $nonce->getPlatform()->getRecordId();
899 $value = $nonce->getValue();
900 $sql = "SELECT value AS T FROM {$this->dbTableNamePrefix}" . static::NONCE_TABLE_NAME . ' WHERE (consumer_pk = ?) AND (value = ?)';
901 $stmt = $this->db->prepare($sql);
902 $stmt->bind_param('is', $id, $value);
903 $ok = $this->executeQuery($sql, $stmt);
904 if ($ok) {
905 $rsNonce = $stmt->get_result();
906 if (!$rsNonce->fetch_object()) {
907 $ok = false;
908 }
909 }
910 }
911
912 return $ok;
913 }
914
922 public function savePlatformNonce($nonce)
923 {
924 if (parent::useMemcache()) {
925 $ok = parent::savePlatformNonce($nonce);
926 } else {
927 $id = $nonce->getPlatform()->getRecordId();
928 $value = $nonce->getValue();
929 $expires = date("{$this->dateFormat} {$this->timeFormat}", $nonce->expires);
930 $sql = "INSERT INTO {$this->dbTableNamePrefix}" . static::NONCE_TABLE_NAME . " (consumer_pk, value, expires) VALUES (?, ?, ?)";
931 $stmt = $this->db->prepare($sql);
932 $stmt->bind_param('iss', $id, $value, $expires);
933 $ok = $this->executeQuery($sql, $stmt);
934 }
935
936 return $ok;
937 }
938
946 public function deletePlatformNonce($nonce)
947 {
948 if (parent::useMemcache()) {
949 $ok = parent::deletePlatformNonce($nonce);
950 } else {
951 $sql = "DELETE FROM {$this->dbTableNamePrefix}" . static::NONCE_TABLE_NAME . ' WHERE (consumer_pk = ?) AND (value = ?)';
952 $stmt = $this->db->prepare($sql);
953 $id = $nonce->getPlatform()->getRecordId();
954 $value = $nonce->getValue();
955 $stmt->bind_param('is', $id, $value);
956 $ok = $this->executeQuery($sql, $stmt);
957 }
958
959 return $ok;
960 }
961
962###
963### AccessToken methods
964###
965
973 public function loadAccessToken($accessToken)
974 {
975 if (parent::useMemcache()) {
976 $ok = parent::loadAccessToken($accessToken);
977 } else {
978 $consumer_pk = $accessToken->getPlatform()->getRecordId();
979 $sql = 'SELECT scopes, token, expires, created, updated ' .
980 "FROM {$this->dbTableNamePrefix}" . static::ACCESS_TOKEN_TABLE_NAME . ' ' .
981 'WHERE (consumer_pk = ?)';
982 $stmt = $this->db->prepare($sql);
983 $stmt->bind_param('i', $consumer_pk);
984 $ok = $this->executeQuery($sql, $stmt);
985 if ($ok) {
986 $rsAccessToken = $stmt->get_result();
987 $row = $rsAccessToken->fetch_object();
988 if ($row) {
989 $scopes = Util::jsonDecode($row->scopes, true);
990 if (!is_array($scopes)) {
991 $scopes = array();
992 }
993 $accessToken->scopes = $scopes;
994 $accessToken->token = $row->token;
995 $accessToken->expires = strtotime($row->expires);
996 $accessToken->created = strtotime($row->created);
997 $accessToken->updated = strtotime($row->updated);
998 } else {
999 $ok = false;
1000 }
1001 }
1002 }
1003
1004 return $ok;
1005 }
1006
1014 public function saveAccessToken($accessToken)
1015 {
1016 if (parent::useMemcache()) {
1017 $ok = parent::saveAccessToken($accessToken);
1018 } else {
1019 $consumer_pk = $accessToken->getPlatform()->getRecordId();
1020 $scopes = json_encode($accessToken->scopes, JSON_UNESCAPED_SLASHES);
1021 $token = $accessToken->token;
1022 $expires = date("{$this->dateFormat} {$this->timeFormat}", $accessToken->expires);
1023 $time = time();
1024 $now = date("{$this->dateFormat} {$this->timeFormat}", $time);
1025 if (empty($accessToken->created)) {
1026 $sql = "INSERT INTO {$this->dbTableNamePrefix}" . static::ACCESS_TOKEN_TABLE_NAME . ' ' .
1027 '(consumer_pk, scopes, token, expires, created, updated) ' .
1028 'VALUES (?, ?, ?, ?, ?, ?)';
1029 $stmt = $this->db->prepare($sql);
1030 $stmt->bind_param('isssss', $consumer_pk, $scopes, $token, $expires, $now, $now);
1031 } else {
1032 $sql = 'UPDATE ' . $this->dbTableNamePrefix . static::ACCESS_TOKEN_TABLE_NAME . ' ' .
1033 'SET scopes = ?, token = ?, expires = ?, updated = ? WHERE consumer_pk = ?';
1034 $stmt = $this->db->prepare($sql);
1035 $stmt->bind_param('ssssi', $scopes, $token, $expires, $now, $consumer_pk);
1036 }
1037 $ok = $this->executeQuery($sql, $stmt);
1038 }
1039
1040 return $ok;
1041 }
1042
1043###
1044### ResourceLinkShareKey methods
1045###
1046
1054 public function loadResourceLinkShareKey($shareKey)
1055 {
1056// Clear expired share keys
1057 $now = date("{$this->dateFormat} {$this->timeFormat}", time());
1058 $sql = "DELETE FROM {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_SHARE_KEY_TABLE_NAME . " WHERE expires <= ?";
1059 $stmt = $this->db->prepare($sql);
1060 $stmt->bind_param('s', $now);
1061 $this->executeQuery($sql, $stmt);
1062// Load share key
1063 $id = $shareKey->getId();
1064 $sql = 'SELECT resource_link_pk, auto_approve, expires ' .
1065 "FROM {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_SHARE_KEY_TABLE_NAME . ' ' .
1066 "WHERE share_key_id = ?";
1067 $stmt = $this->db->prepare($sql);
1068 $stmt->bind_param('s', $id);
1069 $ok = $this->executeQuery($sql, $stmt);
1070 if ($ok) {
1071 $rsShareKey = $stmt->get_result();
1072 $row = $rsShareKey->fetch_object();
1073 if ($row) {
1074 $shareKey->resourceLinkId = intval($row->resource_link_pk);
1075 $shareKey->autoApprove = (intval($row->auto_approve) === 1);
1076 $shareKey->expires = strtotime($row->expires);
1077 } else {
1078 $ok = false;
1079 }
1080 }
1081
1082 return $ok;
1083 }
1084
1092 public function saveResourceLinkShareKey($shareKey)
1093 {
1094 $id = $shareKey->getId();
1095 if ($shareKey->autoApprove) {
1096 $approve = 1;
1097 } else {
1098 $approve = 0;
1099 }
1100 $expires = date("{$this->dateFormat} {$this->timeFormat}", $shareKey->expires);
1101 $sql = "INSERT INTO {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_SHARE_KEY_TABLE_NAME . ' ' .
1102 '(share_key_id, resource_link_pk, auto_approve, expires) ' .
1103 "VALUES (?, ?, ?, ?)";
1104 $stmt = $this->db->prepare($sql);
1105 $stmt->bind_param('ssis', $id, $shareKey->resourceLinkId, $approve, $expires);
1106 $ok = $this->executeQuery($sql, $stmt);
1107
1108 return $ok;
1109 }
1110
1118 public function deleteResourceLinkShareKey($shareKey)
1119 {
1120 $id = $shareKey->getId();
1121 $sql = "DELETE FROM {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_SHARE_KEY_TABLE_NAME . " WHERE share_key_id = ?";
1122 $stmt = $this->db->prepare($sql);
1123 $stmt->bind_param('s', $id);
1124 $ok = $this->executeQuery($sql, $stmt);
1125
1126 if ($ok) {
1127 $shareKey->initialize();
1128 }
1129
1130 return $ok;
1131 }
1132
1133###
1134### UserResult methods
1135###
1136
1144 public function loadUserResult($userresult)
1145 {
1146 $id = $userresult->getRecordId();
1147 if (!is_null($id)) {
1148 $sql = 'SELECT user_result_pk, resource_link_pk, lti_user_id, lti_result_sourcedid, created, updated ' .
1149 "FROM {$this->dbTableNamePrefix}" . static::USER_RESULT_TABLE_NAME . ' ' .
1150 'WHERE (user_result_pk = ?)';
1151 $stmt = $this->db->prepare($sql);
1152 $stmt->bind_param('i', $id);
1153 } else {
1154 $rid = $userresult->getResourceLink()->getRecordId();
1155 $uid = $userresult->getId(LTI\Tool::ID_SCOPE_ID_ONLY);
1156 $sql = 'SELECT user_result_pk, resource_link_pk, lti_user_id, lti_result_sourcedid, created, updated ' .
1157 "FROM {$this->dbTableNamePrefix}" . static::USER_RESULT_TABLE_NAME . ' ' .
1158 'WHERE (resource_link_pk = ?) AND (lti_user_id = ?)';
1159 $stmt = $this->db->prepare($sql);
1160 $stmt->bind_param('is', $rid, $uid);
1161 }
1162 $ok = $this->executeQuery($sql, $stmt);
1163 if ($ok) {
1164 $rsUserResult = $stmt->get_result();
1165 $row = $rsUserResult->fetch_object();
1166 if ($row) {
1167 $userresult->setRecordId(intval($row->user_result_pk));
1168 $userresult->setResourceLinkId(intval($row->resource_link_pk));
1169 $userresult->ltiUserId = $row->lti_user_id;
1170 $userresult->ltiResultSourcedId = $row->lti_result_sourcedid;
1171 $userresult->created = strtotime($row->created);
1172 $userresult->updated = strtotime($row->updated);
1173 } else {
1174 $ok = false;
1175 }
1176 }
1177
1178 return $ok;
1179 }
1180
1188 public function saveUserResult($userresult)
1189 {
1190 $time = time();
1191 $now = date("{$this->dateFormat} {$this->timeFormat}", $time);
1192 if (is_null($userresult->created)) {
1193 $rid = $userresult->getResourceLink()->getRecordId();
1194 $uid = $userresult->getId(LTI\Tool::ID_SCOPE_ID_ONLY);
1195 $sql = "INSERT INTO {$this->dbTableNamePrefix}" . static::USER_RESULT_TABLE_NAME . ' (resource_link_pk, ' .
1196 'lti_user_id, lti_result_sourcedid, created, updated) ' .
1197 'VALUES (?, ?, ?, ?, ?)';
1198 $stmt = $this->db->prepare($sql);
1199 $stmt->bind_param('issss', $rid, $uid, $userresult->ltiResultSourcedId, $now, $now);
1200 } else {
1201 $id = $userresult->getRecordId();
1202 $sql = "UPDATE {$this->dbTableNamePrefix}" . static::USER_RESULT_TABLE_NAME . ' ' .
1203 'SET lti_result_sourcedid = ?, updated = ? ' .
1204 'WHERE (user_result_pk = ?)';
1205 $stmt = $this->db->prepare($sql);
1206 $stmt->bind_param('ssi', $userresult->ltiResultSourcedId, $now, $id);
1207 }
1208 $ok = $this->executeQuery($sql, $stmt);
1209 if ($ok) {
1210 if (is_null($userresult->created)) {
1211 $userresult->setRecordId(mysqli_insert_id($this->db));
1212 $userresult->created = $time;
1213 }
1214 $userresult->updated = $time;
1215 }
1216
1217 return $ok;
1218 }
1219
1227 public function deleteUserResult($userresult)
1228 {
1229 $id = $userresult->getRecordId();
1230 $sql = "DELETE FROM {$this->dbTableNamePrefix}" . static::USER_RESULT_TABLE_NAME . ' ' .
1231 'WHERE (user_result_pk = ?)';
1232 $stmt = $this->db->prepare($sql);
1233 $stmt->bind_param('i', $id);
1234 $ok = $this->executeQuery($sql, $stmt);
1235
1236 if ($ok) {
1237 $userresult->initialize();
1238 }
1239
1240 return $ok;
1241 }
1242
1243###
1244### Tool methods
1245###
1246
1254 public function loadTool($tool)
1255 {
1256 $id = $tool->getRecordId();
1257 if (!is_null($id)) {
1258 $sql = 'SELECT tool_pk, name, consumer_key, secret, ' .
1259 'message_url, initiate_login_url, redirection_uris, public_key, ' .
1260 'lti_version, signature_method, settings, enabled, ' .
1261 'enable_from, enable_until, last_access, created, updated ' .
1262 "FROM {$this->dbTableNamePrefix}" . static::TOOL_TABLE_NAME . ' ' .
1263 'WHERE tool_pk = ?';
1264 $stmt = $this->db->prepare($sql);
1265 $stmt->bind_param('i', $id);
1266 } elseif (!empty($tool->initiateLoginUrl)) {
1267 $sql = 'SELECT tool_pk, name, consumer_key, secret, ' .
1268 'message_url, initiate_login_url, redirection_uris, public_key, ' .
1269 'lti_version, signature_method, settings, enabled, ' .
1270 'enable_from, enable_until, last_access, created, updated ' .
1271 "FROM {$this->dbTableNamePrefix}" . static::TOOL_TABLE_NAME . ' ' .
1272 'WHERE initiate_login_url = ?';
1273 $stmt = $this->db->prepare($sql);
1274 $stmt->bind_param('s', $tool->initiateLoginUrl);
1275 } else {
1276 $key = $tool->getKey();
1277 $sql = 'SELECT tool_pk, name, consumer_key, secret, ' .
1278 'message_url, initiate_login_url, redirection_uris, public_key, ' .
1279 'lti_version, signature_method, settings, enabled, ' .
1280 'enable_from, enable_until, last_access, created, updated ' .
1281 "FROM {$this->dbTableNamePrefix}" . static::TOOL_TABLE_NAME . ' ' .
1282 'WHERE consumer_key = ?';
1283 $stmt = $this->db->prepare($sql);
1284 $stmt->bind_param('s', $key);
1285 }
1286 $ok = $this->executeQuery($sql, $stmt);
1287 if ($ok) {
1288 $rsTool = $stmt->get_result();
1289 $row = $rsTool->fetch_object();
1290 if ($row) {
1291 $tool->setRecordId(intval($row->tool_pk));
1292 $tool->name = $row->name;
1293 $tool->setkey($row->consumer_key);
1294 $tool->secret = $row->secret;
1295 $tool->messageUrl = $row->message_url;
1296 $tool->initiateLoginUrl = $row->initiate_login_url;
1297 $tool->redirectionUris = Util::jsonDecode($row->redirection_uris, true);
1298 if (!is_array($tool->redirectionUris)) {
1299 $tool->redirectionUris = array();
1300 }
1301 $tool->rsaKey = $row->public_key;
1302 $tool->ltiVersion = $row->lti_version;
1303 $tool->signatureMethod = $row->signature_method;
1304 $settings = Util::jsonDecode($row->settings, true);
1305 if (!is_array($settings)) {
1306 $settings = array();
1307 }
1308 $tool->setSettings($settings);
1309 $tool->enabled = (intval($row->enabled) === 1);
1310 $tool->enableFrom = null;
1311 if (!is_null($row->enable_from)) {
1312 $tool->enableFrom = strtotime($row->enable_from);
1313 }
1314 $tool->enableUntil = null;
1315 if (!is_null($row->enable_until)) {
1316 $tool->enableUntil = strtotime($row->enable_until);
1317 }
1318 $tool->lastAccess = null;
1319 if (!is_null($row->last_access)) {
1320 $tool->lastAccess = strtotime($row->last_access);
1321 }
1322 $tool->created = strtotime($row->created);
1323 $tool->updated = strtotime($row->updated);
1324 $this->fixToolSettings($tool, false);
1325 } else {
1326 $ok = false;
1327 }
1328 }
1329
1330 return $ok;
1331 }
1332
1340 public function saveTool($tool)
1341 {
1342 $id = $tool->getRecordId();
1343 $enabled = ($tool->enabled) ? 1 : 0;
1344 $redirectionUrisValue = json_encode($tool->redirectionUris);
1345 $this->fixToolSettings($tool, true);
1346 $settingsValue = json_encode($tool->getSettings());
1347 $this->fixToolSettings($tool, false);
1348 $time = time();
1349 $now = date("{$this->dateFormat} {$this->timeFormat}", $time);
1350 $from = null;
1351 if (!is_null($tool->enableFrom)) {
1352 $from = date("{$this->dateFormat} {$this->timeFormat}", $tool->enableFrom);
1353 }
1354 $until = null;
1355 if (!is_null($tool->enableUntil)) {
1356 $until = date("{$this->dateFormat} {$this->timeFormat}", $tool->enableUntil);
1357 }
1358 $last = null;
1359 if (!is_null($tool->lastAccess)) {
1360 $last = date($this->dateFormat, $tool->lastAccess);
1361 }
1362 $key = $tool->getKey();
1363 if (empty($id)) {
1364 $sql = "INSERT INTO {$this->dbTableNamePrefix}" . static::TOOL_TABLE_NAME . ' (name, consumer_key, secret, ' .
1365 'message_url, initiate_login_url, redirection_uris, public_key, ' .
1366 'lti_version, signature_method, settings, enabled, enable_from, enable_until, ' .
1367 'last_access, created, updated) ' .
1368 'VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)';
1369 $stmt = $this->db->prepare($sql);
1370 $stmt->bind_param('ssssssssssisssss', $tool->name, $key, $tool->secret, $tool->messageUrl, $tool->initiateLoginUrl,
1371 $redirectionUrisValue, $tool->rsaKey, $tool->ltiVersion, $tool->signatureMethod, $settingsValue, $enabled, $from,
1372 $until, $last, $now, $now);
1373 } else {
1374 $sql = "UPDATE {$this->dbTableNamePrefix}" . static::TOOL_TABLE_NAME . ' SET ' .
1375 'name = ?, consumer_key = ?, secret= ?, ' .
1376 'message_url = ?, initiate_login_url = ?, redirection_uris = ?, public_key = ?, ' .
1377 'lti_version = ?, signature_method = ?, settings = ?, enabled = ?, enable_from = ?, enable_until = ?, ' .
1378 'last_access = ?, updated = ? ' .
1379 'WHERE tool_pk = ?';
1380 $stmt = $this->db->prepare($sql);
1381 $stmt->bind_param('ssssssssssissssi', $tool->name, $key, $tool->secret, $tool->messageUrl, $tool->initiateLoginUrl,
1382 $redirectionUrisValue, $tool->rsaKey, $tool->ltiVersion, $tool->signatureMethod, $settingsValue, $enabled, $from,
1383 $until, $last, $now, $id);
1384 }
1385 $ok = $this->executeQuery($sql, $stmt);
1386 if ($ok) {
1387 if (empty($id)) {
1388 $tool->setRecordId($this->db->insert_id);
1389 $tool->created = $time;
1390 }
1391 $tool->updated = $time;
1392 }
1393
1394 return $ok;
1395 }
1396
1404 public function deleteTool($tool)
1405 {
1406 $id = $tool->getRecordId();
1407 $sql = 'DELETE t ' .
1408 "FROM {$this->dbTableNamePrefix}" . static::TOOL_TABLE_NAME . ' t ' .
1409 'WHERE t.tool_pk = ?';
1410 $stmt = $this->db->prepare($sql);
1411 $stmt->bind_param('i', $id);
1412 $ok = $this->executeQuery($sql, $stmt);
1413
1414 if ($ok) {
1415 $tool->initialize();
1416 }
1417
1418 return $ok;
1419 }
1420
1426 public function getTools()
1427 {
1428 $tools = array();
1429
1430 $sql = 'SELECT tool_pk, name, consumer_key, secret, ' .
1431 'message_url, initiate_login_url, redirection_uris, public_key, ' .
1432 'lti_version, signature_method, settings, enabled, ' .
1433 'enable_from, enable_until, last_access, created, updated ' .
1434 "FROM {$this->dbTableNamePrefix}" . static::TOOL_TABLE_NAME . ' ' .
1435 'ORDER BY name';
1436 $stmt = $this->db->prepare($sql);
1437 if ($this->executeQuery($sql, $stmt)) {
1438 $rsTools = $stmt->get_result();
1439 while ($row = $rsTools->fetch_object()) {
1440 $tool = new Tool($this);
1441 $tool->setRecordId(intval($row->tool_pk));
1442 $tool->name = $row->name;
1443 $tool->setkey($row->consumer_key);
1444 $tool->secret = $row->secret;
1445 $tool->messageUrl = $row->message_url;
1446 $tool->initiateLoginUrl = $row->initiate_login_url;
1447 $tool->redirectionUris = Util::jsonDecode($row->redirection_uris, true);
1448 if (!is_array($tool->redirectionUris)) {
1449 $tool->redirectionUris = array();
1450 }
1451 $tool->rsaKey = $row->public_key;
1452 $tool->ltiVersion = $row->lti_version;
1453 $tool->signatureMethod = $row->signature_method;
1454 $settings = Util::jsonDecode($row->settings, true);
1455 if (!is_array($settings)) {
1456 $settings = array();
1457 }
1458 $tool->setSettings($settings);
1459 $tool->enabled = (intval($row->enabled) === 1);
1460 $tool->enableFrom = null;
1461 if (!is_null($row->enable_from)) {
1462 $tool->enableFrom = strtotime($row->enable_from);
1463 }
1464 $tool->enableUntil = null;
1465 if (!is_null($row->enable_until)) {
1466 $tool->enableUntil = strtotime($row->enable_until);
1467 }
1468 $tool->lastAccess = null;
1469 if (!is_null($row->last_access)) {
1470 $tool->lastAccess = strtotime($row->last_access);
1471 }
1472 $tool->created = strtotime($row->created);
1473 $tool->updated = strtotime($row->updated);
1474 $this->fixToolSettings($tool, false);
1475 $tools[] = $tool;
1476 }
1477 $rsTools->free_result();
1478 }
1479
1480 return $tools;
1481 }
1482
1483###
1484### Other methods
1485###
1486
1498 private function executeQuery($sql, $stmt, $reportError = true)
1499 {
1500 try {
1501 $ok = $stmt->execute();
1502 } catch (\Exception $e) {
1503 $ok = false;
1504 }
1505 $info = $this->db->info;
1506 if (!empty($info)) {
1507 $info = PHP_EOL . $info;
1508 }
1509 if (!$ok && $reportError) {
1510 Util::logError($sql . $info . $this->errorListToString($stmt->error_list));
1511 } else {
1512 Util::logDebug($sql . $info);
1513 }
1514
1515 return $ok;
1516 }
1517
1525 private function errorListToString($errorList)
1526 {
1527 $errors = '';
1528 if (is_array($errorList) && !empty($errorList)) {
1529 if (count($errorList) <= 1) {
1530 $sep = 'Error ';
1531 } else {
1532 $sep = 'Errors:' . PHP_EOL . ' ';
1533 }
1534 foreach ($errorList as $error) {
1535 $errors .= PHP_EOL . "{$sep}{$error['errno']}/{$error['sqlstate']}: {$error['error']}";
1536 $sep = ' ';
1537 }
1538 }
1539
1540 return $errors;
1541 }
1542
1543}
Class to represent an HTTP message.
Class to represent a platform context.
Definition Context.php:18
Class to represent an LTI Data Connector for MySQLi.
loadResourceLinkShareKey($shareKey)
Load resource link share key object.
deletePlatform($platform)
Delete platform object.
saveAccessToken($accessToken)
Save access token object.
saveResourceLinkShareKey($shareKey)
Save resource link share key object.
loadAccessToken($accessToken)
Load access token object.
getUserResultSourcedIDsResourceLink($resourceLink, $localOnly, $idScope)
Get array of user objects.
getPlatforms()
Load all platforms from the database.
getSharesResourceLink($resourceLink)
Get array of shares defined for this resource link.
loadResourceLink($resourceLink)
Load resource link object.
saveResourceLink($resourceLink)
Save resource link object.
deleteResourceLinkShareKey($shareKey)
Delete resource link share key object.
deleteResourceLink($resourceLink)
Delete resource link object.
Class to provide a connection to a persistent store for LTI objects.
fixToolSettings($tool, $isSave)
Adjust the settings for any tool properties being stored as a setting value.
fixPlatformSettings($platform, $isSave)
Adjust the settings for any platform properties being stored as a setting value.
Class to represent a platform nonce.
Class to represent a platform.
Definition Platform.php:18
Class to represent a platform resource link share key.
Class to represent a platform resource link share.
Class to represent an LTI Tool.
Definition Tool.php:24
const ID_SCOPE_ID_ONLY
Use ID value only.
Definition Tool.php:34
Class to represent a platform user association with a resource link.
Class to implement utility methods.
Definition Util.php:15
static logError($message, $showSource=true)
Log an error message.
Definition Util.php:248
static jsonDecode($str, $associative=false)
Decode a JSON string.
Definition Util.php:560
static logDebug($message, $showSource=false)
Log a debug message.
Definition Util.php:274