Differences Between: [Versions 310 and 403] [Versions 311 and 403] [Versions 39 and 403] [Versions 400 and 403] [Versions 401 and 403]
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 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body