From: poltawski Date: Sun, 8 Mar 2009 15:53:11 +0000 (+0000) Subject: repository/googledocs New repository plugin MDL-16383 X-Git-Url: http://git.mjollnir.org/gw?a=commitdiff_plain;h=6667f9e43935fcf183185cb9f1ef0daad9b6e164;p=moodle.git repository/googledocs New repository plugin MDL-16383 Google have now allowed documents to be downloaded via their API (http://googledataapis.blogspot.com/2009/02/start-downloads.html) so the google docs repo plugin could be finished. At the moment i've set the export format hardcoded, hopefully we can allow the repo api let the user choose later... --- diff --git a/lang/en_utf8/repository_googledocs.php b/lang/en_utf8/repository_googledocs.php new file mode 100644 index 0000000000..e6bd104fca --- /dev/null +++ b/lang/en_utf8/repository_googledocs.php @@ -0,0 +1,3 @@ + diff --git a/lib/googleapi.php b/lib/googleapi.php index f945ce321d..e2bb069a31 100644 --- a/lib/googleapi.php +++ b/lib/googleapi.php @@ -52,6 +52,18 @@ abstract class google_auth_request extends curl{ return $ret; } + protected function multi($requests, $options = array()) { + if($this->token){ + // Adds authorisation head to a request so that it can be authentcated + $this->setHeader('Authorization: '. $this->get_auth_header_name().'"'.$this->token.'"'); + } + + $ret = parent::multi($requests, $options); + // reset headers for next request + $this->header = array(); + return $ret; + } + public function get_sessiontoken(){ return $this->token; } @@ -190,7 +202,8 @@ class google_authsub extends google_auth_request { * http://code.google.com/apis/documents/docs/2.0/developers_guide_protocol.html */ class google_docs { - const REALM = 'http://docs.google.com/feeds/documents'; + // need both docs and the spreadsheets realm + const REALM = 'http://docs.google.com/feeds/ http://spreadsheets.google.com/feeds/'; const DOCUMENTFEED_URL = 'http://docs.google.com/feeds/documents/private/full'; const USER_PREF_NAME = 'google_authsub_sesskey'; @@ -229,6 +242,7 @@ class google_docs { */ #FIXME public function get_file_list($search = ''){ + global $CFG; $url = google_docs::DOCUMENTFEED_URL; if($search){ @@ -238,14 +252,41 @@ class google_docs { $xml = new SimpleXMLElement($content); + + $files = array(); foreach($xml->entry as $gdoc){ - $files[] = array( 'title' => "$gdoc->title", - 'url' => "{$gdoc->content['src']}", - 'source' => "{$gdoc->content['src']}", - 'date' => usertime(strtotime($gdoc->updated)), - ); + // there doesn't seem to to be cleaner way of getting the id/type + // than spliting this.. + if (preg_match('/^http:\/\/docs.google.com\/feeds\/documents\/private\/full\/([^%]*)%3A(.*)$/', $gdoc->id, $matches)){ + $docid = $matches[2]; + + // FIXME: We're making hard-coded choices about format here. + // If the repo api can support it, we could let the user + // chose. + switch($matches[1]){ + case 'document': + $title = $gdoc->title.'.rtf'; + $source = 'http://docs.google.com/feeds/download/documents/Export?docID='.$docid.'&exportFormat=rtf'; + break; + case 'presentation': + $title = $gdoc->title.'.ppt'; + $source = 'http://docs.google.com/feeds/download/presentations/Export?docID='.$docid.'&exportFormat=ppt'; + break; + case 'spreadsheet': + $title = $gdoc->title.'.xls'; + $source = 'http://spreadsheets.google.com/feeds/download/spreadsheets/Export?key='.$docid.'&fmcmd=4'; + break; + } + + $files[] = array( 'title' => $title, + 'url' => "{$gdoc->link[0]->attributes()->href}", + 'source' => $source, + 'date' => usertime(strtotime($gdoc->updated)), + 'thumbnail' => $CFG->pixpath.'/f/'.mimeinfo('icon32', $title) + ); + } } return $files; diff --git a/repository/googledocs/icon.png b/repository/googledocs/icon.png new file mode 100644 index 0000000000..cfefa4bbaf Binary files /dev/null and b/repository/googledocs/icon.png differ diff --git a/repository/googledocs/repository.class.php b/repository/googledocs/repository.class.php new file mode 100644 index 0000000000..01803551b3 --- /dev/null +++ b/repository/googledocs/repository.class.php @@ -0,0 +1,127 @@ + + * @version $Id$ + * @license http://www.gnu.org/copyleft/gpl.html GNU Public License + */ + +require_once($CFG->libdir.'/googleapi.php'); + +class repository_googledocs extends repository { + private $subauthtoken = ''; + + public function __construct($repositoryid, $context = SITEID, $options = array()) { + global $USER; + parent::__construct($repositoryid, $context, $options); + + // TODO: I wish there was somewhere we could explicitly put this outside of constructor.. + $googletoken = optional_param('token', false, PARAM_RAW); + if($googletoken){ + $gauth = new google_authsub(false, $googletoken); // will throw exception if fails + google_docs::set_sesskey($gauth->get_sessiontoken(), $USER->id); + } + + # fixme - we are not checking login before all functions in the repo api.. eg search + # MDL-17474 + $this->check_login(); + } + + public function check_login() { + global $USER; + + $sesskey = google_docs::get_sesskey($USER->id); + + if($sesskey){ + try{ + $gauth = new google_authsub($sesskey); + $this->subauthtoken = $sesskey; + return true; + }catch(Exception $e){ + // sesskey is not valid, delete store and re-auth + google_docs::delete_sesskey($USER->id); + } + } + + return false; + } + + public function print_login($ajax = true){ + global $CFG; + if($ajax){ + $ret = array(); + $popup_btn = new stdclass; + $popup_btn->type = 'popup'; + $returnurl = $CFG->wwwroot.'/repository/ws.php?callback=yes&repo_id='.$this->id; + $popup_btn->url = google_authsub::login_url($returnurl, google_docs::REALM); + $ret['login'] = array($popup_btn); + return $ret; + } + } + + public function get_listing($path='', $page = '') { + $gdocs = new google_docs(new google_authsub($this->subauthtoken)); + + $ret = array(); + $ret['dynload'] = true; + $ret['list'] = $gdocs->get_file_list(); + return $ret; + } + + public function search($query){ + $gdocs = new google_docs(new google_authsub($this->subauthtoken)); + + $ret = array(); + $ret['dynload'] = true; + $ret['list'] = $gdocs->get_file_list($query); + return $ret; + } + + public function logout(){ + global $USER; + + $token = google_docs::get_sesskey($USER->id); + + $gauth = new google_authsub($token); + // revoke token from google + $gauth->revoke_session_token(); + + google_docs::delete_sesskey($USER->id); + $this->subauthtoken = ''; + + return parent::logout(); + } + + public function get_name(){ + return get_string('repositoryname', 'repository_googledocs'); + } + + public function get_file($url, $file) { + global $CFG; + + + //FIXME: Why does every repo plugin.. do this mktemp file itself.. + + if (!file_exists($CFG->dataroot.'/repository/download')) { + mkdir($CFG->dataroot.'/repository/download/', 0777, true); + } + + if(is_dir($CFG->dataroot.'/repository/download')) { + $dir = $CFG->dataroot.'/repository/download/'; + } + + if (empty($file)){ + $file = time(); + } + + $fp = fopen($dir.$file, 'w'); + $gdocs = new google_docs(new google_authsub($this->subauthtoken)); + $gdocs->download_file($url, $fp); + + return $dir.$file; + } + + +} +//Icon from: http://www.iconspedia.com/icon/google-2706.html