[ Index ] |
PHP Cross Reference of moodle-2.8 |
[Summary view] [Print] [Text view]
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 <[email protected]> 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 <[email protected]> 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 foreach ($xml->entry as $gdoc) { 98 $docid = (string) $gdoc->children('http://schemas.google.com/g/2005')->resourceId; 99 list($type, $docid) = explode(':', $docid); 100 101 $title = ''; 102 $source = ''; 103 // FIXME: We're making hard-coded choices about format here. 104 // If the repo api can support it, we could let the user 105 // chose. 106 switch($type){ 107 case 'document': 108 $title = $gdoc->title.'.rtf'; 109 $source = 'https://docs.google.com/feeds/download/documents/Export?id='.$docid.'&exportFormat=rtf'; 110 break; 111 case 'presentation': 112 $title = $gdoc->title.'.ppt'; 113 $source = 'https://docs.google.com/feeds/download/presentations/Export?id='.$docid.'&exportFormat=ppt'; 114 break; 115 case 'spreadsheet': 116 $title = $gdoc->title.'.xls'; 117 $source = 'https://spreadsheets.google.com/feeds/download/spreadsheets/Export?key='.$docid.'&exportFormat=xls'; 118 break; 119 case 'pdf': 120 case 'file': 121 $title = (string)$gdoc->title; 122 // Some files don't have a content probably because the download has been restricted. 123 if (isset($gdoc->content)) { 124 $source = (string)$gdoc->content[0]->attributes()->src; 125 } 126 break; 127 } 128 129 $files[] = array( 'title' => $title, 130 'url' => "{$gdoc->link[0]->attributes()->href}", 131 'source' => $source, 132 'date' => usertime(strtotime($gdoc->updated)), 133 'thumbnail' => (string) $OUTPUT->pix_url(file_extension_icon($title, 32)) 134 ); 135 } 136 137 return $files; 138 } 139 140 /** 141 * Sends a file object to google documents 142 * 143 * @param object $file File object 144 * @return boolean True on success 145 */ 146 public function send_file($file) { 147 // First we create the 'resumable upload request'. 148 $this->googleoauth->setHeader("Content-Length: 0"); 149 $this->googleoauth->setHeader("X-Upload-Content-Length: ". $file->get_filesize()); 150 $this->googleoauth->setHeader("X-Upload-Content-Type: ". $file->get_mimetype()); 151 $this->googleoauth->setHeader("Slug: ". $file->get_filename()); 152 $this->googleoauth->post(self::UPLOAD_URL); 153 154 if ($this->googleoauth->info['http_code'] !== 200) { 155 throw new moodle_exception('Cantpostupload'); 156 } 157 158 // Now we http PUT the file in the location returned. 159 $location = $this->googleoauth->response['Location']; 160 if (empty($location)) { 161 throw new moodle_exception('Nouploadlocation'); 162 } 163 164 // Reset the curl object for actually sending the file. 165 $this->reset_curl_state(); 166 $this->googleoauth->setHeader("Content-Length: ". $file->get_filesize()); 167 $this->googleoauth->setHeader("Content-Type: ". $file->get_mimetype()); 168 169 // We can't get a filepointer, so have to copy the file.. 170 $tmproot = make_temp_directory('googledocsuploads'); 171 $tmpfilepath = $tmproot.'/'.$file->get_contenthash(); 172 $file->copy_content_to($tmpfilepath); 173 174 // HTTP PUT the file. 175 $this->googleoauth->put($location, array('file'=>$tmpfilepath)); 176 177 // Remove the temporary file we created.. 178 unlink($tmpfilepath); 179 180 if ($this->googleoauth->info['http_code'] === 201) { 181 // Clear headers for further requests. 182 $this->reset_curl_state(); 183 return true; 184 } else { 185 return false; 186 } 187 } 188 189 /** 190 * Downloads a file using authentication 191 * 192 * @param string $url url of file 193 * @param string $path path to save file to 194 * @param int $timeout request timeout, default 0 which means no timeout 195 * @return array stucture for repository download_file 196 */ 197 public function download_file($url, $path, $timeout = 0) { 198 $result = $this->googleoauth->download_one($url, null, array('filepath' => $path, 'timeout' => $timeout)); 199 if ($result === true) { 200 $info = $this->googleoauth->get_info(); 201 if (isset($info['http_code']) && $info['http_code'] == 200) { 202 return array('path'=>$path, 'url'=>$url); 203 } else { 204 throw new moodle_exception('cannotdownload', 'repository'); 205 } 206 } else { 207 throw new moodle_exception('errorwhiledownload', 'repository', '', $result); 208 } 209 } 210 } 211 212 /** 213 * Class for manipulating picasa through the google data api. 214 * 215 * Docs for this can be found here: 216 * {@link http://code.google.com/apis/picasaweb/developers_guide_protocol.html} 217 * 218 * @package core 219 * @copyright Dan Poltawski <[email protected]> 220 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 221 */ 222 class google_picasa { 223 /** @var string Realm for authentication */ 224 const REALM = 'http://picasaweb.google.com/data/'; 225 /** @var string Upload url */ 226 const UPLOAD_LOCATION = 'https://picasaweb.google.com/data/feed/api/user/default/albumid/default'; 227 /** @var string photo list url */ 228 const ALBUM_PHOTO_LIST = 'https://picasaweb.google.com/data/feed/api/user/default/albumid/'; 229 /** @var string search url */ 230 const PHOTO_SEARCH_URL = 'https://picasaweb.google.com/data/feed/api/user/default?kind=photo&q='; 231 /** @var string album list url */ 232 const LIST_ALBUMS_URL = 'https://picasaweb.google.com/data/feed/api/user/default'; 233 /** @var string manage files url */ 234 const MANAGE_URL = 'http://picasaweb.google.com/'; 235 236 /** @var google_oauth oauth curl class for making authenticated requests */ 237 private $googleoauth = null; 238 /** @var string Last album name retrievied */ 239 private $lastalbumname = null; 240 241 /** 242 * Constructor. 243 * 244 * @param google_oauth $googleoauth oauth curl class for making authenticated requests 245 */ 246 public function __construct(google_oauth $googleoauth) { 247 $this->googleoauth = $googleoauth; 248 $this->googleoauth->setHeader('GData-Version: 2'); 249 } 250 251 /** 252 * Sends a file object to picasaweb 253 * 254 * @param object $file File object 255 * @return boolean True on success 256 */ 257 public function send_file($file) { 258 $this->googleoauth->setHeader("Content-Length: ". $file->get_filesize()); 259 $this->googleoauth->setHeader("Content-Type: ". $file->get_mimetype()); 260 $this->googleoauth->setHeader("Slug: ". $file->get_filename()); 261 262 $this->googleoauth->post(self::UPLOAD_LOCATION, $file->get_content()); 263 264 if ($this->googleoauth->info['http_code'] === 201) { 265 return true; 266 } else { 267 return false; 268 } 269 } 270 271 /** 272 * Returns list of photos for file picker. 273 * If top level then returns list of albums, otherwise 274 * photos within an album. 275 * 276 * @param string $path The path to files (assumed to be albumid) 277 * @return mixed $files A list of files for the file picker 278 */ 279 public function get_file_list($path = '') { 280 if (!$path) { 281 return $this->get_albums(); 282 } else { 283 return $this->get_album_photos($path); 284 } 285 } 286 287 /** 288 * Returns list of photos in album specified 289 * 290 * @param int $albumid Photo album to list photos from 291 * @return mixed $files A list of files for the file picker 292 */ 293 public function get_album_photos($albumid) { 294 $albumcontent = $this->googleoauth->get(self::ALBUM_PHOTO_LIST.$albumid); 295 296 return $this->get_photo_details($albumcontent); 297 } 298 299 /** 300 * Returns the name of the album for which get_photo_details was called last time. 301 * 302 * @return string 303 */ 304 public function get_last_album_name() { 305 return $this->lastalbumname; 306 } 307 308 /** 309 * Does text search on the users photos and returns 310 * matches in format for picasa api 311 * 312 * @param string $query Search terms 313 * @return mixed $files A list of files for the file picker 314 */ 315 public function do_photo_search($query) { 316 $content = $this->googleoauth->get(self::PHOTO_SEARCH_URL.htmlentities($query)); 317 318 return $this->get_photo_details($content); 319 } 320 321 /** 322 * Gets all the users albums and returns them as a list of folders 323 * for the file picker 324 * 325 * @return mixes $files Array in the format get_listing uses for folders 326 */ 327 public function get_albums() { 328 $files = array(); 329 $content = $this->googleoauth->get(self::LIST_ALBUMS_URL); 330 331 try { 332 if (strpos($content, '<?xml') !== 0) { 333 throw new moodle_exception('invalidxmlresponse'); 334 } 335 $xml = new SimpleXMLElement($content); 336 } catch (Exception $e) { 337 // An error occured while trying to parse the XML, let's just return nothing. SimpleXML does not 338 // return a more specific Exception, that's why the global Exception class is caught here. 339 return $files; 340 } 341 342 foreach ($xml->entry as $album) { 343 $gphoto = $album->children('http://schemas.google.com/photos/2007'); 344 345 $mediainfo = $album->children('http://search.yahoo.com/mrss/'); 346 // Hacky... 347 $thumbnailinfo = $mediainfo->group->thumbnail[0]->attributes(); 348 349 $files[] = array( 'title' => (string) $album->title, 350 'date' => userdate($gphoto->timestamp), 351 'size' => (int) $gphoto->bytesUsed, 352 'path' => (string) $gphoto->id, 353 'thumbnail' => (string) $thumbnailinfo['url'], 354 'thumbnail_width' => 160, // 160 is the native maximum dimension. 355 'thumbnail_height' => 160, 356 'children' => array(), 357 ); 358 } 359 360 return $files; 361 } 362 363 /** 364 * Recieves XML from a picasa list of photos and returns 365 * array in format for file picker. 366 * 367 * @param string $rawxml XML from picasa api 368 * @return mixed $files A list of files for the file picker 369 */ 370 public function get_photo_details($rawxml) { 371 $files = array(); 372 373 try { 374 if (strpos($rawxml, '<?xml') !== 0) { 375 throw new moodle_exception('invalidxmlresponse'); 376 } 377 $xml = new SimpleXMLElement($rawxml); 378 } catch (Exception $e) { 379 // An error occured while trying to parse the XML, let's just return nothing. SimpleXML does not 380 // return a more specific Exception, that's why the global Exception class is caught here. 381 return $files; 382 } 383 $this->lastalbumname = (string)$xml->title; 384 385 foreach ($xml->entry as $photo) { 386 $gphoto = $photo->children('http://schemas.google.com/photos/2007'); 387 388 $mediainfo = $photo->children('http://search.yahoo.com/mrss/'); 389 $fullinfo = $mediainfo->group->content->attributes(); 390 // Hacky... 391 $thumbnailinfo = $mediainfo->group->thumbnail[0]->attributes(); 392 393 // Derive the nicest file name we can. 394 if (!empty($mediainfo->group->description)) { 395 $title = shorten_text((string)$mediainfo->group->description, 20, false, ''); 396 $title = clean_filename($title).'.jpg'; 397 } else { 398 $title = (string)$mediainfo->group->title; 399 } 400 401 $files[] = array( 402 'title' => $title, 403 'date' => userdate($gphoto->timestamp), 404 'size' => (int) $gphoto->size, 405 'path' => $gphoto->albumid.'/'.$gphoto->id, 406 'thumbnail' => (string) $thumbnailinfo['url'], 407 'thumbnail_width' => 72, // 72 is the native maximum dimension. 408 'thumbnail_height' => 72, 409 'source' => (string) $fullinfo['url'], 410 'url' => (string) $fullinfo['url'] 411 ); 412 } 413 414 return $files; 415 } 416 } 417 418 /** 419 * OAuth 2.0 client for Google Services 420 * 421 * @package core 422 * @copyright 2012 Dan Poltawski 423 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 424 */ 425 class google_oauth extends oauth2_client { 426 /** 427 * Returns the auth url for OAuth 2.0 request 428 * @return string the auth url 429 */ 430 protected function auth_url() { 431 return 'https://accounts.google.com/o/oauth2/auth'; 432 } 433 434 /** 435 * Returns the token url for OAuth 2.0 request 436 * @return string the auth url 437 */ 438 protected function token_url() { 439 return 'https://accounts.google.com/o/oauth2/token'; 440 } 441 442 /** 443 * Resets headers and response for multiple requests 444 */ 445 public function reset_state() { 446 $this->header = array(); 447 $this->response = array(); 448 } 449 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 20:29:05 2014 | Cross-referenced by PHPXref 0.7.1 |