Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.2.x will end 22 April 2024 (12 months).
  • Bug fixes for security issues in 4.2.x will end 7 October 2024 (18 months).
  • PHP version: minimum PHP 8.0.0 Note: minimum PHP version has increased since Moodle 4.1. PHP 8.1.x is supported too.

Differences Between: [Versions 310 and 402] [Versions 311 and 402] [Versions 39 and 402] [Versions 400 and 402] [Versions 401 and 402]

   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  }