1 |
efrain |
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 |
* Class communication
|
|
|
19 |
*
|
|
|
20 |
* @package core
|
|
|
21 |
* @copyright 2017 Marina Glancy
|
|
|
22 |
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
|
|
23 |
*/
|
|
|
24 |
|
|
|
25 |
namespace core\hub;
|
|
|
26 |
defined('MOODLE_INTERNAL') || die();
|
|
|
27 |
|
|
|
28 |
use moodle_exception;
|
|
|
29 |
use curl;
|
|
|
30 |
use stdClass;
|
|
|
31 |
use coding_exception;
|
|
|
32 |
use moodle_url;
|
|
|
33 |
|
|
|
34 |
/**
|
|
|
35 |
* Provides methods to communicate with the hub (sites directory) web services.
|
|
|
36 |
*
|
|
|
37 |
* @package core
|
|
|
38 |
* @copyright 2017 Marina Glancy
|
|
|
39 |
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
|
|
40 |
*/
|
|
|
41 |
class api {
|
|
|
42 |
|
|
|
43 |
/** @var File type: Course screenshot */
|
|
|
44 |
const HUB_SCREENSHOT_FILE_TYPE = 'screenshot';
|
|
|
45 |
|
|
|
46 |
/** @var File type: Hub screenshot */
|
|
|
47 |
const HUB_HUBSCREENSHOT_FILE_TYPE = 'hubscreenshot';
|
|
|
48 |
|
|
|
49 |
/** @var File type: Backup */
|
|
|
50 |
const HUB_BACKUP_FILE_TYPE = 'backup';
|
|
|
51 |
|
|
|
52 |
/**
|
|
|
53 |
* Calls a remote function exposed via web services on the hub.
|
|
|
54 |
*
|
|
|
55 |
* @param string $function name of WS function
|
|
|
56 |
* @param array $data parameters of WS function
|
|
|
57 |
* @param bool $allowpublic allow request without registration on the hub
|
|
|
58 |
* @return mixed depends on the function
|
|
|
59 |
* @throws moodle_exception
|
|
|
60 |
*/
|
|
|
61 |
protected static function call($function, array $data = [], $allowpublic = false) {
|
|
|
62 |
|
|
|
63 |
$token = registration::get_token() ?: 'publichub';
|
|
|
64 |
if (!$allowpublic && $token === 'publichub') {
|
|
|
65 |
// This will throw an exception.
|
|
|
66 |
registration::require_registration();
|
|
|
67 |
}
|
|
|
68 |
|
|
|
69 |
return self::call_rest($token, $function, $data);
|
|
|
70 |
}
|
|
|
71 |
|
|
|
72 |
/**
|
|
|
73 |
* Performs a REST request to the hub site (using the GET method).
|
|
|
74 |
*
|
|
|
75 |
* @param string $token
|
|
|
76 |
* @param string $function
|
|
|
77 |
* @param array $data
|
|
|
78 |
* @return mixed
|
|
|
79 |
* @throws moodle_exception
|
|
|
80 |
*/
|
|
|
81 |
protected static function call_rest($token, $function, array $data) {
|
|
|
82 |
$params = [
|
|
|
83 |
'wstoken' => $token,
|
|
|
84 |
'wsfunction' => $function,
|
|
|
85 |
'moodlewsrestformat' => 'json'
|
|
|
86 |
] + $data;
|
|
|
87 |
|
|
|
88 |
$curl = new curl();
|
|
|
89 |
$serverurl = HUB_MOODLEORGHUBURL . "/local/hub/webservice/webservices.php";
|
|
|
90 |
$query = http_build_query($params, '', '&');
|
|
|
91 |
$curloutput = @json_decode($curl->post($serverurl, $query), true);
|
|
|
92 |
$info = $curl->get_info();
|
|
|
93 |
if ($curl->get_errno()) {
|
|
|
94 |
// Connection error.
|
|
|
95 |
throw new moodle_exception('errorconnect', 'hub', '', $curl->error);
|
|
|
96 |
} else if (isset($curloutput['exception'])) {
|
|
|
97 |
// Exception occurred on the remote side.
|
|
|
98 |
self::process_curl_exception($token, $curloutput);
|
|
|
99 |
} else if ($info['http_code'] != 200) {
|
|
|
100 |
throw new moodle_exception('errorconnect', 'hub', '', $info['http_code']);
|
|
|
101 |
} else {
|
|
|
102 |
return $curloutput;
|
|
|
103 |
}
|
|
|
104 |
}
|
|
|
105 |
|
|
|
106 |
/**
|
|
|
107 |
* Analyses exception received from the hub server.
|
|
|
108 |
*
|
|
|
109 |
* @param string $token token used for CURL request
|
|
|
110 |
* @param array $curloutput output from CURL request
|
|
|
111 |
* @throws moodle_exception
|
|
|
112 |
*/
|
|
|
113 |
protected static function process_curl_exception($token, $curloutput) {
|
|
|
114 |
if (!isset($curloutput['exception'])) {
|
|
|
115 |
return;
|
|
|
116 |
}
|
|
|
117 |
if ($token === registration::get_token()) {
|
|
|
118 |
// Check if registration token was rejected or there are other problems with registration.
|
|
|
119 |
if (($curloutput['exception'] === 'moodle_exception' && $curloutput['errorcode'] === 'invalidtoken')
|
|
|
120 |
|| $curloutput['exception'] === 'registration_exception') {
|
|
|
121 |
// Force admin to repeat site registration process.
|
|
|
122 |
registration::reset_token();
|
|
|
123 |
throw new moodle_exception('errorwstokenreset', 'hub', '', $curloutput['message']);
|
|
|
124 |
}
|
|
|
125 |
}
|
|
|
126 |
throw new moodle_exception('errorws', 'hub', '', $curloutput['message']);
|
|
|
127 |
}
|
|
|
128 |
|
|
|
129 |
/**
|
|
|
130 |
* Update site registration on the hub.
|
|
|
131 |
*
|
|
|
132 |
* @param array $siteinfo
|
|
|
133 |
* @throws moodle_exception
|
|
|
134 |
*/
|
|
|
135 |
public static function update_registration(array $siteinfo) {
|
|
|
136 |
$params = array('siteinfo' => $siteinfo, 'validateurl' => 1);
|
|
|
137 |
self::call('hub_update_site_info', $params);
|
|
|
138 |
}
|
|
|
139 |
|
|
|
140 |
/**
|
|
|
141 |
* Returns information about the hub.
|
|
|
142 |
*
|
|
|
143 |
* Example of the return array:
|
|
|
144 |
* {
|
|
|
145 |
* "courses": 384,
|
|
|
146 |
* "description": "Official Moodle sites directory.",
|
|
|
147 |
* "downloadablecourses": 0,
|
|
|
148 |
* "enrollablecourses": 0,
|
|
|
149 |
* "hublogo": 1,
|
|
|
150 |
* "language": "en",
|
|
|
151 |
* "name": "moodle",
|
|
|
152 |
* "sites": 274175,
|
|
|
153 |
* "url": "https://stats.moodle.org",
|
|
|
154 |
* "imgurl": "https://stats.moodle.org/local/hub/webservice/download.php?filetype=hubscreenshot"
|
|
|
155 |
* }
|
|
|
156 |
*
|
|
|
157 |
* @return array
|
|
|
158 |
* @throws moodle_exception
|
|
|
159 |
*/
|
|
|
160 |
public static function get_hub_info() {
|
|
|
161 |
$info = self::call('hub_get_info', [], true);
|
|
|
162 |
$info['imgurl'] = new moodle_url(HUB_MOODLEORGHUBURL . '/local/hub/webservice/download.php',
|
|
|
163 |
['filetype' => self::HUB_HUBSCREENSHOT_FILE_TYPE]);
|
|
|
164 |
return $info;
|
|
|
165 |
}
|
|
|
166 |
|
|
|
167 |
/**
|
|
|
168 |
* Calls WS function hub_get_courses
|
|
|
169 |
*
|
|
|
170 |
* @deprecated since Moodle 3.8. Moodle.net has been sunsetted making this function useless.
|
|
|
171 |
*
|
|
|
172 |
* Parameter $options may have any of these fields:
|
|
|
173 |
* [
|
|
|
174 |
* 'ids' => new external_multiple_structure(new external_value(PARAM_INT, 'id of a course in the hub course
|
|
|
175 |
* directory'), 'ids of course', VALUE_OPTIONAL),
|
|
|
176 |
* 'sitecourseids' => new external_multiple_structure(new external_value(PARAM_INT, 'id of a course in the
|
|
|
177 |
* site'), 'ids of course in the site', VALUE_OPTIONAL),
|
|
|
178 |
* 'coverage' => new external_value(PARAM_TEXT, 'coverage', VALUE_OPTIONAL),
|
|
|
179 |
* 'licenceshortname' => new external_value(PARAM_ALPHANUMEXT, 'licence short name', VALUE_OPTIONAL),
|
|
|
180 |
* 'subject' => new external_value(PARAM_ALPHANUM, 'subject', VALUE_OPTIONAL),
|
|
|
181 |
* 'audience' => new external_value(PARAM_ALPHA, 'audience', VALUE_OPTIONAL),
|
|
|
182 |
* 'educationallevel' => new external_value(PARAM_ALPHA, 'educational level', VALUE_OPTIONAL),
|
|
|
183 |
* 'language' => new external_value(PARAM_ALPHANUMEXT, 'language', VALUE_OPTIONAL),
|
|
|
184 |
* 'orderby' => new external_value(PARAM_ALPHA, 'orderby method: newest, eldest, publisher, fullname,
|
|
|
185 |
* ratingaverage', VALUE_OPTIONAL),
|
|
|
186 |
* 'givememore' => new external_value(PARAM_INT, 'next range of result - range size being set by the hub
|
|
|
187 |
* server ', VALUE_OPTIONAL),
|
|
|
188 |
* 'allsitecourses' => new external_value(PARAM_INT,
|
|
|
189 |
* 'if 1 return all not visible and visible courses whose siteid is the site
|
|
|
190 |
* matching token. Only courses of this site are returned.
|
|
|
191 |
* givememore parameter is ignored if this param = 1.
|
|
|
192 |
* In case of public token access, this param option is ignored', VALUE_DEFAULT, 0),
|
|
|
193 |
* ]
|
|
|
194 |
*
|
|
|
195 |
* Each course in the returned array of courses will have fields:
|
|
|
196 |
* [
|
|
|
197 |
* 'id' => new external_value(PARAM_INT, 'id'),
|
|
|
198 |
* 'fullname' => new external_value(PARAM_TEXT, 'course name'),
|
|
|
199 |
* 'shortname' => new external_value(PARAM_TEXT, 'course short name'),
|
|
|
200 |
* 'description' => new external_value(PARAM_TEXT, 'course description'),
|
|
|
201 |
* 'language' => new external_value(PARAM_ALPHANUMEXT, 'course language'),
|
|
|
202 |
* 'publishername' => new external_value(PARAM_TEXT, 'publisher name'),
|
|
|
203 |
* 'publisheremail' => new external_value(PARAM_EMAIL, 'publisher email', VALUE_OPTIONAL),
|
|
|
204 |
* 'privacy' => new external_value(PARAM_INT, 'privacy: published or not', VALUE_OPTIONAL),
|
|
|
205 |
* 'sitecourseid' => new external_value(PARAM_INT, 'course id on the site', VALUE_OPTIONAL),
|
|
|
206 |
* 'contributornames' => new external_value(PARAM_TEXT, 'contributor names', VALUE_OPTIONAL),
|
|
|
207 |
* 'coverage' => new external_value(PARAM_TEXT, 'coverage', VALUE_OPTIONAL),
|
|
|
208 |
* 'creatorname' => new external_value(PARAM_TEXT, 'creator name'),
|
|
|
209 |
* 'licenceshortname' => new external_value(PARAM_ALPHANUMEXT, 'licence short name'),
|
|
|
210 |
* 'subject' => new external_value(PARAM_ALPHANUM, 'subject'),
|
|
|
211 |
* 'audience' => new external_value(PARAM_ALPHA, 'audience'),
|
|
|
212 |
* 'educationallevel' => new external_value(PARAM_ALPHA, 'educational level'),
|
|
|
213 |
* 'creatornotes' => new external_value(PARAM_RAW, 'creator notes'),
|
|
|
214 |
* 'creatornotesformat' => new external_value(PARAM_INT, 'notes format'),
|
|
|
215 |
* 'demourl' => new external_value(PARAM_URL, 'demo URL', VALUE_OPTIONAL),
|
|
|
216 |
* 'courseurl' => new external_value(PARAM_URL, 'course URL', VALUE_OPTIONAL),
|
|
|
217 |
* 'backupsize' => new external_value(PARAM_INT, 'course backup size in bytes', VALUE_OPTIONAL),
|
|
|
218 |
* 'enrollable' => new external_value(PARAM_BOOL, 'is the course enrollable'),
|
|
|
219 |
* 'screenshots' => new external_value(PARAM_INT, 'total number of screenshots'),
|
|
|
220 |
* 'timemodified' => new external_value(PARAM_INT, 'time of last modification - timestamp'),
|
|
|
221 |
* 'contents' => new external_multiple_structure(new external_single_structure(
|
|
|
222 |
* array(
|
|
|
223 |
* 'moduletype' => new external_value(PARAM_ALPHA, 'the type of module (activity/block)'),
|
|
|
224 |
* 'modulename' => new external_value(PARAM_TEXT, 'the name of the module (forum, resource etc)'),
|
|
|
225 |
* 'contentcount' => new external_value(PARAM_INT, 'how many time the module is used in the course'),
|
|
|
226 |
* )), 'contents', VALUE_OPTIONAL),
|
|
|
227 |
* 'rating' => new external_single_structure (
|
|
|
228 |
* array(
|
|
|
229 |
* 'aggregate' => new external_value(PARAM_FLOAT, 'Rating average', VALUE_OPTIONAL),
|
|
|
230 |
* 'scaleid' => new external_value(PARAM_INT, 'Rating scale'),
|
|
|
231 |
* 'count' => new external_value(PARAM_INT, 'Rating count'),
|
|
|
232 |
* ), 'rating', VALUE_OPTIONAL),
|
|
|
233 |
* 'comments' => new external_multiple_structure(new external_single_structure (
|
|
|
234 |
* array(
|
|
|
235 |
* 'comment' => new external_value(PARAM_TEXT, 'the comment'),
|
|
|
236 |
* 'commentator' => new external_value(PARAM_TEXT, 'the name of commentator'),
|
|
|
237 |
* 'date' => new external_value(PARAM_INT, 'date of the comment'),
|
|
|
238 |
* )), 'contents', VALUE_OPTIONAL),
|
|
|
239 |
* 'outcomes' => new external_multiple_structure(new external_single_structure(
|
|
|
240 |
* array(
|
|
|
241 |
* 'fullname' => new external_value(PARAM_TEXT, 'the outcome fullname')
|
|
|
242 |
* )), 'outcomes', VALUE_OPTIONAL)
|
|
|
243 |
* ]
|
|
|
244 |
*
|
|
|
245 |
* Additional fields for each course:
|
|
|
246 |
* 'screenshotbaseurl' (moodle_url) URL of the first screenshot, only set if $course['screenshots']>0
|
|
|
247 |
* 'commenturl' (moodle_url) URL for comments
|
|
|
248 |
*
|
|
|
249 |
* @param string $search search string
|
|
|
250 |
* @param bool $downloadable return downloadable courses
|
|
|
251 |
* @param bool $enrollable return enrollable courses
|
|
|
252 |
* @param array|\stdClass $options other options from the list of allowed options:
|
|
|
253 |
* 'ids', 'sitecourseids', 'coverage', 'licenceshortname', 'subject', 'audience',
|
|
|
254 |
* 'educationallevel', 'language', 'orderby', 'givememore', 'allsitecourses'
|
|
|
255 |
* @return array of two elements: [$courses, $coursetotal]
|
|
|
256 |
* @throws \coding_exception
|
|
|
257 |
* @throws moodle_exception
|
|
|
258 |
*/
|
|
|
259 |
public static function get_courses($search, $downloadable, $enrollable, $options) {
|
|
|
260 |
debugging("This function has been deprecated as part of the Moodle.net sunsetting process.");
|
|
|
261 |
return [[], 0];
|
|
|
262 |
}
|
|
|
263 |
|
|
|
264 |
/**
|
|
|
265 |
* Unregister the site
|
|
|
266 |
*
|
|
|
267 |
* @throws moodle_exception
|
|
|
268 |
*/
|
|
|
269 |
public static function unregister_site() {
|
|
|
270 |
global $CFG;
|
|
|
271 |
self::call('hub_unregister_site', ['url' => [$CFG->wwwroot]]);
|
|
|
272 |
}
|
|
|
273 |
|
|
|
274 |
/**
|
|
|
275 |
* Unpublish courses
|
|
|
276 |
*
|
|
|
277 |
* @deprecated since Moodle 3.8. Moodle.net has been sunsetted making this function useless.
|
|
|
278 |
*
|
|
|
279 |
* @param int[]|int $courseids
|
|
|
280 |
* @throws moodle_exception
|
|
|
281 |
*/
|
|
|
282 |
public static function unregister_courses($courseids) {
|
|
|
283 |
debugging("This function has been deprecated as part of the Moodle.net sunsetting process.");
|
|
|
284 |
}
|
|
|
285 |
|
|
|
286 |
/**
|
|
|
287 |
* Publish one course
|
|
|
288 |
*
|
|
|
289 |
* @deprecated since Moodle 3.8. Moodle.net has been sunsetted making this function useless.
|
|
|
290 |
*
|
|
|
291 |
* Expected contents of $courseinfo:
|
|
|
292 |
* [
|
|
|
293 |
* 'sitecourseid' => new external_value(PARAM_INT, 'the id of the course on the publishing site'),
|
|
|
294 |
* 'fullname' => new external_value(PARAM_TEXT, 'course name'),
|
|
|
295 |
* 'shortname' => new external_value(PARAM_TEXT, 'course short name'),
|
|
|
296 |
* 'description' => new external_value(PARAM_TEXT, 'course description'),
|
|
|
297 |
* 'language' => new external_value(PARAM_ALPHANUMEXT, 'course language'),
|
|
|
298 |
* 'publishername' => new external_value(PARAM_TEXT, 'publisher name'),
|
|
|
299 |
* 'publisheremail' => new external_value(PARAM_EMAIL, 'publisher email'),
|
|
|
300 |
* 'contributornames' => new external_value(PARAM_TEXT, 'contributor names'),
|
|
|
301 |
* 'coverage' => new external_value(PARAM_TEXT, 'coverage'),
|
|
|
302 |
* 'creatorname' => new external_value(PARAM_TEXT, 'creator name'),
|
|
|
303 |
* 'licenceshortname' => new external_value(PARAM_ALPHANUMEXT, 'licence short name'),
|
|
|
304 |
* 'subject' => new external_value(PARAM_ALPHANUM, 'subject'),
|
|
|
305 |
* 'audience' => new external_value(PARAM_ALPHA, 'audience'),
|
|
|
306 |
* 'educationallevel' => new external_value(PARAM_ALPHA, 'educational level'),
|
|
|
307 |
* 'creatornotes' => new external_value(PARAM_RAW, 'creator notes'),
|
|
|
308 |
* 'creatornotesformat' => new external_value(PARAM_INT, 'notes format'),
|
|
|
309 |
* 'demourl' => new external_value(PARAM_URL, 'demo URL', VALUE_OPTIONAL),
|
|
|
310 |
* 'courseurl' => new external_value(PARAM_URL, 'course URL', VALUE_OPTIONAL),
|
|
|
311 |
* 'enrollable' => new external_value(PARAM_BOOL, 'is the course enrollable', VALUE_DEFAULT, 0),
|
|
|
312 |
* 'screenshots' => new external_value(PARAM_INT, 'the number of screenhots', VALUE_OPTIONAL),
|
|
|
313 |
* 'deletescreenshots' => new external_value(PARAM_INT, 'ask to delete all the existing screenshot files
|
|
|
314 |
* (it does not reset the screenshot number)', VALUE_DEFAULT, 0),
|
|
|
315 |
* 'contents' => new external_multiple_structure(new external_single_structure(
|
|
|
316 |
* array(
|
|
|
317 |
* 'moduletype' => new external_value(PARAM_ALPHA, 'the type of module (activity/block)'),
|
|
|
318 |
* 'modulename' => new external_value(PARAM_TEXT, 'the name of the module (forum, resource etc)'),
|
|
|
319 |
* 'contentcount' => new external_value(PARAM_INT, 'how many time the module is used in the course'),
|
|
|
320 |
* )), 'contents', VALUE_OPTIONAL),
|
|
|
321 |
* 'outcomes' => new external_multiple_structure(new external_single_structure(
|
|
|
322 |
* array(
|
|
|
323 |
* 'fullname' => new external_value(PARAM_TEXT, 'the outcome fullname')
|
|
|
324 |
* )), 'outcomes', VALUE_OPTIONAL)
|
|
|
325 |
* ]
|
|
|
326 |
*
|
|
|
327 |
* @param array|\stdClass $courseinfo
|
|
|
328 |
* @return int id of the published course on the hub
|
|
|
329 |
* @throws moodle_exception if the communication with the hub failed or the course could not be published
|
|
|
330 |
*/
|
|
|
331 |
public static function register_course($courseinfo) {
|
|
|
332 |
debugging("This function has been deprecated as part of the Moodle.net sunsetting process.");
|
|
|
333 |
throw new moodle_exception('errorcoursewronglypublished', 'hub');
|
|
|
334 |
}
|
|
|
335 |
|
|
|
336 |
/**
|
|
|
337 |
* Uploads a screenshot for the published course
|
|
|
338 |
*
|
|
|
339 |
* @deprecated since Moodle 3.8. Moodle.net has been sunsetted making this function useless.
|
|
|
340 |
*
|
|
|
341 |
* @param int $hubcourseid id of the published course on the hub, it must be published from this site
|
|
|
342 |
* @param \stored_file $file
|
|
|
343 |
* @param int $screenshotnumber ordinal number of the screenshot
|
|
|
344 |
*/
|
|
|
345 |
public static function add_screenshot($hubcourseid, \stored_file $file, $screenshotnumber) {
|
|
|
346 |
debugging("This function has been deprecated as part of the Moodle.net sunsetting process.");
|
|
|
347 |
}
|
|
|
348 |
|
|
|
349 |
/**
|
|
|
350 |
* Downloads course backup
|
|
|
351 |
*
|
|
|
352 |
* @deprecated since Moodle 3.8. Moodle.net has been sunsetted making this function useless.
|
|
|
353 |
*
|
|
|
354 |
* @param int $hubcourseid id of the course on the hub
|
|
|
355 |
* @param string $path local path (in tempdir) to save the downloaded backup to.
|
|
|
356 |
*/
|
|
|
357 |
public static function download_course_backup($hubcourseid, $path) {
|
|
|
358 |
debugging("This function has been deprecated as part of the Moodle.net sunsetting process.");
|
|
|
359 |
}
|
|
|
360 |
|
|
|
361 |
/**
|
|
|
362 |
* Uploads a course backup
|
|
|
363 |
*
|
|
|
364 |
* @deprecated since Moodle 3.8. Moodle.net has been sunsetted making this function useless.
|
|
|
365 |
*
|
|
|
366 |
* @param int $hubcourseid id of the published course on the hub, it must be published from this site
|
|
|
367 |
* @param \stored_file $backupfile
|
|
|
368 |
*/
|
|
|
369 |
public static function upload_course_backup($hubcourseid, \stored_file $backupfile) {
|
|
|
370 |
debugging("This function has been deprecated as part of the Moodle.net sunsetting process.");
|
|
|
371 |
}
|
|
|
372 |
}
|