mirror of
https://github.com/moodle/moodle.git
synced 2025-04-13 04:22:07 +02:00
MDL-58126 googledocs: Re-implement the google docs repo
Use latest REST API (v3) - but avoid the google client libraries (too big, too much to update, not integrated with auth). Part of MDL-58220
This commit is contained in:
parent
299112498b
commit
0e59638bdb
@ -25,6 +25,6 @@
|
||||
defined('MOODLE_INTERNAL') || die;
|
||||
|
||||
if ($hassiteconfig) {
|
||||
$ADMIN->add('server', new admin_externalpage('oauth2', new lang_string('pluginname','tool_oauth2'),
|
||||
$ADMIN->add('server', new admin_externalpage('oauth2', new lang_string('pluginname', 'tool_oauth2'),
|
||||
"$CFG->wwwroot/$CFG->admin/tool/oauth2/issuers.php"));
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ defined('MOODLE_INTERNAL') || die();
|
||||
require_once($CFG->libdir.'/authlib.php');
|
||||
|
||||
/**
|
||||
* Plugin for oauth2 authentication.
|
||||
* Plugin for oauth2 authentication.
|
||||
*
|
||||
* @package auth_oauth2
|
||||
* @copyright 2017 Damyon Wiese
|
||||
|
@ -37,6 +37,10 @@ $returnurl = new moodle_url('/auth/oauth2/login.php', $returnparams);
|
||||
$client = \core\oauth2\api::get_user_oauth_client($issuer, $returnurl);
|
||||
|
||||
if ($client) {
|
||||
if (!$client->is_logged_in()) {
|
||||
redirect($client->get_login_url());
|
||||
}
|
||||
|
||||
$auth = new \auth_oauth2\auth();
|
||||
$auth->complete_login($client, $wantsurl);
|
||||
} else {
|
||||
|
@ -321,9 +321,6 @@ class api {
|
||||
public static function get_user_oauth_client(issuer $issuer, moodle_url $currenturl, $additionalscopes = '') {
|
||||
$client = new \core\oauth2\client($issuer, $currenturl, $additionalscopes);
|
||||
|
||||
if (!$client->is_logged_in()) {
|
||||
redirect($client->get_login_url());
|
||||
}
|
||||
return $client;
|
||||
}
|
||||
|
||||
|
105
lib/classes/oauth2/rest.php
Normal file
105
lib/classes/oauth2/rest.php
Normal file
@ -0,0 +1,105 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Rest API base class mapping rest api methods to endpoints with http methods, args and post body.
|
||||
*
|
||||
* @package core
|
||||
* @copyright 2017 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace core\oauth2;
|
||||
|
||||
use curl;
|
||||
use coding_exception;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
require_once($CFG->libdir . '/filelib.php');
|
||||
|
||||
/**
|
||||
* Rest API base class mapping rest api methods to endpoints with http methods, args and post body.
|
||||
*
|
||||
* @copyright 2017 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
abstract class rest {
|
||||
|
||||
/** @var curl $curl */
|
||||
private $curl;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param curl $curl
|
||||
*/
|
||||
public function __construct(curl $curl) {
|
||||
$this->curl = $curl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Abstract function to define the functions of the rest API.
|
||||
*
|
||||
* @return array Example:
|
||||
* [ 'listFiles' => [ 'method' => 'get', 'args' => [ 'folder' => PARAM_STRING ], 'response' => 'json' ] ]
|
||||
*/
|
||||
public abstract function get_api_functions();
|
||||
|
||||
/**
|
||||
* Call a function from the Api with a set of arguments and optional data.
|
||||
*
|
||||
* @param string $functionname
|
||||
* @param array $functionargs
|
||||
*/
|
||||
public function call($functionname, $functionargs) {
|
||||
$functions = $this->get_api_functions();
|
||||
$supportedmethods = [ 'get', 'put', 'post', 'patch', 'head', 'delete' ];
|
||||
if (empty($functions[$functionname])) {
|
||||
throw new coding_exception('unsupported api functionname: ' . $functionname);
|
||||
}
|
||||
|
||||
$method = $functions[$functionname]['method'];
|
||||
$endpoint = $functions[$functionname]['endpoint'];
|
||||
$responsetype = $functions[$functionname]['response'];
|
||||
if (!in_array($method, $supportedmethods)) {
|
||||
throw new coding_exception('unsupported api method: ' . $method);
|
||||
}
|
||||
|
||||
$args = $functions[$functionname]['args'];
|
||||
$callargs = [];
|
||||
foreach ($args as $argname => $argtype) {
|
||||
if (isset($functionargs[$argname])) {
|
||||
$callargs[$argname] = clean_param($functionargs[$argname], $argtype);
|
||||
}
|
||||
}
|
||||
|
||||
$response = $this->curl->$method($endpoint, $callargs);
|
||||
|
||||
if ($this->curl->errno == 0) {
|
||||
if ($responsetype == 'json') {
|
||||
$json = json_decode($response);
|
||||
|
||||
if (!empty($json->error)) {
|
||||
throw new rest_exception($json->error->message, $json->error->code);
|
||||
}
|
||||
return $json;
|
||||
}
|
||||
return $response;
|
||||
} else {
|
||||
throw new rest_exception($this->curl->error, $this->curl->errno);
|
||||
}
|
||||
}
|
||||
}
|
40
lib/classes/oauth2/rest_exception.php
Normal file
40
lib/classes/oauth2/rest_exception.php
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Rest Exception class containing error code and message.
|
||||
*
|
||||
* @package core
|
||||
* @copyright 2017 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace core\oauth2;
|
||||
|
||||
use Exception;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
require_once($CFG->libdir . '/filelib.php');
|
||||
|
||||
/**
|
||||
* Rest Exception class containing error code and message.
|
||||
*
|
||||
* @copyright 2017 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class rest_exception extends Exception {
|
||||
|
||||
}
|
60
repository/googledocs/classes/rest.php
Normal file
60
repository/googledocs/classes/rest.php
Normal file
@ -0,0 +1,60 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Google Drive Rest API.
|
||||
*
|
||||
* @package repository_googledocs
|
||||
* @copyright 2017 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace repository_googledocs;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Google Drive Rest API.
|
||||
*
|
||||
* @copyright 2017 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class rest extends \core\oauth2\rest {
|
||||
|
||||
/**
|
||||
* Define the functions of the rest API.
|
||||
*
|
||||
* @return array Example:
|
||||
* [ 'listFiles' => [ 'method' => 'get', 'endpoint' => 'http://...', 'args' => [ 'folder' => PARAM_STRING ] ] ]
|
||||
*/
|
||||
public function get_api_functions() {
|
||||
return [
|
||||
'list' => [
|
||||
'endpoint' => 'https://www.googleapis.com/drive/v3/files',
|
||||
'method' => 'get',
|
||||
'args' => [
|
||||
'corpus' => PARAM_RAW,
|
||||
'orderBy' => PARAM_RAW,
|
||||
'fields' => PARAM_RAW,
|
||||
'pageSize' => PARAM_INT,
|
||||
'pageToken' => PARAM_RAW,
|
||||
'q' => PARAM_RAW,
|
||||
'spaces' => PARAM_RAW
|
||||
],
|
||||
'response' => 'json'
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
@ -22,15 +22,21 @@
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
$string['clientid'] = 'Client ID';
|
||||
$string['configplugin'] = 'Configure Google Drive plugin';
|
||||
$string['docsformat'] = 'Default document import format';
|
||||
$string['drawingformat'] = 'Default drawing import format';
|
||||
$string['googledocs:view'] = 'View Google Drive repository';
|
||||
$string['importformat'] = 'Configure the default import formats from google';
|
||||
$string['oauthinfo'] = '<p>To use this plugin, you must register your site with Google, as described in the documentation <a href="{$a->docsurl}">Google OAuth 2.0 setup</a>.</p><p>As part of the registration process, you will need to enter the following URL as \'Authorized Redirect URIs\':</p><p>{$a->callbackurl}</p><p>Once registered, you will be provided with a client ID and secret which can be used to configure all Google Drive and Picasa plugins.</p><p>Please also note that you will have to enable the service \'Drive API\'.</p>';
|
||||
$string['pluginname'] = 'Google Drive';
|
||||
$string['presentationformat'] = 'Default presentation import format';
|
||||
$string['secret'] = 'Secret';
|
||||
$string['servicenotenabled'] = 'Access not configured. Make sure the service \'Drive API\' is enabled.';
|
||||
$string['spreadsheetformat'] = 'Default spreadsheet import format';
|
||||
$string['issuer'] = 'OAuth 2 service';
|
||||
$string['issuer_help'] = 'Select the OAuth 2 service that is configured to talk to the Google Drive API. If the services does not exist yet, you might need to create it.';
|
||||
$string['servicenotenabled'] = 'Access not configured. Make sure the service \'Drive API\' is enabled.';
|
||||
$string['oauth2serviceslink'] = '<a href="{$a}" title="Link to OAuth Services configuration">OAuth 2 Services Configuration</a>';
|
||||
$string['searchfor'] = 'Search for {$a}';
|
||||
|
||||
// Deprecated since Moodle 3.3.
|
||||
$string['oauthinfo'] = '<p>To use this plugin, you must register your site with Google, as described in the documentation <a href="{$a->docsurl}">Google OAuth 2.0 setup</a>.</p><p>As part of the registration process, you will need to enter the following URL as \'Authorized Redirect URIs\':</p><p>{$a->callbackurl}</p><p>Once registered, you will be provided with a client ID and secret which can be used to configure all Google Drive and Picasa plugins.</p><p>Please also note that you will have to enable the service \'Drive API\'.</p>';
|
||||
$string['secret'] = 'Secret';
|
||||
$string['clientid'] = 'Client ID';
|
||||
|
@ -39,28 +39,21 @@ require_once($CFG->libdir . '/google/lib.php');
|
||||
class repository_googledocs extends repository {
|
||||
|
||||
/**
|
||||
* Google Client.
|
||||
* @var Google_Client
|
||||
* OAuth 2 client
|
||||
* @var \core\oauth2\client
|
||||
*/
|
||||
private $client = null;
|
||||
|
||||
/**
|
||||
* Google Drive Service.
|
||||
* @var Google_Drive_Service
|
||||
* OAuth 2 Issuer
|
||||
* @var \core\oauth2\issuer
|
||||
*/
|
||||
private $service = null;
|
||||
private $issuer = null;
|
||||
|
||||
/**
|
||||
* Session key to store the accesstoken.
|
||||
* @var string
|
||||
* Additional scopes required for drive.
|
||||
*/
|
||||
const SESSIONKEY = 'googledrive_accesstoken';
|
||||
|
||||
/**
|
||||
* URI to the callback file for OAuth.
|
||||
* @var string
|
||||
*/
|
||||
const CALLBACKURL = '/admin/oauth2callback.php';
|
||||
const SCOPES = 'https://www.googleapis.com/auth/drive';
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
@ -74,52 +67,26 @@ class repository_googledocs extends repository {
|
||||
public function __construct($repositoryid, $context = SYSCONTEXTID, $options = array(), $readonly = 0) {
|
||||
parent::__construct($repositoryid, $context, $options, $readonly = 0);
|
||||
|
||||
$callbackurl = new moodle_url(self::CALLBACKURL);
|
||||
|
||||
$this->client = get_google_client();
|
||||
$this->client->setClientId(get_config('googledocs', 'clientid'));
|
||||
$this->client->setClientSecret(get_config('googledocs', 'secret'));
|
||||
$this->client->setScopes(array(Google_Service_Drive::DRIVE_READONLY));
|
||||
$this->client->setRedirectUri($callbackurl->out(false));
|
||||
$this->service = new Google_Service_Drive($this->client);
|
||||
|
||||
$this->check_login();
|
||||
$this->issuer = \core\oauth2\api::get_issuer(get_config('googledocs', 'issuerid'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the access token if any.
|
||||
* Get a cached user authenticated oauth client.
|
||||
*
|
||||
* @return string|null access token.
|
||||
* @return \core\oauth2\client
|
||||
*/
|
||||
protected function get_access_token() {
|
||||
global $SESSION;
|
||||
if (isset($SESSION->{self::SESSIONKEY})) {
|
||||
return $SESSION->{self::SESSIONKEY};
|
||||
protected function get_user_oauth_client() {
|
||||
if ($this->client) {
|
||||
return $this->client;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
$returnurl = new moodle_url('/repository/repository_callback.php');
|
||||
$returnurl->param('callback', 'yes');
|
||||
$returnurl->param('repo_id', $this->id);
|
||||
$returnurl->param('sesskey', sesskey());
|
||||
|
||||
/**
|
||||
* Store the access token in the session.
|
||||
*
|
||||
* @param string $token token to store.
|
||||
* @return void
|
||||
*/
|
||||
protected function store_access_token($token) {
|
||||
global $SESSION;
|
||||
$SESSION->{self::SESSIONKEY} = $token;
|
||||
}
|
||||
$this->client = \core\oauth2\api::get_user_oauth_client($this->issuer, $returnurl, self::SCOPES);
|
||||
|
||||
/**
|
||||
* Callback method during authentication.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function callback() {
|
||||
if ($code = optional_param('oauth2code', null, PARAM_RAW)) {
|
||||
$this->client->authenticate($code);
|
||||
$this->store_access_token($this->client->getAccessToken());
|
||||
}
|
||||
return $this->client;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -128,11 +95,8 @@ class repository_googledocs extends repository {
|
||||
* @return bool true when logged in.
|
||||
*/
|
||||
public function check_login() {
|
||||
if ($token = $this->get_access_token()) {
|
||||
$this->client->setAccessToken($token);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
$client = $this->get_user_oauth_client();
|
||||
return $client->is_logged_in();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -141,13 +105,9 @@ class repository_googledocs extends repository {
|
||||
* @return void|array for ajax.
|
||||
*/
|
||||
public function print_login() {
|
||||
$returnurl = new moodle_url('/repository/repository_callback.php');
|
||||
$returnurl->param('callback', 'yes');
|
||||
$returnurl->param('repo_id', $this->id);
|
||||
$returnurl->param('sesskey', sesskey());
|
||||
$client = $this->get_user_oauth_client();
|
||||
$url = $client->get_login_url();
|
||||
|
||||
$url = new moodle_url($this->client->createAuthUrl());
|
||||
$url->param('state', $returnurl->out_as_local_url(false));
|
||||
if ($this->options['ajax']) {
|
||||
$popup = new stdClass();
|
||||
$popup->type = 'popup';
|
||||
@ -159,11 +119,11 @@ class repository_googledocs extends repository {
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the breadcrumb from a path.
|
||||
*
|
||||
* @param string $path to create a breadcrumb from.
|
||||
* @return array containing name and path of each crumb.
|
||||
*/
|
||||
* Build the breadcrumb from a path.
|
||||
*
|
||||
* @param string $path to create a breadcrumb from.
|
||||
* @return array containing name and path of each crumb.
|
||||
*/
|
||||
protected function build_breadcrumb($path) {
|
||||
$bread = explode('/', $path);
|
||||
$crumbtrail = '';
|
||||
@ -181,15 +141,15 @@ class repository_googledocs extends repository {
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a safe path to a node.
|
||||
*
|
||||
* Typically, a node will be id|Name of the node.
|
||||
*
|
||||
* @param string $id of the node.
|
||||
* @param string $name of the node, will be URL encoded.
|
||||
* @param string $root to append the node on, must be a result of this function.
|
||||
* @return string path to the node.
|
||||
*/
|
||||
* Generates a safe path to a node.
|
||||
*
|
||||
* Typically, a node will be id|Name of the node.
|
||||
*
|
||||
* @param string $id of the node.
|
||||
* @param string $name of the node, will be URL encoded.
|
||||
* @param string $root to append the node on, must be a result of this function.
|
||||
* @return string path to the node.
|
||||
*/
|
||||
protected function build_node_path($id, $name = '', $root = '') {
|
||||
$path = $id;
|
||||
if (!empty($name)) {
|
||||
@ -202,12 +162,12 @@ class repository_googledocs extends repository {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns information about a node in a path.
|
||||
*
|
||||
* @see self::build_node_path()
|
||||
* @param string $node to extrat information from.
|
||||
* @return array about the node.
|
||||
*/
|
||||
* Returns information about a node in a path.
|
||||
*
|
||||
* @see self::build_node_path()
|
||||
* @param string $node to extrat information from.
|
||||
* @return array about the node.
|
||||
*/
|
||||
protected function explode_node_path($node) {
|
||||
if (strpos($node, '|') !== false) {
|
||||
list($id, $name) = explode('|', $node, 2);
|
||||
@ -265,16 +225,17 @@ class repository_googledocs extends repository {
|
||||
/**
|
||||
* Search throughout the Google Drive.
|
||||
*
|
||||
* @param string $search_text text to search for.
|
||||
* @param string $searchtext text to search for.
|
||||
* @param int $page search page.
|
||||
* @return array of results.
|
||||
*/
|
||||
public function search($search_text, $page = 0) {
|
||||
public function search($searchtext, $page = 0) {
|
||||
$path = $this->build_node_path('root', get_string('pluginname', 'repository_googledocs'));
|
||||
$path = $this->build_node_path('search', $search_text, $path);
|
||||
$str = get_string('searchfor', 'repository_googledocs', $searchtext);
|
||||
$path = $this->build_node_path('search', $str, $path);
|
||||
|
||||
// Query the Drive.
|
||||
$q = "fullText contains '" . str_replace("'", "\'", $search_text) . "'";
|
||||
$q = "fullText contains '" . str_replace("'", "\'", $searchtext) . "'";
|
||||
$q .= ' AND trashed = false';
|
||||
$results = $this->query($q, $path);
|
||||
|
||||
@ -304,14 +265,17 @@ class repository_googledocs extends repository {
|
||||
|
||||
$files = array();
|
||||
$folders = array();
|
||||
$fields = "items(id,title,mimeType,downloadUrl,fileExtension,exportLinks,modifiedDate,fileSize,thumbnailLink)";
|
||||
$params = array('q' => $q, 'fields' => $fields);
|
||||
$config = get_config('googledocs');
|
||||
$fields = "files(id,name,mimeType,webContentLink,fileExtension,modifiedTime,size,thumbnailLink,iconLink)";
|
||||
$params = array('q' => $q, 'fields' => $fields, 'spaces' => 'drive');
|
||||
|
||||
try {
|
||||
// Retrieving files and folders.
|
||||
$response = $this->service->files->listFiles($params);
|
||||
} catch (Google_Service_Exception $e) {
|
||||
$client = $this->get_user_oauth_client();
|
||||
$service = new repository_googledocs\rest($client);
|
||||
|
||||
$response = $service->call('list', $params);
|
||||
} catch (Exception $e) {
|
||||
if ($e->getCode() == 403 && strpos($e->getMessage(), 'Access Not Configured') !== false) {
|
||||
// This is raised when the service Drive API has not been enabled on Google APIs control panel.
|
||||
throw new repository_exception('servicenotenabled', 'repository_googledocs');
|
||||
@ -320,14 +284,15 @@ class repository_googledocs extends repository {
|
||||
}
|
||||
}
|
||||
|
||||
$items = isset($response['items']) ? $response['items'] : array();
|
||||
foreach ($items as $item) {
|
||||
if ($item['mimeType'] == 'application/vnd.google-apps.folder') {
|
||||
$base = 'https://www.googleapis.com/drive/v3';
|
||||
$gfiles = isset($response->files) ? $response->files : array();
|
||||
foreach ($gfiles as $gfile) {
|
||||
if ($gfile->mimeType == 'application/vnd.google-apps.folder') {
|
||||
// This is a folder.
|
||||
$folders[$item['title'] . $item['id']] = array(
|
||||
'title' => $item['title'],
|
||||
'path' => $this->build_node_path($item['id'], $item['title'], $path),
|
||||
'date' => strtotime($item['modifiedDate']),
|
||||
$folders[$gfile->name . $gfile->id] = array(
|
||||
'title' => $gfile->name,
|
||||
'path' => $this->build_node_path($gfile->id, $gfile->name, $path),
|
||||
'date' => strtotime($gfile->modifiedTime),
|
||||
'thumbnail' => $OUTPUT->image_url(file_folder_icon(64))->out(false),
|
||||
'thumbnail_height' => 64,
|
||||
'thumbnail_width' => 64,
|
||||
@ -335,16 +300,18 @@ class repository_googledocs extends repository {
|
||||
);
|
||||
} else {
|
||||
// This is a file.
|
||||
if (isset($item['fileExtension'])) {
|
||||
// The file has an extension, therefore there is a download link.
|
||||
$title = $item['title'];
|
||||
$source = $item['downloadUrl'];
|
||||
if (isset($gfile->fileExtension)) {
|
||||
// The file has an extension, therefore we can download it.
|
||||
$title = $gfile->name;
|
||||
$params = ['alt' => 'media'];
|
||||
$sourceurl = new moodle_url($base . '/files/' . $gfile->id, $params);
|
||||
$source = $sourceurl->out(false);
|
||||
} else {
|
||||
// The file is probably a Google Doc file, we get the corresponding export link.
|
||||
// This should be improved by allowing the user to select the type of export they'd like.
|
||||
$type = str_replace('application/vnd.google-apps.', '', $item['mimeType']);
|
||||
$type = str_replace('application/vnd.google-apps.', '', $gfile->mimeType);
|
||||
$title = '';
|
||||
$exportType = '';
|
||||
$exporttype = '';
|
||||
$types = get_mimetypes_array();
|
||||
|
||||
switch ($type){
|
||||
@ -355,54 +322,52 @@ class repository_googledocs extends repository {
|
||||
// Moodle user 'text/rtf' as the MIME type for RTF files.
|
||||
// Google uses 'application/rtf' for the same type of file.
|
||||
// See https://developers.google.com/drive/v3/web/manage-downloads.
|
||||
$exportType = 'application/rtf';
|
||||
$exporttype = 'application/rtf';
|
||||
} else {
|
||||
$exportType = $types[$ext]['type'];
|
||||
$exporttype = $types[$ext]['type'];
|
||||
}
|
||||
break;
|
||||
case 'presentation':
|
||||
$ext = $config->presentationformat;
|
||||
$title = $item['title'] . '.'. $ext;
|
||||
$exportType = $types[$ext]['type'];
|
||||
$exporttype = $types[$ext]['type'];
|
||||
break;
|
||||
case 'spreadsheet':
|
||||
$ext = $config->spreadsheetformat;
|
||||
$title = $item['title'] . '.'. $ext;
|
||||
$exportType = $types[$ext]['type'];
|
||||
$exporttype = $types[$ext]['type'];
|
||||
break;
|
||||
case 'drawing':
|
||||
$ext = $config->drawingformat;
|
||||
$title = $item['title'] . '.'. $ext;
|
||||
$exportType = $types[$ext]['type'];
|
||||
$exporttype = $types[$ext]['type'];
|
||||
break;
|
||||
}
|
||||
// Skips invalid/unknown types.
|
||||
if (empty($title) || !isset($item['exportLinks'][$exportType])) {
|
||||
if (empty($title)) {
|
||||
continue;
|
||||
}
|
||||
$source = $item['exportLinks'][$exportType];
|
||||
$params = ['mimeType' => $exporttype];
|
||||
$sourceurl = new moodle_url($base . '/files/' . $gfile->id . '/export', $params);
|
||||
$source = $sourceurl->out(false);
|
||||
}
|
||||
// Adds the file to the file list. Using the itemId along with the title as key
|
||||
// Adds the file to the file list. Using the itemId along with the name as key
|
||||
// of the array because Google Drive allows files with identical names.
|
||||
$files[$title . $item['id']] = array(
|
||||
$thumb = '';
|
||||
if (isset($gfile->thumbnailLink)) {
|
||||
$thumb = $gfile->thumbnailLink;
|
||||
} else if (isset($gfile->iconLink)) {
|
||||
$thumb = $gfile->iconLink;
|
||||
}
|
||||
$files[$title . $gfile->id] = array(
|
||||
'title' => $title,
|
||||
'source' => $source,
|
||||
'date' => strtotime($item['modifiedDate']),
|
||||
'size' => isset($item['fileSize']) ? $item['fileSize'] : null,
|
||||
'thumbnail' => $OUTPUT->image_url(file_extension_icon($title, 64))->out(false),
|
||||
'date' => strtotime($gfile->modifiedTime),
|
||||
'size' => isset($gfile->size) ? $gfile->size : null,
|
||||
'thumbnail' => $thumb,
|
||||
'thumbnail_height' => 64,
|
||||
'thumbnail_width' => 64,
|
||||
// Do not use real thumbnails as they wouldn't work if the user disabled 3rd party
|
||||
// plugins in his browser, or if they're not logged in their Google account.
|
||||
);
|
||||
|
||||
// Sometimes the real thumbnails can't be displayed, for example if 3rd party cookies are disabled
|
||||
// or if the user is not logged in Google anymore. But this restriction does not seem to be applied
|
||||
// to a small subset of files.
|
||||
$extension = strtolower(pathinfo($title, PATHINFO_EXTENSION));
|
||||
if (isset($item['thumbnailLink']) && in_array($extension, array('jpg', 'png', 'txt', 'pdf'))) {
|
||||
$files[$title . $item['id']]['realthumbnail'] = $item['thumbnailLink'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -419,7 +384,8 @@ class repository_googledocs extends repository {
|
||||
* @return string
|
||||
*/
|
||||
public function logout() {
|
||||
$this->store_access_token(null);
|
||||
$client = $this->get_user_oauth_client();
|
||||
$client->log_out();
|
||||
return parent::logout();
|
||||
}
|
||||
|
||||
@ -433,18 +399,18 @@ class repository_googledocs extends repository {
|
||||
public function get_file($reference, $filename = '') {
|
||||
global $CFG;
|
||||
|
||||
$auth = $this->client->getAuth();
|
||||
$request = $auth->authenticatedRequest(new Google_Http_Request($reference));
|
||||
if ($request->getResponseHttpCode() == 200) {
|
||||
$path = $this->prepare_file($filename);
|
||||
$content = $request->getResponseBody();
|
||||
if (file_put_contents($path, $content) !== false) {
|
||||
@chmod($path, $CFG->filepermissions);
|
||||
return array(
|
||||
'path' => $path,
|
||||
'url' => $reference
|
||||
);
|
||||
}
|
||||
$client = $this->get_user_oauth_client();
|
||||
|
||||
$path = $this->prepare_file($filename);
|
||||
$options = ['filepath' => $path, 'timeout' => 15, 'followlocation' => true, 'maxredirs' => 5];
|
||||
$result = $client->download_one($reference, null, $options);
|
||||
|
||||
if ($result) {
|
||||
@chmod($path, $CFG->filepermissions);
|
||||
return array(
|
||||
'path' => $path,
|
||||
'url' => $reference
|
||||
);
|
||||
}
|
||||
throw new repository_exception('cannotdownload', 'repository');
|
||||
}
|
||||
@ -490,11 +456,20 @@ class repository_googledocs extends repository {
|
||||
* @return array
|
||||
*/
|
||||
public static function get_type_option_names() {
|
||||
return array('clientid', 'secret', 'pluginname',
|
||||
return array('issuerid', 'pluginname',
|
||||
'documentformat', 'drawingformat',
|
||||
'presentationformat', 'spreadsheetformat');
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the access token.
|
||||
*/
|
||||
public function callback() {
|
||||
$client = $this->get_user_oauth_client();
|
||||
// This will upgrade to an access token if we have an authorization code.
|
||||
$client->is_logged_in();
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit/Create Admin Settings Moodle form.
|
||||
*
|
||||
@ -502,25 +477,24 @@ class repository_googledocs extends repository {
|
||||
* @param string $classname repository class name.
|
||||
*/
|
||||
public static function type_config_form($mform, $classname = 'repository') {
|
||||
$callbackurl = new moodle_url(self::CALLBACKURL);
|
||||
$url = (string)new moodle_url('/admin/tool/oauth2/issuers.php');
|
||||
|
||||
$a = new stdClass;
|
||||
$a->docsurl = get_docs_url('Google_OAuth_2.0_setup');
|
||||
$a->callbackurl = $callbackurl->out(false);
|
||||
|
||||
$mform->addElement('static', null, '', get_string('oauthinfo', 'repository_googledocs', $a));
|
||||
$mform->addElement('static', null, '', get_string('oauth2serviceslink', 'repository_googledocs', $url));
|
||||
|
||||
parent::type_config_form($mform);
|
||||
$mform->addElement('text', 'clientid', get_string('clientid', 'repository_googledocs'));
|
||||
$mform->setType('clientid', PARAM_RAW_TRIMMED);
|
||||
$mform->addElement('text', 'secret', get_string('secret', 'repository_googledocs'));
|
||||
$mform->setType('secret', PARAM_RAW_TRIMMED);
|
||||
$options = [];
|
||||
$issuers = \core\oauth2\api::get_all_issuers();
|
||||
|
||||
foreach ($issuers as $issuer) {
|
||||
$options[$issuer->get('id')] = s($issuer->get('name'));
|
||||
}
|
||||
$mform->addElement('select', 'issuerid', get_string('issuer', 'repository_googledocs'), $options);
|
||||
$mform->addHelpButton('issuerid', 'issuer', 'repository_googledocs');
|
||||
$mform->addRule('issuerid', $strrequired, 'required', null, 'client');
|
||||
|
||||
$strrequired = get_string('required');
|
||||
$mform->addRule('clientid', $strrequired, 'required', null, 'client');
|
||||
$mform->addRule('secret', $strrequired, 'required', null, 'client');
|
||||
|
||||
$mform->addElement('static', null, '', get_string('importformat', 'repository_googledocs', $a));
|
||||
$mform->addElement('static', null, '', get_string('importformat', 'repository_googledocs'));
|
||||
|
||||
// Documents.
|
||||
$docsformat = array();
|
||||
|
@ -23,6 +23,9 @@
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
use \core\oauth2\issuer;
|
||||
use \core\oauth2\endpoint;
|
||||
|
||||
/**
|
||||
* Google Docs repository data generator class
|
||||
*
|
||||
@ -41,11 +44,27 @@ class repository_googledocs_generator extends testing_repository_generator {
|
||||
*/
|
||||
protected function prepare_type_record(array $record) {
|
||||
$record = parent::prepare_type_record($record);
|
||||
if (!isset($record['clientid'])) {
|
||||
$record['clientid'] = 'clientid';
|
||||
}
|
||||
if (!isset($record['secret'])) {
|
||||
$record['secret'] = 'secret';
|
||||
$issuerrecord = (object) [
|
||||
'name' => 'Google',
|
||||
'image' => 'https://accounts.google.com/favicon.ico',
|
||||
'baseurl' => 'http://accounts.google.com/',
|
||||
'loginparamsoffline' => 'access_type=offline&prompt=consent',
|
||||
'showonloginpage' => true
|
||||
];
|
||||
|
||||
$issuer = new issuer(0, $issuerrecord);
|
||||
$issuer->create();
|
||||
|
||||
$endpointrecord = (object) [
|
||||
'issuerid' => $issuer->get('id'),
|
||||
'name' => 'discovery_endpoint',
|
||||
'url' => 'https://accounts.google.com/.well-known/openid-configuration'
|
||||
];
|
||||
$endpoint = new endpoint(0, $endpointrecord);
|
||||
$endpoint->create();
|
||||
|
||||
if (!isset($record['issuerid'])) {
|
||||
$record['issuerid'] = $issuer->get('id');
|
||||
}
|
||||
if (!isset($record['documentformat'])) {
|
||||
$record['documentformat'] = 'pdf';
|
||||
|
Loading…
x
Reference in New Issue
Block a user