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\ConsumerNonce;
   6  use IMSGlobal\LTI\ToolProvider\Context;
   7  use IMSGlobal\LTI\ToolProvider\ResourceLink;
   8  use IMSGlobal\LTI\ToolProvider\ResourceLinkShareKey;
   9  use IMSGlobal\LTI\ToolProvider\ToolConsumer;
  10  use IMSGlobal\LTI\ToolProvider\ToolProxy;
  11  use IMSGlobal\LTI\ToolProvider\User;
  12  use PDO;
  13  
  14  /**
  15   * Class to provide a connection to a persistent store for LTI objects
  16   *
  17   * This class assumes no data persistence - it should be extended for specific database connections.
  18   *
  19   * @author  Stephen P Vickers <svickers@imsglobal.org>
  20   * @copyright  IMS Global Learning Consortium Inc
  21   * @date  2016
  22   * @version 3.0.0
  23   * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
  24   */
  25  #[\AllowDynamicProperties]
  26  class DataConnector
  27  {
  28  
  29  /**
  30   * Default name for database table used to store tool consumers.
  31   */
  32      const CONSUMER_TABLE_NAME = 'lti2_consumer';
  33  /**
  34   * Default name for database table used to store pending tool proxies.
  35   */
  36      const TOOL_PROXY_TABLE_NAME = 'lti2_tool_proxy';
  37  /**
  38   * Default name for database table used to store contexts.
  39   */
  40      const CONTEXT_TABLE_NAME = 'lti2_context';
  41  /**
  42   * Default name for database table used to store resource links.
  43   */
  44      const RESOURCE_LINK_TABLE_NAME = 'lti2_resource_link';
  45  /**
  46   * Default name for database table used to store users.
  47   */
  48      const USER_RESULT_TABLE_NAME = 'lti2_user_result';
  49  /**
  50   * Default name for database table used to store resource link share keys.
  51   */
  52      const RESOURCE_LINK_SHARE_KEY_TABLE_NAME = 'lti2_share_key';
  53  /**
  54   * Default name for database table used to store nonce values.
  55   */
  56      const NONCE_TABLE_NAME = 'lti2_nonce';
  57  
  58  /**
  59   * Database object.
  60   *
  61   * @var object $db
  62   */
  63      protected $db = null;
  64  /**
  65   * Prefix for database table names.
  66   *
  67   * @var string $dbTableNamePrefix
  68   */
  69      protected $dbTableNamePrefix = '';
  70  /**
  71   * SQL date format (default = 'Y-m-d')
  72   *
  73   * @var string $dateFormat
  74   */
  75      protected $dateFormat = 'Y-m-d';
  76  /**
  77   * SQL time format (default = 'H:i:s')
  78   *
  79   * @var string $timeFormat
  80   */
  81      protected $timeFormat = 'H:i:s';
  82  
  83  /**
  84   * Class constructor
  85   *
  86   * @param object $db                 Database connection object
  87   * @param string $dbTableNamePrefix  Prefix for database table names (optional, default is none)
  88   */
  89      public function __construct($db, $dbTableNamePrefix = '')
  90      {
  91  
  92          $this->db = $db;
  93          $this->dbTableNamePrefix = $dbTableNamePrefix;
  94  
  95      }
  96  
  97  ###
  98  ###  ToolConsumer methods
  99  ###
 100  
 101  /**
 102   * Load tool consumer object.
 103   *
 104   * @param ToolConsumer $consumer ToolConsumer object
 105   *
 106   * @return boolean True if the tool consumer object was successfully loaded
 107   */
 108      public function loadToolConsumer($consumer)
 109      {
 110  
 111          $consumer->secret = 'secret';
 112          $consumer->enabled = true;
 113          $now = time();
 114          $consumer->created = $now;
 115          $consumer->updated = $now;
 116  
 117          return true;
 118  
 119      }
 120  
 121  /**
 122   * Save tool consumer object.
 123   *
 124   * @param ToolConsumer $consumer Consumer object
 125   *
 126   * @return boolean True if the tool consumer object was successfully saved
 127   */
 128      public function saveToolConsumer($consumer)
 129      {
 130  
 131          $consumer->updated = time();
 132  
 133          return true;
 134  
 135      }
 136  
 137  /**
 138   * Delete tool consumer object.
 139   *
 140   * @param ToolConsumer $consumer Consumer object
 141   *
 142   * @return boolean True if the tool consumer object was successfully deleted
 143   */
 144      public function deleteToolConsumer($consumer)
 145      {
 146  
 147          $consumer->initialize();
 148  
 149          return true;
 150  
 151      }
 152  
 153  /**
 154   * Load tool consumer objects.
 155   *
 156   * @return array Array of all defined ToolConsumer objects
 157   */
 158      public function getToolConsumers()
 159      {
 160  
 161          return array();
 162  
 163      }
 164  
 165  
 166  ###
 167  ###  ToolProxy methods
 168  ###
 169  
 170  /**
 171   * Load tool proxy object.
 172   *
 173   * @param ToolProxy $toolProxy ToolProxy object
 174   *
 175   * @return boolean True if the tool proxy object was successfully loaded
 176   */
 177      public function loadToolProxy($toolProxy)
 178      {
 179  
 180          $now = time();
 181          $toolProxy->created = $now;
 182          $toolProxy->updated = $now;
 183  
 184          return true;
 185  
 186      }
 187  
 188  /**
 189   * Save tool proxy object.
 190   *
 191   * @param ToolProxy $toolProxy ToolProxy object
 192   *
 193   * @return boolean True if the tool proxy object was successfully saved
 194   */
 195      public function saveToolProxy($toolProxy)
 196      {
 197  
 198          $toolProxy->updated = time();
 199  
 200          return true;
 201  
 202      }
 203  
 204  /**
 205   * Delete tool proxy object.
 206   *
 207   * @param ToolProxy $toolProxy ToolProxy object
 208   *
 209   * @return boolean True if the tool proxy object was successfully deleted
 210   */
 211      public function deleteToolProxy($toolProxy)
 212      {
 213  
 214          $toolProxy->initialize();
 215  
 216          return true;
 217  
 218      }
 219  
 220  ###
 221  ###  Context methods
 222  ###
 223  
 224  /**
 225   * Load context object.
 226   *
 227   * @param Context $context Context object
 228   *
 229   * @return boolean True if the context object was successfully loaded
 230   */
 231      public function loadContext($context)
 232      {
 233  
 234          $now = time();
 235          $context->created = $now;
 236          $context->updated = $now;
 237  
 238          return true;
 239  
 240      }
 241  
 242  /**
 243   * Save context object.
 244   *
 245   * @param Context $context Context object
 246   *
 247   * @return boolean True if the context object was successfully saved
 248   */
 249      public function saveContext($context)
 250      {
 251  
 252          $context->updated = time();
 253  
 254          return true;
 255  
 256      }
 257  
 258  /**
 259   * Delete context object.
 260   *
 261   * @param Context $context Context object
 262   *
 263   * @return boolean True if the Context object was successfully deleted
 264   */
 265      public function deleteContext($context)
 266      {
 267  
 268          $context->initialize();
 269  
 270          return true;
 271  
 272      }
 273  
 274  ###
 275  ###  ResourceLink methods
 276  ###
 277  
 278  /**
 279   * Load resource link object.
 280   *
 281   * @param ResourceLink $resourceLink Resource_Link object
 282   *
 283   * @return boolean True if the resource link object was successfully loaded
 284   */
 285      public function loadResourceLink($resourceLink)
 286      {
 287  
 288          $now = time();
 289          $resourceLink->created = $now;
 290          $resourceLink->updated = $now;
 291  
 292          return true;
 293  
 294      }
 295  
 296  /**
 297   * Save resource link object.
 298   *
 299   * @param ResourceLink $resourceLink Resource_Link object
 300   *
 301   * @return boolean True if the resource link object was successfully saved
 302   */
 303      public function saveResourceLink($resourceLink)
 304      {
 305  
 306          $resourceLink->updated = time();
 307  
 308          return true;
 309  
 310      }
 311  
 312  /**
 313   * Delete resource link object.
 314   *
 315   * @param ResourceLink $resourceLink Resource_Link object
 316   *
 317   * @return boolean True if the resource link object was successfully deleted
 318   */
 319      public function deleteResourceLink($resourceLink)
 320      {
 321  
 322          $resourceLink->initialize();
 323  
 324          return true;
 325  
 326      }
 327  
 328  /**
 329   * Get array of user objects.
 330   *
 331   * Obtain an array of User objects for users with a result sourcedId.  The array may include users from other
 332   * resource links which are sharing this resource link.  It may also be optionally indexed by the user ID of a specified scope.
 333   *
 334   * @param ResourceLink $resourceLink      Resource link object
 335   * @param boolean     $localOnly True if only users within the resource link are to be returned (excluding users sharing this resource link)
 336   * @param int         $idScope     Scope value to use for user IDs
 337   *
 338   * @return array Array of User objects
 339   */
 340      public function getUserResultSourcedIDsResourceLink($resourceLink, $localOnly, $idScope)
 341      {
 342  
 343          return array();
 344  
 345      }
 346  
 347  /**
 348   * Get array of shares defined for this resource link.
 349   *
 350   * @param ResourceLink $resourceLink Resource_Link object
 351   *
 352   * @return array Array of ResourceLinkShare objects
 353   */
 354      public function getSharesResourceLink($resourceLink)
 355      {
 356  
 357          return array();
 358  
 359      }
 360  
 361  ###
 362  ###  ConsumerNonce methods
 363  ###
 364  
 365  /**
 366   * Load nonce object.
 367   *
 368   * @param ConsumerNonce $nonce Nonce object
 369   *
 370   * @return boolean True if the nonce object was successfully loaded
 371   */
 372      public function loadConsumerNonce($nonce)
 373      {
 374          return false;  // assume the nonce does not already exist
 375  
 376      }
 377  
 378  /**
 379   * Save nonce object.
 380   *
 381   * @param ConsumerNonce $nonce Nonce object
 382   *
 383   * @return boolean True if the nonce object was successfully saved
 384   */
 385      public function saveConsumerNonce($nonce)
 386      {
 387  
 388          return true;
 389  
 390      }
 391  
 392  ###
 393  ###  ResourceLinkShareKey methods
 394  ###
 395  
 396  /**
 397   * Load resource link share key object.
 398   *
 399   * @param ResourceLinkShareKey $shareKey Resource_Link share key object
 400   *
 401   * @return boolean True if the resource link share key object was successfully loaded
 402   */
 403      public function loadResourceLinkShareKey($shareKey)
 404      {
 405  
 406          return true;
 407  
 408      }
 409  
 410  /**
 411   * Save resource link share key object.
 412   *
 413   * @param ResourceLinkShareKey $shareKey Resource link share key object
 414   *
 415   * @return boolean True if the resource link share key object was successfully saved
 416   */
 417      public function saveResourceLinkShareKey($shareKey)
 418      {
 419  
 420          return true;
 421  
 422      }
 423  
 424  /**
 425   * Delete resource link share key object.
 426   *
 427   * @param ResourceLinkShareKey $shareKey Resource link share key object
 428   *
 429   * @return boolean True if the resource link share key object was successfully deleted
 430   */
 431      public function deleteResourceLinkShareKey($shareKey)
 432      {
 433  
 434          return true;
 435  
 436      }
 437  
 438  ###
 439  ###  User methods
 440  ###
 441  
 442  /**
 443   * Load user object.
 444   *
 445   * @param User $user User object
 446   *
 447   * @return boolean True if the user object was successfully loaded
 448   */
 449      public function loadUser($user)
 450      {
 451  
 452          $now = time();
 453          $user->created = $now;
 454          $user->updated = $now;
 455  
 456          return true;
 457  
 458      }
 459  
 460  /**
 461   * Save user object.
 462   *
 463   * @param User $user User object
 464   *
 465   * @return boolean True if the user object was successfully saved
 466   */
 467      public function saveUser($user)
 468      {
 469  
 470          $user->updated = time();
 471  
 472          return true;
 473  
 474      }
 475  
 476  /**
 477   * Delete user object.
 478   *
 479   * @param User $user User object
 480   *
 481   * @return boolean True if the user object was successfully deleted
 482   */
 483      public function deleteUser($user)
 484      {
 485  
 486          $user->initialize();
 487  
 488          return true;
 489  
 490      }
 491  
 492  ###
 493  ###  Other methods
 494  ###
 495  
 496  /**
 497   * Return a hash of a consumer key for values longer than 255 characters.
 498   *
 499   * @param string $key
 500   * @return string
 501   */
 502      protected static function getConsumerKey($key)
 503      {
 504  
 505          $len = strlen($key);
 506          if ($len > 255) {
 507              $key = 'sha512:' . hash('sha512', $key);
 508          }
 509  
 510          return $key;
 511  
 512      }
 513  
 514  /**
 515   * Create data connector object.
 516   *
 517   * A data connector provides access to persistent storage for the different objects.
 518   *
 519   * Names of tables may be given a prefix to allow multiple versions to share the same schema.  A separate sub-class is defined for
 520   * each different database connection - the class to use is determined by inspecting the database object passed, but this can be overridden
 521   * (for example, to use a bespoke connector) by specifying a type.  If no database is passed then this class is used which acts as a dummy
 522   * connector with no persistence.
 523   *
 524   * @param string  $dbTableNamePrefix  Prefix for database table names (optional, default is none)
 525   * @param object  $db                 A database connection object or string (optional, default is no persistence)
 526   * @param string  $type               The type of data connector (optional, default is based on $db parameter)
 527   *
 528   * @return DataConnector Data connector object
 529   */
 530      public static function getDataConnector($dbTableNamePrefix = '', $db = null, $type = '')
 531      {
 532  
 533          if (is_null($dbTableNamePrefix)) {
 534              $dbTableNamePrefix = '';
 535          }
 536          if (!is_null($db) && empty($type)) {
 537              if (is_object($db)) {
 538                  $type = get_class($db);
 539              }
 540          }
 541          $type = strtolower($type);
 542          if (($type === 'pdo') && ($db->getAttribute(PDO::ATTR_DRIVER_NAME) === 'sqlite')) {
 543              $type .= '_sqlite';
 544          }
 545          if (!empty($type)) {
 546              $type ="DataConnector_{$type}";
 547          } else {
 548              $type ='DataConnector';
 549          }
 550          $type = "\\IMSGlobal\\LTI\\ToolProvider\\DataConnector\\{$type}";
 551          $dataConnector = new $type($db, $dbTableNamePrefix);
 552  
 553          return $dataConnector;
 554  
 555      }
 556  
 557  /**
 558   * Generate a random string.
 559   *
 560   * The generated string will only comprise letters (upper- and lower-case) and digits.
 561   *
 562   * @param int $length Length of string to be generated (optional, default is 8 characters)
 563   *
 564   * @return string Random string
 565   */
 566      static function getRandomString($length = 8)
 567      {
 568  
 569          $chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
 570  
 571          $value = '';
 572          $charsLength = strlen($chars) - 1;
 573  
 574          for ($i = 1 ; $i <= $length; $i++) {
 575              $value .= $chars[rand(0, $charsLength)];
 576          }
 577  
 578          return $value;
 579  
 580      }
 581  
 582  /**
 583   * Quote a string for use in a database query.
 584   *
 585   * Any single quotes in the value passed will be replaced with two single quotes.  If a null value is passed, a string
 586   * of 'null' is returned (which will never be enclosed in quotes irrespective of the value of the $addQuotes parameter.
 587   *
 588   * @param string $value Value to be quoted
 589   * @param bool $addQuotes If true the returned string will be enclosed in single quotes (optional, default is true)
 590   * @return string The quoted string.
 591   */
 592      static function quoted($value, $addQuotes = true)
 593      {
 594  
 595          if (is_null($value)) {
 596              $value = 'null';
 597          } else {
 598              $value = str_replace('\'', '\'\'', $value);
 599              if ($addQuotes) {
 600                  $value = "'{$value}'";
 601              }
 602          }
 603  
 604          return $value;
 605  
 606      }
 607  
 608  }