LTI Integration Library  3.1.0
PHP class library for building LTI integrations
DataConnector_sqlsrv.php
Go to the documentation of this file.
1 <?php
2 
4 
5 use ceLTIc\LTI;
13 
22 ###
23 # NB This class assumes that a MS SQL Server connection has already been opened to the appropriate schema
24 ###
25 
26 
28 {
29 ###
30 ### ToolConsumer methods
31 ###
32 
40  public function loadToolConsumer($consumer)
41  {
42  $ok = false;
43  if (!is_null($consumer->getRecordId())) {
44  $sql = sprintf('SELECT consumer_pk, name, consumer_key256, consumer_key, secret, lti_version, ' .
45  'signature_method, consumer_name, consumer_version, consumer_guid, ' .
46  'profile, tool_proxy, settings, protected, enabled, ' .
47  'enable_from, enable_until, last_access, created, updated ' .
48  "FROM {$this->dbTableNamePrefix}" . static::CONSUMER_TABLE_NAME . ' ' .
49  "WHERE consumer_pk = %d", $consumer->getRecordId());
50  } else {
51  $key256 = static::getConsumerKey($consumer->getKey());
52  $sql = sprintf('SELECT consumer_pk, name, consumer_key256, consumer_key, secret, lti_version, ' .
53  'signature_method, consumer_name, consumer_version, consumer_guid, ' .
54  'profile, tool_proxy, settings, protected, enabled, ' .
55  'enable_from, enable_until, last_access, created, updated ' .
56  "FROM {$this->dbTableNamePrefix}" . static::CONSUMER_TABLE_NAME . ' ' .
57  "WHERE consumer_key256 = %s", $this->escape($key256));
58  }
59  $rsConsumer = sqlsrv_query($this->db, $sql);
60  if ($rsConsumer) {
61  while ($row = sqlsrv_fetch_object($rsConsumer)) {
62  if (empty($key256) || empty($row->consumer_key) || ($consumer->getKey() === $row->consumer_key)) {
63  $consumer->setRecordId(intval($row->consumer_pk));
64  $consumer->name = $row->name;
65  $consumer->setkey(empty($row->consumer_key) ? $row->consumer_key256 : $row->consumer_key);
66  $consumer->secret = $row->secret;
67  $consumer->ltiVersion = $row->lti_version;
68  $consumer->signatureMethod = $row->signature_method;
69  $consumer->consumerName = $row->consumer_name;
70  $consumer->consumerVersion = $row->consumer_version;
71  $consumer->consumerGuid = $row->consumer_guid;
72  $consumer->profile = json_decode($row->profile);
73  $consumer->toolProxy = $row->tool_proxy;
74  $settings = json_decode($row->settings, TRUE);
75  if (!is_array($settings)) {
76  $settings = @unserialize($row->settings); // check for old serialized setting
77  }
78  if (!is_array($settings)) {
79  $settings = array();
80  }
81  $consumer->setSettings($settings);
82  $consumer->protected = (intval($row->protected) === 1);
83  $consumer->enabled = (intval($row->enabled) === 1);
84  $consumer->enableFrom = null;
85  if (!is_null($row->enable_from)) {
86  $consumer->enableFrom = date_timestamp_get($row->enable_from);
87  }
88  $consumer->enableUntil = null;
89  if (!is_null($row->enable_until)) {
90  $consumer->enableUntil = date_timestamp_get($row->enable_until);
91  }
92  $consumer->lastAccess = null;
93  if (!is_null($row->last_access)) {
94  $consumer->lastAccess = date_timestamp_get($row->last_access);
95  }
96  $consumer->created = date_timestamp_get($row->created);
97  $consumer->updated = date_timestamp_get($row->updated);
98  $ok = true;
99  break;
100  }
101  }
102  sqlsrv_free_stmt($rsConsumer);
103  }
104 
105  return $ok;
106  }
107 
115  public function saveToolConsumer($consumer)
116  {
117  $id = $consumer->getRecordId();
118  $key = $consumer->getKey();
119  $key256 = static::getConsumerKey($key);
120  if ($key === $key256) {
121  $key = null;
122  }
123  $protected = ($consumer->protected) ? 1 : 0;
124  $enabled = ($consumer->enabled) ? 1 : 0;
125  $profile = (!empty($consumer->profile)) ? json_encode($consumer->profile) : null;
126  $settingsValue = json_encode($consumer->getSettings());
127  $time = time();
128  $now = date("{$this->dateFormat} {$this->timeFormat}", $time);
129  $from = null;
130  if (!is_null($consumer->enableFrom)) {
131  $from = date_format($consumer->enableFrom, "{$this->dateFormat} {$this->timeFormat}");
132  }
133  $until = null;
134  if (!is_null($consumer->enableUntil)) {
135  $until = date_format($consumer->enableUntil, "{$this->dateFormat} {$this->timeFormat}");
136  }
137  $last = null;
138  if (!is_null($consumer->lastAccess)) {
139  $last = date_format($consumer->lastAccess, $this->dateFormat);
140  }
141  if (empty($id)) {
142  $sql = sprintf("INSERT INTO {$this->dbTableNamePrefix}" . static::CONSUMER_TABLE_NAME . ' (consumer_key256, consumer_key, name, ' .
143  'secret, lti_version, signature_method, consumer_name, consumer_version, consumer_guid, profile, ' .
144  'tool_proxy, settings, protected, enabled, ' .
145  'enable_from, enable_until, last_access, created, updated) ' .
146  'VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %d, %d, %s, %s, %s, %s, %s)', $this->escape($key256),
147  $this->escape($key), $this->escape($consumer->name), $this->escape($consumer->secret),
148  $this->escape($consumer->ltiVersion), $this->escape($consumer->signatureMethod),
149  $this->escape($consumer->consumerName), $this->escape($consumer->consumerVersion),
150  $this->escape($consumer->consumerGuid), $this->escape($profile), $this->escape($consumer->toolProxy),
151  $this->escape($settingsValue), $protected, $enabled, $this->escape($from), $this->escape($until),
152  $this->escape($last), $this->escape($now), $this->escape($now));
153  } else {
154  $sql = sprintf("UPDATE {$this->dbTableNamePrefix}" . static::CONSUMER_TABLE_NAME . ' SET ' .
155  'consumer_key256 = %s, consumer_key = %s, ' .
156  'name = %s, secret= %s, lti_version = %s, signature_method = %s, consumer_name = %s, consumer_version = %s, consumer_guid = %s, ' .
157  'profile = %s, tool_proxy = %s, settings = %s, ' .
158  'protected = %d, enabled = %d, enable_from = %s, enable_until = %s, last_access = %s, updated = %s ' .
159  'WHERE consumer_pk = %d', $this->escape($key256), $this->escape($key), $this->escape($consumer->name),
160  $this->escape($consumer->secret), $this->escape($consumer->ltiVersion), $this->escape($consumer->signatureMethod),
161  $this->escape($consumer->consumerName), $this->escape($consumer->consumerVersion),
162  $this->escape($consumer->consumerGuid), $this->escape($profile), $this->escape($consumer->toolProxy),
163  $this->escape($settingsValue), $protected, $enabled, $this->escape($from), $this->escape($until),
164  $this->escape($last), $this->escape($now), $consumer->getRecordId());
165  }
166  $ok = sqlsrv_query($this->db, $sql);
167  if ($ok) {
168  if (empty($id)) {
169  $consumer->setRecordId($this->insert_id());
170  $consumer->created = $time;
171  }
172  $consumer->updated = $time;
173  }
174 
175  return $ok;
176  }
177 
185  public function deleteToolConsumer($consumer)
186  {
187 // Delete any nonce values for this consumer
188  $sql = sprintf("DELETE FROM {$this->dbTableNamePrefix}" . static::NONCE_TABLE_NAME . ' WHERE consumer_pk = %d',
189  $consumer->getRecordId());
190  sqlsrv_query($this->db, $sql);
191 
192 // Delete any outstanding share keys for resource links for this consumer
193  $sql = sprintf('DELETE sk ' .
194  "FROM {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_SHARE_KEY_TABLE_NAME . ' sk ' .
195  "INNER JOIN {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' rl ON sk.resource_link_pk = rl.resource_link_pk ' .
196  'WHERE rl.consumer_pk = %d', $consumer->getRecordId());
197  sqlsrv_query($this->db, $sql);
198 
199 // Delete any outstanding share keys for resource links for contexts in this consumer
200  $sql = sprintf('DELETE sk ' .
201  "FROM {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_SHARE_KEY_TABLE_NAME . ' sk ' .
202  "INNER JOIN {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' rl ON sk.resource_link_pk = rl.resource_link_pk ' .
203  "INNER JOIN {$this->dbTableNamePrefix}" . static::CONTEXT_TABLE_NAME . ' c ON rl.context_pk = c.context_pk ' .
204  'WHERE c.consumer_pk = %d', $consumer->getRecordId());
205  sqlsrv_query($this->db, $sql);
206 
207 // Delete any users in resource links for this consumer
208  $sql = sprintf('DELETE u ' .
209  "FROM {$this->dbTableNamePrefix}" . static::USER_RESULT_TABLE_NAME . ' u ' .
210  "INNER JOIN {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' rl ON u.resource_link_pk = rl.resource_link_pk ' .
211  'WHERE rl.consumer_pk = %d', $consumer->getRecordId());
212  sqlsrv_query($this->db, $sql);
213 
214 // Delete any users in resource links for contexts in this consumer
215  $sql = sprintf('DELETE u ' .
216  "FROM {$this->dbTableNamePrefix}" . static::USER_RESULT_TABLE_NAME . ' u ' .
217  "INNER JOIN {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' rl ON u.resource_link_pk = rl.resource_link_pk ' .
218  "INNER JOIN {$this->dbTableNamePrefix}" . static::CONTEXT_TABLE_NAME . ' c ON rl.context_pk = c.context_pk ' .
219  'WHERE c.consumer_pk = %d', $consumer->getRecordId());
220  sqlsrv_query($this->db, $sql);
221 
222 // Update any resource links for which this consumer is acting as a primary resource link
223  $sql = sprintf("UPDATE {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' prl ' .
224  "INNER JOIN {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' rl ON prl.primary_resource_link_pk = rl.resource_link_pk ' .
225  'SET prl.primary_resource_link_pk = NULL, prl.share_approved = NULL ' .
226  'WHERE rl.consumer_pk = %d', $consumer->getRecordId());
227  $ok = sqlsrv_query($this->db, $sql);
228 
229 // Update any resource links for contexts in which this consumer is acting as a primary resource link
230  $sql = sprintf("UPDATE {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' prl ' .
231  "INNER JOIN {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' rl ON prl.primary_resource_link_pk = rl.resource_link_pk ' .
232  "INNER JOIN {$this->dbTableNamePrefix}" . static::CONTEXT_TABLE_NAME . ' c ON rl.context_pk = c.context_pk ' .
233  'SET prl.primary_resource_link_pk = NULL, prl.share_approved = NULL ' .
234  'WHERE c.consumer_pk = %d', $consumer->getRecordId());
235  $ok = sqlsrv_query($this->db, $sql);
236 
237 // Delete any resource links for this consumer
238  $sql = sprintf('DELETE rl ' .
239  "FROM {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' rl ' .
240  'WHERE rl.consumer_pk = %d', $consumer->getRecordId());
241  sqlsrv_query($this->db, $sql);
242 
243 // Delete any resource links for contexts in this consumer
244  $sql = sprintf('DELETE rl ' .
245  "FROM {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' rl ' .
246  "INNER JOIN {$this->dbTableNamePrefix}" . static::CONTEXT_TABLE_NAME . ' c ON rl.context_pk = c.context_pk ' .
247  'WHERE c.consumer_pk = %d', $consumer->getRecordId());
248  sqlsrv_query($this->db, $sql);
249 
250 // Delete any contexts for this consumer
251  $sql = sprintf('DELETE c ' .
252  "FROM {$this->dbTableNamePrefix}" . static::CONTEXT_TABLE_NAME . ' c ' .
253  'WHERE c.consumer_pk = %d', $consumer->getRecordId());
254  sqlsrv_query($this->db, $sql);
255 
256 // Delete consumer
257  $sql = sprintf('DELETE c ' .
258  "FROM {$this->dbTableNamePrefix}" . static::CONSUMER_TABLE_NAME . ' c ' .
259  'WHERE c.consumer_pk = %d', $consumer->getRecordId());
260  $ok = sqlsrv_query($this->db, $sql);
261 
262  if ($ok) {
263  $consumer->initialize();
264  }
265 
266  return $ok;
267  }
268 
274  public function getToolConsumers()
275  {
276  $consumers = array();
277 
278  $sql = 'SELECT consumer_pk, consumer_key256, consumer_key, name, secret, lti_version, ' .
279  'signature_method, consumer_name, consumer_version, consumer_guid, ' .
280  'profile, tool_proxy, settings, ' .
281  'protected, enabled, enable_from, enable_until, last_access, created, updated ' .
282  "FROM {$this->dbTableNamePrefix}" . static::CONSUMER_TABLE_NAME . ' ' .
283  'ORDER BY name';
284  $rsConsumers = sqlsrv_query($this->db, $sql);
285  if ($rsConsumers) {
286  while ($row = sqlsrv_fetch_object($rsConsumers)) {
287  $key = empty($row->consumer_key) ? $row->consumer_key256 : $row->consumer_key;
288  $consumer = new ToolConsumer($key, $this);
289  $consumer->setRecordId(intval($row->consumer_pk));
290  $consumer->name = $row->name;
291  $consumer->secret = $row->secret;
292  $consumer->ltiVersion = $row->lti_version;
293  $consumer->signatureMethod = $row->signature_method;
294  $consumer->consumerName = $row->consumer_name;
295  $consumer->consumerVersion = $row->consumer_version;
296  $consumer->consumerGuid = $row->consumer_guid;
297  $consumer->profile = json_decode($row->profile);
298  $consumer->toolProxy = $row->tool_proxy;
299  $settings = json_decode($row->settings, TRUE);
300  if (!is_array($settings)) {
301  $settings = @unserialize($row->settings); // check for old serialized setting
302  }
303  if (!is_array($settings)) {
304  $settings = array();
305  }
306  $consumer->setSettings($settings);
307  $consumer->protected = (intval($row->protected) === 1);
308  $consumer->enabled = (intval($row->enabled) === 1);
309  $consumer->enableFrom = null;
310  if (!is_null($row->enable_from)) {
311  $consumer->enableFrom = date_timestamp_get($row->enable_from);
312  }
313  $consumer->enableUntil = null;
314  if (!is_null($row->enable_until)) {
315  $consumer->enableUntil = date_timestamp_get($row->enable_until);
316  }
317  $consumer->lastAccess = null;
318  if (!is_null($row->last_access)) {
319  $consumer->lastAccess = date_timestamp_get($row->last_access);
320  }
321  $consumer->created = date_timestamp_get($row->created);
322  $consumer->updated = date_timestamp_get($row->updated);
323  $consumers[] = $consumer;
324  }
325  sqlsrv_free_stmt($rsConsumers);
326  }
327 
328  return $consumers;
329  }
330 
331 ###
332 ### Context methods
333 ###
334 
342  public function loadContext($context)
343  {
344  $ok = false;
345  if (!is_null($context->getRecordId())) {
346  $sql = sprintf('SELECT context_pk, consumer_pk, title, lti_context_id, type, settings, created, updated ' .
347  "FROM {$this->dbTableNamePrefix}" . static::CONTEXT_TABLE_NAME . ' ' .
348  'WHERE (context_pk = %d)', $context->getRecordId());
349  } else {
350  $sql = sprintf('SELECT context_pk, consumer_pk, title, lti_context_id, type, settings, created, updated ' .
351  "FROM {$this->dbTableNamePrefix}" . static::CONTEXT_TABLE_NAME . ' ' .
352  'WHERE (consumer_pk = %d) AND (lti_context_id = %s)', $context->getConsumer()->getRecordId(),
353  $this->escape($context->ltiContextId));
354  }
355  $rs_context = sqlsrv_query($this->db, $sql);
356  if ($rs_context) {
357  $row = sqlsrv_fetch_object($rs_context);
358  if ($row) {
359  $context->setRecordId(intval($row->context_pk));
360  $context->setConsumerId(intval($row->consumer_pk));
361  $context->title = $row->title;
362  $context->ltiContextId = $row->lti_context_id;
363  $context->type = $row->type;
364  $settings = json_decode($row->settings, TRUE);
365  if (!is_array($settings)) {
366  $settings = @unserialize($row->settings); // check for old serialized setting
367  }
368  if (!is_array($settings)) {
369  $settings = array();
370  }
371  $context->setSettings($settings);
372  $context->created = date_timestamp_get($row->created);
373  $context->updated = date_timestamp_get($row->updated);
374  $ok = true;
375  }
376  }
377 
378  return $ok;
379  }
380 
388  public function saveContext($context)
389  {
390  $time = time();
391  $now = date("{$this->dateFormat} {$this->timeFormat}", $time);
392  $settingsValue = json_encode($context->getSettings());
393  $id = $context->getRecordId();
394  $consumer_pk = $context->getConsumer()->getRecordId();
395  if (empty($id)) {
396  $sql = sprintf("INSERT INTO {$this->dbTableNamePrefix}" . static::CONTEXT_TABLE_NAME . ' (consumer_pk, title, ' .
397  'lti_context_id, type, settings, created, updated) ' .
398  'VALUES (%d, %s, %s, %s, %s, %s, %s)', $consumer_pk, $this->escape($context->title),
399  $this->escape($context->ltiContextId), $this->escape($context->type), $this->escape($settingsValue),
400  $this->escape($now), $this->escape($now));
401  } else {
402  $sql = sprintf("UPDATE {$this->dbTableNamePrefix}" . static::CONTEXT_TABLE_NAME . ' SET ' .
403  'title = %s, lti_context_id = %s, type = %s, settings = %s, ' .
404  'updated = %s' .
405  'WHERE (consumer_pk = %d) AND (context_pk = %d)', $this->escape($context->title),
406  $this->escape($context->ltiContextId), $this->escape($context->type), $this->escape($settingsValue),
407  $this->escape($now), $consumer_pk, $id);
408  }
409  $ok = sqlsrv_query($this->db, $sql);
410  if ($ok) {
411  if (empty($id)) {
412  $context->setRecordId($this->insert_id());
413  $context->created = $time;
414  }
415  $context->updated = $time;
416  }
417 
418  return $ok;
419  }
420 
428  public function deleteContext($context)
429  {
430 // Delete any outstanding share keys for resource links for this context
431  $sql = sprintf('DELETE sk ' .
432  "FROM {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_SHARE_KEY_TABLE_NAME . ' sk ' .
433  "INNER JOIN {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' rl ON sk.resource_link_pk = rl.resource_link_pk ' .
434  'WHERE rl.context_pk = %d', $context->getRecordId());
435  sqlsrv_query($this->db, $sql);
436 
437 // Delete any users in resource links for this context
438  $sql = sprintf('DELETE u ' .
439  "FROM {$this->dbTableNamePrefix}" . static::USER_RESULT_TABLE_NAME . ' u ' .
440  "INNER JOIN {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' rl ON u.resource_link_pk = rl.resource_link_pk ' .
441  'WHERE rl.context_pk = %d', $context->getRecordId());
442  sqlsrv_query($this->db, $sql);
443 
444 // Update any resource links for which this consumer is acting as a primary resource link
445  $sql = sprintf("UPDATE {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' prl ' .
446  "INNER JOIN {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' rl ON prl.primary_resource_link_pk = rl.resource_link_pk ' .
447  'SET prl.primary_resource_link_pk = null, prl.share_approved = null ' .
448  'WHERE rl.context_pk = %d', $context->getRecordId());
449  $ok = sqlsrv_query($this->db, $sql);
450 
451 // Delete any resource links for this consumer
452  $sql = sprintf('DELETE rl ' .
453  "FROM {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' rl ' .
454  'WHERE rl.context_pk = %d', $context->getRecordId());
455  sqlsrv_query($this->db, $sql);
456 
457 // Delete context
458  $sql = sprintf('DELETE c ' .
459  "FROM {$this->dbTableNamePrefix}" . static::CONTEXT_TABLE_NAME . ' c ', 'WHERE c.context_pk = %d',
460  $context->getRecordId());
461  $ok = sqlsrv_query($this->db, $sql);
462  if ($ok) {
463  $context->initialize();
464  }
465 
466  return $ok;
467  }
468 
469 ###
470 ### ResourceLink methods
471 ###
472 
480  public function loadResourceLink($resourceLink)
481  {
482  $ok = false;
483  if (!is_null($resourceLink->getRecordId())) {
484  $sql = sprintf('SELECT resource_link_pk, context_pk, consumer_pk, title, lti_resource_link_id, settings, primary_resource_link_pk, share_approved, created, updated ' .
485  "FROM {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' ' .
486  'WHERE (resource_link_pk = %d)', $resourceLink->getRecordId());
487  } elseif (!is_null($resourceLink->getContext())) {
488  $sql = sprintf('SELECT resource_link_pk, context_pk, consumer_pk, title, lti_resource_link_id, settings, primary_resource_link_pk, share_approved, created, updated ' .
489  "FROM {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' ' .
490  'WHERE (context_pk = %d) AND (lti_resource_link_id = %s)', $resourceLink->getContext()->getRecordId(),
491  $this->escape($resourceLink->getId()));
492  } else {
493  $sql = sprintf('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 ' .
494  "FROM {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' r LEFT OUTER JOIN ' .
495  $this->dbTableNamePrefix . static::CONTEXT_TABLE_NAME . ' c ON r.context_pk = c.context_pk ' .
496  ' WHERE ((r.consumer_pk = %d) OR (c.consumer_pk = %d)) AND (lti_resource_link_id = %s)',
497  $resourceLink->getConsumer()->getRecordId(), $resourceLink->getConsumer()->getRecordId(),
498  $this->escape($resourceLink->getId()));
499  }
500  $rsContext = sqlsrv_query($this->db, $sql);
501  if ($rsContext) {
502  $row = sqlsrv_fetch_object($rsContext);
503  if ($row) {
504  $resourceLink->setRecordId(intval($row->resource_link_pk));
505  if (!is_null($row->context_pk)) {
506  $resourceLink->setContextId(intval($row->context_pk));
507  } else {
508  $resourceLink->setContextId(null);
509  }
510  if (!is_null($row->consumer_pk)) {
511  $resourceLink->setConsumerId(intval($row->consumer_pk));
512  } else {
513  $resourceLink->setConsumerId(null);
514  }
515  $resourceLink->title = $row->title;
516  $resourceLink->ltiResourceLinkId = $row->lti_resource_link_id;
517  $settings = json_decode($row->settings, TRUE);
518  if (!is_array($settings)) {
519  $settings = @unserialize($row->settings); // check for old serialized setting
520  }
521  if (!is_array($settings)) {
522  $settings = array();
523  }
524  $resourceLink->setSettings($settings);
525  if (!is_null($row->primary_resource_link_pk)) {
526  $resourceLink->primaryResourceLinkId = intval($row->primary_resource_link_pk);
527  } else {
528  $resourceLink->primaryResourceLinkId = null;
529  }
530  $resourceLink->shareApproved = (is_null($row->share_approved)) ? null : (intval($row->share_approved) === 1);
531  $resourceLink->created = date_timestamp_get($row->created);
532  $resourceLink->updated = date_timestamp_get($row->updated);
533  $ok = true;
534  }
535  }
536 
537  return $ok;
538  }
539 
547  public function saveResourceLink($resourceLink)
548  {
549  if (is_null($resourceLink->shareApproved)) {
550  $approved = 'NULL';
551  } elseif ($resourceLink->shareApproved) {
552  $approved = '1';
553  } else {
554  $approved = '0';
555  }
556  if (empty($resourceLink->primaryResourceLinkId)) {
557  $primaryResourceLinkId = 'NULL';
558  } else {
559  $primaryResourceLinkId = strval($resourceLink->primaryResourceLinkId);
560  }
561  $time = time();
562  $now = date("{$this->dateFormat} {$this->timeFormat}", $time);
563  $settingsValue = json_encode($resourceLink->getSettings());
564  if (!is_null($resourceLink->getContext())) {
565  $consumerId = 'NULL';
566  $contextId = strval($resourceLink->getContext()->getRecordId());
567  } elseif (!is_null($resourceLink->getContextId())) {
568  $consumerId = 'NULL';
569  $contextId = strval($resourceLink->getContextId());
570  } else {
571  $consumerId = strval($resourceLink->getConsumer()->getRecordId());
572  $contextId = 'NULL';
573  }
574  $id = $resourceLink->getRecordId();
575  if (empty($id)) {
576  $sql = sprintf("INSERT INTO {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' (consumer_pk, context_pk, ' .
577  'title, lti_resource_link_id, settings, primary_resource_link_pk, share_approved, created, updated) ' .
578  'VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)', $consumerId, $contextId, $this->escape($resourceLink->title),
579  $this->escape($resourceLink->getId()), $this->escape($settingsValue), $primaryResourceLinkId, $approved,
580  $this->escape($now), $this->escape($now));
581  } elseif ($contextId !== 'NULL') {
582  $sql = sprintf("UPDATE {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' SET ' .
583  'consumer_pk = %s, title = %s, lti_resource_link_id = %s, settings = %s, ' .
584  'primary_resource_link_pk = %s, share_approved = %s, updated = %s ' .
585  'WHERE (context_pk = %s) AND (resource_link_pk = %d)', $consumerId, $this->escape($resourceLink->title),
586  $this->escape($resourceLink->getId()), $this->escape($settingsValue), $primaryResourceLinkId, $approved,
587  $this->escape($now), $contextId, $id);
588  } else {
589  $sql = sprintf("UPDATE {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' SET ' .
590  'context_pk = %s, title = %s, lti_resource_link_id = %s, settings = %s, ' .
591  'primary_resource_link_pk = %s, share_approved = %s, updated = %s ' .
592  'WHERE (consumer_pk = %s) AND (resource_link_pk = %d)', $contextId, $this->escape($resourceLink->title),
593  $this->escape($resourceLink->getId()), $this->escape($settingsValue), $primaryResourceLinkId, $approved,
594  $this->escape($now), $consumerId, $id);
595  }
596  $ok = sqlsrv_query($this->db, $sql);
597  if ($ok) {
598  if (empty($id)) {
599  $resourceLink->setRecordId($this->insert_id());
600  $resourceLink->created = $time;
601  }
602  $resourceLink->updated = $time;
603  }
604 
605  return $ok;
606  }
607 
615  public function deleteResourceLink($resourceLink)
616  {
617 // Delete any outstanding share keys for resource links for this consumer
618  $sql = sprintf("DELETE FROM {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_SHARE_KEY_TABLE_NAME . ' ' .
619  'WHERE (resource_link_pk = %d)', $resourceLink->getRecordId());
620  $ok = sqlsrv_query($this->db, $sql);
621 
622 // Delete users
623  if ($ok) {
624  $sql = sprintf("DELETE FROM {$this->dbTableNamePrefix}" . static::USER_RESULT_TABLE_NAME . ' ' .
625  'WHERE (resource_link_pk = %d)', $resourceLink->getRecordId());
626  $ok = sqlsrv_query($this->db, $sql);
627  }
628 
629 // Update any resource links for which this is the primary resource link
630  if ($ok) {
631  $sql = sprintf("UPDATE {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' ' .
632  'SET primary_resource_link_pk = NULL ' .
633  'WHERE (primary_resource_link_pk = %d)', $resourceLink->getRecordId());
634  $ok = sqlsrv_query($this->db, $sql);
635  }
636 
637 // Delete resource link
638  if ($ok) {
639  $sql = sprintf("DELETE FROM {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' ' .
640  'WHERE (resource_link_pk = %s)', $resourceLink->getRecordId());
641  $ok = sqlsrv_query($this->db, $sql);
642  }
643 
644  if ($ok) {
645  $resourceLink->initialize();
646  }
647 
648  return $ok;
649  }
650 
663  public function getUserResultSourcedIDsResourceLink($resourceLink, $localOnly, $idScope)
664  {
665  $userResults = array();
666 
667  if ($localOnly) {
668  $sql = sprintf('SELECT u.user_result_pk, u.lti_result_sourcedid, u.lti_user_id, u.created, u.updated ' .
669  "FROM {$this->dbTableNamePrefix}" . static::USER_RESULT_TABLE_NAME . ' AS u ' .
670  "INNER JOIN {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' AS rl ' .
671  'ON u.resource_link_pk = rl.resource_link_pk ' .
672  "WHERE (rl.resource_link_pk = %d) AND (rl.primary_resource_link_pk IS NULL)", $resourceLink->getRecordId());
673  } else {
674  $sql = sprintf('SELECT u.user_result_pk, u.lti_result_sourcedid, u.lti_user_id, u.created, u.updated ' .
675  "FROM {$this->dbTableNamePrefix}" . static::USER_RESULT_TABLE_NAME . ' AS u ' .
676  "INNER JOIN {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' AS rl ' .
677  'ON u.resource_link_pk = rl.resource_link_pk ' .
678  'WHERE ((rl.resource_link_pk = %d) AND (rl.primary_resource_link_pk IS NULL)) OR ' .
679  '((rl.primary_resource_link_pk = %d) AND (share_approved = 1))', $resourceLink->getRecordId(),
680  $resourceLink->getRecordId());
681  }
682  $rsUser = sqlsrv_query($this->db, $sql);
683  if ($rsUser) {
684  while ($row = sqlsrv_fetch_object($rsUser)) {
685  $userresult = LTI\UserResult::fromResourceLink($resourceLink, $row->lti_user_id);
686  if (is_null($idScope)) {
687  $userResults[] = $userresult;
688  } else {
689  $userResults[$userresult->getId($idScope)] = $userresult;
690  }
691  }
692  }
693 
694  return $userResults;
695  }
696 
704  public function getSharesResourceLink($resourceLink)
705  {
706  $shares = array();
707 
708  $sql = sprintf('SELECT c.consumer_name, r.resource_link_pk, r.title, r.share_approved ' .
709  "FROM {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' AS r ' .
710  "INNER JOIN {$this->dbTableNamePrefix}" . static::CONSUMER_TABLE_NAME . ' AS c ON r.consumer_pk = c.consumer_pk ' .
711  'WHERE (r.primary_resource_link_pk = %d) ' .
712  'UNION ' .
713  'SELECT c2.consumer_name, r2.resource_link_pk, r2.title, r2.share_approved ' .
714  "FROM {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' AS r2 ' .
715  "INNER JOIN {$this->dbTableNamePrefix}" . static::CONTEXT_TABLE_NAME . ' AS x ON r2.context_pk = x.context_pk ' .
716  "INNER JOIN {$this->dbTableNamePrefix}" . static::CONSUMER_TABLE_NAME . ' AS c2 ON x.consumer_pk = c2.consumer_pk ' .
717  'WHERE (r2.primary_resource_link_pk = %d) ' .
718  'ORDER BY consumer_name, title', $resourceLink->getRecordId(), $resourceLink->getRecordId());
719  $rsShare = sqlsrv_query($this->db, $sql);
720  if ($rsShare) {
721  while ($row = sqlsrv_fetch_object($rsShare)) {
722  $share = new LTI\ResourceLinkShare();
723  $share->resourceLinkId = intval($row->resource_link_pk);
724  $share->approved = (intval($row->share_approved) === 1);
725  $shares[] = $share;
726  }
727  }
728 
729  return $shares;
730  }
731 
732 ###
733 ### ConsumerNonce methods
734 ###
735 
743  public function loadConsumerNonce($nonce)
744  {
745  $ok = false;
746 
747 // Delete any expired nonce values
748  $now = date("{$this->dateFormat} {$this->timeFormat}", time());
749  $sql = "DELETE FROM {$this->dbTableNamePrefix}" . static::NONCE_TABLE_NAME . " WHERE expires <= '{$now}'";
750  sqlsrv_query($this->db, $sql);
751 
752 // Load the nonce
753  $sql = sprintf("SELECT value AS T FROM {$this->dbTableNamePrefix}" . static::NONCE_TABLE_NAME . ' WHERE (consumer_pk = %d) AND (value = %s)',
754  $nonce->getConsumer()->getRecordId(), $this->escape($nonce->getValue()));
755  $rs_nonce = sqlsrv_query($this->db, $sql);
756  if ($rs_nonce) {
757  if (sqlsrv_fetch_object($rs_nonce)) {
758  $ok = true;
759  }
760  }
761 
762  return $ok;
763  }
764 
772  public function saveConsumerNonce($nonce)
773  {
774  $expires = date("{$this->dateFormat} {$this->timeFormat}", $nonce->expires);
775  $sql = sprintf("INSERT INTO {$this->dbTableNamePrefix}" . static::NONCE_TABLE_NAME . " (consumer_pk, value, expires) VALUES (%d, %s, %s)",
776  $nonce->getConsumer()->getRecordId(), $this->escape($nonce->getValue()), $this->escape($expires));
777  $ok = sqlsrv_query($this->db, $sql);
778 
779  return $ok;
780  }
781 
782 ###
783 ### ResourceLinkShareKey methods
784 ###
785 
793  public function loadResourceLinkShareKey($shareKey)
794  {
795  $ok = false;
796 
797 // Clear expired share keys
798  $now = date("{$this->dateFormat} {$this->timeFormat}", time());
799  $sql = "DELETE FROM {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_SHARE_KEY_TABLE_NAME . " WHERE expires <= '{$now}'";
800  sqlsrv_query($this->db, $sql);
801 
802 // Load share key
803 // $id = $this->escape_string($this->db, $shareKey->getId());
804  $id = $shareKey->getId();
805  $sql = 'SELECT resource_link_pk, auto_approve, expires ' .
806  "FROM {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_SHARE_KEY_TABLE_NAME . ' ' .
807  "WHERE share_key_id = '{$id}'";
808  $rsShareKey = sqlsrv_query($this->db, $sql);
809  if ($rsShareKey) {
810  $row = sqlsrv_fetch_object($rsShareKey);
811  if ($row && (intval($row->resource_link_pk) === $shareKey->resourceLinkId)) {
812  $shareKey->autoApprove = (intval($row->auto_approve) === 1);
813  $shareKey->expires = date_timestamp_get($row->expires);
814  $ok = true;
815  }
816  }
817 
818  return $ok;
819  }
820 
828  public function saveResourceLinkShareKey($shareKey)
829  {
830  if ($shareKey->autoApprove) {
831  $approve = 1;
832  } else {
833  $approve = 0;
834  }
835  $expires = date("{$this->dateFormat} {$this->timeFormat}", $shareKey->expires);
836  $sql = sprintf("INSERT INTO {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_SHARE_KEY_TABLE_NAME . ' ' .
837  '(share_key_id, resource_link_pk, auto_approve, expires) ' .
838  "VALUES (%s, %d, {$approve}, '{$expires}')", $this->escape($shareKey->getId()), $shareKey->resourceLinkId);
839  $ok = sqlsrv_query($this->db, $sql);
840 
841  return $ok;
842  }
843 
851  public function deleteResourceLinkShareKey($shareKey)
852  {
853  $sql = "DELETE FROM {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_SHARE_KEY_TABLE_NAME . " WHERE share_key_id = '{$shareKey->getId()}'";
854 
855  $ok = sqlsrv_query($this->db, $sql);
856 
857  if ($ok) {
858  $shareKey->initialize();
859  }
860 
861  return $ok;
862  }
863 
864 ###
865 ### UserResult methods
866 ###
867 
875  public function loadUserResult($userresult)
876  {
877  $ok = false;
878  if (!is_null($userresult->getRecordId())) {
879  $sql = sprintf('SELECT user_result_pk, resource_link_pk, lti_user_id, lti_result_sourcedid, created, updated ' .
880  "FROM {$this->dbTableNamePrefix}" . static::USER_RESULT_TABLE_NAME . ' ' .
881  'WHERE (user_result_pk = %d)', $userresult->getRecordId());
882  } else {
883  $sql = sprintf('SELECT user_result_pk, resource_link_pk, lti_user_id, lti_result_sourcedid, created, updated ' .
884  "FROM {$this->dbTableNamePrefix}" . static::USER_RESULT_TABLE_NAME . ' ' .
885  'WHERE (resource_link_pk = %d) AND (lti_user_id = %s)', $userresult->getResourceLink()->getRecordId(),
886  $this->escape($userresult->getId(LTI\ToolProvider::ID_SCOPE_ID_ONLY)));
887  }
888  $rsUser = sqlsrv_query($this->db, $sql);
889  if ($rsUser) {
890  $row = sqlsrv_fetch_object($rsUser);
891  if ($row) {
892  $userresult->setRecordId(intval($row->user_result_pk));
893  $userresult->setResourceLinkId(intval($row->resource_link_pk));
894  $userresult->ltiUserId = $row->lti_user_id;
895  $userresult->ltiResultSourcedId = $row->lti_result_sourcedid;
896  $userresult->created = date_timestamp_get($row->created);
897  $userresult->updated = date_timestamp_get($row->updated);
898  $ok = true;
899  }
900  }
901 
902  return $ok;
903  }
904 
912  public function saveUserResult($userresult)
913  {
914  $time = time();
915  $now = date("{$this->dateFormat} {$this->timeFormat}", $time);
916  if (is_null($userresult->created)) {
917  $sql = sprintf("INSERT INTO {$this->dbTableNamePrefix}" . static::USER_RESULT_TABLE_NAME . ' (resource_link_pk, ' .
918  'lti_user_id, lti_result_sourcedid, created, updated) ' .
919  'VALUES (%d, %s, %s, %s, %s)', $userresult->getResourceLink()->getRecordId(),
920  $this->escape($userresult->getId(LTI\ToolProvider::ID_SCOPE_ID_ONLY)),
921  $this->escape($userresult->ltiResultSourcedId), $this->escape($now), $this->escape($now));
922  } else {
923  $sql = sprintf("UPDATE {$this->dbTableNamePrefix}" . static::USER_RESULT_TABLE_NAME . ' ' .
924  'SET lti_result_sourcedid = %s, updated = %s ' .
925  'WHERE (user_result_pk = %d)', $this->escape($userresult->ltiResultSourcedId), $this->escape($now),
926  $userresult->getRecordId());
927  }
928  $ok = sqlsrv_query($this->db, $sql);
929  if ($ok) {
930  if (is_null($userresult->created)) {
931  $userresult->setRecordId($this->insert_id());
932  $userresult->created = $time;
933  }
934  $userresult->updated = $time;
935  }
936 
937  return $ok;
938  }
939 
947  public function deleteUserResult($userresult)
948  {
949  $sql = sprintf("DELETE FROM {$this->dbTableNamePrefix}" . static::USER_RESULT_TABLE_NAME . ' ' .
950  'WHERE (user_result_pk = %d)', $userresult->getRecordId());
951  $ok = sqlsrv_query($this->db, $sql);
952 
953  if ($ok) {
954  $userresult->initialize();
955  }
956 
957  return $ok;
958  }
959 
971  public function escape($value, $addQuotes = true)
972  {
973  if (is_null($value)) {
974  $value = 'null';
975  } else {
976  if ($addQuotes) {
977  $value = str_replace("'", "''", $value);
978  $value = "'{$value}'";
979  }
980  }
981 
982  return $value;
983  }
984 
985  private function insert_id()
986  {
987  $id = 0;
988  $sql = 'SELECT SCOPE_IDENTITY() AS insid;';
989  $rsId = sqlsrv_query($this->db, $sql);
990  if ($rsId) {
991  sqlsrv_fetch($rsId);
992  $id = sqlsrv_get_field($rsId, 0, SQLSRV_PHPTYPE_INT);
993  }
994 
995  return $id;
996  }
997 
998 }
getToolConsumers()
Load all tool consumers from the database.
static fromResourceLink($resourceLink, $ltiUserId)
Class constructor from resource link.
Definition: UserResult.php:255
Class to provide a connection to a persistent store for LTI objects.
const ID_SCOPE_ID_ONLY
Use ID value only.
loadResourceLink($resourceLink)
Load resource link object.
Class to represent a tool consumer.
Class to represent a tool consumer context.
Definition: Context.php:17
deleteResourceLink($resourceLink)
Delete resource link object.
deleteResourceLinkShareKey($shareKey)
Delete resource link share key object.
saveToolConsumer($consumer)
Save tool consumer object.
Class to represent a tool consumer nonce.
Class to represent a tool consumer resource link share.
getUserResultSourcedIDsResourceLink($resourceLink, $localOnly, $idScope)
Get array of user objects.
loadToolConsumer($consumer)
Load tool consumer object.
saveResourceLinkShareKey($shareKey)
Save resource link share key object.
deleteToolConsumer($consumer)
Delete tool consumer object.
Class to represent a tool consumer user.
Definition: UserResult.php:15
Class to represent a tool consumer resource link share key.
loadResourceLinkShareKey($shareKey)
Load resource link share key object.
getSharesResourceLink($resourceLink)
Get array of shares defined for this resource link.
escape($value, $addQuotes=true)
Escape a string for use in a database query.
Class to represent an LTI Data Connector for MS SQL Server.
deleteUserResult($userresult)
Delete user object.
saveResourceLink($resourceLink)
Save resource link object.