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 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 400 and 401]

   1  <?php
   2  // This file is part of Moodle - http://moodle.org/
   3  //
   4  // Moodle is free software: you can redistribute it and/or modify
   5  // it under the terms of the GNU General Public License as published by
   6  // the Free Software Foundation, either version 3 of the License, or
   7  // (at your option) any later version.
   8  //
   9  // Moodle is distributed in the hope that it will be useful,
  10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12  // GNU General Public License for more details.
  13  //
  14  // You should have received a copy of the GNU General Public License
  15  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  16  
  17  /**
  18   * This file contains the class for restore of this gradebookservices plugin
  19   *
  20   * @package    ltiservice_gradebookservices
  21   * @copyright  2017 Cengage Learning http://www.cengage.com
  22   * @author     Dirk Singels, Diego del Blanco, Claude Vervoort
  23   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  24   */
  25  
  26  defined('MOODLE_INTERNAL') || die();
  27  
  28  global $CFG;
  29  require_once($CFG->dirroot.'/mod/lti/locallib.php');
  30  
  31  /**
  32   * Restore subplugin class.
  33   *
  34   * Provides the necessary information
  35   * needed to restore the lineitems related with the lti activity (coupled),
  36   * and all the uncoupled ones from the course.
  37   *
  38   * @package    ltiservice_gradebookservices
  39   * @copyright  2017 Cengage Learning http://www.cengage.com
  40   * @author     Dirk Singels, Diego del Blanco, Claude Vervoort
  41   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  42   */
  43  class restore_ltiservice_gradebookservices_subplugin extends restore_subplugin {
  44  
  45      /**
  46       * Returns the subplugin structure to attach to the XML element.
  47       *
  48       * @return restore_path_element[] array of elements to be processed on restore.
  49       */
  50      protected function define_lti_subplugin_structure() {
  51  
  52          $paths = array();
  53          $elename = $this->get_namefor('lineitem');
  54          $elepath = $this->get_pathfor('/lineitems/lineitem');
  55          $paths[] = new restore_path_element($elename, $elepath);
  56          return $paths;
  57      }
  58  
  59      /**
  60       * Processes one lineitem
  61       *
  62       * @param mixed $data
  63       * @return void
  64       */
  65      public function process_ltiservice_gradebookservices_lineitem($data) {
  66          global $DB;
  67          $data = (object)$data;
  68          // The coupled lineitems are restored as any other grade item
  69          // so we will only create the entry in the ltiservice_gradebookservices table.
  70          // We will try to find a valid toolproxy in the system.
  71          // If it has been found before... we use it.
  72          /* cache parent property to account for missing PHPDoc type specification */
  73          /** @var backup_activity_task $activitytask */
  74          $activitytask = $this->task;
  75          $courseid = $activitytask->get_courseid();
  76          if ($data->typeid != null) {
  77              if ($ltitypeid = $this->get_mappingid('ltitype', $data->typeid)) {
  78                  $newtypeid = $ltitypeid;
  79              } else { // If not, then we will call our own function to find it.
  80                  $newtypeid = $this->find_typeid($data, $courseid);
  81              }
  82          } else {
  83              $newtypeid = null;
  84          }
  85          if ($data->toolproxyid != null) {
  86              $ltitoolproxy = $this->get_mappingid('ltitoolproxy', $data->toolproxyid);
  87              if ($ltitoolproxy && $ltitoolproxy != 0) {
  88                  $newtoolproxyid = $ltitoolproxy;
  89              } else { // If not, then we will call our own function to find it.
  90                  $newtoolproxyid = $this->find_proxy_id($data);
  91              }
  92          } else {
  93              $newtoolproxyid = null;
  94          }
  95          if ($data->ltilinkid != null) {
  96              if ($data->ltilinkid != $this->get_old_parentid('lti')) {
  97                  // This is a linked item, but not for the current lti link, so skip it.
  98                  return;
  99              }
 100              $ltilinkid = $this->get_new_parentid('lti');
 101          } else {
 102              $ltilinkid = null;
 103          }
 104          $resourceid = null;
 105          if (property_exists( $data, 'resourceid' )) {
 106              $resourceid = $data->resourceid;
 107          }
 108          // If this has not been restored before.
 109          if ($this->get_mappingid('gbsgradeitemrestored',  $data->id, 0) == 0) {
 110              $newgbsid = $DB->insert_record('ltiservice_gradebookservices', (object) array(
 111                      'gradeitemid' => 0,
 112                      'courseid' => $courseid,
 113                      'toolproxyid' => $newtoolproxyid,
 114                      'ltilinkid' => $ltilinkid,
 115                      'typeid' => $newtypeid,
 116                      'baseurl' => $data->baseurl,
 117                      'resourceid' => $resourceid,
 118                      'tag' => $data->tag,
 119                      'subreviewparams' => $data->subreviewparams ?? '',
 120                      'subreviewurl' => $data->subreviewurl ?? ''
 121              ));
 122              $this->set_mapping('gbsgradeitemoldid', $newgbsid, $data->gradeitemid);
 123              $this->set_mapping('gbsgradeitemrestored', $data->id, $data->id);
 124          }
 125      }
 126  
 127      /**
 128       * If the toolproxy is not in the mapping (or it is 0)
 129       * we try to find the toolproxyid.
 130       * If none is found, then we set it to 0.
 131       *
 132       * @param mixed $data
 133       * @return integer $newtoolproxyid
 134       */
 135      private function find_proxy_id($data) {
 136          global $DB;
 137          $newtoolproxyid = 0;
 138          $oldtoolproxyguid = $data->guid;
 139          $oldtoolproxyvendor = $data->vendorcode;
 140  
 141          $dbtoolproxyjsonparams = array('guid' => $oldtoolproxyguid, 'vendorcode' => $oldtoolproxyvendor);
 142          $dbtoolproxy = $DB->get_field('lti_tool_proxies', 'id', $dbtoolproxyjsonparams, IGNORE_MISSING);
 143          if ($dbtoolproxy) {
 144              $newtoolproxyid = $dbtoolproxy;
 145          }
 146          return $newtoolproxyid;
 147      }
 148  
 149      /**
 150       * If the typeid is not in the mapping or it is 0, (it should be most of the times)
 151       * we will try to find the better typeid that matches with the lineitem.
 152       * If none is found, then we set it to 0.
 153       *
 154       * @param stdClass $data
 155       * @param int $courseid
 156       * @return int The item type id
 157       */
 158      private function find_typeid($data, $courseid) {
 159          global $DB;
 160          $newtypeid = 0;
 161          $oldtypeid = $data->typeid;
 162  
 163          // 1. Find a type with the same id in the same course.
 164          $dbtypeidparameter = array('id' => $oldtypeid, 'course' => $courseid, 'baseurl' => $data->baseurl);
 165          $dbtype = $DB->get_field_select('lti_types', 'id', "id=:id
 166                  AND course=:course AND ".$DB->sql_compare_text('baseurl')."=:baseurl",
 167                  $dbtypeidparameter);
 168          if ($dbtype) {
 169              $newtypeid = $dbtype;
 170          } else {
 171              // 2. Find a site type for all the courses (course == 1), but with the same id.
 172              $dbtypeidparameter = array('id' => $oldtypeid, 'baseurl' => $data->baseurl);
 173              $dbtype = $DB->get_field_select('lti_types', 'id', "id=:id
 174                      AND course=1 AND ".$DB->sql_compare_text('baseurl')."=:baseurl",
 175                      $dbtypeidparameter);
 176              if ($dbtype) {
 177                  $newtypeid = $dbtype;
 178              } else {
 179                  // 3. Find a type with the same baseurl in the actual site.
 180                  $dbtypeidparameter = array('course' => $courseid, 'baseurl' => $data->baseurl);
 181                  $dbtype = $DB->get_field_select('lti_types', 'id', "course=:course
 182                          AND ".$DB->sql_compare_text('baseurl')."=:baseurl",
 183                          $dbtypeidparameter);
 184                  if ($dbtype) {
 185                      $newtypeid = $dbtype;
 186                  } else {
 187                      // 4. Find a site type for all the courses (course == 1) with the same baseurl.
 188                      $dbtypeidparameter = array('course' => 1, 'baseurl' => $data->baseurl);
 189                      $dbtype = $DB->get_field_select('lti_types', 'id', "course=1
 190                              AND ".$DB->sql_compare_text('baseurl')."=:baseurl",
 191                              $dbtypeidparameter);
 192                      if ($dbtype) {
 193                          $newtypeid = $dbtype;
 194                      }
 195                  }
 196              }
 197          }
 198          return $newtypeid;
 199      }
 200  
 201      /**
 202       * We call the after_restore_lti to update the grade_items id's that we didn't know in the moment of creating
 203       * the gradebookservices rows.
 204       */
 205      protected function after_restore_lti() {
 206          global $DB;
 207          $activitytask = $this->task;
 208          $courseid = $activitytask->get_courseid();
 209          $gbstoupdate = $DB->get_records('ltiservice_gradebookservices', array('gradeitemid' => 0, 'courseid' => $courseid));
 210          foreach ($gbstoupdate as $gbs) {
 211              $oldgradeitemid = $this->get_mappingid('gbsgradeitemoldid', $gbs->id, 0);
 212              $newgradeitemid = $this->get_mappingid('grade_item', $oldgradeitemid, 0);
 213              if ($newgradeitemid > 0) {
 214                  $gbs->gradeitemid = $newgradeitemid;
 215                  if (!isset($gbs->resourceid)) {
 216                      // Before 3.9 resourceid was stored in grade_item->idnumber.
 217                      $gbs->resourceid = $DB->get_field_select('grade_items', 'idnumber', "id=:id", ['id' => $newgradeitemid]);
 218                  }
 219                  $DB->update_record('ltiservice_gradebookservices', $gbs);
 220              }
 221          }
 222          // Pre 3.9 backups did not include a gradebookservices record. Adding one here if missing for the restored instance.
 223          $gi = $DB->get_record('grade_items', array('itemtype' => 'mod', 'itemmodule' => 'lti', 'courseid' => $courseid,
 224              'iteminstance' => $this->task->get_activityid()));
 225          if ($gi) {
 226              $gbs = $DB->get_records('ltiservice_gradebookservices', ['gradeitemid' => $gi->id]);
 227              if (empty($gbs)) {
 228                  // The currently restored LTI link has a grade item but no gbs, so let's create a gbs entry.
 229                  if ($instance = $DB->get_record('lti', array('id' => $gi->iteminstance))) {
 230                      if ($tool = lti_get_instance_type($instance)) {
 231                          $DB->insert_record('ltiservice_gradebookservices', (object) array(
 232                              'gradeitemid' => $gi->id,
 233                              'courseid' => $courseid,
 234                              'toolproxyid' => $tool->toolproxyid,
 235                              'ltilinkid' => $gi->iteminstance,
 236                              'typeid' => $tool->id,
 237                              'baseurl' => $tool->baseurl,
 238                              'resourceid' => $gi->idnumber
 239                          ));
 240                      }
 241                  }
 242              }
 243          }
 244      }
 245  
 246  }