Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.

Differences Between: [Versions 401 and 402] [Versions 401 and 403]

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