Differences Between: [Versions 310 and 402] [Versions 311 and 402] [Versions 39 and 402] [Versions 402 and 403]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 /** 18 * Simple implementation of some Google API functions for Moodle. 19 * 20 * @package core 21 * @copyright Dan Poltawski <talktodan@gmail.com> 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 25 defined('MOODLE_INTERNAL') || die(); 26 27 require_once($CFG->libdir.'/filelib.php'); 28 require_once($CFG->libdir.'/oauthlib.php'); 29 30 /** 31 * Class for manipulating google documents through the google data api. 32 * 33 * Docs for this can be found here: 34 * {@link http://code.google.com/apis/documents/docs/2.0/developers_guide_protocol.html} 35 * 36 * @package core 37 * @subpackage lib 38 * @copyright Dan Poltawski <talktodan@gmail.com> 39 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 40 */ 41 class google_docs { 42 /** @var string Realm for authentication, need both docs and spreadsheet realm */ 43 const REALM = 'https://docs.google.com/feeds/ https://spreadsheets.google.com/feeds/ https://docs.googleusercontent.com/'; 44 /** @var string Document list url */ 45 const DOCUMENTFEED_URL = 'https://docs.google.com/feeds/default/private/full'; 46 /** @var string Upload url */ 47 const UPLOAD_URL = 'https://docs.google.com/feeds/upload/create-session/default/private/full?convert=false'; 48 49 /** @var google_oauth oauth curl class for making authenticated requests */ 50 private $googleoauth = null; 51 52 /** 53 * Constructor. 54 * 55 * @param google_oauth $googleoauth oauth curl class for making authenticated requests 56 */ 57 public function __construct(google_oauth $googleoauth) { 58 $this->googleoauth = $googleoauth; 59 $this->reset_curl_state(); 60 } 61 62 /** 63 * Resets state on oauth curl object and set GData protocol 64 * version 65 */ 66 private function reset_curl_state() { 67 $this->googleoauth->reset_state(); 68 $this->googleoauth->setHeader('GData-Version: 3.0'); 69 } 70 71 /** 72 * Returns a list of files the user has formated for files api 73 * 74 * @param string $search A search string to do full text search on the documents 75 * @return mixed Array of files formated for fileapoi 76 */ 77 public function get_file_list($search = '') { 78 global $CFG, $OUTPUT; 79 $url = self::DOCUMENTFEED_URL; 80 81 if ($search) { 82 $url.='?q='.urlencode($search); 83 } 84 85 $files = array(); 86 $content = $this->googleoauth->get($url); 87 try { 88 if (strpos($content, '<?xml') !== 0) { 89 throw new moodle_exception('invalidxmlresponse'); 90 } 91 $xml = new SimpleXMLElement($content); 92 } catch (Exception $e) { 93 // An error occured while trying to parse the XML, let's just return nothing. SimpleXML does not 94 // return a more specific Exception, that's why the global Exception class is caught here. 95 return $files; 96 } 97 date_default_timezone_set(core_date::get_user_timezone()); 98 foreach ($xml->entry as $gdoc) { 99 $docid = (string) $gdoc->children('http://schemas.google.com/g/2005')->resourceId; 100 list($type, $docid) = explode(':', $docid); 101 102 $title = ''; 103 $source = ''; 104 // FIXME: We're making hard-coded choices about format here. 105 // If the repo api can support it, we could let the user 106 // chose. 107 switch($type){ 108 case 'document': 109 $title = $gdoc->title.'.rtf'; 110 $source = 'https://docs.google.com/feeds/download/documents/Export?id='.$docid.'&exportFormat=rtf'; 111 break; 112 case 'presentation': 113 $title = $gdoc->title.'.ppt'; 114 $source = 'https://docs.google.com/feeds/download/presentations/Export?id='.$docid.'&exportFormat=ppt'; 115 break; 116 case 'spreadsheet': 117 $title = $gdoc->title.'.xls'; 118 $source = 'https://spreadsheets.google.com/feeds/download/spreadsheets/Export?key='.$docid.'&exportFormat=xls'; 119 break; 120 case 'pdf': 121 case 'file': 122 $title = (string)$gdoc->title; 123 // Some files don't have a content probably because the download has been restricted. 124 if (isset($gdoc->content)) { 125 $source = (string)$gdoc->content[0]->attributes()->src; 126 } 127 break; 128 } 129 130 $files[] = array( 'title' => $title, 131 'url' => "{$gdoc->link[0]->attributes()->href}", 132 'source' => $source, 133 'date' => strtotime($gdoc->updated), 134 'thumbnail' => (string) $OUTPUT->image_url(file_extension_icon($title, 32)) 135 ); 136 } 137 core_date::set_default_server_timezone(); 138 139 return $files; 140 } 141 142 /** 143 * Sends a file object to google documents 144 * 145 * @param object $file File object 146 * @return boolean True on success 147 */ 148 public function send_file($file) { 149 // First we create the 'resumable upload request'. 150 $this->googleoauth->setHeader("Content-Length: 0"); 151 $this->googleoauth->setHeader("X-Upload-Content-Length: ". $file->get_filesize()); 152 $this->googleoauth->setHeader("X-Upload-Content-Type: ". $file->get_mimetype()); 153 $this->googleoauth->setHeader("Slug: ". $file->get_filename()); 154 $this->googleoauth->post(self::UPLOAD_URL); 155 156 if ($this->googleoauth->info['http_code'] !== 200) { 157 throw new moodle_exception('Cantpostupload'); 158 } 159 160 // Now we http PUT the file in the location returned. 161 $location = $this->googleoauth->response['Location']; 162 if (empty($location)) { 163 throw new moodle_exception('Nouploadlocation'); 164 } 165 166 // Reset the curl object for actually sending the file. 167 $this->reset_curl_state(); 168 $this->googleoauth->setHeader("Content-Length: ". $file->get_filesize()); 169 $this->googleoauth->setHeader("Content-Type: ". $file->get_mimetype()); 170 171 // We can't get a filepointer, so have to copy the file.. 172 $tmproot = make_temp_directory('googledocsuploads'); 173 $tmpfilepath = $tmproot.'/'.$file->get_contenthash(); 174 $file->copy_content_to($tmpfilepath); 175 176 // HTTP PUT the file. 177 $this->googleoauth->put($location, array('file'=>$tmpfilepath)); 178 179 // Remove the temporary file we created.. 180 unlink($tmpfilepath); 181 182 if ($this->googleoauth->info['http_code'] === 201) { 183 // Clear headers for further requests. 184 $this->reset_curl_state(); 185 return true; 186 } else { 187 return false; 188 } 189 } 190 191 /** 192 * Downloads a file using authentication 193 * 194 * @param string $url url of file 195 * @param string $path path to save file to 196 * @param int $timeout request timeout, default 0 which means no timeout 197 * @return array stucture for repository download_file 198 */ 199 public function download_file($url, $path, $timeout = 0) { 200 $result = $this->googleoauth->download_one($url, null, array('filepath' => $path, 'timeout' => $timeout)); 201 if ($result === true) { 202 $info = $this->googleoauth->get_info(); 203 if (isset($info['http_code']) && $info['http_code'] == 200) { 204 return array('path'=>$path, 'url'=>$url); 205 } else { 206 throw new moodle_exception('cannotdownload', 'repository'); 207 } 208 } else { 209 throw new moodle_exception('errorwhiledownload', 'repository', '', $result); 210 } 211 } 212 } 213 214 /** 215 * OAuth 2.0 client for Google Services 216 * 217 * @package core 218 * @copyright 2012 Dan Poltawski 219 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 220 */ 221 class google_oauth extends oauth2_client { 222 /** 223 * Returns the auth url for OAuth 2.0 request 224 * @return string the auth url 225 */ 226 protected function auth_url() { 227 return 'https://accounts.google.com/o/oauth2/auth'; 228 } 229 230 /** 231 * Returns the token url for OAuth 2.0 request 232 * @return string the auth url 233 */ 234 protected function token_url() { 235 return 'https://accounts.google.com/o/oauth2/token'; 236 } 237 238 /** 239 * Resets headers and response for multiple requests 240 */ 241 public function reset_state() { 242 $this->header = array(); 243 $this->response = array(); 244 } 245 246 /** 247 * Make a HTTP request, we override the parents because we do not 248 * want to send accept headers (this was a change in the parent class and we want to keep the old behaviour). 249 * 250 * @param string $url The URL to request 251 * @param array $options 252 * @param mixed $acceptheader Not used. 253 * @return bool 254 */ 255 protected function request($url, $options = array(), $acceptheader = 'application/json') { 256 return parent::request($url, $options, false); 257 } 258 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body