LTI Integration Library  3.1.0
PHP class library for building LTI integrations
DataConnector_pg.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 MySQLi 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 = pg_query($this->db, $sql);
60  if ($rsConsumer) {
61  while ($row = pg_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 = $row->protected;
83  $consumer->enabled = $row->enabled;
84  $consumer->enableFrom = null;
85  if (!is_null($row->enable_from)) {
86  $consumer->enableFrom = strtotime($row->enable_from);
87  }
88  $consumer->enableUntil = null;
89  if (!is_null($row->enable_until)) {
90  $consumer->enableUntil = strtotime($row->enable_until);
91  }
92  $consumer->lastAccess = null;
93  if (!is_null($row->last_access)) {
94  $consumer->lastAccess = strtotime($row->last_access);
95  }
96  $consumer->created = strtotime($row->created);
97  $consumer->updated = strtotime($row->updated);
98  $ok = true;
99  break;
100  }
101  }
102  pg_free_result($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) ? 'true' : 'false';
124  $enabled = ($consumer->enabled) ? 'true' : 'false';
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("{$this->dateFormat} {$this->timeFormat}", $consumer->enableFrom);
132  }
133  $until = null;
134  if (!is_null($consumer->enableUntil)) {
135  $until = date("{$this->dateFormat} {$this->timeFormat}", $consumer->enableUntil);
136  }
137  $last = null;
138  if (!is_null($consumer->lastAccess)) {
139  $last = date($this->dateFormat, $consumer->lastAccess);
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, %s, %s, %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 = %s, enabled = %s, 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 = pg_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  pg_query($this->db, $sql);
191 
192 // Delete any outstanding share keys for resource links for this consumer
193  $sql = sprintf("DELETE FROM {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_SHARE_KEY_TABLE_NAME . ' ' .
194  "WHERE resource_link_pk IN (SELECT resource_link_pk FROM {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' ' .
195  'WHERE consumer_pk = %d)', $consumer->getRecordId());
196  pg_query($this->db, $sql);
197 
198 // Delete any outstanding share keys for resource links for contexts in this consumer
199  $sql = sprintf("DELETE FROM {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_SHARE_KEY_TABLE_NAME . ' ' .
200  "WHERE resource_link_pk IN (SELECT resource_link_pk FROM {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' rl ' .
201  "INNER JOIN {$this->dbTableNamePrefix}" . static::CONTEXT_TABLE_NAME . ' c ON rl.context_pk = c.context_pk WHERE c.consumer_pk = %d)',
202  $consumer->getRecordId());
203  pg_query($this->db, $sql);
204 
205 // Delete any users in resource links for this consumer
206  $sql = sprintf("DELETE FROM {$this->dbTableNamePrefix}" . static::USER_RESULT_TABLE_NAME . ' ' .
207  "WHERE resource_link_pk IN (SELECT resource_link_pk FROM {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' ' .
208  'WHERE consumer_pk = %d)', $consumer->getRecordId());
209  pg_query($this->db, $sql);
210 
211 // Delete any users in resource links for contexts in this consumer
212  $sql = sprintf("DELETE FROM {$this->dbTableNamePrefix}" . static::USER_RESULT_TABLE_NAME . ' ' .
213  "WHERE resource_link_pk IN (SELECT resource_link_pk FROM {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' rl ' .
214  "INNER JOIN {$this->dbTableNamePrefix}" . static::CONTEXT_TABLE_NAME . ' c ON rl.context_pk = c.context_pk WHERE c.consumer_pk = %d)',
215  $consumer->getRecordId());
216  pg_query($this->db, $sql);
217 
218 // Update any resource links for which this consumer is acting as a primary resource link
219  $sql = sprintf("UPDATE {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' ' .
220  'SET primary_resource_link_pk = NULL, share_approved = NULL ' .
221  'WHERE primary_resource_link_pk IN ' .
222  "(SELECT resource_link_pk FROM {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' ' .
223  'WHERE consumer_pk = %d)', $consumer->getRecordId());
224  $ok = pg_query($this->db, $sql);
225 
226 // Update any resource links for contexts in which this consumer is acting as a primary resource link
227  $sql = sprintf("UPDATE {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' ' .
228  'SET primary_resource_link_pk = NULL, share_approved = NULL ' .
229  'WHERE primary_resource_link_pk IN ' .
230  "(SELECT rl.resource_link_pk FROM {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' rl ' .
231  "INNER JOIN {$this->dbTableNamePrefix}" . static::CONTEXT_TABLE_NAME . ' c ON rl.context_pk = c.context_pk ' .
232  'WHERE c.consumer_pk = %d)', $consumer->getRecordId());
233  $ok = pg_query($this->db, $sql);
234 
235 // Delete any resource links for this consumer
236  $sql = sprintf("DELETE FROM {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' ' .
237  'WHERE consumer_pk = %d', $consumer->getRecordId());
238  pg_query($this->db, $sql);
239 
240 // Delete any resource links for contexts in this consumer
241  $sql = sprintf("DELETE FROM {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' ' .
242  'WHERE context_pk IN (' .
243  "SELECT context_pk FROM {$this->dbTableNamePrefix}" . static::CONTEXT_TABLE_NAME . ' ' . 'WHERE consumer_pk = %d)',
244  $consumer->getRecordId());
245  pg_query($this->db, $sql);
246 
247 // Delete any contexts for this consumer
248  $sql = sprintf("DELETE FROM {$this->dbTableNamePrefix}" . static::CONTEXT_TABLE_NAME . ' ' .
249  'WHERE consumer_pk = %d', $consumer->getRecordId());
250  pg_query($this->db, $sql);
251 
252 // Delete consumer
253  $sql = sprintf("DELETE FROM {$this->dbTableNamePrefix}" . static::CONSUMER_TABLE_NAME . ' ' .
254  'WHERE consumer_pk = %d', $consumer->getRecordId());
255  $ok = pg_query($this->db, $sql);
256 
257  if ($ok) {
258  $consumer->initialize();
259  }
260 
261  return $ok;
262  }
263 
269  public function getToolConsumers()
270  {
271  $consumers = array();
272 
273  $sql = 'SELECT consumer_pk, consumer_key256, consumer_key, name, secret, lti_version, ' .
274  'signature_method, consumer_name, consumer_version, consumer_guid, ' .
275  'profile, tool_proxy, settings, ' .
276  'protected, enabled, enable_from, enable_until, last_access, created, updated ' .
277  "FROM {$this->dbTableNamePrefix}" . static::CONSUMER_TABLE_NAME . ' ' .
278  'ORDER BY name';
279  $rsConsumers = pg_query($this->db, $sql);
280  if ($rsConsumers) {
281  while ($row = pg_fetch_object($rsConsumers)) {
282  $key = empty($row->consumer_key) ? $row->consumer_key256 : $row->consumer_key;
283  $consumer = new ToolConsumer($key, $this);
284  $consumer->setRecordId(intval($row->consumer_pk));
285  $consumer->name = $row->name;
286  $consumer->secret = $row->secret;
287  $consumer->ltiVersion = $row->lti_version;
288  $consumer->signatureMethod = $row->signature_method;
289  $consumer->consumerName = $row->consumer_name;
290  $consumer->consumerVersion = $row->consumer_version;
291  $consumer->consumerGuid = $row->consumer_guid;
292  $consumer->profile = json_decode($row->profile);
293  $consumer->toolProxy = $row->tool_proxy;
294  $settings = json_decode($row->settings, TRUE);
295  if (!is_array($settings)) {
296  $settings = @unserialize($row->settings); // check for old serialized setting
297  }
298  if (!is_array($settings)) {
299  $settings = array();
300  }
301  $consumer->setSettings($settings);
302  $consumer->protected = (intval($row->protected) === 1);
303  $consumer->enabled = (intval($row->enabled) === 1);
304  $consumer->enableFrom = null;
305  if (!is_null($row->enable_from)) {
306  $consumer->enableFrom = strtotime($row->enable_from);
307  }
308  $consumer->enableUntil = null;
309  if (!is_null($row->enable_until)) {
310  $consumer->enableUntil = strtotime($row->enable_until);
311  }
312  $consumer->lastAccess = null;
313  if (!is_null($row->last_access)) {
314  $consumer->lastAccess = strtotime($row->last_access);
315  }
316  $consumer->created = strtotime($row->created);
317  $consumer->updated = strtotime($row->updated);
318  $consumers[] = $consumer;
319  }
320  pg_free_result($rsConsumers);
321  }
322 
323  return $consumers;
324  }
325 
326 ###
327 ### Context methods
328 ###
329 
337  public function loadContext($context)
338  {
339  $ok = false;
340  if (!is_null($context->getRecordId())) {
341  $sql = sprintf('SELECT context_pk, consumer_pk, title, lti_context_id, type, settings, created, updated ' .
342  "FROM {$this->dbTableNamePrefix}" . static::CONTEXT_TABLE_NAME . ' ' .
343  'WHERE (context_pk = %d)', $context->getRecordId());
344  } else {
345  $sql = sprintf('SELECT context_pk, consumer_pk, title, lti_context_id, type, settings, created, updated ' .
346  "FROM {$this->dbTableNamePrefix}" . static::CONTEXT_TABLE_NAME . ' ' .
347  'WHERE (consumer_pk = %d) AND (lti_context_id = %s)', $context->getConsumer()->getRecordId(),
348  $this->escape($context->ltiContextId));
349  }
350  $rs_context = pg_query($this->db, $sql);
351  if ($rs_context) {
352  $row = pg_fetch_object($rs_context);
353  if ($row) {
354  $context->setRecordId(intval($row->context_pk));
355  $context->setConsumerId(intval($row->consumer_pk));
356  $context->title = $row->title;
357  $context->ltiContextId = $row->lti_context_id;
358  $context->type = $row->type;
359  $settings = json_decode($row->settings, TRUE);
360  if (!is_array($settings)) {
361  $settings = @unserialize($row->settings); // check for old serialized setting
362  }
363  if (!is_array($settings)) {
364  $settings = array();
365  }
366  $context->setSettings($settings);
367  $context->created = strtotime($row->created);
368  $context->updated = strtotime($row->updated);
369  $ok = true;
370  }
371  }
372 
373  return $ok;
374  }
375 
383  public function saveContext($context)
384  {
385  $time = time();
386  $now = date("{$this->dateFormat} {$this->timeFormat}", $time);
387  $settingsValue = json_encode($context->getSettings());
388  $id = $context->getRecordId();
389  $consumer_pk = $context->getConsumer()->getRecordId();
390  if (empty($id)) {
391  $sql = sprintf("INSERT INTO {$this->dbTableNamePrefix}" . static::CONTEXT_TABLE_NAME . ' (consumer_pk, title, ' .
392  'lti_context_id, type, settings, created, updated) ' .
393  'VALUES (%d, %s, %s, %s, %s, %s, %s)', $consumer_pk, $this->escape($context->title),
394  $this->escape($context->ltiContextId), $this->escape($context->type), $this->escape($settingsValue),
395  $this->escape($now), $this->escape($now));
396  } else {
397  $sql = sprintf("UPDATE {$this->dbTableNamePrefix}" . static::CONTEXT_TABLE_NAME . ' SET ' .
398  'title = %s, lti_context_id = %s, type = %s, settings = %s, ' .
399  'updated = %s' .
400  'WHERE (consumer_pk = %d) AND (context_pk = %d)', $this->escape($context->title),
401  $this->escape($context->ltiContextId), $this->escape($context->type), $this->escape($settingsValue),
402  $this->escape($now), $consumer_pk, $id);
403  }
404  $ok = pg_query($this->db, $sql);
405  if ($ok) {
406  if (empty($id)) {
407  $context->setRecordId($this->insert_id());
408  $context->created = $time;
409  }
410  $context->updated = $time;
411  }
412 
413  return $ok;
414  }
415 
423  public function deleteContext($context)
424  {
425 // Delete any outstanding share keys for resource links for this context
426  $sql = sprintf("DELETE FROM {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_SHARE_KEY_TABLE_NAME . ' ' .
427  "WHERE resource_link_pk IN (SELECT resource_link_pk FROM {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' ' .
428  'WHERE context_pk = %d)', $context->getRecordId());
429  pg_query($this->db, $sql);
430 
431 // Delete any users in resource links for this context
432  $sql = sprintf("DELETE FROM {$this->dbTableNamePrefix}" . static::USER_RESULT_TABLE_NAME . ' ' .
433  "WHERE resource_link_pk IN (SELECT resource_link_pk FROM {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' ' .
434  'WHERE context_pk = %d)', $context->getRecordId());
435  pg_query($this->db, $sql);
436 
437 // Update any resource links for which this consumer is acting as a primary resource link
438  $sql = sprintf("UPDATE {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' ' .
439  'SET primary_resource_link_pk = null, share_approved = null ' .
440  'WHERE primary_resource_link_pk IN ' .
441  "(SELECT resource_link_pk FROM {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' WHERE context_pk = %d)',
442  $context->getRecordId());
443  $ok = pg_query($this->db, $sql);
444 
445 // Delete any resource links for this consumer
446  $sql = sprintf("DELETE FROM {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' ' .
447  'WHERE context_pk = %d', $context->getRecordId());
448  pg_query($this->db, $sql);
449 
450 // Delete context
451  $sql = sprintf("DELETE FROM {$this->dbTableNamePrefix}" . static::CONTEXT_TABLE_NAME . ' ', 'WHERE context_pk = %d',
452  $context->getRecordId());
453  $ok = pg_query($this->db, $sql);
454  if ($ok) {
455  $context->initialize();
456  }
457 
458  return $ok;
459  }
460 
461 ###
462 ### ResourceLink methods
463 ###
464 
472  public function loadResourceLink($resourceLink)
473  {
474  $ok = false;
475  if (!is_null($resourceLink->getRecordId())) {
476  $sql = sprintf('SELECT resource_link_pk, context_pk, consumer_pk, title, lti_resource_link_id, settings, primary_resource_link_pk, share_approved, created, updated ' .
477  "FROM {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' ' .
478  'WHERE (resource_link_pk = %d)', $resourceLink->getRecordId());
479  } elseif (!is_null($resourceLink->getContext())) {
480  $sql = sprintf('SELECT resource_link_pk, context_pk, consumer_pk, title, lti_resource_link_id, settings, primary_resource_link_pk, share_approved, created, updated ' .
481  "FROM {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' ' .
482  'WHERE (context_pk = %d) AND (lti_resource_link_id = %s)', $resourceLink->getContext()->getRecordId(),
483  $this->escape($resourceLink->getId()));
484  } else {
485  $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 ' .
486  "FROM {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' r LEFT OUTER JOIN ' .
487  $this->dbTableNamePrefix . static::CONTEXT_TABLE_NAME . ' c ON r.context_pk = c.context_pk ' .
488  ' WHERE ((r.consumer_pk = %d) OR (c.consumer_pk = %d)) AND (lti_resource_link_id = %s)',
489  $resourceLink->getConsumer()->getRecordId(), $resourceLink->getConsumer()->getRecordId(),
490  $this->escape($resourceLink->getId()));
491  }
492  $rsContext = pg_query($this->db, $sql);
493  if ($rsContext) {
494  $row = pg_fetch_object($rsContext);
495  if ($row) {
496  $resourceLink->setRecordId(intval($row->resource_link_pk));
497  if (!is_null($row->context_pk)) {
498  $resourceLink->setContextId(intval($row->context_pk));
499  } else {
500  $resourceLink->setContextId(null);
501  }
502  if (!is_null($row->consumer_pk)) {
503  $resourceLink->setConsumerId(intval($row->consumer_pk));
504  } else {
505  $resourceLink->setConsumerId(null);
506  }
507  $resourceLink->title = $row->title;
508  $resourceLink->ltiResourceLinkId = $row->lti_resource_link_id;
509  $settings = json_decode($row->settings, TRUE);
510  if (!is_array($settings)) {
511  $settings = @unserialize($row->settings); // check for old serialized setting
512  }
513  if (!is_array($settings)) {
514  $settings = array();
515  }
516  $resourceLink->setSettings($settings);
517  if (!is_null($row->primary_resource_link_pk)) {
518  $resourceLink->primaryResourceLinkId = intval($row->primary_resource_link_pk);
519  } else {
520  $resourceLink->primaryResourceLinkId = null;
521  }
522  $resourceLink->shareApproved = (is_null($row->share_approved)) ? null : (intval($row->share_approved) === 1);
523  $resourceLink->created = strtotime($row->created);
524  $resourceLink->updated = strtotime($row->updated);
525  $ok = true;
526  }
527  }
528 
529  return $ok;
530  }
531 
539  public function saveResourceLink($resourceLink)
540  {
541  if (is_null($resourceLink->shareApproved)) {
542  $approved = 'NULL';
543  } elseif ($resourceLink->shareApproved) {
544  $approved = 'true';
545  } else {
546  $approved = 'false';
547  }
548  if (empty($resourceLink->primaryResourceLinkId)) {
549  $primaryResourceLinkId = 'NULL';
550  } else {
551  $primaryResourceLinkId = strval($resourceLink->primaryResourceLinkId);
552  }
553  $time = time();
554  $now = date("{$this->dateFormat} {$this->timeFormat}", $time);
555  $settingsValue = json_encode($resourceLink->getSettings());
556  if (!is_null($resourceLink->getContext())) {
557  $consumerId = 'NULL';
558  $contextId = strval($resourceLink->getContext()->getRecordId());
559  } elseif (!is_null($resourceLink->getContextId())) {
560  $consumerId = 'NULL';
561  $contextId = strval($resourceLink->getContextId());
562  } else {
563  $consumerId = strval($resourceLink->getConsumer()->getRecordId());
564  $contextId = 'NULL';
565  }
566  $id = $resourceLink->getRecordId();
567  if (empty($id)) {
568  $sql = sprintf("INSERT INTO {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' (consumer_pk, context_pk, ' .
569  'title, lti_resource_link_id, settings, primary_resource_link_pk, share_approved, created, updated) ' .
570  'VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)', $consumerId, $contextId, $this->escape($resourceLink->title),
571  $this->escape($resourceLink->getId()), $this->escape($settingsValue), $primaryResourceLinkId, $approved,
572  $this->escape($now), $this->escape($now));
573  } elseif ($contextId !== 'NULL') {
574  $sql = sprintf("UPDATE {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' SET ' .
575  'consumer_pk = %s, title = %s, lti_resource_link_id = %s, settings = %s, ' .
576  'primary_resource_link_pk = %s, share_approved = %s, updated = %s ' .
577  'WHERE (context_pk = %s) AND (resource_link_pk = %d)', $consumerId, $this->escape($resourceLink->title),
578  $this->escape($resourceLink->getId()), $this->escape($settingsValue), $primaryResourceLinkId, $approved,
579  $this->escape($now), $contextId, $id);
580  } else {
581  $sql = sprintf("UPDATE {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' SET ' .
582  'context_pk = %s, title = %s, lti_resource_link_id = %s, settings = %s, ' .
583  'primary_resource_link_pk = %s, share_approved = %s, updated = %s ' .
584  'WHERE (consumer_pk = %s) AND (resource_link_pk = %d)', $contextId, $this->escape($resourceLink->title),
585  $this->escape($resourceLink->getId()), $this->escape($settingsValue), $primaryResourceLinkId, $approved,
586  $this->escape($now), $consumerId, $id);
587  }
588  $ok = pg_query($this->db, $sql);
589  if ($ok) {
590  if (empty($id)) {
591  $resourceLink->setRecordId($this->insert_id());
592  $resourceLink->created = $time;
593  }
594  $resourceLink->updated = $time;
595  }
596 
597  return $ok;
598  }
599 
607  public function deleteResourceLink($resourceLink)
608  {
609 // Delete any outstanding share keys for resource links for this consumer
610  $sql = sprintf("DELETE FROM {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_SHARE_KEY_TABLE_NAME . ' ' .
611  'WHERE (resource_link_pk = %d)', $resourceLink->getRecordId());
612  $ok = pg_query($this->db, $sql);
613 
614 // Delete users
615  if ($ok) {
616  $sql = sprintf("DELETE FROM {$this->dbTableNamePrefix}" . static::USER_RESULT_TABLE_NAME . ' ' .
617  'WHERE (resource_link_pk = %d)', $resourceLink->getRecordId());
618  $ok = pg_query($this->db, $sql);
619  }
620 
621 // Update any resource links for which this is the primary resource link
622  if ($ok) {
623  $sql = sprintf("UPDATE {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' ' .
624  'SET primary_resource_link_pk = NULL ' .
625  'WHERE (primary_resource_link_pk = %d)', $resourceLink->getRecordId());
626  $ok = pg_query($this->db, $sql);
627  }
628 
629 // Delete resource link
630  if ($ok) {
631  $sql = sprintf("DELETE FROM {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' ' .
632  'WHERE (resource_link_pk = %s)', $resourceLink->getRecordId());
633  $ok = pg_query($this->db, $sql);
634  }
635 
636  if ($ok) {
637  $resourceLink->initialize();
638  }
639 
640  return $ok;
641  }
642 
655  public function getUserResultSourcedIDsResourceLink($resourceLink, $localOnly, $idScope)
656  {
657  $userResults = array();
658 
659  if ($localOnly) {
660  $sql = sprintf('SELECT u.user_result_pk, u.lti_result_sourcedid, u.lti_user_id, u.created, u.updated ' .
661  "FROM {$this->dbTableNamePrefix}" . static::USER_RESULT_TABLE_NAME . ' AS u ' .
662  "INNER JOIN {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' AS rl ' .
663  'ON u.resource_link_pk = rl.resource_link_pk ' .
664  "WHERE (rl.resource_link_pk = %d) AND (rl.primary_resource_link_pk IS NULL)", $resourceLink->getRecordId());
665  } else {
666  $sql = sprintf('SELECT u.user_result_pk, u.lti_result_sourcedid, u.lti_user_id, u.created, u.updated ' .
667  "FROM {$this->dbTableNamePrefix}" . static::USER_RESULT_TABLE_NAME . ' AS u ' .
668  "INNER JOIN {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' AS rl ' .
669  'ON u.resource_link_pk = rl.resource_link_pk ' .
670  'WHERE ((rl.resource_link_pk = %d) AND (rl.primary_resource_link_pk IS NULL)) OR ' .
671  '((rl.primary_resource_link_pk = %d) AND share_approved)', $resourceLink->getRecordId(),
672  $resourceLink->getRecordId());
673  }
674  $rsUser = pg_query($this->db, $sql);
675  if ($rsUser) {
676  while ($row = pg_fetch_object($rsUser)) {
677  $userresult = LTI\UserResult::fromResourceLink($resourceLink, $row->lti_user_id);
678  if (is_null($idScope)) {
679  $userResults[] = $userresult;
680  } else {
681  $userResults[$userresult->getId($idScope)] = $userresult;
682  }
683  }
684  }
685 
686  return $userResults;
687  }
688 
696  public function getSharesResourceLink($resourceLink)
697  {
698  $shares = array();
699 
700  $sql = sprintf('SELECT c.consumer_name, r.resource_link_pk, r.title, r.share_approved ' .
701  "FROM {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' AS r ' .
702  "INNER JOIN {$this->dbTableNamePrefix}" . static::CONSUMER_TABLE_NAME . ' AS c ON r.consumer_pk = c.consumer_pk ' .
703  'WHERE (r.primary_resource_link_pk = %d) ' .
704  'UNION ' .
705  'SELECT c2.consumer_name, r2.resource_link_pk, r2.title, r2.share_approved ' .
706  "FROM {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_TABLE_NAME . ' AS r2 ' .
707  "INNER JOIN {$this->dbTableNamePrefix}" . static::CONTEXT_TABLE_NAME . ' AS x ON r2.context_pk = x.context_pk ' .
708  "INNER JOIN {$this->dbTableNamePrefix}" . static::CONSUMER_TABLE_NAME . ' AS c2 ON x.consumer_pk = c2.consumer_pk ' .
709  'WHERE (r2.primary_resource_link_pk = %d) ' .
710  'ORDER BY consumer_name, title', $resourceLink->getRecordId(), $resourceLink->getRecordId());
711  $rsShare = pg_query($this->db, $sql);
712  if ($rsShare) {
713  while ($row = pg_fetch_object($rsShare)) {
714  $share = new LTI\ResourceLinkShare();
715  $share->resourceLinkId = intval($row->resource_link_pk);
716  $share->approved = (intval($row->share_approved) === 1);
717  $shares[] = $share;
718  }
719  }
720 
721  return $shares;
722  }
723 
724 ###
725 ### ConsumerNonce methods
726 ###
727 
735  public function loadConsumerNonce($nonce)
736  {
737  $ok = false;
738 
739 // Delete any expired nonce values
740  $now = date("{$this->dateFormat} {$this->timeFormat}", time());
741  $sql = "DELETE FROM {$this->dbTableNamePrefix}" . static::NONCE_TABLE_NAME . " WHERE expires <= '{$now}'";
742  pg_query($this->db, $sql);
743 
744 // Load the nonce
745  $sql = sprintf("SELECT value AS T FROM {$this->dbTableNamePrefix}" . static::NONCE_TABLE_NAME . ' WHERE (consumer_pk = %d) AND (value = %s)',
746  $nonce->getConsumer()->getRecordId(), $this->escape($nonce->getValue()));
747  $rs_nonce = pg_query($this->db, $sql);
748  if ($rs_nonce) {
749  if (pg_fetch_object($rs_nonce)) {
750  $ok = true;
751  }
752  }
753 
754  return $ok;
755  }
756 
764  public function saveConsumerNonce($nonce)
765  {
766  $expires = date("{$this->dateFormat} {$this->timeFormat}", $nonce->expires);
767  $sql = sprintf("INSERT INTO {$this->dbTableNamePrefix}" . static::NONCE_TABLE_NAME . " (consumer_pk, value, expires) VALUES (%d, %s, %s)",
768  $nonce->getConsumer()->getRecordId(), $this->escape($nonce->getValue()), $this->escape($expires));
769  $ok = pg_query($this->db, $sql);
770 
771  return $ok;
772  }
773 
774 ###
775 ### ResourceLinkShareKey methods
776 ###
777 
785  public function loadResourceLinkShareKey($shareKey)
786  {
787  $ok = false;
788 
789 // Clear expired share keys
790  $now = date("{$this->dateFormat} {$this->timeFormat}", time());
791  $sql = "DELETE FROM {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_SHARE_KEY_TABLE_NAME . " WHERE expires <= '{$now}'";
792  pg_query($this->db, $sql);
793 
794 // Load share key
795  $id = pg_escape_string($this->db, $shareKey->getId());
796  $sql = 'SELECT resource_link_pk, auto_approve, expires ' .
797  "FROM {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_SHARE_KEY_TABLE_NAME . ' ' .
798  "WHERE share_key_id = '{$id}'";
799  $rsShareKey = pg_query($this->db, $sql);
800  if ($rsShareKey) {
801  $row = pg_fetch_object($rsShareKey);
802  if ($row && (intval($row->resource_link_pk) === $shareKey->resourceLinkId)) {
803  $shareKey->autoApprove = (intval($row->auto_approve) === 1);
804  $shareKey->expires = strtotime($row->expires);
805  $ok = true;
806  }
807  }
808 
809  return $ok;
810  }
811 
819  public function saveResourceLinkShareKey($shareKey)
820  {
821  if ($shareKey->autoApprove) {
822  $approve = 'true';
823  } else {
824  $approve = 'false';
825  }
826  $expires = date("{$this->dateFormat} {$this->timeFormat}", $shareKey->expires);
827  $sql = sprintf("INSERT INTO {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_SHARE_KEY_TABLE_NAME . ' ' .
828  '(share_key_id, resource_link_pk, auto_approve, expires) ' .
829  "VALUES (%s, %d, {$approve}, '{$expires}')", $this->escape($shareKey->getId()), $shareKey->resourceLinkId);
830  $ok = pg_query($this->db, $sql);
831 
832  return $ok;
833  }
834 
842  public function deleteResourceLinkShareKey($shareKey)
843  {
844  $sql = "DELETE FROM {$this->dbTableNamePrefix}" . static::RESOURCE_LINK_SHARE_KEY_TABLE_NAME . " WHERE share_key_id = '{$shareKey->getId()}'";
845 
846  $ok = pg_query($this->db, $sql);
847 
848  if ($ok) {
849  $shareKey->initialize();
850  }
851 
852  return $ok;
853  }
854 
855 ###
856 ### UserResult methods
857 ###
858 
866  public function loadUserResult($userresult)
867  {
868  $ok = false;
869  if (!is_null($userresult->getRecordId())) {
870  $sql = sprintf('SELECT user_result_pk, resource_link_pk, lti_user_id, lti_result_sourcedid, created, updated ' .
871  "FROM {$this->dbTableNamePrefix}" . static::USER_RESULT_TABLE_NAME . ' ' .
872  'WHERE (user_result_pk = %d)', $userresult->getRecordId());
873  } else {
874  $sql = sprintf('SELECT user_result_pk, resource_link_pk, lti_user_id, lti_result_sourcedid, created, updated ' .
875  "FROM {$this->dbTableNamePrefix}" . static::USER_RESULT_TABLE_NAME . ' ' .
876  'WHERE (resource_link_pk = %d) AND (lti_user_id = %s)', $userresult->getResourceLink()->getRecordId(),
877  $this->escape($userresult->getId(LTI\ToolProvider::ID_SCOPE_ID_ONLY)));
878  }
879  $rsUser = pg_query($this->db, $sql);
880  if ($rsUser) {
881  $row = pg_fetch_object($rsUser);
882  if ($row) {
883  $userresult->setRecordId(intval($row->user_result_pk));
884  $userresult->setResourceLinkId(intval($row->resource_link_pk));
885  $userresult->ltiUserId = $row->lti_user_id;
886  $userresult->ltiResultSourcedId = $row->lti_result_sourcedid;
887  $userresult->created = strtotime($row->created);
888  $userresult->updated = strtotime($row->updated);
889  $ok = true;
890  }
891  }
892 
893  return $ok;
894  }
895 
903  public function saveUserResult($userresult)
904  {
905  $time = time();
906  $now = date("{$this->dateFormat} {$this->timeFormat}", $time);
907  if (is_null($userresult->created)) {
908  $sql = sprintf("INSERT INTO {$this->dbTableNamePrefix}" . static::USER_RESULT_TABLE_NAME . ' (resource_link_pk, ' .
909  'lti_user_id, lti_result_sourcedid, created, updated) ' .
910  'VALUES (%d, %s, %s, %s, %s)', $userresult->getResourceLink()->getRecordId(),
911  $this->escape($userresult->getId(LTI\ToolProvider::ID_SCOPE_ID_ONLY)),
912  $this->escape($userresult->ltiResultSourcedId), $this->escape($now), $this->escape($now));
913  } else {
914  $sql = sprintf("UPDATE {$this->dbTableNamePrefix}" . static::USER_RESULT_TABLE_NAME . ' ' .
915  'SET lti_result_sourcedid = %s, updated = %s ' .
916  'WHERE (user_result_pk = %d)', $this->escape($userresult->ltiResultSourcedId), $this->escape($now),
917  $userresult->getRecordId());
918  }
919  $ok = pg_query($this->db, $sql);
920  if ($ok) {
921  if (is_null($userresult->created)) {
922  $userresult->setRecordId($this->insert_id());
923  $userresult->created = $time;
924  }
925  $userresult->updated = $time;
926  }
927 
928  return $ok;
929  }
930 
938  public function deleteUserResult($userresult)
939  {
940  $sql = sprintf("DELETE FROM {$this->dbTableNamePrefix}" . static::USER_RESULT_TABLE_NAME . ' ' .
941  'WHERE (user_result_pk = %d)', $userresult->getRecordId());
942  $ok = pg_query($this->db, $sql);
943 
944  if ($ok) {
945  $userresult->initialize();
946  }
947 
948  return $ok;
949  }
950 
951  private function insert_id()
952  {
953  $rsId = pg_query('SELECT lastval();');
954  $row = pg_fetch_row($rsId);
955  return intval($row[0]);
956  }
957 
969  public function escape($value, $addQuotes = true)
970  {
971  if (is_null($value)) {
972  $value = 'null';
973  } else {
974  $value = pg_escape_string($this->db, $value);
975  if ($addQuotes) {
976  $value = "'{$value}'";
977  }
978  }
979 
980  return $value;
981  }
982 
983 }
static fromResourceLink($resourceLink, $ltiUserId)
Class constructor from resource link.
Definition: UserResult.php:255
getSharesResourceLink($resourceLink)
Get array of shares defined for this resource link.
Class to provide a connection to a persistent store for LTI objects.
deleteUserResult($userresult)
Delete user object.
saveResourceLinkShareKey($shareKey)
Save resource link share key object.
saveContext($context)
Save context object.
const ID_SCOPE_ID_ONLY
Use ID value only.
loadToolConsumer($consumer)
Load tool consumer object.
Class to represent a tool consumer.
Class to represent a tool consumer context.
Definition: Context.php:17
loadContext($context)
Load context object.
saveToolConsumer($consumer)
Save tool consumer object.
Class to represent a tool consumer nonce.
Class to represent a tool consumer resource link share.
deleteResourceLinkShareKey($shareKey)
Delete resource link share key object.
loadResourceLinkShareKey($shareKey)
Load resource link share key object.
deleteResourceLink($resourceLink)
Delete resource link object.
Class to represent an LTI Data Connector for PostgreSQL.
loadUserResult($userresult)
Load user object.
Class to represent a tool consumer user.
Definition: UserResult.php:15
getToolConsumers()
Load all tool consumers from the database.
saveUserResult($userresult)
Save user object.
loadResourceLink($resourceLink)
Load resource link object.
Class to represent a tool consumer resource link share key.
escape($value, $addQuotes=true)
Escape a string for use in a database query.
saveResourceLink($resourceLink)
Save resource link object.
deleteContext($context)
Delete context object.
getUserResultSourcedIDsResourceLink($resourceLink, $localOnly, $idScope)
Get array of user objects.
deleteToolConsumer($consumer)
Delete tool consumer object.