2 // This file is part of Moodle - http://moodle.org/
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.
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.
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/>.
18 * Google Documents Portfolio Plugin
20 * @author Dan Poltawski <talktodan@gmail.com>
21 * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
23 require_once($CFG->libdir.'/portfolio/plugin.php');
24 require_once($CFG->libdir . '/google/lib.php');
25 require_once($CFG->libdir . '/google/Google/Service/Drive.php');
27 class portfolio_plugin_googledocs extends portfolio_plugin_push_base {
32 private $client = null;
35 * Google Drive Service.
36 * @var Google_Service_Drive
38 private $service = null;
41 * URL to redirect Google to.
44 const REDIRECTURL = '/admin/oauth2callback.php';
46 * Key in session which stores token (_drive_file is access level).
49 const SESSIONKEY = 'googledrive_accesstoken_drive_file';
51 public function supported_formats() {
52 return array(PORTFOLIO_FORMAT_FILE, PORTFOLIO_FORMAT_RICHHTML);
55 public static function get_name() {
56 return get_string('pluginname', 'portfolio_googledocs');
59 public function prepare_package() {
60 // We send the files as they are, no prep required.
64 public function get_interactive_continue_url() {
65 return 'http://drive.google.com/';
68 public function expected_time($callertime) {
69 // We're forcing this to be run 'interactively' because the plugin
70 // does not support running in cron.
71 return PORTFOLIO_TIME_LOW;
74 public function send_package() {
76 throw new portfolio_plugin_exception('noauthtoken', 'portfolio_googledocs');
79 foreach ($this->exporter->get_tempfiles() as $file) {
81 // Create drivefile object and fill it with data.
82 $drivefile = new Google_Service_Drive_DriveFile();
83 $drivefile->setTitle($file->get_filename());
84 $drivefile->setMimeType($file->get_mimetype());
86 $filecontent = $file->get_content();
87 $createdfile = $this->service->files->insert($drivefile,
88 array('data' => $filecontent,
89 'mimeType' => $file->get_mimetype(),
90 'uploadType' => 'multipart'));
91 } catch ( Exception $e ) {
92 throw new portfolio_plugin_exception('sendfailed', 'portfolio_gdocs', $file->get_filename());
98 * Gets the access token from session and sets it to client.
100 * @return null|string null or token.
102 private function get_access_token() {
104 if (isset($SESSION->{self::SESSIONKEY}) && $SESSION->{self::SESSIONKEY}) {
105 $this->client->setAccessToken($SESSION->{self::SESSIONKEY});
106 return $SESSION->{self::SESSIONKEY};
111 * Sets the access token to session
113 * @param string $token access token in json format
116 private function set_access_token($token) {
118 $SESSION->{self::SESSIONKEY} = $token;
121 public function steal_control($stage) {
123 if ($stage != PORTFOLIO_STAGE_CONFIG) {
127 $this->initialize_oauth();
128 if ($this->get_access_token()) {
129 // Ensure that token is not expired.
130 if (!$this->client->isAccessTokenExpired()) {
134 return $this->client->createAuthUrl();
138 public function post_control($stage, $params) {
139 if ($stage != PORTFOLIO_STAGE_CONFIG) {
142 // Get the authentication code send by Google.
143 $code = isset($params['oauth2code']) ? $params['oauth2code'] : null;
144 // Try to authenticate (throws exception which is catched higher).
145 $this->client->authenticate($code);
146 // Make sure we accually have access token at this time
147 // ...and store it for further use.
148 if ($accesstoken = $this->client->getAccessToken()) {
149 $this->set_access_token($accesstoken);
151 throw new portfolio_plugin_exception('nosessiontoken', 'portfolio_gdocs');
155 public static function allows_multiple_instances() {
159 public static function has_admin_config() {
163 public static function get_allowed_config() {
164 return array('clientid', 'secret');
167 public static function admin_config_form(&$mform) {
169 $a->docsurl = get_docs_url('Google_OAuth_2.0_setup');
170 $a->callbackurl = (new moodle_url(self::REDIRECTURL))->out(false);
172 $mform->addElement('static', null, '', get_string('oauthinfo', 'portfolio_googledocs', $a));
174 $mform->addElement('text', 'clientid', get_string('clientid', 'portfolio_googledocs'));
175 $mform->setType('clientid', PARAM_RAW_TRIMMED);
176 $mform->addElement('text', 'secret', get_string('secret', 'portfolio_googledocs'));
177 $mform->setType('secret', PARAM_RAW_TRIMMED);
179 $strrequired = get_string('required');
180 $mform->addRule('clientid', $strrequired, 'required', null, 'client');
181 $mform->addRule('secret', $strrequired, 'required', null, 'client');
184 private function initialize_oauth() {
185 $redirecturi = new moodle_url(self::REDIRECTURL);
186 $returnurl = new moodle_url('/portfolio/add.php');
187 $returnurl->param('postcontrol', 1);
188 $returnurl->param('id', $this->exporter->get('id'));
189 $returnurl->param('sesskey', sesskey());
191 $clientid = $this->get_config('clientid');
192 $secret = $this->get_config('secret');
194 // Setup Google client.
195 $this->client = get_google_client();
196 $this->client->setClientId($clientid);
197 $this->client->setClientSecret($secret);
198 $this->client->setScopes(array(Google_Service_Drive::DRIVE_FILE));
199 $this->client->setRedirectUri($redirecturi->out(false));
200 // URL to be called when redirecting from authentication.
201 $this->client->setState($returnurl->out_as_local_url(false));
202 // Setup drive upload service.
203 $this->service = new Google_Service_Drive($this->client);
207 public function instance_sanity_check() {
208 $clientid = $this->get_config('clientid');
209 $secret = $this->get_config('secret');
211 // If there is no oauth config (e.g. plugins upgraded from < 2.3 then
212 // there will be no config and this plugin should be disabled.
213 if (empty($clientid) or empty($secret)) {
214 return 'nooauthcredentials';