diff --git a/blocks/tag_youtube/block_tag_youtube.php b/blocks/tag_youtube/block_tag_youtube.php
index a06588e5e98..7ab13be342c 100644
--- a/blocks/tag_youtube/block_tag_youtube.php
+++ b/blocks/tag_youtube/block_tag_youtube.php
@@ -26,14 +26,29 @@ define('DEFAULT_NUMBER_OF_VIDEOS', 5);
class block_tag_youtube extends block_base {
+ /**
+ * @var Google_Service_Youtube
+ */
+ protected $service = null;
+
function init() {
$this->title = get_string('pluginname','block_tag_youtube');
+ $this->config = new stdClass();
}
function applicable_formats() {
return array('tag' => true);
}
+ /**
+ * It can be configured.
+ *
+ * @return bool
+ */
+ public function has_config() {
+ return true;
+ }
+
function specialization() {
$this->title = !empty($this->config->title) ? $this->config->title : get_string('pluginname', 'block_tag_youtube');
// Convert numeric categories (old YouTube API) to
@@ -56,6 +71,14 @@ class block_tag_youtube extends block_base {
return $this->content;
}
+ $this->content = new stdClass();
+ $this->content->footer = '';
+
+ if (!$this->get_service()) {
+ $this->content->text = $this->get_error_message();
+ return $this->content;
+ }
+
$text = '';
if(!empty($this->config->playlist)){
//videos from a playlist
@@ -72,31 +95,41 @@ class block_tag_youtube extends block_base {
}
}
- $this->content = new stdClass;
$this->content->text = $text;
- $this->content->footer = '';
return $this->content;
}
function get_videos_by_playlist(){
+ if (!$service = $this->get_service()) {
+ return $this->get_error_message();
+ }
+
$numberofvideos = DEFAULT_NUMBER_OF_VIDEOS;
if( !empty($this->config->numberofvideos)) {
$numberofvideos = $this->config->numberofvideos;
}
- $request = 'http://gdata.youtube.com/feeds/api/playlists/' .
- $this->config->playlist .
- '?start-index=1&max-results=' .
- $numberofvideos .
- '&format=5';
+ try {
+ $response = $service->playlistItems->listPlaylistItems('id,snippet', array(
+ 'playlistId' => $this->config->playlist,
+ 'maxResults' => $numberofvideos
+ ));
+ } catch (Google_Service_Exception $e) {
+ debugging('Google service exception: ' . $e->getMessage(), DEBUG_DEVELOPER);
+ return $this->get_error_message(get_string('requesterror', 'block_tag_youtube'));
+ }
- return $this->fetch_request($request);
+ return $this->render_items($response);
}
function get_videos_by_tag(){
+ if (!$service = $this->get_service()) {
+ return $this->get_error_message();
+ }
+
$tagid = optional_param('id', 0, PARAM_INT); // tag id - for backware compatibility
$tag = optional_param('tag', '', PARAM_TAG); // tag
@@ -117,17 +150,26 @@ class block_tag_youtube extends block_base {
$numberofvideos = $this->config->numberofvideos;
}
- $request = 'http://gdata.youtube.com/feeds/api/videos?vq=' .
- $querytag .
- '&start-index=1&max-results=' .
- $numberofvideos .
- '&format=5';
+ try {
+ $response = $service->search->listSearch('id,snippet', array(
+ 'q' => $querytag,
+ 'type' => 'video',
+ 'maxResults' => $numberofvideos
+ ));
+ } catch (Google_Service_Exception $e) {
+ debugging('Google service exception: ' . $e->getMessage(), DEBUG_DEVELOPER);
+ return $this->get_error_message(get_string('requesterror', 'block_tag_youtube'));
+ }
- return $this->fetch_request($request);
+ return $this->render_items($response);
}
function get_videos_by_tag_and_category(){
+ if (!$service = $this->get_service()) {
+ return $this->get_error_message();
+ }
+
$tagid = optional_param('id', 0, PARAM_INT); // tag id - for backware compatibility
$tag = optional_param('tag', '', PARAM_TAG); // tag
@@ -148,19 +190,32 @@ class block_tag_youtube extends block_base {
$numberofvideos = $this->config->numberofvideos;
}
- $request = 'http://gdata.youtube.com/feeds/api/videos?category=' .
- $this->config->category .
- '&vq=' .
- $querytag .
- '&start-index=1&max-results=' .
- $numberofvideos .
- '&format=5';
+ try {
+ $response = $service->search->listSearch('id,snippet', array(
+ 'q' => $querytag,
+ 'type' => 'video',
+ 'maxResults' => $numberofvideos,
+ 'videoCategoryId' => $this->config->category
+ ));
+ } catch (Google_Service_Exception $e) {
+ debugging('Google service exception: ' . $e->getMessage(), DEBUG_DEVELOPER);
+ return $this->get_error_message(get_string('requesterror', 'block_tag_youtube'));
+ }
-
- return $this->fetch_request($request);
+ return $this->render_items($response);
}
- function fetch_request($request){
+ /**
+ * Sends a request to fetch data.
+ *
+ * @see block_tag_youtube::service
+ * @deprecated since Moodle 2.8.8, 2.9.2 and 3.0 MDL-49085 - please do not use this function any more.
+ * @param string $request
+ * @throws coding_exception
+ */
+ public function fetch_request($request) {
+ throw new coding_exception('Sorry, this function has been deprecated in Moodle 2.8.8, 2.9.2 and 3.0. Use block_tag_youtube::get_service instead.');
+
$c = new curl(array('cache' => true, 'module_cache'=>'tag_youtube'));
$c->setopt(array('CURLOPT_TIMEOUT' => 3, 'CURLOPT_CONNECTTIMEOUT' => 3));
@@ -170,32 +225,118 @@ class block_tag_youtube extends block_base {
return $this->render_video_list($xml);
}
+ /**
+ * Renders the video list.
+ *
+ * @see block_tag_youtube::render_items
+ * @deprecated since Moodle 2.8.8, 2.9.2 and 3.0 MDL-49085 - please do not use this function any more.
+ * @param SimpleXMLElement $xml
+ * @throws coding_exception
+ */
function render_video_list(SimpleXMLElement $xml){
+ throw new coding_exception('Sorry, this function has been deprecated in Moodle 2.8.8, 2.9.2 and 3.0. Use block_tag_youtube::render_items instead.');
+ }
- $text = '';
- $text .= '
';
+ /**
+ * Returns an error message.
+ *
+ * Useful when the block is not properly set or something goes wrong.
+ *
+ * @param string $message The message to display.
+ * @return string HTML
+ */
+ protected function get_error_message($message = null) {
+ global $OUTPUT;
- foreach($xml->entry as $entry){
- $media = $entry->children('http://search.yahoo.com/mrss/');
- $playerattrs = $media->group->player->attributes();
- $url = s($playerattrs['url']);
- $thumbattrs = $media->group->thumbnail[0]->attributes();
- $thumbnail = s($thumbattrs['url']);
- $title = s($media->group->title);
- $yt = $media->children('http://gdata.youtube.com/schemas/2007');
- $secattrs = $yt->duration->attributes();
- $seconds = $secattrs['seconds'];
-
- $text .= '- ';
- $text .= ''. $title .'';
- $text .= '
';
- $text .= format_time($seconds);
- $text .= "
\n";
+ if (empty($message)) {
+ $message = get_string('apierror', 'block_tag_youtube');
}
- $text .= "
\n";
+ return $OUTPUT->notification($message);
+ }
+
+ /**
+ * Gets the youtube service object.
+ *
+ * @return Google_Service_YouTube
+ */
+ protected function get_service() {
+ global $CFG;
+
+ if (!$apikey = get_config('block_tag_youtube', 'apikey')) {
+ return false;
+ }
+
+ // Wrapped in an if in case we call different get_videos_* multiple times.
+ if (!isset($this->service)) {
+ require_once($CFG->libdir . '/google/lib.php');
+ $client = get_google_client();
+ $client->setDeveloperKey($apikey);
+ $client->setScopes(array(Google_Service_YouTube::YOUTUBE_READONLY));
+ $this->service = new Google_Service_YouTube($client);
+ }
+
+ return $this->service;
+ }
+
+ /**
+ * Renders the list of items.
+ *
+ * @param array $videosdata
+ * @return string HTML
+ */
+ protected function render_items($videosdata) {
+
+ if (!$videosdata || empty($videosdata->items)) {
+ if (!empty($videosdata->error)) {
+ debugging('Error fetching data from youtube: ' . $videosdata->error->message, DEBUG_DEVELOPER);
+ }
+ return '';
+ }
+
+ // If we reach that point we already know that the API key is set.
+ $service = $this->get_service();
+
+ $text = html_writer::start_tag('ul', array('class' => 'yt-video-entry unlist img-text'));
+ foreach ($videosdata->items as $video) {
+
+ // Link to the video included in the playlist if listing a playlist.
+ if (!empty($video->snippet->resourceId)) {
+ $id = $video->snippet->resourceId->videoId;
+ $playlist = '&list=' . $video->snippet->playlistId;
+ } else {
+ $id = $video->id->videoId;
+ $playlist = '';
+ }
+
+ $thumbnail = $video->snippet->getThumbnails()->getDefault();
+ $url = 'http://www.youtube.com/watch?v=' . $id . $playlist;
+
+ $videodetails = $service->videos->listVideos('id,contentDetails', array('id' => $id));
+ if ($videodetails && !empty($videodetails->items)) {
+
+ // We fetch by id so we just use the first one.
+ $details = $videodetails->items[0];
+ $start = new DateTime('@0');
+ $start->add(new DateInterval($details->contentDetails->duration));
+ $seconds = $start->format('U');
+ }
+
+ $text .= html_writer::start_tag('li');
+
+ $imgattrs = array('class' => 'youtube-thumb', 'src' => $thumbnail->url, 'alt' => $video->snippet->title);
+ $thumbhtml = html_writer::empty_tag('img', $imgattrs);
+ $link = html_writer::tag('a', $thumbhtml, array('href' => $url));
+ $text .= html_writer::tag('div', $link, array('class' => 'clearfix'));
+
+ $text .= html_writer::tag('span', html_writer::tag('a', $video->snippet->title, array('href' => $url)));
+
+ if (!empty($seconds)) {
+ $text .= html_writer::tag('div', format_time($seconds));
+ }
+ $text .= html_writer::end_tag('li');
+ }
+ $text .= html_writer::end_tag('ul');
+
return $text;
}
diff --git a/blocks/tag_youtube/lang/en/block_tag_youtube.php b/blocks/tag_youtube/lang/en/block_tag_youtube.php
index 2f3cec16795..4cdcdf7916f 100644
--- a/blocks/tag_youtube/lang/en/block_tag_youtube.php
+++ b/blocks/tag_youtube/lang/en/block_tag_youtube.php
@@ -23,6 +23,9 @@
*/
$string['anycategory'] = 'Any category';
+$string['apierror'] = 'The Youtube API key is not set. Contact your administrator.';
+$string['apikey'] = 'API key';
+$string['apikeyinfo'] = 'Get a Google API key for your Moodle site.';
$string['autosvehicles'] = 'Autos & Vehicles';
$string['category'] = 'Category';
$string['comedy'] = 'Comedy';
@@ -39,6 +42,7 @@ $string['numberofvideos'] = 'Number of videos';
$string['peopleblogs'] = 'People & Blogs';
$string['petsanimals'] = 'Pets & Animals';
$string['pluginname'] = 'Youtube';
+$string['requesterror'] = 'Data could not be obtained from the server. Contact your administrator if the problem persist.';
$string['scienceandtech'] = 'Science & Tech';
$string['sports'] = 'Sports';
$string['tag_youtube:addinstance'] = 'Add a new youtube block';
diff --git a/blocks/tag_youtube/settings.php b/blocks/tag_youtube/settings.php
new file mode 100644
index 00000000000..ad9f4436a67
--- /dev/null
+++ b/blocks/tag_youtube/settings.php
@@ -0,0 +1,30 @@
+.
+
+/**
+ * Settings for the RSS client block.
+ *
+ * @package block_tag_youtube
+ * @copyright 2015 David Monllao
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die;
+
+if ($ADMIN->fulltree) {
+ $settings->add(new admin_setting_configtext('block_tag_youtube/apikey', get_string('apikey', 'block_tag_youtube'),
+ get_string('apikeyinfo', 'block_tag_youtube'), '', PARAM_RAW_TRIMMED, 40));
+}
diff --git a/blocks/tag_youtube/upgrade.txt b/blocks/tag_youtube/upgrade.txt
new file mode 100644
index 00000000000..ae3d80dc16f
--- /dev/null
+++ b/blocks/tag_youtube/upgrade.txt
@@ -0,0 +1,8 @@
+This files describes API changes in the block tag_youtube code.
+
+=== 3.0 ===
+
+* Due to the final YouTube API v2.0 deprecation we needed to adapt the current
+ code to YouTube Data API v3. block_tag_youtube::fetch_request and
+ block_tag_youtube::render_video_list have been deprecated as they can not be
+ used any more.
diff --git a/blocks/tag_youtube/version.php b/blocks/tag_youtube/version.php
index 1a5c4def806..832b9f1bb2d 100644
--- a/blocks/tag_youtube/version.php
+++ b/blocks/tag_youtube/version.php
@@ -24,6 +24,6 @@
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2015051100; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->version = 2015051101; // The current plugin version (Date: YYYYMMDDXX)
$plugin->requires = 2015050500; // Requires this Moodle version
$plugin->component = 'block_tag_youtube'; // Full name of the plugin (used for diagnostics)