Commit | Line | Data |
---|---|---|
74462841 DP |
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 | * Microsoft Live Skydrive Repository Plugin | |
19 | * | |
e518ea79 | 20 | * @package repository_onedrive |
74462841 DP |
21 | * @copyright 2012 Lancaster University Network Services Ltd |
22 | * @author Dan Poltawski <dan.poltawski@luns.net.uk> | |
23 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
24 | */ | |
25 | ||
26 | defined('MOODLE_INTERNAL') || die(); | |
27 | ||
74462841 | 28 | /** |
e518ea79 | 29 | * Microsoft onedrive repository plugin. |
74462841 | 30 | * |
e518ea79 | 31 | * @package repository_onedrive |
74462841 DP |
32 | * @copyright 2012 Lancaster University Network Services Ltd |
33 | * @author Dan Poltawski <dan.poltawski@luns.net.uk> | |
34 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
35 | */ | |
e518ea79 | 36 | class repository_onedrive extends repository { |
ffda3e39 DW |
37 | /** |
38 | * OAuth 2 client | |
39 | * @var \core\oauth2\client | |
40 | */ | |
41 | private $client = null; | |
42 | ||
43 | /** | |
44 | * OAuth 2 Issuer | |
45 | * @var \core\oauth2\issuer | |
46 | */ | |
47 | private $issuer = null; | |
48 | ||
49 | /** | |
50 | * Additional scopes required for drive. | |
51 | */ | |
52 | const SCOPES = 'files.readwrite.all'; | |
74462841 DP |
53 | |
54 | /** | |
ffda3e39 | 55 | * Constructor. |
74462841 DP |
56 | * |
57 | * @param int $repositoryid repository instance id. | |
58 | * @param int|stdClass $context a context id or context object. | |
59 | * @param array $options repository options. | |
ffda3e39 DW |
60 | * @param int $readonly indicate this repo is readonly or not. |
61 | * @return void | |
74462841 | 62 | */ |
ffda3e39 DW |
63 | public function __construct($repositoryid, $context = SYSCONTEXTID, $options = array(), $readonly = 0) { |
64 | parent::__construct($repositoryid, $context, $options, $readonly = 0); | |
65 | ||
5afb4f0e | 66 | try { |
e518ea79 | 67 | $this->issuer = \core\oauth2\api::get_issuer(get_config('onedrive', 'issuerid')); |
5afb4f0e DP |
68 | } catch (dml_missing_record_exception $e) { |
69 | $this->disabled = true; | |
70 | } | |
33536fb2 DW |
71 | |
72 | if ($this->issuer && !$this->issuer->get('enabled')) { | |
73 | $this->disabled = true; | |
74 | } | |
ffda3e39 DW |
75 | } |
76 | ||
77 | /** | |
78 | * Get a cached user authenticated oauth client. | |
79 | * | |
80 | * @param moodle_url $overrideurl - Use this url instead of the repo callback. | |
81 | * @return \core\oauth2\client | |
82 | */ | |
83 | protected function get_user_oauth_client($overrideurl = false) { | |
84 | if ($this->client) { | |
85 | return $this->client; | |
86 | } | |
87 | if ($overrideurl) { | |
88 | $returnurl = $overrideurl; | |
89 | } else { | |
90 | $returnurl = new moodle_url('/repository/repository_callback.php'); | |
91 | $returnurl->param('callback', 'yes'); | |
92 | $returnurl->param('repo_id', $this->id); | |
93 | $returnurl->param('sesskey', sesskey()); | |
94 | } | |
74462841 | 95 | |
ffda3e39 | 96 | $this->client = \core\oauth2\api::get_user_oauth_client($this->issuer, $returnurl, self::SCOPES); |
74462841 | 97 | |
ffda3e39 | 98 | return $this->client; |
74462841 DP |
99 | } |
100 | ||
101 | /** | |
ffda3e39 | 102 | * Checks whether the user is authenticate or not. |
74462841 | 103 | * |
ffda3e39 | 104 | * @return bool true when logged in. |
74462841 DP |
105 | */ |
106 | public function check_login() { | |
ffda3e39 DW |
107 | $client = $this->get_user_oauth_client(); |
108 | return $client->is_logged_in(); | |
74462841 DP |
109 | } |
110 | ||
111 | /** | |
ffda3e39 | 112 | * Print or return the login form. |
74462841 | 113 | * |
ffda3e39 | 114 | * @return void|array for ajax. |
74462841 DP |
115 | */ |
116 | public function print_login() { | |
ffda3e39 DW |
117 | $client = $this->get_user_oauth_client(); |
118 | $url = $client->get_login_url(); | |
c4a8d8e4 DP |
119 | |
120 | if ($this->options['ajax']) { | |
121 | $popup = new stdClass(); | |
122 | $popup->type = 'popup'; | |
123 | $popup->url = $url->out(false); | |
124 | return array('login' => array($popup)); | |
125 | } else { | |
126 | echo '<a target="_blank" href="'.$url->out(false).'">'.get_string('login', 'repository').'</a>'; | |
127 | } | |
74462841 DP |
128 | } |
129 | ||
130 | /** | |
ffda3e39 | 131 | * Build the breadcrumb from a path. |
74462841 | 132 | * |
ffda3e39 DW |
133 | * @param string $path to create a breadcrumb from. |
134 | * @return array containing name and path of each crumb. | |
135 | */ | |
136 | protected function build_breadcrumb($path) { | |
137 | $bread = explode('/', $path); | |
138 | $crumbtrail = ''; | |
139 | foreach ($bread as $crumb) { | |
140 | list($id, $name) = $this->explode_node_path($crumb); | |
141 | $name = empty($name) ? $id : $name; | |
142 | $breadcrumb[] = array( | |
143 | 'name' => $name, | |
144 | 'path' => $this->build_node_path($id, $name, $crumbtrail) | |
145 | ); | |
146 | $tmp = end($breadcrumb); | |
147 | $crumbtrail = $tmp['path']; | |
148 | } | |
149 | return $breadcrumb; | |
150 | } | |
151 | ||
152 | /** | |
153 | * Generates a safe path to a node. | |
154 | * | |
155 | * Typically, a node will be id|Name of the node. | |
74462841 | 156 | * |
ffda3e39 DW |
157 | * @param string $id of the node. |
158 | * @param string $name of the node, will be URL encoded. | |
159 | * @param string $root to append the node on, must be a result of this function. | |
160 | * @return string path to the node. | |
161 | */ | |
162 | protected function build_node_path($id, $name = '', $root = '') { | |
163 | $path = $id; | |
164 | if (!empty($name)) { | |
165 | $path .= '|' . urlencode($name); | |
166 | } | |
167 | if (!empty($root)) { | |
168 | $path = trim($root, '/') . '/' . $path; | |
169 | } | |
170 | return $path; | |
171 | } | |
172 | ||
173 | /** | |
174 | * Returns information about a node in a path. | |
175 | * | |
176 | * @see self::build_node_path() | |
177 | * @param string $node to extrat information from. | |
178 | * @return array about the node. | |
179 | */ | |
180 | protected function explode_node_path($node) { | |
181 | if (strpos($node, '|') !== false) { | |
182 | list($id, $name) = explode('|', $node, 2); | |
183 | $name = urldecode($name); | |
184 | } else { | |
185 | $id = $node; | |
186 | $name = ''; | |
187 | } | |
188 | $id = urldecode($id); | |
189 | return array( | |
190 | 0 => $id, | |
191 | 1 => $name, | |
192 | 'id' => $id, | |
193 | 'name' => $name | |
194 | ); | |
195 | } | |
196 | ||
197 | /** | |
198 | * List the files and folders. | |
199 | * | |
200 | * @param string $path path to browse. | |
201 | * @param string $page page to browse. | |
202 | * @return array of result. | |
74462841 DP |
203 | */ |
204 | public function get_listing($path='', $page = '') { | |
ffda3e39 | 205 | if (empty($path)) { |
e518ea79 | 206 | $path = $this->build_node_path('root', get_string('pluginname', 'repository_onedrive')); |
ffda3e39 DW |
207 | } |
208 | ||
33536fb2 | 209 | if ($this->disabled) { |
eca128bf DW |
210 | // Empty list of files for disabled repository. |
211 | return ['dynload' => false, 'list' => [], 'nologin' => true]; | |
212 | } | |
213 | ||
ffda3e39 DW |
214 | // We analyse the path to extract what to browse. |
215 | $trail = explode('/', $path); | |
216 | $uri = array_pop($trail); | |
217 | list($id, $name) = $this->explode_node_path($uri); | |
218 | ||
219 | // Handle the special keyword 'search', which we defined in self::search() so that | |
220 | // we could set up a breadcrumb in the search results. In any other case ID would be | |
221 | // 'root' which is a special keyword, or a parent (folder) ID. | |
222 | if ($id === 'search') { | |
223 | $q = $name; | |
224 | $id = 'root'; | |
225 | ||
226 | // Append the active path for search. | |
e518ea79 | 227 | $str = get_string('searchfor', 'repository_onedrive', $searchtext); |
ffda3e39 DW |
228 | $path = $this->build_node_path('search', $str, $path); |
229 | } | |
230 | ||
231 | // Query the Drive. | |
232 | $parent = $id; | |
233 | if ($parent != 'root') { | |
234 | $parent = 'items/' . $parent; | |
235 | } | |
236 | $q = ''; | |
237 | $results = $this->query($q, $path, $parent); | |
238 | ||
239 | $ret = []; | |
74462841 | 240 | $ret['dynload'] = true; |
ffda3e39 DW |
241 | $ret['path'] = $this->build_breadcrumb($path); |
242 | $ret['list'] = $results; | |
243 | $ret['manage'] = 'https://www.office.com/'; | |
244 | return $ret; | |
245 | } | |
246 | ||
247 | /** | |
ba3b0145 | 248 | * Search throughout the OneDrive |
ffda3e39 DW |
249 | * |
250 | * @param string $searchtext text to search for. | |
251 | * @param int $page search page. | |
252 | * @return array of results. | |
253 | */ | |
254 | public function search($searchtext, $page = 0) { | |
e518ea79 DW |
255 | $path = $this->build_node_path('root', get_string('pluginname', 'repository_onedrive')); |
256 | $str = get_string('searchfor', 'repository_onedrive', $searchtext); | |
ffda3e39 DW |
257 | $path = $this->build_node_path('search', $str, $path); |
258 | ||
259 | // Query the Drive. | |
260 | $parent = 'root'; | |
261 | $results = $this->query($searchtext, $path, 'root'); | |
262 | ||
263 | $ret = []; | |
264 | $ret['dynload'] = true; | |
265 | $ret['path'] = $this->build_breadcrumb($path); | |
266 | $ret['list'] = $results; | |
267 | $ret['manage'] = 'https://www.office.com/'; | |
268 | return $ret; | |
269 | } | |
270 | ||
271 | /** | |
ba3b0145 | 272 | * Query OneDrive for files and folders using a search query. |
ffda3e39 DW |
273 | * |
274 | * Documentation about the query format can be found here: | |
ba3b0145 DW |
275 | * https://developer.microsoft.com/en-us/graph/docs/api-reference/v1.0/resources/driveitem |
276 | * https://developer.microsoft.com/en-us/graph/docs/overview/query_parameters | |
ffda3e39 DW |
277 | * |
278 | * This returns a list of files and folders with their details as they should be | |
279 | * formatted and returned by functions such as get_listing() or search(). | |
280 | * | |
ba3b0145 | 281 | * @param string $q search query as expected by the Graph API. |
ffda3e39 | 282 | * @param string $path parent path of the current files, will not be used for the query. |
092304a3 | 283 | * @param string $parent Parent id. |
ffda3e39 DW |
284 | * @param int $page page. |
285 | * @return array of files and folders. | |
089810fb JP |
286 | * @throws Exception |
287 | * @throws repository_exception | |
ffda3e39 DW |
288 | */ |
289 | protected function query($q, $path = null, $parent = null, $page = 0) { | |
290 | global $OUTPUT; | |
291 | ||
292 | $files = []; | |
293 | $folders = []; | |
294 | $fields = "folder,id,lastModifiedDateTime,name,size,webUrl,thumbnails"; | |
295 | $params = ['$select' => $fields, '$expand' => 'thumbnails', 'parent' => $parent]; | |
296 | ||
297 | try { | |
298 | // Retrieving files and folders. | |
299 | $client = $this->get_user_oauth_client(); | |
e518ea79 | 300 | $service = new repository_onedrive\rest($client); |
ffda3e39 DW |
301 | |
302 | if (!empty($q)) { | |
303 | $params['search'] = urlencode($q); | |
304 | ||
305 | // MS does not return thumbnails on a search. | |
306 | unset($params['$expand']); | |
307 | $response = $service->call('search', $params); | |
308 | } else { | |
309 | $response = $service->call('list', $params); | |
310 | } | |
311 | } catch (Exception $e) { | |
312 | if ($e->getCode() == 403 && strpos($e->getMessage(), 'Access Not Configured') !== false) { | |
e518ea79 | 313 | throw new repository_exception('servicenotenabled', 'repository_onedrive'); |
ffda3e39 DW |
314 | } else { |
315 | throw $e; | |
316 | } | |
317 | } | |
318 | ||
319 | $remotefiles = isset($response->value) ? $response->value : []; | |
320 | foreach ($remotefiles as $remotefile) { | |
321 | if (!empty($remotefile->folder)) { | |
322 | // This is a folder. | |
323 | $folders[$remotefile->id] = [ | |
324 | 'title' => $remotefile->name, | |
325 | 'path' => $this->build_node_path($remotefile->id, $remotefile->name, $path), | |
326 | 'date' => strtotime($remotefile->lastModifiedDateTime), | |
089810fb | 327 | 'thumbnail' => $OUTPUT->image_url(file_folder_icon(64))->out(false), |
ffda3e39 DW |
328 | 'thumbnail_height' => 64, |
329 | 'thumbnail_width' => 64, | |
330 | 'children' => [] | |
331 | ]; | |
332 | } else { | |
333 | // We can download all other file types. | |
334 | $title = $remotefile->name; | |
335 | $source = json_encode([ | |
336 | 'id' => $remotefile->id, | |
337 | 'name' => $remotefile->name, | |
338 | 'link' => $remotefile->webUrl | |
339 | ]); | |
340 | ||
ffda3e39 DW |
341 | $thumb = ''; |
342 | $thumbwidth = 0; | |
343 | $thumbheight = 0; | |
344 | $extendedinfoerr = false; | |
345 | ||
346 | if (empty($remotefile->thumbnails)) { | |
347 | // Try and get it directly from the item. | |
348 | $params = ['fileid' => $remotefile->id, '$select' => $fields, '$expand' => 'thumbnails']; | |
349 | try { | |
350 | $response = $service->call('get', $params); | |
351 | $remotefile = $response; | |
352 | } catch (Exception $e) { | |
353 | // This is not a failure condition - we just could not get extended info about the file. | |
354 | $extendedinfoerr = true; | |
355 | } | |
356 | } | |
357 | ||
358 | if (!empty($remotefile->thumbnails)) { | |
359 | $thumbs = $remotefile->thumbnails; | |
360 | if (count($thumbs)) { | |
361 | $first = reset($thumbs); | |
362 | if (!empty($first->medium) && !empty($first->medium->url)) { | |
363 | $thumb = $first->medium->url; | |
364 | $thumbwidth = min($first->medium->width, 64); | |
365 | $thumbheight = min($first->medium->height, 64); | |
366 | } | |
367 | } | |
d4fd856b | 368 | } |
ffda3e39 DW |
369 | |
370 | $files[$remotefile->id] = [ | |
371 | 'title' => $title, | |
372 | 'source' => $source, | |
373 | 'date' => strtotime($remotefile->lastModifiedDateTime), | |
374 | 'size' => isset($remotefile->size) ? $remotefile->size : null, | |
375 | 'thumbnail' => $thumb, | |
376 | 'thumbnail_height' => $thumbwidth, | |
377 | 'thumbnail_width' => $thumbheight, | |
378 | ]; | |
d4fd856b DP |
379 | } |
380 | } | |
381 | ||
ffda3e39 DW |
382 | // Filter and order the results. |
383 | $files = array_filter($files, [$this, 'filter']); | |
384 | core_collator::ksort($files, core_collator::SORT_NATURAL); | |
385 | core_collator::ksort($folders, core_collator::SORT_NATURAL); | |
386 | return array_merge(array_values($folders), array_values($files)); | |
387 | } | |
388 | ||
389 | /** | |
390 | * Logout. | |
391 | * | |
392 | * @return string | |
393 | */ | |
394 | public function logout() { | |
395 | $client = $this->get_user_oauth_client(); | |
396 | $client->log_out(); | |
397 | return parent::logout(); | |
74462841 DP |
398 | } |
399 | ||
400 | /** | |
ffda3e39 | 401 | * Get a file. |
74462841 | 402 | * |
ffda3e39 | 403 | * @param string $reference reference of the file. |
092304a3 | 404 | * @param string $filename filename to save the file to. |
ffda3e39 | 405 | * @return string JSON encoded array of information about the file. |
74462841 | 406 | */ |
ffda3e39 DW |
407 | public function get_file($reference, $filename = '') { |
408 | global $CFG; | |
409 | ||
33536fb2 | 410 | if ($this->disabled) { |
eca128bf DW |
411 | throw new repository_exception('cannotdownload', 'repository'); |
412 | } | |
413 | ||
ffda3e39 DW |
414 | $client = $this->get_user_oauth_client(); |
415 | $base = 'https://graph.microsoft.com/v1.0/'; | |
416 | ||
417 | $sourceinfo = json_decode($reference); | |
418 | $sourceurl = new moodle_url($base . 'me/drive/items/' . $sourceinfo->id . '/content'); | |
419 | $source = $sourceurl->out(false); | |
420 | ||
421 | // We use download_one and not the rest API because it has special timeouts etc. | |
74462841 | 422 | $path = $this->prepare_file($filename); |
ffda3e39 DW |
423 | $options = ['filepath' => $path, 'timeout' => 15, 'followlocation' => true, 'maxredirs' => 5]; |
424 | $result = $client->download_one($source, null, $options); | |
425 | ||
426 | if ($result) { | |
427 | @chmod($path, $CFG->filepermissions); | |
428 | return array( | |
429 | 'path' => $path, | |
430 | 'url' => $reference | |
431 | ); | |
432 | } | |
433 | throw new repository_exception('cannotdownload', 'repository'); | |
434 | } | |
435 | ||
436 | /** | |
437 | * Prepare file reference information. | |
438 | * | |
439 | * We are using this method to clean up the source to make sure that it | |
440 | * is a valid source. | |
441 | * | |
442 | * @param string $source of the file. | |
443 | * @return string file reference. | |
444 | */ | |
445 | public function get_file_reference($source) { | |
446 | // We could do some magic upgrade code here. | |
447 | return $source; | |
448 | } | |
449 | ||
450 | /** | |
451 | * What kind of files will be in this repository? | |
452 | * | |
453 | * @return array return '*' means this repository support any files, otherwise | |
454 | * return mimetypes of files, it can be an array | |
455 | */ | |
456 | public function supported_filetypes() { | |
457 | return '*'; | |
74462841 DP |
458 | } |
459 | ||
460 | /** | |
ffda3e39 | 461 | * Tells how the file can be picked from this repository. |
74462841 | 462 | * |
ffda3e39 DW |
463 | * @return int |
464 | */ | |
465 | public function supported_returntypes() { | |
466 | // We can only support references if the system account is connected. | |
467 | if (!empty($this->issuer) && $this->issuer->is_system_account_connected()) { | |
e518ea79 | 468 | $setting = get_config('onedrive', 'supportedreturntypes'); |
ffda3e39 DW |
469 | if ($setting == 'internal') { |
470 | return FILE_INTERNAL; | |
471 | } else if ($setting == 'external') { | |
472 | return FILE_CONTROLLED_LINK; | |
473 | } else { | |
474 | return FILE_CONTROLLED_LINK | FILE_INTERNAL; | |
475 | } | |
476 | } else { | |
477 | return FILE_INTERNAL; | |
478 | } | |
479 | } | |
480 | ||
481 | /** | |
482 | * Which return type should be selected by default. | |
483 | * | |
484 | * @return int | |
485 | */ | |
486 | public function default_returntype() { | |
e518ea79 DW |
487 | $setting = get_config('onedrive', 'defaultreturntype'); |
488 | $supported = get_config('onedrive', 'supportedreturntypes'); | |
ffda3e39 DW |
489 | if (($setting == FILE_INTERNAL && $supported != 'external') || $supported == 'internal') { |
490 | return FILE_INTERNAL; | |
491 | } else { | |
492 | return FILE_CONTROLLED_LINK; | |
493 | } | |
494 | } | |
495 | ||
496 | /** | |
497 | * Return names of the general options. | |
498 | * By default: no general option name. | |
499 | * | |
500 | * @return array | |
74462841 DP |
501 | */ |
502 | public static function get_type_option_names() { | |
ffda3e39 | 503 | return array('issuerid', 'pluginname', 'defaultreturntype', 'supportedreturntypes'); |
74462841 DP |
504 | } |
505 | ||
506 | /** | |
ffda3e39 DW |
507 | * Store the access token. |
508 | */ | |
509 | public function callback() { | |
510 | $client = $this->get_user_oauth_client(); | |
511 | // This will upgrade to an access token if we have an authorization code and save the access token in the session. | |
512 | $client->is_logged_in(); | |
513 | } | |
514 | ||
515 | /** | |
516 | * Repository method to serve the referenced file | |
517 | * | |
518 | * @see send_stored_file | |
74462841 | 519 | * |
ffda3e39 DW |
520 | * @param stored_file $storedfile the file that contains the reference |
521 | * @param int $lifetime Number of seconds before the file should expire from caches (null means $CFG->filelifetime) | |
522 | * @param int $filter 0 (default)=no filtering, 1=all files, 2=html files only | |
523 | * @param bool $forcedownload If true (default false), forces download of file rather than view in browser/plugin | |
524 | * @param array $options additional options affecting the file serving | |
74462841 | 525 | */ |
ffda3e39 | 526 | public function send_file($storedfile, $lifetime=null , $filter=0, $forcedownload=false, array $options = null) { |
33536fb2 | 527 | if ($this->disabled) { |
eca128bf DW |
528 | throw new repository_exception('cannotdownload', 'repository'); |
529 | } | |
530 | ||
ffda3e39 | 531 | $source = json_decode($storedfile->get_reference()); |
74462841 | 532 | |
ffda3e39 DW |
533 | $fb = get_file_browser(); |
534 | $context = context::instance_by_id($storedfile->get_contextid(), MUST_EXIST); | |
535 | $info = $fb->get_file_info($context, | |
536 | $storedfile->get_component(), | |
537 | $storedfile->get_filearea(), | |
538 | $storedfile->get_itemid(), | |
539 | $storedfile->get_filepath(), | |
540 | $storedfile->get_filename()); | |
541 | ||
aa89bf2e | 542 | if (empty($options['offline']) && !empty($info) && $info->is_writable()) { |
ffda3e39 DW |
543 | // Add the current user as an OAuth writer. |
544 | $systemauth = \core\oauth2\api::get_system_oauth_client($this->issuer); | |
545 | ||
546 | if ($systemauth === false) { | |
547 | $details = 'Cannot connect as system user'; | |
548 | throw new repository_exception('errorwhilecommunicatingwith', 'repository', '', $details); | |
549 | } | |
e518ea79 | 550 | $systemservice = new repository_onedrive\rest($systemauth); |
ffda3e39 DW |
551 | |
552 | // Get the user oauth so we can get the account to add. | |
553 | $url = moodle_url::make_pluginfile_url($storedfile->get_contextid(), | |
554 | $storedfile->get_component(), | |
555 | $storedfile->get_filearea(), | |
556 | $storedfile->get_itemid(), | |
557 | $storedfile->get_filepath(), | |
558 | $storedfile->get_filename(), | |
559 | $forcedownload); | |
560 | $url->param('sesskey', sesskey()); | |
561 | $userauth = $this->get_user_oauth_client($url); | |
562 | if (!$userauth->is_logged_in()) { | |
563 | redirect($userauth->get_login_url()); | |
564 | } | |
565 | if ($userauth === false) { | |
566 | $details = 'Cannot connect as current user'; | |
567 | throw new repository_exception('errorwhilecommunicatingwith', 'repository', '', $details); | |
568 | } | |
569 | $userinfo = $userauth->get_userinfo(); | |
570 | $useremail = $userinfo['email']; | |
571 | ||
572 | $this->add_temp_writer_to_file($systemservice, $source->id, $useremail); | |
573 | } | |
574 | ||
d5bb9f1f DW |
575 | if (!empty($options['offline'])) { |
576 | $downloaded = $this->get_file($storedfile->get_reference(), $storedfile->get_filename()); | |
577 | $filename = $storedfile->get_filename(); | |
578 | send_file($downloaded['path'], $filename, $lifetime, $filter, false, $forcedownload, '', false, $options); | |
579 | } else if ($source->link) { | |
ffda3e39 DW |
580 | redirect($source->link); |
581 | } else { | |
582 | $details = 'File is missing source link'; | |
583 | throw new repository_exception('errorwhilecommunicatingwith', 'repository', '', $details); | |
584 | } | |
74462841 DP |
585 | } |
586 | ||
587 | /** | |
ffda3e39 | 588 | * List the permissions on a file. |
74462841 | 589 | * |
e518ea79 | 590 | * @param \repository_onedrive\rest $client Authenticated client. |
ffda3e39 DW |
591 | * @param string $fileid The id of the file. |
592 | * @return array | |
74462841 | 593 | */ |
e518ea79 | 594 | protected function list_file_permissions(\repository_onedrive\rest $client, $fileid) { |
ffda3e39 DW |
595 | $fields = "id,roles,link,grantedTo"; |
596 | return $client->call('list_permissions', ['fileid' => $fileid, '$select' => $fields]); | |
74462841 DP |
597 | } |
598 | ||
599 | /** | |
ffda3e39 | 600 | * See if a folder exists within a folder |
74462841 | 601 | * |
e518ea79 | 602 | * @param \repository_onedrive\rest $client Authenticated client. |
ffda3e39 DW |
603 | * @param string $fullpath |
604 | * @return string|boolean The file id if it exists or false. | |
74462841 | 605 | */ |
e518ea79 | 606 | protected function get_file_id_by_path(\repository_onedrive\rest $client, $fullpath) { |
ffda3e39 DW |
607 | $fields = "id"; |
608 | try { | |
609 | $response = $client->call('get_file_by_path', ['fullpath' => $fullpath, '$select' => $fields]); | |
610 | } catch (\core\oauth2\rest_exception $re) { | |
611 | return false; | |
612 | } | |
613 | return $response->id; | |
74462841 DP |
614 | } |
615 | ||
616 | /** | |
ffda3e39 | 617 | * Delete a file by full path. |
74462841 | 618 | * |
e518ea79 | 619 | * @param \repository_onedrive\rest $client Authenticated client. |
ffda3e39 DW |
620 | * @param string $fullpath |
621 | * @return boolean | |
74462841 | 622 | */ |
e518ea79 | 623 | protected function delete_file_by_path(\repository_onedrive\rest $client, $fullpath) { |
ffda3e39 DW |
624 | try { |
625 | $response = $client->call('delete_file_by_path', ['fullpath' => $fullpath]); | |
626 | } catch (\core\oauth2\rest_exception $re) { | |
627 | return false; | |
628 | } | |
629 | return true; | |
74462841 DP |
630 | } |
631 | ||
ffda3e39 | 632 | |
74462841 | 633 | /** |
ffda3e39 | 634 | * Get a file summary by full path. |
74462841 | 635 | * |
e518ea79 | 636 | * @param \repository_onedrive\rest $client Authenticated client. |
ffda3e39 DW |
637 | * @param string $fullpath |
638 | * @return stdClass | |
74462841 | 639 | */ |
e518ea79 | 640 | protected function get_file_summary_by_path(\repository_onedrive\rest $client, $fullpath) { |
ffda3e39 DW |
641 | $fields = "folder,id,lastModifiedDateTime,name,size,webUrl,createdByUser"; |
642 | $response = $client->call('get_file_by_path', ['fullpath' => $fullpath, '$select' => $fields]); | |
643 | if (empty($response->id)) { | |
644 | $details = 'Cannot get file summary:' . $fullpath; | |
645 | throw new repository_exception('errorwhilecommunicatingwith', 'repository', '', $details); | |
646 | } | |
647 | return $response; | |
648 | } | |
649 | ||
650 | /** | |
651 | * Create a folder within a folder | |
652 | * | |
e518ea79 | 653 | * @param \repository_onedrive\rest $client Authenticated client. |
ffda3e39 DW |
654 | * @param string $foldername The folder we are creating. |
655 | * @param string $parentid The parent folder we are creating in. | |
656 | * | |
657 | * @return string The file id of the new folder. | |
658 | */ | |
e518ea79 | 659 | protected function create_folder_in_folder(\repository_onedrive\rest $client, $foldername, $parentid) { |
ffda3e39 DW |
660 | $params = ['parentid' => $parentid]; |
661 | $folder = [ 'name' => $foldername, 'folder' => [ 'childCount' => 0 ]]; | |
662 | $created = $client->call('create_folder', $params, json_encode($folder)); | |
663 | if (empty($created->id)) { | |
664 | $details = 'Cannot create folder:' . $foldername; | |
665 | throw new repository_exception('errorwhilecommunicatingwith', 'repository', '', $details); | |
666 | } | |
667 | return $created->id; | |
668 | } | |
669 | ||
670 | /** | |
671 | * Get simple file info for humans. | |
672 | * | |
e518ea79 | 673 | * @param \repository_onedrive\rest $client Authenticated client. |
ffda3e39 DW |
674 | * @param string $fileid The file we are querying. |
675 | * | |
676 | * @return stdClass | |
677 | */ | |
e518ea79 | 678 | protected function get_file_summary(\repository_onedrive\rest $client, $fileid) { |
ffda3e39 DW |
679 | $fields = "folder,id,lastModifiedDateTime,name,size,webUrl,createdByUser"; |
680 | $response = $client->call('get', ['fileid' => $fileid, '$select' => $fields]); | |
681 | return $response; | |
682 | } | |
683 | ||
684 | /** | |
685 | * Get the id of this users root drive. | |
686 | * | |
e518ea79 | 687 | * @param \repository_onedrive\rest $client Authenticated client. |
ffda3e39 DW |
688 | * |
689 | * @return string id | |
690 | */ | |
e518ea79 | 691 | protected function get_root_drive_id(\repository_onedrive\rest $client) { |
ffda3e39 DW |
692 | $response = $client->call('get_drive', []); |
693 | ||
694 | if (empty($response->id)) { | |
695 | $details = 'Cannot get driveid'; | |
696 | throw new repository_exception('errorwhilecommunicatingwith', 'repository', '', $details); | |
697 | } | |
698 | return $response->id; | |
699 | } | |
700 | ||
701 | /** | |
702 | * Add a writer to the permissions on the file (temporary). | |
703 | * | |
e518ea79 | 704 | * @param \repository_onedrive\rest $client Authenticated client. |
ffda3e39 DW |
705 | * @param string $fileid The file we are updating. |
706 | * @param string $email The email of the writer account to add. | |
707 | * @return boolean | |
708 | */ | |
e518ea79 | 709 | protected function add_temp_writer_to_file(\repository_onedrive\rest $client, $fileid, $email) { |
ffda3e39 DW |
710 | // Expires in 7 days. |
711 | $expires = new DateTime(); | |
712 | $expires->add(new DateInterval("P7D")); | |
713 | ||
714 | $updateeditor = [ | |
715 | 'recipients' => [[ 'email' => $email ]], | |
716 | 'roles' => ['write'], | |
717 | 'requireSignIn' => true, | |
718 | 'sendInvitation' => false | |
719 | ]; | |
720 | $params = ['fileid' => $fileid]; | |
721 | $response = $client->call('create_permission', $params, json_encode($updateeditor)); | |
722 | if (empty($response->value[0]->id)) { | |
723 | $details = 'Cannot add user ' . $email . ' as a writer for document: ' . $fileid; | |
724 | throw new repository_exception('errorwhilecommunicatingwith', 'repository', '', $details); | |
725 | } | |
726 | // Store the permission id in the DB. Scheduled task will remove this permission after 7 days. | |
e518ea79 | 727 | if ($access = repository_onedrive\access::get_record(['permissionid' => $response->value[0]->id, 'itemid' => $fileid ])) { |
ffda3e39 DW |
728 | // Update the timemodified. |
729 | $access->update(); | |
730 | } else { | |
731 | $record = (object) [ 'permissionid' => $response->value[0]->id, 'itemid' => $fileid ]; | |
e518ea79 | 732 | $access = new repository_onedrive\access(0, $record); |
ffda3e39 DW |
733 | $access->create(); |
734 | } | |
735 | return true; | |
736 | } | |
737 | ||
738 | /** | |
739 | * Add a writer to the permissions on the file. | |
740 | * | |
e518ea79 | 741 | * @param \repository_onedrive\rest $client Authenticated client. |
ffda3e39 | 742 | * @param string $fileid The file we are updating. |
092304a3 | 743 | * @param string $useremail The user email of the writer account to add. |
ffda3e39 DW |
744 | * @return boolean |
745 | */ | |
e518ea79 | 746 | protected function add_writer_to_file(\repository_onedrive\rest $client, $fileid, $useremail) { |
ffda3e39 DW |
747 | $updateeditor = [ |
748 | 'recipients' => [ [ 'email' => $useremail ] ], | |
749 | 'roles' => ['write'], | |
750 | 'requireSignIn' => true, | |
751 | 'sendInvitation' => false | |
752 | ]; | |
753 | $params = [ 'fileid' => $fileid ]; | |
754 | $response = $client->call('create_permission', $params, json_encode($updateeditor)); | |
755 | if (empty($response->value)) { | |
756 | $details = 'Cannot add user ' . $useremail . ' as a writer for document: ' . $fileid; | |
757 | throw new repository_exception('errorwhilecommunicatingwith', 'repository', '', $details); | |
758 | } | |
759 | return true; | |
760 | } | |
761 | ||
762 | /** | |
763 | * Allow anyone with the link to read the file. | |
764 | * | |
e518ea79 | 765 | * @param \repository_onedrive\rest $client Authenticated client. |
ffda3e39 DW |
766 | * @param string $fileid The file we are updating. |
767 | * @return boolean | |
768 | */ | |
e518ea79 | 769 | protected function set_file_sharing_anyone_with_link_can_read(\repository_onedrive\rest $client, $fileid) { |
ffda3e39 DW |
770 | $updateread = [ |
771 | 'type' => 'view', | |
772 | 'scope' => 'anonymous' | |
773 | ]; | |
774 | $params = ['fileid' => $fileid]; | |
775 | $response = $client->call('create_link', $params, json_encode($updateread)); | |
776 | if (empty($response->link)) { | |
777 | $details = 'Cannot update link sharing for the document: ' . $fileid; | |
778 | throw new repository_exception('errorwhilecommunicatingwith', 'repository', '', $details); | |
779 | } | |
780 | return true; | |
781 | } | |
782 | ||
783 | /** | |
092304a3 | 784 | * Copy a shared file to a new folder. |
ffda3e39 | 785 | * |
e518ea79 | 786 | * @param \repository_onedrive\rest $client Authenticated client. |
ffda3e39 | 787 | * @param string $sharetoken The share we are querying. |
092304a3 DW |
788 | * @param string $newdrive Id of the drive to copy to. |
789 | * @param string $parentid Id of the folder to copy to. | |
ffda3e39 DW |
790 | * @return stdClass |
791 | */ | |
e518ea79 | 792 | protected function copy_share(\repository_onedrive\rest $client, $sharetoken, $newdrive, $parentid) { |
ffda3e39 DW |
793 | $folder = [ |
794 | 'parentReference' => ['id' => $parentid, 'driveId' => $newdrive] | |
795 | ]; | |
796 | $params = ['sharetoken' => $sharetoken]; | |
797 | $response = $client->call('copy_share', $params, json_encode($folder)); | |
798 | return true; | |
799 | } | |
800 | ||
801 | /** | |
802 | * From MS docs - to get a share token from a url, do this: | |
803 | * Reference: https://developer.microsoft.com/en-us/graph/docs/api-reference/v1.0/api/shares_get | |
804 | * To access a sharing URL using the shares API, the URL needs to be transformed into a sharing token. | |
805 | * To transform a URL into a sharing token: | |
806 | * Base64 encode the sharing URL. | |
807 | * Convert the base64 encoded data to unpadded base64url format by: | |
808 | * Trim trailing = characeters from the string. | |
809 | * Replace unsafe URL characters with an equivelent character; replace / with _ and + with -. | |
810 | * Append u! to the beginning of the string. | |
811 | * | |
092304a3 DW |
812 | * @param string $shareurl |
813 | * @return string The sharing token | |
ffda3e39 DW |
814 | */ |
815 | protected function get_share_token($shareurl) { | |
816 | return 'u!' . str_replace(['/', '+'], ['_', '-'], rtrim(base64_encode($shareurl), '=')); | |
817 | } | |
818 | ||
819 | /** | |
820 | * Called when a file is selected as a "link". | |
821 | * Invoked at MOODLE/repository/repository_ajax.php | |
822 | * | |
eb47ad4a DW |
823 | * What should happen here is that the file should be copied to a new file owned by the moodle system user. |
824 | * It should be organised in a folder based on the file context. | |
825 | * It's sharing permissions should allow read access with the link. | |
826 | * The returned reference should point to the newly copied file - not the original. | |
827 | * | |
ffda3e39 DW |
828 | * @param string $reference this reference is generated by |
829 | * repository::get_file_reference() | |
830 | * @param context $context the target context for this new file. | |
831 | * @param string $component the target component for this new file. | |
832 | * @param string $filearea the target filearea for this new file. | |
833 | * @param string $itemid the target itemid for this new file. | |
834 | * @return string $modifiedreference (final one before saving to DB) | |
835 | */ | |
836 | public function reference_file_selected($reference, $context, $component, $filearea, $itemid) { | |
837 | // What we need to do here is transfer ownership to the system user (or copy) | |
838 | // then set the permissions so anyone with the share link can view, | |
839 | // finally update the reference to contain the share link if it was not | |
840 | // already there (and point to new file id if we copied). | |
eb47ad4a DW |
841 | |
842 | // Get a system and a user oauth client. | |
ffda3e39 DW |
843 | $systemauth = \core\oauth2\api::get_system_oauth_client($this->issuer); |
844 | ||
845 | if ($systemauth === false) { | |
846 | $details = 'Cannot connect as system user'; | |
847 | throw new repository_exception('errorwhilecommunicatingwith', 'repository', '', $details); | |
848 | } | |
849 | $systemuserinfo = $systemauth->get_userinfo(); | |
850 | $systemuseremail = $systemuserinfo['email']; | |
851 | ||
852 | $source = json_decode($reference); | |
853 | ||
854 | $userauth = $this->get_user_oauth_client(); | |
855 | if ($userauth === false) { | |
856 | $details = 'Cannot connect as current user'; | |
857 | throw new repository_exception('errorwhilecommunicatingwith', 'repository', '', $details); | |
858 | } | |
859 | $userinfo = $userauth->get_userinfo(); | |
860 | $useremail = $userinfo['email']; | |
861 | ||
e518ea79 DW |
862 | $userservice = new repository_onedrive\rest($userauth); |
863 | $systemservice = new repository_onedrive\rest($systemauth); | |
ffda3e39 DW |
864 | |
865 | // Get the list of existing permissions so we can see if the owner is already the system account, | |
866 | // and whether we need to update the link sharing options. | |
867 | $permissions = $this->list_file_permissions($userservice, $source->id); | |
868 | ||
869 | $readshareupdaterequired = true; | |
870 | $ownerupdaterequired = true; | |
871 | foreach ($permissions->value as $permission) { | |
872 | if (!empty($permission->link)) { | |
873 | if ($permission->link->scope == 'anonymous' && | |
874 | $permission->link->type == 'view') { | |
875 | $shareurl = $permission->link->webUrl; | |
876 | $readshareupdaterequired = false; | |
877 | break; | |
878 | } | |
879 | } | |
880 | } | |
881 | ||
882 | // Add Moodle as writer. | |
883 | $this->add_writer_to_file($userservice, $source->id, $systemuseremail); | |
884 | ||
885 | // Now copy it to a sensible folder. | |
886 | $contextlist = array_reverse($context->get_parent_contexts(true)); | |
887 | ||
e518ea79 | 888 | $cache = cache::make('repository_onedrive', 'folder'); |
ffda3e39 DW |
889 | $parentid = 'root'; |
890 | $fullpath = ''; | |
891 | $allfolders = []; | |
892 | foreach ($contextlist as $context) { | |
893 | // Make sure a folder exists here. | |
894 | $foldername = urlencode(clean_param($context->get_context_name(), PARAM_PATH)); | |
895 | $allfolders[] = $foldername; | |
896 | } | |
897 | ||
898 | $allfolders[] = urlencode(clean_param($component, PARAM_PATH)); | |
899 | $allfolders[] = urlencode(clean_param($filearea, PARAM_PATH)); | |
900 | $allfolders[] = urlencode(clean_param($itemid, PARAM_PATH)); | |
901 | ||
eb47ad4a DW |
902 | // Variable $allfolders now has the complete path we want to store the file in. |
903 | // Create each folder in $allfolders under the system account. | |
ffda3e39 DW |
904 | foreach ($allfolders as $foldername) { |
905 | if ($fullpath) { | |
906 | $fullpath .= '/'; | |
907 | } | |
908 | $fullpath .= $foldername; | |
909 | ||
910 | $folderid = $cache->get($fullpath); | |
911 | if (empty($folderid)) { | |
912 | $folderid = $this->get_file_id_by_path($systemservice, $fullpath); | |
913 | } | |
914 | if ($folderid !== false) { | |
915 | $cache->set($fullpath, $folderid); | |
916 | $parentid = $folderid; | |
917 | } else { | |
918 | // Create it. | |
919 | $parentid = $this->create_folder_in_folder($systemservice, $foldername, $parentid); | |
920 | $cache->set($fullpath, $parentid); | |
921 | } | |
922 | } | |
923 | ||
924 | // Get the users drive id. | |
925 | $newdrive = $this->get_root_drive_id($systemservice); | |
926 | ||
927 | if ($readshareupdaterequired) { | |
928 | $response = $this->set_file_sharing_anyone_with_link_can_read($userservice, $source->id); | |
929 | $shareurl = $response->value->webUrl; | |
930 | } | |
931 | ||
932 | // Turn the share url into a sharing token. | |
933 | $sharetoken = $this->get_share_token($shareurl); | |
934 | ||
935 | // Delete any existing file at this path. | |
936 | $path = $fullpath . '/' . $source->name; | |
937 | $this->delete_file_by_path($systemservice, $path); | |
938 | ||
eb47ad4a DW |
939 | // Copy the file to the moodle account. |
940 | // Note this method (copying via a share link) is the only way to copy a file in | |
941 | // office 365 from one user to another. | |
ffda3e39 DW |
942 | $this->copy_share($systemservice, $sharetoken, $newdrive, $parentid); |
943 | ||
944 | $summary = $this->get_file_summary_by_path($systemservice, $path); | |
945 | ||
946 | // Update the details in the file reference before it is saved. | |
947 | $source->id = $summary->id; | |
948 | $source->link = $summary->webUrl; | |
949 | ||
950 | $reference = json_encode($source); | |
951 | ||
952 | return $reference; | |
953 | } | |
954 | ||
955 | /** | |
956 | * Get human readable file info from the reference. | |
957 | * | |
958 | * @param string $reference | |
959 | * @param int $filestatus | |
960 | */ | |
961 | public function get_reference_details($reference, $filestatus = 0) { | |
962 | if (empty($reference)) { | |
963 | return get_string('unknownsource', 'repository'); | |
964 | } | |
965 | $source = json_decode($reference); | |
966 | $systemauth = \core\oauth2\api::get_system_oauth_client($this->issuer); | |
967 | ||
968 | if ($systemauth === false) { | |
969 | return ''; | |
970 | } | |
e518ea79 | 971 | $systemservice = new repository_onedrive\rest($systemauth); |
ffda3e39 DW |
972 | $info = $this->get_file_summary($systemservice, $source->id); |
973 | ||
974 | $owner = ''; | |
975 | if (!empty($info->createdByUser->displayName)) { | |
976 | $owner = $info->createdByUser->displayName; | |
977 | } | |
978 | if ($owner) { | |
e518ea79 | 979 | return get_string('owner', 'repository_onedrive', $owner); |
ffda3e39 DW |
980 | } else { |
981 | return $info->name; | |
982 | } | |
983 | } | |
984 | ||
e7688f55 DW |
985 | /** |
986 | * Return true if any instances of the skydrive repo exist - and we can import them. | |
987 | * | |
988 | * @return bool | |
989 | */ | |
990 | public static function can_import_skydrive_files() { | |
991 | global $DB; | |
992 | ||
993 | $skydrive = $DB->get_record('repository', ['type' => 'skydrive'], 'id', IGNORE_MISSING); | |
994 | $onedrive = $DB->get_record('repository', ['type' => 'onedrive'], 'id', IGNORE_MISSING); | |
995 | ||
996 | if (empty($skydrive) || empty($onedrive)) { | |
997 | return false; | |
998 | } | |
999 | ||
1000 | $ready = true; | |
1001 | try { | |
1002 | $issuer = \core\oauth2\api::get_issuer(get_config('onedrive', 'issuerid')); | |
1003 | if (!$issuer->get('enabled')) { | |
1004 | $ready = false; | |
1005 | } | |
1006 | if (!$issuer->is_configured()) { | |
1007 | $ready = false; | |
1008 | } | |
1009 | } catch (dml_missing_record_exception $e) { | |
1010 | $ready = false; | |
1011 | } | |
1012 | if (!$ready) { | |
1013 | return false; | |
1014 | } | |
1015 | ||
1016 | $sql = "SELECT count('x') | |
1017 | FROM {repository_instances} i, {repository} r | |
1018 | WHERE r.type=:plugin AND r.id=i.typeid"; | |
1019 | $params = array('plugin' => 'skydrive'); | |
1020 | return $DB->count_records_sql($sql, $params) > 0; | |
1021 | } | |
1022 | ||
1023 | /** | |
1024 | * Import all the files that were created with the skydrive repo to this repo. | |
1025 | * | |
1026 | * @return bool | |
1027 | */ | |
1028 | public static function import_skydrive_files() { | |
1029 | global $DB; | |
1030 | ||
1031 | if (!self::can_import_skydrive_files()) { | |
1032 | return false; | |
1033 | } | |
1034 | // Should only be one of each. | |
1035 | $skydrivetype = repository::get_type_by_typename('skydrive'); | |
1036 | ||
1037 | $skydriveinstances = repository::get_instances(['type' => 'skydrive']); | |
1038 | $skydriveinstance = reset($skydriveinstances); | |
1039 | $onedriveinstances = repository::get_instances(['type' => 'onedrive']); | |
1040 | $onedriveinstance = reset($onedriveinstances); | |
1041 | ||
1042 | // Update all file references. | |
1043 | $DB->set_field('files_reference', 'repositoryid', $onedriveinstance->id, ['repositoryid' => $skydriveinstance->id]); | |
1044 | ||
1045 | // Delete and disable the skydrive repo. | |
1046 | $skydrivetype->delete(); | |
1047 | core_plugin_manager::reset_caches(); | |
1048 | ||
1049 | $sql = "SELECT count('x') | |
1050 | FROM {repository_instances} i, {repository} r | |
1051 | WHERE r.type=:plugin AND r.id=i.typeid"; | |
1052 | $params = array('plugin' => 'skydrive'); | |
1053 | return $DB->count_records_sql($sql, $params) == 0; | |
1054 | } | |
1055 | ||
ffda3e39 DW |
1056 | /** |
1057 | * Edit/Create Admin Settings Moodle form. | |
1058 | * | |
1059 | * @param moodleform $mform Moodle form (passed by reference). | |
1060 | * @param string $classname repository class name. | |
1061 | */ | |
1062 | public static function type_config_form($mform, $classname = 'repository') { | |
e7688f55 DW |
1063 | global $OUTPUT; |
1064 | ||
ffda3e39 DW |
1065 | $url = new moodle_url('/admin/tool/oauth2/issuers.php'); |
1066 | $url = $url->out(); | |
1067 | ||
e518ea79 | 1068 | $mform->addElement('static', null, '', get_string('oauth2serviceslink', 'repository_onedrive', $url)); |
ffda3e39 | 1069 | |
e7688f55 DW |
1070 | if (self::can_import_skydrive_files()) { |
1071 | $notice = get_string('skydrivefilesexist', 'repository_onedrive'); | |
1072 | $url = new moodle_url('/repository/onedrive/importskydrive.php'); | |
1073 | $attrs = ['class' => 'btn btn-primary']; | |
1074 | $button = $OUTPUT->action_link($url, get_string('importskydrivefiles', 'repository_onedrive'), null, $attrs); | |
1075 | $mform->addElement('static', null, '', $OUTPUT->notification($notice) . $button); | |
1076 | } | |
1077 | ||
ffda3e39 DW |
1078 | parent::type_config_form($mform); |
1079 | $options = []; | |
1080 | $issuers = \core\oauth2\api::get_all_issuers(); | |
1081 | ||
1082 | foreach ($issuers as $issuer) { | |
1083 | $options[$issuer->get('id')] = s($issuer->get('name')); | |
1084 | } | |
1085 | ||
1086 | $strrequired = get_string('required'); | |
1087 | ||
e518ea79 DW |
1088 | $mform->addElement('select', 'issuerid', get_string('issuer', 'repository_onedrive'), $options); |
1089 | $mform->addHelpButton('issuerid', 'issuer', 'repository_onedrive'); | |
ffda3e39 DW |
1090 | $mform->addRule('issuerid', $strrequired, 'required', null, 'client'); |
1091 | ||
e518ea79 | 1092 | $mform->addElement('static', null, '', get_string('fileoptions', 'repository_onedrive')); |
ffda3e39 | 1093 | $choices = [ |
e518ea79 DW |
1094 | 'internal' => get_string('internal', 'repository_onedrive'), |
1095 | 'external' => get_string('external', 'repository_onedrive'), | |
1096 | 'both' => get_string('both', 'repository_onedrive') | |
ffda3e39 | 1097 | ]; |
e518ea79 | 1098 | $mform->addElement('select', 'supportedreturntypes', get_string('supportedreturntypes', 'repository_onedrive'), $choices); |
ffda3e39 DW |
1099 | |
1100 | $choices = [ | |
e518ea79 DW |
1101 | FILE_INTERNAL => get_string('internal', 'repository_onedrive'), |
1102 | FILE_CONTROLLED_LINK => get_string('external', 'repository_onedrive'), | |
ffda3e39 | 1103 | ]; |
e518ea79 | 1104 | $mform->addElement('select', 'defaultreturntype', get_string('defaultreturntype', 'repository_onedrive'), $choices); |
e7688f55 | 1105 | |
ffda3e39 DW |
1106 | } |
1107 | } | |
1108 | ||
1109 | /** | |
1110 | * Callback to get the required scopes for system account. | |
1111 | * | |
13b449f4 | 1112 | * @param \core\oauth2\issuer $issuer |
ffda3e39 DW |
1113 | * @return string |
1114 | */ | |
e518ea79 DW |
1115 | function repository_onedrive_oauth2_system_scopes(\core\oauth2\issuer $issuer) { |
1116 | if ($issuer->get('id') == get_config('onedrive', 'issuerid')) { | |
1117 | return repository_onedrive::SCOPES; | |
74462841 | 1118 | } |
ffda3e39 | 1119 | return ''; |
74462841 | 1120 | } |