See Release Notes
Long Term Support Release
Differences Between: [Versions 39 and 401] [Versions 39 and 402] [Versions 39 and 403]
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 a class definition for the LineItem resource 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 namespace ltiservice_gradebookservices\local\resources; 27 28 use ltiservice_gradebookservices\local\service\gradebookservices; 29 use mod_lti\local\ltiservice\resource_base; 30 31 defined('MOODLE_INTERNAL') || die(); 32 33 /** 34 * A resource implementing LineItem. 35 * 36 * @package ltiservice_gradebookservices 37 * @copyright 2017 Cengage Learning http://www.cengage.com 38 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 39 */ 40 class lineitem extends resource_base { 41 42 /** 43 * Class constructor. 44 * 45 * @param gradebookservices $service Service instance 46 */ 47 public function __construct($service) { 48 49 parent::__construct($service); 50 $this->id = 'LineItem.item'; 51 $this->template = '/{context_id}/lineitems/{item_id}/lineitem'; 52 $this->variables[] = 'LineItem.url'; 53 $this->formats[] = 'application/vnd.ims.lis.v2.lineitem+json'; 54 $this->methods[] = self::HTTP_GET; 55 $this->methods[] = self::HTTP_PUT; 56 $this->methods[] = self::HTTP_DELETE; 57 58 } 59 60 /** 61 * Execute the request for this resource. 62 * 63 * @param \mod_lti\local\ltiservice\response $response Response object for this request. 64 */ 65 public function execute($response) { 66 global $CFG, $DB; 67 68 $params = $this->parse_template(); 69 $contextid = $params['context_id']; 70 $itemid = $params['item_id']; 71 $isget = $response->get_request_method() === self::HTTP_GET; 72 // We will receive typeid when working with LTI 1.x, if not then we are in LTI 2. 73 $typeid = optional_param('type_id', null, PARAM_INT); 74 75 $scopes = array(gradebookservices::SCOPE_GRADEBOOKSERVICES_LINEITEM); 76 if ($response->get_request_method() === self::HTTP_GET) { 77 $scopes[] = gradebookservices::SCOPE_GRADEBOOKSERVICES_LINEITEM_READ; 78 } 79 80 try { 81 if (!$this->check_tool($typeid, $response->get_request_data(), $scopes)) { 82 throw new \Exception(null, 401); 83 } 84 $typeid = $this->get_service()->get_type()->id; 85 if (!($course = $DB->get_record('course', array('id' => $contextid), 'id', IGNORE_MISSING))) { 86 throw new \Exception("Not Found: Course {$contextid} doesn't exist", 404); 87 } 88 if (!$this->get_service()->is_allowed_in_context($typeid, $course->id)) { 89 throw new \Exception('Not allowed in context', 403); 90 } 91 if (!$DB->record_exists('grade_items', array('id' => $itemid))) { 92 throw new \Exception("Not Found: Grade item {$itemid} doesn't exist", 404); 93 } 94 $item = $this->get_service()->get_lineitem($contextid, $itemid, $typeid); 95 if ($item === false) { 96 throw new \Exception('Line item does not exist', 404); 97 } 98 require_once($CFG->libdir.'/gradelib.php'); 99 switch ($response->get_request_method()) { 100 case self::HTTP_GET: 101 $this->get_request($response, $item, $typeid); 102 break; 103 case self::HTTP_PUT: 104 $json = $this->process_put_request($response->get_request_data(), $item, $typeid); 105 $response->set_body($json); 106 $response->set_code(200); 107 break; 108 case self::HTTP_DELETE: 109 $this->process_delete_request($item); 110 $response->set_code(204); 111 break; 112 } 113 } catch (\Exception $e) { 114 $response->set_code($e->getCode()); 115 $response->set_reason($e->getMessage()); 116 } 117 } 118 119 /** 120 * Process a GET request. 121 * 122 * @param \mod_lti\local\ltiservice\response $response Response object for this request. 123 * @param object $item Grade item instance. 124 * @param string $typeid Tool Type Id 125 */ 126 private function get_request($response, $item, $typeid) { 127 128 $response->set_content_type($this->formats[0]); 129 $lineitem = gradebookservices::item_for_json($item, substr(parent::get_endpoint(), 130 0, strrpos(parent::get_endpoint(), "/", -10)), $typeid); 131 $response->set_body(json_encode($lineitem)); 132 133 } 134 135 /** 136 * Process a PUT request. 137 * 138 * @param string $body PUT body 139 * @param \ltiservice_gradebookservices\local\resources\lineitem $olditem Grade item instance 140 * @param string $typeid Tool Type Id 141 * 142 * @return string 143 * @throws \Exception 144 */ 145 private function process_put_request($body, $olditem, $typeid) { 146 global $DB; 147 $json = json_decode($body); 148 if (empty($json) || 149 !isset($json->scoreMaximum) || 150 !isset($json->label)) { 151 throw new \Exception(null, 400); 152 } 153 $item = \grade_item::fetch(array('id' => $olditem->id, 'courseid' => $olditem->courseid)); 154 $gbs = gradebookservices::find_ltiservice_gradebookservice_for_lineitem($olditem->id); 155 $updategradeitem = false; 156 $rescalegrades = false; 157 $oldgrademax = grade_floatval($item->grademax); 158 $upgradegradebookservices = false; 159 if ($item->itemname !== $json->label) { 160 $updategradeitem = true; 161 } 162 $item->itemname = $json->label; 163 if (!is_numeric($json->scoreMaximum)) { 164 throw new \Exception(null, 400); 165 } else { 166 if (grade_floats_different($oldgrademax, 167 grade_floatval($json->scoreMaximum))) { 168 $updategradeitem = true; 169 $rescalegrades = true; 170 } 171 $item->grademax = grade_floatval($json->scoreMaximum); 172 } 173 if ($gbs) { 174 $resourceid = (isset($json->resourceId)) ? $json->resourceId : ''; 175 $tag = (isset($json->tag)) ? $json->tag : ''; 176 if ($gbs->tag !== $tag || $gbs->resourceid !== $resourceid) { 177 $upgradegradebookservices = true; 178 } 179 $gbs->tag = $tag; 180 $gbs->resourceid = $resourceid; 181 } 182 $ltilinkid = null; 183 if (isset($json->resourceLinkId)) { 184 if (is_numeric($json->resourceLinkId)) { 185 $ltilinkid = $json->resourceLinkId; 186 if ($gbs) { 187 if (intval($gbs->ltilinkid) !== intval($json->resourceLinkId)) { 188 $gbs->ltilinkid = $json->resourceLinkId; 189 $upgradegradebookservices = true; 190 } 191 } else { 192 if (intval($item->iteminstance) !== intval($json->resourceLinkId)) { 193 $item->iteminstance = intval($json->resourceLinkId); 194 $updategradeitem = true; 195 } 196 } 197 } else { 198 throw new \Exception(null, 400); 199 } 200 } else if (isset($json->ltiLinkId)) { 201 if (is_numeric($json->ltiLinkId)) { 202 $ltilinkid = $json->ltiLinkId; 203 if ($gbs) { 204 if (intval($gbs->ltilinkid) !== intval($json->ltiLinkId)) { 205 $gbs->ltilinkid = $json->ltiLinkId; 206 $upgradegradebookservices = true; 207 } 208 } else { 209 if (intval($item->iteminstance) !== intval($json->ltiLinkId)) { 210 $item->iteminstance = intval($json->ltiLinkId); 211 $updategradeitem = true; 212 } 213 } 214 } else { 215 throw new \Exception(null, 400); 216 } 217 } 218 if ($ltilinkid != null) { 219 if (is_null($typeid)) { 220 if (!gradebookservices::check_lti_id($ltilinkid, $item->courseid, 221 $this->get_service()->get_tool_proxy()->id)) { 222 throw new \Exception(null, 403); 223 } 224 } else { 225 if (!gradebookservices::check_lti_1x_id($ltilinkid, $item->courseid, 226 $typeid)) { 227 throw new \Exception(null, 403); 228 } 229 } 230 } 231 if ($updategradeitem) { 232 if (!$item->update('mod/ltiservice_gradebookservices')) { 233 throw new \Exception(null, 500); 234 } 235 if ($rescalegrades) { 236 $item->rescale_grades_keep_percentage(0, $oldgrademax, 0, $item->grademax); 237 } 238 } 239 240 $lineitem = new lineitem($this->get_service()); 241 $endpoint = $lineitem->get_endpoint(); 242 243 if ($upgradegradebookservices) { 244 if (is_null($typeid)) { 245 $toolproxyid = $this->get_service()->get_tool_proxy()->id; 246 $baseurl = null; 247 } else { 248 $toolproxyid = null; 249 $baseurl = lti_get_type_type_config($typeid)->lti_toolurl; 250 } 251 $DB->update_record('ltiservice_gradebookservices', (object)array( 252 'id' => $gbs->id, 253 'gradeitemid' => $gbs->gradeitemid, 254 'courseid' => $gbs->courseid, 255 'toolproxyid' => $toolproxyid, 256 'typeid' => $typeid, 257 'baseurl' => $baseurl, 258 'ltilinkid' => $ltilinkid, 259 'resourceid' => $resourceid, 260 'tag' => $gbs->tag 261 )); 262 } 263 264 if (is_null($typeid)) { 265 $id = "{$endpoint}"; 266 $json->id = $id; 267 } else { 268 $id = "{$endpoint}?type_id={$typeid}"; 269 $json->id = $id; 270 } 271 return json_encode($json, JSON_UNESCAPED_SLASHES); 272 273 } 274 275 /** 276 * Process a DELETE request. 277 * 278 * @param \ltiservice_gradebookservices\local\resources\lineitem $item Grade item instance 279 * @throws \Exception 280 */ 281 private function process_delete_request($item) { 282 global $DB; 283 284 $gradeitem = \grade_item::fetch(array('id' => $item->id)); 285 if (($gbs = gradebookservices::find_ltiservice_gradebookservice_for_lineitem($item->id)) == false) { 286 throw new \Exception(null, 403); 287 } 288 if (!$gradeitem->delete('mod/ltiservice_gradebookservices')) { 289 throw new \Exception(null, 500); 290 } else { 291 $sqlparams = array(); 292 $sqlparams['id'] = $gbs->id; 293 if (!$DB->delete_records('ltiservice_gradebookservices', $sqlparams)) { 294 throw new \Exception(null, 500); 295 } 296 } 297 } 298 299 /** 300 * Parse a value for custom parameter substitution variables. 301 * 302 * @param string $value String to be parsed 303 * 304 * @return string 305 */ 306 public function parse_value($value) { 307 global $COURSE, $CFG; 308 if (strpos($value, '$LineItem.url') !== false) { 309 $resolved = ''; 310 require_once($CFG->libdir . '/gradelib.php'); 311 312 $this->params['context_id'] = $COURSE->id; 313 if ($tool = $this->get_service()->get_type()) { 314 $this->params['tool_code'] = $tool->id; 315 } 316 $id = optional_param('id', 0, PARAM_INT); // Course Module ID. 317 if (empty($id)) { 318 $id = optional_param('lti_message_hint', 0, PARAM_INT); 319 } 320 if (!empty($id)) { 321 $cm = get_coursemodule_from_id('lti', $id, 0, false, MUST_EXIST); 322 $id = $cm->instance; 323 $item = grade_get_grades($COURSE->id, 'mod', 'lti', $id); 324 if ($item && $item->items) { 325 $this->params['item_id'] = $item->items[0]->id; 326 $resolved = parent::get_endpoint(); 327 $resolved .= "?type_id={$tool->id}"; 328 } 329 } 330 $value = str_replace('$LineItem.url', $resolved, $value); 331 } 332 return $value; 333 } 334 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body