MDL-68800 mod_lti: create gbs only for restored activity
[moodle.git] / mod / lti / service / gradebookservices / backup / moodle2 / restore_ltiservice_gradebookservices_subplugin.class.php
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/>.
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  */
26 defined('MOODLE_INTERNAL') || die();
28 global $CFG;
29 require_once($CFG->dirroot.'/mod/lti/locallib.php');
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 {
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() {
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     }
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             $ltilinkid = $this->get_new_parentid('lti');
97         } else {
98             $ltilinkid = null;
99         }
100         $resourceid = null;
101         if (property_exists( $data, 'resourceid' )) {
102             $resourceid = $data->resourceid;
103         }
104         // If this has not been restored before.
105         if ($this->get_mappingid('gbsgradeitemrestored',  $data->id, 0) == 0) {
106             $newgbsid = $DB->insert_record('ltiservice_gradebookservices', (object) array(
107                     'gradeitemid' => 0,
108                     'courseid' => $courseid,
109                     'toolproxyid' => $newtoolproxyid,
110                     'ltilinkid' => $ltilinkid,
111                     'typeid' => $newtypeid,
112                     'baseurl' => $data->baseurl,
113                     'resourceid' => $resourceid,
114                     'tag' => $data->tag
115             ));
116             $this->set_mapping('gbsgradeitemoldid', $newgbsid, $data->gradeitemid);
117             $this->set_mapping('gbsgradeitemrestored', $data->id, $data->id);
118         }
119     }
121     /**
122      * If the toolproxy is not in the mapping (or it is 0)
123      * we try to find the toolproxyid.
124      * If none is found, then we set it to 0.
125      *
126      * @param mixed $data
127      * @return integer $newtoolproxyid
128      */
129     private function find_proxy_id($data) {
130         global $DB;
131         $newtoolproxyid = 0;
132         $oldtoolproxyguid = $data->guid;
133         $oldtoolproxyvendor = $data->vendorcode;
135         $dbtoolproxyjsonparams = array('guid' => $oldtoolproxyguid, 'vendorcode' => $oldtoolproxyvendor);
136         $dbtoolproxy = $DB->get_field('lti_tool_proxies', 'id', $dbtoolproxyjsonparams, IGNORE_MISSING);
137         if ($dbtoolproxy) {
138             $newtoolproxyid = $dbtoolproxy;
139         }
140         return $newtoolproxyid;
141     }
143     /**
144      * If the typeid is not in the mapping or it is 0, (it should be most of the times)
145      * we will try to find the better typeid that matches with the lineitem.
146      * If none is found, then we set it to 0.
147      *
148      * @param stdClass $data
149      * @param int $courseid
150      * @return int The item type id
151      */
152     private function find_typeid($data, $courseid) {
153         global $DB;
154         $newtypeid = 0;
155         $oldtypeid = $data->typeid;
157         // 1. Find a type with the same id in the same course.
158         $dbtypeidparameter = array('id' => $oldtypeid, 'course' => $courseid, 'baseurl' => $data->baseurl);
159         $dbtype = $DB->get_field_select('lti_types', 'id', "id=:id
160                 AND course=:course AND ".$DB->sql_compare_text('baseurl')."=:baseurl",
161                 $dbtypeidparameter);
162         if ($dbtype) {
163             $newtypeid = $dbtype;
164         } else {
165             // 2. Find a site type for all the courses (course == 1), but with the same id.
166             $dbtypeidparameter = array('id' => $oldtypeid, 'baseurl' => $data->baseurl);
167             $dbtype = $DB->get_field_select('lti_types', 'id', "id=:id
168                     AND course=1 AND ".$DB->sql_compare_text('baseurl')."=:baseurl",
169                     $dbtypeidparameter);
170             if ($dbtype) {
171                 $newtypeid = $dbtype;
172             } else {
173                 // 3. Find a type with the same baseurl in the actual site.
174                 $dbtypeidparameter = array('course' => $courseid, 'baseurl' => $data->baseurl);
175                 $dbtype = $DB->get_field_select('lti_types', 'id', "course=:course
176                         AND ".$DB->sql_compare_text('baseurl')."=:baseurl",
177                         $dbtypeidparameter);
178                 if ($dbtype) {
179                     $newtypeid = $dbtype;
180                 } else {
181                     // 4. Find a site type for all the courses (course == 1) with the same baseurl.
182                     $dbtypeidparameter = array('course' => 1, 'baseurl' => $data->baseurl);
183                     $dbtype = $DB->get_field_select('lti_types', 'id', "course=1
184                             AND ".$DB->sql_compare_text('baseurl')."=:baseurl",
185                             $dbtypeidparameter);
186                     if ($dbtype) {
187                         $newtypeid = $dbtype;
188                     }
189                 }
190             }
191         }
192         return $newtypeid;
193     }
195     /**
196      * We call the after_restore_lti to update the grade_items id's that we didn't know in the moment of creating
197      * the gradebookservices rows.
198      */
199     protected function after_restore_lti() {
200         global $DB;
201         $activitytask = $this->task;
202         $courseid = $activitytask->get_courseid();
203         $gbstoupdate = $DB->get_records('ltiservice_gradebookservices', array('gradeitemid' => 0, 'courseid' => $courseid));
204         foreach ($gbstoupdate as $gbs) {
205             $oldgradeitemid = $this->get_mappingid('gbsgradeitemoldid', $gbs->id, 0);
206             $newgradeitemid = $this->get_mappingid('grade_item', $oldgradeitemid, 0);
207             if ($newgradeitemid > 0) {
208                 $gbs->gradeitemid = $newgradeitemid;
209                 if (!isset($gbs->resourceid)) {
210                     // Before 3.9 resourceid was stored in grade_item->idnumber.
211                     $gbs->resourceid = $DB->get_field_select('grade_items', 'idnumber', "id=:id", ['id' => $newgradeitemid]);
212                 }
213                 $DB->update_record('ltiservice_gradebookservices', $gbs);
214             }
215         }
216         // Pre 3.9 backups did not include a gradebookservices record. Adding one here if missing for the restored instance.
217         $gi = $DB->get_record('grade_items', array('itemtype' => 'mod', 'itemmodule' => 'lti', 'courseid' => $courseid,
218             'iteminstance' => $this->task->get_activityid()));
219         if ($gi) {
220             $gbs = $DB->get_records('ltiservice_gradebookservices', ['gradeitemid' => $gi->id]);
221             if (empty($gbs)) {
222                 // The currently restored LTI link has a grade item but no gbs, so let's create a gbs entry.
223                 if ($instance = $DB->get_record('lti', array('id' => $gi->iteminstance))) {
224                     if ($tool = lti_get_instance_type($instance)) {
225                         $DB->insert_record('ltiservice_gradebookservices', (object) array(
226                             'gradeitemid' => $gi->id,
227                             'courseid' => $courseid,
228                             'toolproxyid' => $tool->toolproxyid,
229                             'ltilinkid' => $gi->iteminstance,
230                             'typeid' => $tool->id,
231                             'baseurl' => $tool->baseurl,
232                             'resourceid' => $gi->idnumber
233                         ));
234                     }
235                 }
236             }
237         }
238     }