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 .= '
\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)