* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require_once($CFG->dirroot . '/repository/lib.php');
+require_once($CFG->libdir . '/google/lib.php');
/**
* repository_youtube class
/** @var int maximum number of thumbs per page */
const YOUTUBE_THUMBS_PER_PAGE = 27;
+ /**
+ * API key for using the YouTube Data API.
+ * @var mixed
+ */
+ private $apikey;
+
+ /**
+ * Google Client.
+ * @var Google_Client
+ */
+ private $client = null;
+
+ /**
+ * YouTube Service.
+ * @var Google_Service_YouTube
+ */
+ private $service = null;
+
/**
* Youtube plugin constructor
* @param int $repositoryid
*/
public function __construct($repositoryid, $context = SYSCONTEXTID, $options = array()) {
parent::__construct($repositoryid, $context, $options);
+
+ $this->apikey = $this->get_option('apikey');
+ $this->client = get_google_client();
+ $this->client->setDeveloperKey($this->apikey);
+ $this->client->setScopes(array(Google_Service_YouTube::YOUTUBE_READONLY));
+ $this->service = new Google_Service_YouTube($this->client);
+
+ // Without an API key, don't show this repo to users as its useless without it.
+ if (empty($this->apikey)) {
+ $this->disabled = true;
+ }
+ }
+
+ /**
+ * Save apikey in config table.
+ * @param array $options
+ * @return boolean
+ */
+ public function set_option($options = array()) {
+ if (!empty($options['apikey'])) {
+ set_config('apikey', trim($options['apikey']), 'youtube');
+ }
+ unset($options['apikey']);
+ return parent::set_option($options);
+ }
+
+ /**
+ * Get apikey from config table.
+ *
+ * @param string $config
+ * @return mixed
+ */
+ public function get_option($config = '') {
+ if ($config === 'apikey') {
+ return trim(get_config('youtube', 'apikey'));
+ } else {
+ $options['apikey'] = trim(get_config('youtube', 'apikey'));
+ }
+ return parent::get_option($config);
}
public function check_login() {
* @param int $start
* @param int $max max results
* @param string $sort
+ * @throws moodle_exception If the google API returns an error.
* @return array
*/
private function _get_collection($keyword, $start, $max, $sort) {
+ global $SESSION;
+
+ // The new API doesn't use "page" numbers for browsing through results.
+ // It uses a prev and next token in each set that you need to use to
+ // request the next page of results.
+ $sesspagetoken = 'youtube_'.$this->id.'_nextpagetoken';
+ $pagetoken = '';
+ if ($start > 1 && isset($SESSION->{$sesspagetoken})) {
+ $pagetoken = $SESSION->{$sesspagetoken};
+ }
+
$list = array();
- $this->feed_url = 'http://gdata.youtube.com/feeds/api/videos?q=' . urlencode($keyword) . '&format=5&start-index=' . $start . '&max-results=' .$max . '&orderby=' . $sort;
- $c = new curl(array('cache'=>true, 'module_cache'=>'repository'));
- $content = $c->get($this->feed_url);
- $xml = simplexml_load_string($content);
- $media = $xml->entry->children('http://search.yahoo.com/mrss/');
- $links = $xml->children('http://www.w3.org/2005/Atom');
- foreach ($xml->entry as $entry) {
- $media = $entry->children('http://search.yahoo.com/mrss/');
- $title = (string)$media->group->title;
- $description = (string)$media->group->description;
- if (empty($description)) {
- $description = $title;
+ $error = null;
+ try {
+ $response = $this->service->search->listSearch('id,snippet', array(
+ 'q' => $keyword,
+ 'maxResults' => $max,
+ 'order' => $sort,
+ 'pageToken' => $pagetoken,
+ 'type' => 'video',
+ 'videoEmbeddable' => 'true',
+ ));
+
+ // Track the next page token for the next request (when a user
+ // scrolls down in the file picker for more videos).
+ $SESSION->{$sesspagetoken} = $response['nextPageToken'];
+
+ foreach ($response['items'] as $result) {
+ $title = $result->snippet->title;
+ $source = 'http://www.youtube.com/v/' . $result->id->videoId . '#' . $title;
+ $thumb = $result->snippet->getThumbnails()->getDefault();
+
+ $list[] = array(
+ 'shorttitle' => $title,
+ 'thumbnail_title' => $result->snippet->description,
+ 'title' => $title.'.avi', // This is a hack so we accept this file by extension.
+ 'thumbnail' => $thumb->url,
+ 'thumbnail_width' => (int)$thumb->width,
+ 'thumbnail_height' => (int)$thumb->height,
+ 'size' => '',
+ 'date' => '',
+ 'source' => $source,
+ );
}
- $attrs = $media->group->thumbnail[2]->attributes();
- $thumbnail = $attrs['url'];
- $arr = explode('/', $entry->id);
- $id = $arr[count($arr)-1];
- $source = 'http://www.youtube.com/v/' . $id . '#' . $title;
- $list[] = array(
- 'shorttitle'=>$title,
- 'thumbnail_title'=>$description,
- 'title'=>$title.'.avi', // this is a hack so we accept this file by extension
- 'thumbnail'=>(string)$attrs['url'],
- 'thumbnail_width'=>(int)$attrs['width'],
- 'thumbnail_height'=>(int)$attrs['height'],
- 'size'=>'',
- 'date'=>'',
- 'source'=>$source
- );
+ } catch (Google_Service_Exception $e) {
+ // If we throw the google exception as-is, we may expose the apikey
+ // to end users. The full message in the google exception includes
+ // the apikey param, so we take just the part pertaining to the
+ // actual error.
+ $error = $e->getErrors()[0]['message'];
+ throw new moodle_exception('apierror', 'repository_youtube', '', $error);
}
+
return $list;
}
'label' => get_string('sortrelevance', 'repository_youtube')
),
(object)array(
- 'value' => 'published',
+ 'value' => 'date',
'label' => get_string('sortpublished', 'repository_youtube')
),
(object)array(
public function contains_private_data() {
return false;
}
+
+ /**
+ * Add plugin settings input to Moodle form.
+ * @param object $mform
+ * @param string $classname
+ */
+ public static function type_config_form($mform, $classname = 'repository') {
+ parent::type_config_form($mform, $classname);
+ $apikey = get_config('youtube', 'apikey');
+ if (empty($apikey)) {
+ $apikey = '';
+ }
+
+ $mform->addElement('text', 'apikey', get_string('apikey', 'repository_youtube'), array('value' => $apikey, 'size' => '40'));
+ $mform->setType('apikey', PARAM_RAW_TRIMMED);
+ $mform->addRule('apikey', get_string('required'), 'required', null, 'client');
+
+ $mform->addElement('static', null, '', get_string('information', 'repository_youtube'));
+ }
+
+ /**
+ * Names of the plugin settings
+ * @return array
+ */
+ public static function get_type_option_names() {
+ return array('apikey', 'pluginname');
+ }
}