Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
 
3
namespace IMSGlobal\LTI\ToolProvider\DataConnector;
4
 
5
use IMSGlobal\LTI\ToolProvider;
6
use IMSGlobal\LTI\ToolProvider\ConsumerNonce;
7
use IMSGlobal\LTI\ToolProvider\Context;
8
use IMSGlobal\LTI\ToolProvider\ResourceLink;
9
use IMSGlobal\LTI\ToolProvider\ResourceLinkShareKey;
10
use IMSGlobal\LTI\ToolProvider\ToolConsumer;
11
use IMSGlobal\LTI\ToolProvider\User;
12
 
13
/**
14
 * Class to represent an LTI Data Connector for MySQL
15
 *
16
 * @author  Stephen P Vickers <svickers@imsglobal.org>
17
 * @copyright  IMS Global Learning Consortium Inc
18
 * @date  2016
19
 * @version 3.0.0
20
 * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
21
 */
22
 
23
###
24
#    NB This class assumes that a MySQL connection has already been opened to the appropriate schema
25
###
26
 
27
 
28
#[\AllowDynamicProperties]
29
class DataConnector_mysql extends DataConnector
30
{
31
 
32
###
33
###  ToolConsumer methods
34
###
35
 
36
/**
37
 * Load tool consumer object.
38
 *
39
 * @param ToolConsumer $consumer ToolConsumer object
40
 *
41
 * @return boolean True if the tool consumer object was successfully loaded
42
 */
43
    public function loadToolConsumer($consumer)
44
    {
45
 
46
        $ok = false;
47
        if (!empty($consumer->getRecordId())) {
48
            $sql = sprintf('SELECT consumer_pk, name, consumer_key256, consumer_key, secret, lti_version, ' .
49
                           '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}" . DataConnector::CONSUMER_TABLE_NAME . ' ' .
53
                           "WHERE consumer_pk = %d",
54
                           $consumer->getRecordId());
55
        } else {
56
            $key256 = DataConnector::getConsumerKey($consumer->getKey());
57
            $sql = sprintf('SELECT consumer_pk, name, consumer_key256, consumer_key, secret, lti_version, ' .
58
                           'consumer_name, consumer_version, consumer_guid, ' .
59
                           'profile, tool_proxy, settings, protected, enabled, ' .
60
                           'enable_from, enable_until, last_access, created, updated ' .
61
                           "FROM {$this->dbTableNamePrefix}" . DataConnector::CONSUMER_TABLE_NAME . ' ' .
62
                           "WHERE consumer_key256 = %s",
63
                           DataConnector::quoted($key256));
64
        }
65
        $rsConsumer = mysql_query($sql);
66
        if ($rsConsumer) {
67
            while ($row = mysql_fetch_object($rsConsumer)) {
68
                if (empty($key256) || empty($row->consumer_key) || ($consumer->getKey() === $row->consumer_key)) {
69
                    $consumer->setRecordId(intval($row->consumer_pk));
70
                    $consumer->name = $row->name;
71
                    $consumer->setkey(empty($row->consumer_key) ? $row->consumer_key256 : $row->consumer_key);
72
                    $consumer->secret = $row->secret;
73
                    $consumer->ltiVersion = $row->lti_version;
74
                    $consumer->consumerName = $row->consumer_name;
75
                    $consumer->consumerVersion = $row->consumer_version;
76
                    $consumer->consumerGuid = $row->consumer_guid;
77
                    $consumer->profile = json_decode($row->profile);
78
                    $consumer->toolProxy = $row->tool_proxy;
79
                    $settings = unserialize($row->settings);
80
                    if (!is_array($settings)) {
81
                        $settings = array();
82
                    }
83
                    $consumer->setSettings($settings);
84
                    $consumer->protected = (intval($row->protected) === 1);
85
                    $consumer->enabled = (intval($row->enabled) === 1);
86
                    $consumer->enableFrom = null;
87
                    if (!is_null($row->enable_from)) {
88
                        $consumer->enableFrom = strtotime($row->enable_from);
89
                    }
90
                    $consumer->enableUntil = null;
91
                    if (!is_null($row->enable_until)) {
92
                        $consumer->enableUntil = strtotime($row->enable_until);
93
                    }
94
                    $consumer->lastAccess = null;
95
                    if (!is_null($row->last_access)) {
96
                        $consumer->lastAccess = strtotime($row->last_access);
97
                    }
98
                    $consumer->created = strtotime($row->created);
99
                    $consumer->updated = strtotime($row->updated);
100
                    $ok = true;
101
                    break;
102
                }
103
            }
104
            mysql_free_result($rsConsumer);
105
        }
106
 
107
        return $ok;
108
 
109
    }
110
 
111
/**
112
 * Save tool consumer object.
113
 *
114
 * @param ToolConsumer $consumer Consumer object
115
 *
116
 * @return boolean True if the tool consumer object was successfully saved
117
 */
118
    public function saveToolConsumer($consumer)
119
    {
120
 
121
        $id = $consumer->getRecordId();
122
        $key = $consumer->getKey();
123
        $key256 = DataConnector::getConsumerKey($key);
124
        if ($key === $key256) {
125
            $key = null;
126
        }
127
        $protected = ($consumer->protected) ? 1 : 0;
128
        $enabled = ($consumer->enabled)? 1 : 0;
129
        $profile = (!empty($consumer->profile)) ? json_encode($consumer->profile) : null;
130
        $settingsValue = serialize($consumer->getSettings());
131
        $time = time();
132
        $now = date("{$this->dateFormat} {$this->timeFormat}", $time);
133
        $from = null;
134
        if (!is_null($consumer->enableFrom)) {
135
            $from = date("{$this->dateFormat} {$this->timeFormat}", $consumer->enableFrom);
136
        }
137
        $until = null;
138
        if (!is_null($consumer->enableUntil)) {
139
            $until = date("{$this->dateFormat} {$this->timeFormat}", $consumer->enableUntil);
140
        }
141
        $last = null;
142
        if (!is_null($consumer->lastAccess)) {
143
            $last = date($this->dateFormat, $consumer->lastAccess);
144
        }
145
        if (empty($id)) {
146
            $sql = sprintf("INSERT INTO {$this->dbTableNamePrefix}" . DataConnector::CONSUMER_TABLE_NAME . ' (consumer_key256, consumer_key, name, ' .
147
                           'secret, lti_version, consumer_name, consumer_version, consumer_guid, profile, tool_proxy, settings, protected, enabled, ' .
148
                           'enable_from, enable_until, last_access, created, updated) ' .
149
                           'VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %d, %d, %s, %s, %s, %s, %s)',
150
                           DataConnector::quoted($key256), DataConnector::quoted($key), DataConnector::quoted($consumer->name),
151
                           DataConnector::quoted($consumer->secret), DataConnector::quoted($consumer->ltiVersion),
152
                           DataConnector::quoted($consumer->consumerName), DataConnector::quoted($consumer->consumerVersion), DataConnector::quoted($consumer->consumerGuid),
153
                           DataConnector::quoted($profile), DataConnector::quoted($consumer->toolProxy), DataConnector::quoted($settingsValue),
154
                           $protected, $enabled, DataConnector::quoted($from), DataConnector::quoted($until), DataConnector::quoted($last),
155
                           DataConnector::quoted($now), DataConnector::quoted($now));
156
        } else {
157
            $sql = sprintf("UPDATE {$this->dbTableNamePrefix}" . DataConnector::CONSUMER_TABLE_NAME . ' SET ' .
158
                           'consumer_key256 = %s, consumer_key = %s, ' .
159
                           'name = %s, secret= %s, lti_version = %s, consumer_name = %s, consumer_version = %s, consumer_guid = %s, ' .
160
                           'profile = %s, tool_proxy = %s, settings = %s, ' .
161
                           'protected = %d, enabled = %d, enable_from = %s, enable_until = %s, last_access = %s, updated = %s ' .
162
                           'WHERE consumer_pk = %d',
163
                           DataConnector::quoted($key256), DataConnector::quoted($key),
164
                           DataConnector::quoted($consumer->name),
165
                           DataConnector::quoted($consumer->secret), DataConnector::quoted($consumer->ltiVersion),
166
                           DataConnector::quoted($consumer->consumerName), DataConnector::quoted($consumer->consumerVersion), DataConnector::quoted($consumer->consumerGuid),
167
                           DataConnector::quoted($profile), DataConnector::quoted($consumer->toolProxy), DataConnector::quoted($settingsValue),
168
                           $protected, $enabled,
169
                           DataConnector::quoted($from), DataConnector::quoted($until), DataConnector::quoted($last),
170
                           DataConnector::quoted($now), $consumer->getRecordId());
171
        }
172
        $ok = mysql_query($sql);
173
        if ($ok) {
174
            if (empty($id)) {
175
                $consumer->setRecordId(mysql_insert_id());
176
                $consumer->created = $time;
177
            }
178
            $consumer->updated = $time;
179
        }
180
 
181
        return $ok;
182
 
183
    }
184
 
185
/**
186
 * Delete tool consumer object.
187
 *
188
 * @param ToolConsumer $consumer Consumer object
189
 *
190
 * @return boolean True if the tool consumer object was successfully deleted
191
 */
192
    public function deleteToolConsumer($consumer)
193
    {
194
 
195
// Delete any nonce values for this consumer
196
        $sql = sprintf("DELETE FROM {$this->dbTableNamePrefix}" . DataConnector::NONCE_TABLE_NAME . ' WHERE consumer_pk = %d',
197
                       $consumer->getRecordId());
198
        mysql_query($sql);
199
 
200
// Delete any outstanding share keys for resource links for this consumer
201
        $sql = sprintf('DELETE sk ' .
202
                       "FROM {$this->dbTableNamePrefix}" . DataConnector::RESOURCE_LINK_SHARE_KEY_TABLE_NAME . ' sk ' .
203
                       "INNER JOIN {$this->dbTableNamePrefix}" . DataConnector::RESOURCE_LINK_TABLE_NAME . ' rl ON sk.resource_link_pk = rl.resource_link_pk ' .
204
                       'WHERE rl.consumer_pk = %d',
205
                       $consumer->getRecordId());
206
        mysql_query($sql);
207
 
208
// Delete any outstanding share keys for resource links for contexts in this consumer
209
        $sql = sprintf('DELETE sk ' .
210
                       "FROM {$this->dbTableNamePrefix}" . DataConnector::RESOURCE_LINK_SHARE_KEY_TABLE_NAME . ' sk ' .
211
                       "INNER JOIN {$this->dbTableNamePrefix}" . DataConnector::RESOURCE_LINK_TABLE_NAME . ' rl ON sk.resource_link_pk = rl.resource_link_pk ' .
212
                       "INNER JOIN {$this->dbTableNamePrefix}" . DataConnector::CONTEXT_TABLE_NAME . ' c ON rl.context_pk = c.context_pk ' .
213
                       'WHERE c.consumer_pk = %d',
214
                       $consumer->getRecordId());
215
        mysql_query($sql);
216
 
217
// Delete any users in resource links for this consumer
218
        $sql = sprintf('DELETE u ' .
219
                       "FROM {$this->dbTableNamePrefix}" . DataConnector::USER_RESULT_TABLE_NAME . ' u ' .
220
                       "INNER JOIN {$this->dbTableNamePrefix}" . DataConnector::RESOURCE_LINK_TABLE_NAME . ' rl ON u.resource_link_pk = rl.resource_link_pk ' .
221
                       'WHERE rl.consumer_pk = %d',
222
                       $consumer->getRecordId());
223
        mysql_query($sql);
224
 
225
// Delete any users in resource links for contexts in this consumer
226
        $sql = sprintf('DELETE u ' .
227
                       "FROM {$this->dbTableNamePrefix}" . DataConnector::USER_RESULT_TABLE_NAME . ' u ' .
228
                       "INNER JOIN {$this->dbTableNamePrefix}" . DataConnector::RESOURCE_LINK_TABLE_NAME . ' rl ON u.resource_link_pk = rl.resource_link_pk ' .
229
                       "INNER JOIN {$this->dbTableNamePrefix}" . DataConnector::CONTEXT_TABLE_NAME . ' c ON rl.context_pk = c.context_pk ' .
230
                       'WHERE c.consumer_pk = %d',
231
                       $consumer->getRecordId());
232
        mysql_query($sql);
233
 
234
// Update any resource links for which this consumer is acting as a primary resource link
235
        $sql = sprintf("UPDATE {$this->dbTableNamePrefix}" . DataConnector::RESOURCE_LINK_TABLE_NAME . ' prl ' .
236
                       "INNER JOIN {$this->dbTableNamePrefix}" . DataConnector::RESOURCE_LINK_TABLE_NAME . ' rl ON prl.primary_resource_link_pk = rl.resource_link_pk ' .
237
                       'SET prl.primary_resource_link_pk = NULL, prl.share_approved = NULL ' .
238
                       'WHERE rl.consumer_pk = %d',
239
                       $consumer->getRecordId());
240
        $ok = mysql_query($sql);
241
 
242
// Update any resource links for contexts in which this consumer is acting as a primary resource link
243
        $sql = sprintf("UPDATE {$this->dbTableNamePrefix}" . DataConnector::RESOURCE_LINK_TABLE_NAME . ' prl ' .
244
                       "INNER JOIN {$this->dbTableNamePrefix}" . DataConnector::RESOURCE_LINK_TABLE_NAME . ' rl ON prl.primary_resource_link_pk = rl.resource_link_pk ' .
245
                       "INNER JOIN {$this->dbTableNamePrefix}" . DataConnector::CONTEXT_TABLE_NAME . ' c ON rl.context_pk = c.context_pk ' .
246
                       'SET prl.primary_resource_link_pk = NULL, prl.share_approved = NULL ' .
247
                       'WHERE c.consumer_pk = %d',
248
                       $consumer->getRecordId());
249
        $ok = mysql_query($sql);
250
 
251
// Delete any resource links for this consumer
252
        $sql = sprintf('DELETE rl ' .
253
                       "FROM {$this->dbTableNamePrefix}" . DataConnector::RESOURCE_LINK_TABLE_NAME . ' rl ' .
254
                       'WHERE rl.consumer_pk = %d',
255
                       $consumer->getRecordId());
256
        mysql_query($sql);
257
 
258
// Delete any resource links for contexts in this consumer
259
        $sql = sprintf('DELETE rl ' .
260
                       "FROM {$this->dbTableNamePrefix}" . DataConnector::RESOURCE_LINK_TABLE_NAME . ' rl ' .
261
                       "INNER JOIN {$this->dbTableNamePrefix}" . DataConnector::CONTEXT_TABLE_NAME . ' c ON rl.context_pk = c.context_pk ' .
262
                       'WHERE c.consumer_pk = %d',
263
                       $consumer->getRecordId());
264
        mysql_query($sql);
265
 
266
// Delete any contexts for this consumer
267
        $sql = sprintf('DELETE c ' .
268
                       "FROM {$this->dbTableNamePrefix}" . DataConnector::CONTEXT_TABLE_NAME . ' c ' .
269
                       'WHERE c.consumer_pk = %d',
270
                       $consumer->getRecordId());
271
        mysql_query($sql);
272
 
273
// Delete consumer
274
        $sql = sprintf('DELETE c ' .
275
                       "FROM {$this->dbTableNamePrefix}" . DataConnector::CONSUMER_TABLE_NAME . ' c ' .
276
                       'WHERE c.consumer_pk = %d',
277
                       $consumer->getRecordId());
278
        $ok = mysql_query($sql);
279
 
280
        if ($ok) {
281
            $consumer->initialize();
282
        }
283
 
284
        return $ok;
285
 
286
    }
287
 
288
###
289
#    Load all tool consumers from the database
290
###
291
    public function getToolConsumers()
292
    {
293
 
294
        $consumers = array();
295
 
296
        $sql = 'SELECT consumer_pk, consumer_key, consumer_key, name, secret, lti_version, consumer_name, consumer_version, consumer_guid, ' .
297
               'profile, tool_proxy, settings, ' .
298
               'protected, enabled, enable_from, enable_until, last_access, created, updated ' .
299
               "FROM {$this->dbTableNamePrefix}" . DataConnector::CONSUMER_TABLE_NAME . ' ' .
300
               'ORDER BY name';
301
        $rsConsumers = mysql_query($sql);
302
        if ($rsConsumers) {
303
            while ($row = mysql_fetch_object($rsConsumers)) {
304
                $consumer = new ToolProvider\ToolConsumer($row->consumer_key, $this);
305
                $consumer->setRecordId(intval($row->consumer_pk));
306
                $consumer->name = $row->name;
307
                $consumer->secret = $row->secret;
308
                $consumer->ltiVersion = $row->lti_version;
309
                $consumer->consumerName = $row->consumer_name;
310
                $consumer->consumerVersion = $row->consumer_version;
311
                $consumer->consumerGuid = $row->consumer_guid;
312
                $consumer->profile = json_decode($row->profile);
313
                $consumer->toolProxy = $row->tool_proxy;
314
                $settings = unserialize($row->settings);
315
                if (!is_array($settings)) {
316
                    $settings = array();
317
                }
318
                $consumer->setSettings($settings);
319
                $consumer->protected = (intval($row->protected) === 1);
320
                $consumer->enabled = (intval($row->enabled) === 1);
321
                $consumer->enableFrom = null;
322
                if (!is_null($row->enable_from)) {
323
                    $consumer->enableFrom = strtotime($row->enable_from);
324
                }
325
                $consumer->enableUntil = null;
326
                if (!is_null($row->enable_until)) {
327
                    $consumer->enableUntil = strtotime($row->enable_until);
328
                }
329
                $consumer->lastAccess = null;
330
                if (!is_null($row->last_access)) {
331
                    $consumer->lastAccess = strtotime($row->last_access);
332
                }
333
                $consumer->created = strtotime($row->created);
334
                $consumer->updated = strtotime($row->updated);
335
                $consumers[] = $consumer;
336
            }
337
            mysql_free_result($rsConsumers);
338
        }
339
 
340
        return $consumers;
341
 
342
    }
343
 
344
###
345
###  ToolProxy methods
346
###
347
 
348
###
349
#    Load the tool proxy from the database
350
###
351
    public function loadToolProxy($toolProxy)
352
    {
353
 
354
        return false;
355
 
356
    }
357
 
358
###
359
#    Save the tool proxy to the database
360
###
361
    public function saveToolProxy($toolProxy)
362
    {
363
 
364
        return false;
365
 
366
    }
367
 
368
###
369
#    Delete the tool proxy from the database
370
###
371
    public function deleteToolProxy($toolProxy)
372
    {
373
 
374
        return false;
375
 
376
    }
377
 
378
###
379
###  Context methods
380
###
381
 
382
/**
383
 * Load context object.
384
 *
385
 * @param Context $context Context object
386
 *
387
 * @return boolean True if the context object was successfully loaded
388
 */
389
    public function loadContext($context)
390
    {
391
 
392
        $ok = false;
393
        if (!empty($context->getRecordId())) {
394
            $sql = sprintf('SELECT context_pk, consumer_pk, lti_context_id, type, settings, created, updated ' .
395
                           "FROM {$this->dbTableNamePrefix}" . DataConnector::CONTEXT_TABLE_NAME . ' ' .
396
                           'WHERE (context_pk = %d)',
397
                           $context->getRecordId());
398
        } else {
399
            $sql = sprintf('SELECT context_pk, consumer_pk, lti_context_id, type, settings, created, updated ' .
400
                           "FROM {$this->dbTableNamePrefix}" . DataConnector::CONTEXT_TABLE_NAME . ' ' .
401
                           'WHERE (consumer_pk = %d) AND (lti_context_id = %s)',
402
                           $context->getConsumer()->getRecordId(), DataConnector::quoted($context->ltiContextId));
403
        }
404
        $rs_context = mysql_query($sql);
405
        if ($rs_context) {
406
            $row = mysql_fetch_object($rs_context);
407
            if ($row) {
408
                $context->setRecordId(intval($row->context_pk));
409
                $context->setConsumerId(intval($row->consumer_pk));
410
                $context->ltiContextId = $row->lti_context_id;
411
                $context->type = $row->type;
412
                $settings = unserialize($row->settings);
413
                if (!is_array($settings)) {
414
                    $settings = array();
415
                }
416
                $context->setSettings($settings);
417
                $context->created = strtotime($row->created);
418
                $context->updated = strtotime($row->updated);
419
                $ok = true;
420
            }
421
        }
422
 
423
        return $ok;
424
 
425
    }
426
 
427
/**
428
 * Save context object.
429
 *
430
 * @param Context $context Context object
431
 *
432
 * @return boolean True if the context object was successfully saved
433
 */
434
    public function saveContext($context)
435
    {
436
 
437
        $time = time();
438
        $now = date("{$this->dateFormat} {$this->timeFormat}", $time);
439
        $settingsValue = serialize($context->getSettings());
440
        $id = $context->getRecordId();
441
        $consumer_pk = $context->getConsumer()->getRecordId();
442
        if (empty($id)) {
443
            $sql = sprintf("INSERT INTO {$this->dbTableNamePrefix}" . DataConnector::CONTEXT_TABLE_NAME . ' (consumer_pk, lti_context_id, ' .
444
                           'type, settings, created, updated) ' .
445
                           'VALUES (%d, %s, %s, %s, %s, %s)',
446
               $consumer_pk, DataConnector::quoted($context->ltiContextId),
447
               DataConnector::quoted($context->type),
448
               DataConnector::quoted($settingsValue),
449
               DataConnector::quoted($now), DataConnector::quoted($now));
450
        } else {
451
            $sql = sprintf("UPDATE {$this->dbTableNamePrefix}" . DataConnector::CONTEXT_TABLE_NAME . ' SET ' .
452
                           'lti_context_id = %s, type = %s, settings = %s, '.
453
                           'updated = %s' .
454
                           'WHERE (consumer_pk = %d) AND (context_pk = %d)',
455
               DataConnector::quoted($context->ltiContextId),
456
               DataConnector::quoted($context->type),
457
               DataConnector::quoted($settingsValue),
458
               DataConnector::quoted($now), $consumer_pk, $id);
459
        }
460
        $ok = mysql_query($sql);
461
        if ($ok) {
462
            if (empty($id)) {
463
                $context->setRecordId(mysql_insert_id());
464
                $context->created = $time;
465
            }
466
            $context->updated = $time;
467
        }
468
 
469
        return $ok;
470
 
471
    }
472
 
473
/**
474
 * Delete context object.
475
 *
476
 * @param Context $context Context object
477
 *
478
 * @return boolean True if the Context object was successfully deleted
479
 */
480
    public function deleteContext($context)
481
    {
482
 
483
// Delete any outstanding share keys for resource links for this context
484
        $sql = sprintf('DELETE sk ' .
485
                       "FROM {$this->dbTableNamePrefix}" . DataConnector::RESOURCE_LINK_SHARE_KEY_TABLE_NAME . ' sk ' .
486
                       "INNER JOIN {$this->dbTableNamePrefix}" . DataConnector::RESOURCE_LINK_TABLE_NAME . ' rl ON sk.resource_link_pk = rl.resource_link_pk ' .
487
                       'WHERE rl.context_pk = %d',
488
                       $context->getRecordId());
489
        mysql_query($sql);
490
 
491
// Delete any users in resource links for this context
492
        $sql = sprintf('DELETE u ' .
493
                       "FROM {$this->dbTableNamePrefix}" . DataConnector::USER_RESULT_TABLE_NAME . ' u ' .
494
                       "INNER JOIN {$this->dbTableNamePrefix}" . DataConnector::RESOURCE_LINK_TABLE_NAME . ' rl ON u.resource_link_pk = rl.resource_link_pk ' .
495
                       'WHERE rl.context_pk = %d',
496
                       $context->getRecordId());
497
        mysql_query($sql);
498
 
499
// Update any resource links for which this consumer is acting as a primary resource link
500
        $sql = sprintf("UPDATE {$this->dbTableNamePrefix}" . DataConnector::RESOURCE_LINK_TABLE_NAME . ' prl ' .
501
                       "INNER JOIN {$this->dbTableNamePrefix}" . DataConnector::RESOURCE_LINK_TABLE_NAME . ' rl ON prl.primary_resource_link_pk = rl.resource_link_pk ' .
502
                       'SET prl.primary_resource_link_pk = null, prl.share_approved = null ' .
503
                       'WHERE rl.context_pk = %d',
504
                       $context->getRecordId());
505
        $ok = mysql_query($sql);
506
 
507
// Delete any resource links for this consumer
508
        $sql = sprintf('DELETE rl ' .
509
                       "FROM {$this->dbTableNamePrefix}" . DataConnector::RESOURCE_LINK_TABLE_NAME . ' rl ' .
510
                       'WHERE rl.context_pk = %d',
511
                       $context->getRecordId());
512
        mysql_query($sql);
513
 
514
// Delete context
515
        $sql = sprintf('DELETE c ' .
516
                       "FROM {$this->dbTableNamePrefix}" . DataConnector::CONTEXT_TABLE_NAME . ' c ',
517
                       'WHERE c.context_pk = %d',
518
                       $context->getRecordId());
519
        $ok = mysql_query($sql);
520
        if ($ok) {
521
            $context->initialize();
522
        }
523
 
524
        return $ok;
525
 
526
    }
527
 
528
###
529
###  ResourceLink methods
530
###
531
 
532
/**
533
 * Load resource link object.
534
 *
535
 * @param ResourceLink $resourceLink Resource_Link object
536
 *
537
 * @return boolean True if the resource link object was successfully loaded
538
 */
539
    public function loadResourceLink($resourceLink)
540
    {
541
 
542
        $ok = false;
543
        if (!empty($resourceLink->getRecordId())) {
544
            $sql = sprintf('SELECT resource_link_pk, context_pk, consumer_pk, lti_resource_link_id, settings, primary_resource_link_pk, share_approved, created, updated ' .
545
                           "FROM {$this->dbTableNamePrefix}" . DataConnector::RESOURCE_LINK_TABLE_NAME . ' ' .
546
                           'WHERE (resource_link_pk = %d)',
547
                           $resourceLink->getRecordId());
548
        } else if (!empty($resourceLink->getContext())) {
549
            $sql = sprintf('SELECT resource_link_pk, context_pk, consumer_pk, lti_resource_link_id, settings, primary_resource_link_pk, share_approved, created, updated ' .
550
                           "FROM {$this->dbTableNamePrefix}" . DataConnector::RESOURCE_LINK_TABLE_NAME . ' ' .
551
                           'WHERE (context_pk = %d) AND (lti_resource_link_id = %s)',
552
                           $resourceLink->getContext()->getRecordId(), DataConnector::quoted($resourceLink->getId()));
553
        } else {
554
            $sql = sprintf('SELECT r.resource_link_pk, r.context_pk, r.consumer_pk, r.lti_resource_link_id, r.settings, r.primary_resource_link_pk, r.share_approved, r.created, r.updated ' .
555
                           "FROM {$this->dbTableNamePrefix}" . DataConnector::RESOURCE_LINK_TABLE_NAME . ' r LEFT OUTER JOIN ' .
556
                           $this->dbTableNamePrefix . DataConnector::CONTEXT_TABLE_NAME . ' c ON r.context_pk = c.context_pk ' .
557
                           ' WHERE ((r.consumer_pk = %d) OR (c.consumer_pk = %d)) AND (lti_resource_link_id = %s)',
558
                           $resourceLink->getConsumer()->getRecordId(), $resourceLink->getConsumer()->getRecordId(), DataConnector::quoted($resourceLink->getId()));
559
        }
560
        $rsContext = mysql_query($sql);
561
        if ($rsContext) {
562
            $row = mysql_fetch_object($rsContext);
563
            if ($row) {
564
                $resourceLink->setRecordId(intval($row->resource_link_pk));
565
                if (!is_null($row->context_pk)) {
566
                    $resourceLink->setContextId(intval($row->context_pk));
567
                } else {
568
                    $resourceLink->setContextId(null);
569
                }
570
                if (!is_null($row->consumer_pk)) {
571
                    $resourceLink->setConsumerId(intval($row->consumer_pk));
572
                } else {
573
                    $resourceLink->setConsumerId(null);
574
                }
575
                $resourceLink->ltiResourceLinkId = $row->lti_resource_link_id;
576
                $settings = unserialize($row->settings);
577
                if (!is_array($settings)) {
578
                    $settings = array();
579
                }
580
                $resourceLink->setSettings($settings);
581
                if (!is_null($row->primary_resource_link_pk)) {
582
                    $resourceLink->primaryResourceLinkId = intval($row->primary_resource_link_pk);
583
                } else {
584
                    $resourceLink->primaryResourceLinkId = null;
585
                }
586
                $resourceLink->shareApproved = (is_null($row->share_approved)) ? null : (intval($row->share_approved) === 1);
587
                $resourceLink->created = strtotime($row->created);
588
                $resourceLink->updated = strtotime($row->updated);
589
                $ok = true;
590
            }
591
        }
592
 
593
        return $ok;
594
 
595
    }
596
 
597
/**
598
 * Save resource link object.
599
 *
600
 * @param ResourceLink $resourceLink Resource_Link object
601
 *
602
 * @return boolean True if the resource link object was successfully saved
603
 */
604
    public function saveResourceLink($resourceLink) {
605
 
606
        if (is_null($resourceLink->shareApproved)) {
607
            $approved = 'NULL';
608
        } else if ($resourceLink->shareApproved) {
609
            $approved = '1';
610
        } else {
611
            $approved = '0';
612
        }
613
        if (empty($resourceLink->primaryResourceLinkId)) {
614
            $primaryResourceLinkId = 'NULL';
615
        } else {
616
            $primaryResourceLinkId = strval($resourceLink->primaryResourceLinkId);
617
        }
618
        $time = time();
619
        $now = date("{$this->dateFormat} {$this->timeFormat}", $time);
620
        $settingsValue = serialize($resourceLink->getSettings());
621
        if (!empty($resourceLink->getContext())) {
622
            $consumerId = 'NULL';
623
            $contextId = strval($resourceLink->getContext()->getRecordId());
624
        } else if (!empty($resourceLink->getContextId())) {
625
            $consumerId = 'NULL';
626
            $contextId = strval($resourceLink->getContextId());
627
        } else {
628
            $consumerId = strval($resourceLink->getConsumer()->getRecordId());
629
            $contextId = 'NULL';
630
        }
631
        $id = $resourceLink->getRecordId();
632
        if (empty($id)) {
633
            $sql = sprintf("INSERT INTO {$this->dbTableNamePrefix}" . DataConnector::RESOURCE_LINK_TABLE_NAME . ' (consumer_pk, context_pk, ' .
634
                           'lti_resource_link_id, settings, primary_resource_link_pk, share_approved, created, updated) ' .
635
                           'VALUES (%s, %s, %s, %s, %s, %s, %s, %s)',
636
                           $consumerId, $contextId, DataConnector::quoted($resourceLink->getId()),
637
                           DataConnector::quoted($settingsValue),
638
                           $primaryResourceLinkId, $approved, DataConnector::quoted($now), DataConnector::quoted($now));
639
        } else if ($contextId !== 'NULL') {
640
            $sql = sprintf("UPDATE {$this->dbTableNamePrefix}" . DataConnector::RESOURCE_LINK_TABLE_NAME . ' SET ' .
641
                           'consumer_pk = %s, lti_resource_link_id = %s, settings = %s, '.
642
                           'primary_resource_link_pk = %s, share_approved = %s, updated = %s ' .
643
                           'WHERE (context_pk = %s) AND (resource_link_pk = %d)',
644
                           $consumerId, DataConnector::quoted($resourceLink->getId()),
645
                           DataConnector::quoted($settingsValue), $primaryResourceLinkId, $approved, DataConnector::quoted($now),
646
                           $contextId, $id);
647
        } else {
648
            $sql = sprintf("UPDATE {$this->dbTableNamePrefix}" . DataConnector::RESOURCE_LINK_TABLE_NAME . ' SET ' .
649
                           'context_pk = %s, lti_resource_link_id = %s, settings = %s, '.
650
                           'primary_resource_link_pk = %s, share_approved = %s, updated = %s ' .
651
                           'WHERE (consumer_pk = %s) AND (resource_link_pk = %d)',
652
                           $contextId, DataConnector::quoted($resourceLink->getId()),
653
                           DataConnector::quoted($settingsValue), $primaryResourceLinkId, $approved, DataConnector::quoted($now),
654
                           $consumerId, $id);
655
        }
656
        $ok = mysql_query($sql);
657
        if ($ok) {
658
            if (empty($id)) {
659
                $resourceLink->setRecordId(mysql_insert_id());
660
                $resourceLink->created = $time;
661
            }
662
            $resourceLink->updated = $time;
663
        }
664
 
665
        return $ok;
666
 
667
    }
668
 
669
/**
670
 * Delete resource link object.
671
 *
672
 * @param ResourceLink $resourceLink Resource_Link object
673
 *
674
 * @return boolean True if the resource link object was successfully deleted
675
 */
676
    public function deleteResourceLink($resourceLink)
677
    {
678
 
679
// Delete any outstanding share keys for resource links for this consumer
680
        $sql = sprintf("DELETE FROM {$this->dbTableNamePrefix}" . DataConnector::RESOURCE_LINK_SHARE_KEY_TABLE_NAME . ' ' .
681
                       'WHERE (resource_link_pk = %d)',
682
                       $resourceLink->getRecordId());
683
        $ok = mysql_query($sql);
684
 
685
// Delete users
686
        if ($ok) {
687
            $sql = sprintf("DELETE FROM {$this->dbTableNamePrefix}" . DataConnector::USER_RESULT_TABLE_NAME . ' ' .
688
                           'WHERE (resource_link_pk = %d)',
689
                           $resourceLink->getRecordId());
690
            $ok = mysql_query($sql);
691
        }
692
 
693
// Update any resource links for which this is the primary resource link
694
        if ($ok) {
695
            $sql = sprintf("UPDATE {$this->dbTableNamePrefix}" . DataConnector::RESOURCE_LINK_TABLE_NAME . ' ' .
696
                           'SET primary_resource_link_pk = NULL ' .
697
                           'WHERE (primary_resource_link_pk = %d)',
698
                           $resourceLink->getRecordId());
699
            $ok = mysql_query($sql);
700
        }
701
 
702
// Delete resource link
703
        if ($ok) {
704
            $sql = sprintf("DELETE FROM {$this->dbTableNamePrefix}" . DataConnector::RESOURCE_LINK_TABLE_NAME . ' ' .
705
                           'WHERE (resource_link_pk = %s)',
706
                           $resourceLink->getRecordId());
707
            $ok = mysql_query($sql);
708
        }
709
 
710
        if ($ok) {
711
            $resourceLink->initialize();
712
        }
713
 
714
        return $ok;
715
 
716
    }
717
 
718
/**
719
 * Get array of user objects.
720
 *
721
 * Obtain an array of User objects for users with a result sourcedId.  The array may include users from other
722
 * resource links which are sharing this resource link.  It may also be optionally indexed by the user ID of a specified scope.
723
 *
724
 * @param ResourceLink $resourceLink      Resource link object
725
 * @param boolean     $localOnly True if only users within the resource link are to be returned (excluding users sharing this resource link)
726
 * @param int         $idScope     Scope value to use for user IDs
727
 *
728
 * @return array Array of User objects
729
 */
730
    public function getUserResultSourcedIDsResourceLink($resourceLink, $localOnly, $idScope)
731
    {
732
 
733
        $users = array();
734
 
735
        if ($localOnly) {
736
            $sql = sprintf('SELECT u.user_pk, u.lti_result_sourcedid, u.lti_user_id, u.created, u.updated ' .
737
                           "FROM {$this->dbTableNamePrefix}" . DataConnector::USER_RESULT_TABLE_NAME . ' AS u '  .
738
                           "INNER JOIN {$this->dbTableNamePrefix}" . DataConnector::RESOURCE_LINK_TABLE_NAME . ' AS rl '  .
739
                           'ON u.resource_link_pk = rl.resource_link_pk ' .
740
                           "WHERE (rl.resource_link_pk = %d) AND (rl.primary_resource_link_pk IS NULL)",
741
                           $resourceLink->getRecordId());
742
        } else {
743
            $sql = sprintf('SELECT u.user_pk, u.lti_result_sourcedid, u.lti_user_id, u.created, u.updated ' .
744
                           "FROM {$this->dbTableNamePrefix}" . DataConnector::USER_RESULT_TABLE_NAME . ' AS u '  .
745
                           "INNER JOIN {$this->dbTableNamePrefix}" . DataConnector::RESOURCE_LINK_TABLE_NAME . ' AS rl '  .
746
                           'ON u.resource_link_pk = rl.resource_link_pk ' .
747
                           'WHERE ((rl.resource_link_pk = %d) AND (rl.primary_resource_link_pk IS NULL)) OR ' .
748
                           '((rl.primary_resource_link_pk = %d) AND (share_approved = 1))',
749
                           $resourceLink->getRecordId(), $resourceLink->getRecordId());
750
        }
751
        $rsUser = mysql_query($sql);
752
        if ($rsUser) {
753
            while ($row = mysql_fetch_object($rsUser)) {
754
                $user = ToolProvider\User::fromResourceLink($resourceLink, $row->lti_user_id);
755
                $user->setRecordId(intval($row->user_pk));
756
                $user->ltiResultSourcedId = $row->lti_result_sourcedid;
757
                $user->created = strtotime($row->created);
758
                $user->updated = strtotime($row->updated);
759
                if (is_null($idScope)) {
760
                    $users[] = $user;
761
                } else {
762
                    $users[$user->getId($idScope)] = $user;
763
                }
764
            }
765
        }
766
 
767
        return $users;
768
 
769
    }
770
 
771
/**
772
 * Get array of shares defined for this resource link.
773
 *
774
 * @param ResourceLink $resourceLink Resource_Link object
775
 *
776
 * @return array Array of ResourceLinkShare objects
777
 */
778
    public function getSharesResourceLink($resourceLink)
779
    {
780
 
781
        $shares = array();
782
 
783
        $sql = sprintf('SELECT consumer_pk, resource_link_pk, share_approved ' .
784
                       "FROM {$this->dbTableNamePrefix}" . DataConnector::RESOURCE_LINK_TABLE_NAME . ' ' .
785
                       'WHERE (primary_resource_link_pk = %d) ' .
786
                       'ORDER BY consumer_pk',
787
                       $resourceLink->getRecordId());
788
        $rsShare = mysql_query($sql);
789
        if ($rsShare) {
790
            while ($row = mysql_fetch_object($rsShare)) {
791
                $share = new ToolProvider\ResourceLinkShare();
792
                $share->resourceLinkId = intval($row->resource_link_pk);
793
                $share->approved = (intval($row->share_approved) === 1);
794
                $shares[] = $share;
795
            }
796
        }
797
 
798
        return $shares;
799
 
800
    }
801
 
802
 
803
###
804
###  ConsumerNonce methods
805
###
806
 
807
/**
808
 * Load nonce object.
809
 *
810
 * @param ConsumerNonce $nonce Nonce object
811
 *
812
 * @return boolean True if the nonce object was successfully loaded
813
 */
814
    public function loadConsumerNonce($nonce)
815
    {
816
 
817
        $ok = true;
818
 
819
// Delete any expired nonce values
820
        $now = date("{$this->dateFormat} {$this->timeFormat}", time());
821
        $sql = "DELETE FROM {$this->dbTableNamePrefix}" . DataConnector::NONCE_TABLE_NAME . " WHERE expires <= '{$now}'";
822
        mysql_query($sql);
823
 
824
// Load the nonce
825
        $sql = sprintf("SELECT value AS T FROM {$this->dbTableNamePrefix}" . DataConnector::NONCE_TABLE_NAME . ' WHERE (consumer_pk = %d) AND (value = %s)',
826
                       $nonce->getConsumer()->getRecordId(), DataConnector::quoted($nonce->getValue()));
827
        $rs_nonce = mysql_query($sql);
828
        if ($rs_nonce) {
829
            $row = mysql_fetch_object($rs_nonce);
830
            if ($row === false) {
831
                $ok = false;
832
            }
833
        }
834
 
835
        return $ok;
836
 
837
    }
838
 
839
/**
840
 * Save nonce object.
841
 *
842
 * @param ConsumerNonce $nonce Nonce object
843
 *
844
 * @return boolean True if the nonce object was successfully saved
845
 */
846
    public function saveConsumerNonce($nonce)
847
    {
848
 
849
        $expires = date("{$this->dateFormat} {$this->timeFormat}", $nonce->expires);
850
        $sql = sprintf("INSERT INTO {$this->dbTableNamePrefix}" . DataConnector::NONCE_TABLE_NAME . " (consumer_pk, value, expires) VALUES (%d, %s, %s)",
851
                       $nonce->getConsumer()->getRecordId(), DataConnector::quoted($nonce->getValue()),
852
                       DataConnector::quoted($expires));
853
        $ok = mysql_query($sql);
854
 
855
        return $ok;
856
 
857
    }
858
 
859
 
860
###
861
###  ResourceLinkShareKey methods
862
###
863
 
864
/**
865
 * Load resource link share key object.
866
 *
867
 * @param ResourceLinkShareKey $shareKey Resource_Link share key object
868
 *
869
 * @return boolean True if the resource link share key object was successfully loaded
870
 */
871
    public function loadResourceLinkShareKey($shareKey)
872
    {
873
 
874
        $ok = false;
875
 
876
// Clear expired share keys
877
        $now = date("{$this->dateFormat} {$this->timeFormat}", time());
878
        $sql = "DELETE FROM {$this->dbTableNamePrefix}" . DataConnector::RESOURCE_LINK_SHARE_KEY_TABLE_NAME . " WHERE expires <= '{$now}'";
879
        mysql_query($sql);
880
 
881
// Load share key
882
        $id = mysql_real_escape_string($shareKey->getId());
883
        $sql = 'SELECT resource_link_pk, auto_approve, expires ' .
884
               "FROM {$this->dbTableNamePrefix}" . DataConnector::RESOURCE_LINK_SHARE_KEY_TABLE_NAME . ' ' .
885
               "WHERE share_key_id = '{$id}'";
886
        $rsShareKey = mysql_query($sql);
887
        if ($rsShareKey) {
888
            $row = mysql_fetch_object($rsShareKey);
889
            if ($row && (intval($row->resource_link_pk) === $shareKey->resourceLinkId)) {
890
                $shareKey->autoApprove = (intval($row->auto_approve) === 1);
891
                $shareKey->expires = strtotime($row->expires);
892
                $ok = true;
893
            }
894
        }
895
 
896
        return $ok;
897
 
898
    }
899
 
900
/**
901
 * Save resource link share key object.
902
 *
903
 * @param ResourceLinkShareKey $shareKey Resource link share key object
904
 *
905
 * @return boolean True if the resource link share key object was successfully saved
906
 */
907
    public function saveResourceLinkShareKey($shareKey)
908
    {
909
 
910
        if ($shareKey->autoApprove) {
911
            $approve = 1;
912
        } else {
913
            $approve = 0;
914
        }
915
        $expires = date("{$this->dateFormat} {$this->timeFormat}", $shareKey->expires);
916
        $sql = sprintf("INSERT INTO {$this->dbTableNamePrefix}" . DataConnector::RESOURCE_LINK_SHARE_KEY_TABLE_NAME . ' ' .
917
                       '(share_key_id, resource_link_pk, auto_approve, expires) ' .
918
                       "VALUES (%s, %d, {$approve}, '{$expires}')",
919
                       DataConnector::quoted($shareKey->getId()), $shareKey->resourceLinkId);
920
        $ok = mysql_query($sql);
921
 
922
        return $ok;
923
 
924
    }
925
 
926
/**
927
 * Delete resource link share key object.
928
 *
929
 * @param ResourceLinkShareKey $shareKey Resource link share key object
930
 *
931
 * @return boolean True if the resource link share key object was successfully deleted
932
 */
933
    public function deleteResourceLinkShareKey($shareKey)
934
    {
935
 
936
        $sql = "DELETE FROM {$this->dbTableNamePrefix}" . DataConnector::RESOURCE_LINK_SHARE_KEY_TABLE_NAME . " WHERE share_key_id = '{$shareKey->getId()}'";
937
 
938
        $ok = mysql_query($sql);
939
 
940
        if ($ok) {
941
            $shareKey->initialize();
942
        }
943
 
944
        return $ok;
945
 
946
    }
947
 
948
 
949
###
950
###  User methods
951
###
952
 
953
/**
954
 * Load user object.
955
 *
956
 * @param User $user User object
957
 *
958
 * @return boolean True if the user object was successfully loaded
959
 */
960
    public function loadUser($user)
961
    {
962
 
963
        $ok = false;
964
        if (!empty($user->getRecordId())) {
965
            $sql = sprintf('SELECT user_pk, resource_link_pk, lti_user_id, lti_result_sourcedid, created, updated ' .
966
                           "FROM {$this->dbTableNamePrefix}" . DataConnector::USER_RESULT_TABLE_NAME . ' ' .
967
                           'WHERE (user_pk = %d)',
968
            $user->getRecordId());
969
        } else {
970
            $sql = sprintf('SELECT user_pk, resource_link_pk, lti_user_id, lti_result_sourcedid, created, updated ' .
971
                           "FROM {$this->dbTableNamePrefix}" . DataConnector::USER_RESULT_TABLE_NAME . ' ' .
972
                           'WHERE (resource_link_pk = %d) AND (lti_user_id = %s)',
973
                           $user->getResourceLink()->getRecordId(),
974
                           DataConnector::quoted($user->getId(ToolProvider\ToolProvider::ID_SCOPE_ID_ONLY)));
975
        }
976
        $rsUser = mysql_query($sql);
977
        if ($rsUser) {
978
            $row = mysql_fetch_object($rsUser);
979
            if ($row) {
980
                $user->setRecordId(intval($row->user_pk));
981
                $user->setResourceLinkId(intval($row->resource_link_pk));
982
                $user->ltiUserId = $row->lti_user_id;
983
                $user->ltiResultSourcedId = $row->lti_result_sourcedid;
984
                $user->created = strtotime($row->created);
985
                $user->updated = strtotime($row->updated);
986
                $ok = true;
987
            }
988
        }
989
 
990
        return $ok;
991
 
992
    }
993
 
994
/**
995
 * Save user object.
996
 *
997
 * @param User $user User object
998
 *
999
 * @return boolean True if the user object was successfully saved
1000
 */
1001
    public function saveUser($user)
1002
    {
1003
 
1004
        $time = time();
1005
        $now = date("{$this->dateFormat} {$this->timeFormat}", $time);
1006
        if (is_null($user->created)) {
1007
            $sql = sprintf("INSERT INTO {$this->dbTableNamePrefix}" . DataConnector::USER_RESULT_TABLE_NAME . ' (resource_link_pk, ' .
1008
                           'lti_user_id, lti_result_sourcedid, created, updated) ' .
1009
                           'VALUES (%d, %s, %s, %s, %s)',
1010
                           $user->getResourceLink()->getRecordId(),
1011
                           DataConnector::quoted($user->getId(ToolProvider\ToolProvider::ID_SCOPE_ID_ONLY)), DataConnector::quoted($user->ltiResultSourcedId),
1012
                           DataConnector::quoted($now), DataConnector::quoted($now));
1013
        } else {
1014
            $sql = sprintf("UPDATE {$this->dbTableNamePrefix}" . DataConnector::USER_RESULT_TABLE_NAME . ' ' .
1015
                           'SET lti_result_sourcedid = %s, updated = %s ' .
1016
                           'WHERE (user_pk = %d)',
1017
                           DataConnector::quoted($user->ltiResultSourcedId),
1018
                           DataConnector::quoted($now),
1019
                           $user->getRecordId());
1020
        }
1021
        $ok = mysql_query($sql);
1022
        if ($ok) {
1023
            if (is_null($user->created)) {
1024
                $user->setRecordId(mysql_insert_id());
1025
                $user->created = $time;
1026
            }
1027
            $user->updated = $time;
1028
        }
1029
 
1030
        return $ok;
1031
 
1032
    }
1033
 
1034
/**
1035
 * Delete user object.
1036
 *
1037
 * @param User $user User object
1038
 *
1039
 * @return boolean True if the user object was successfully deleted
1040
 */
1041
    public function deleteUser($user)
1042
    {
1043
 
1044
        $sql = sprintf("DELETE FROM {$this->dbTableNamePrefix}" . DataConnector::USER_RESULT_TABLE_NAME . ' ' .
1045
                       'WHERE (user_pk = %d)',
1046
                       $user->getRecordId());
1047
        $ok = mysql_query($sql);
1048
 
1049
        if ($ok) {
1050
            $user->initialize();
1051
        }
1052
 
1053
        return $ok;
1054
 
1055
    }
1056
 
1057
}