Skip to content

Commit

Permalink
MDL-49085 block_tag_youtube: Using Youtube data api v3
Browse files Browse the repository at this point in the history
  • Loading branch information
David Monllao committed Aug 18, 2015
1 parent f5e48d2 commit c32a27e
Show file tree
Hide file tree
Showing 5 changed files with 231 additions and 48 deletions.
235 changes: 188 additions & 47 deletions blocks/tag_youtube/block_tag_youtube.php
Expand Up @@ -26,14 +26,29 @@

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
Expand All @@ -56,6 +71,14 @@ function get_content() {
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
Expand All @@ -72,31 +95,41 @@ function get_content() {
}
}

$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

Expand All @@ -117,17 +150,26 @@ function get_videos_by_tag(){
$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

Expand All @@ -148,19 +190,32 @@ function get_videos_by_tag_and_category(){
$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));

Expand All @@ -170,32 +225,118 @@ function fetch_request($request){
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 .= '<ul class="yt-video-entry unlist img-text">';

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 .= '<li>';
$text .= '<div class="clearfix">';
$text .= '<a href="'. $url . '">';
$text .= '<img alt="" class="youtube-thumb" src="'. $thumbnail .'" /></a>';
$text .= '</div><span><a href="'. $url . '">'. $title .'</a></span>';
$text .= '<div>';
$text .= format_time($seconds);
$text .= "</div></li>\n";
/**
* 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;

if (empty($message)) {
$message = get_string('apierror', 'block_tag_youtube');
}
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;
}
$text .= "</ul><div class=\"clearer\"></div>\n";

// 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;
}

Expand Down
4 changes: 4 additions & 0 deletions blocks/tag_youtube/lang/en/block_tag_youtube.php
Expand Up @@ -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 <a href="https://developers.google.com/youtube/v3/getting-started">Google API key</a> for your Moodle site.';
$string['autosvehicles'] = 'Autos &amp; Vehicles';
$string['category'] = 'Category';
$string['comedy'] = 'Comedy';
Expand All @@ -39,6 +42,7 @@
$string['peopleblogs'] = 'People &amp; Blogs';
$string['petsanimals'] = 'Pets &amp; Animals';
$string['pluginname'] = 'Youtube';
$string['requesterror'] = 'Data could not be obtained from the server. Contact your administrator if the problem persist.';
$string['scienceandtech'] = 'Science &amp; Tech';
$string['sports'] = 'Sports';
$string['tag_youtube:addinstance'] = 'Add a new youtube block';
Expand Down
30 changes: 30 additions & 0 deletions blocks/tag_youtube/settings.php
@@ -0,0 +1,30 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.

/**
* 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));
}
8 changes: 8 additions & 0 deletions blocks/tag_youtube/upgrade.txt
@@ -0,0 +1,8 @@
This files describes API changes in the block tag_youtube code.

=== 2.9.2 ===

* 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.
2 changes: 1 addition & 1 deletion blocks/tag_youtube/version.php
Expand Up @@ -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)

0 comments on commit c32a27e

Please sign in to comment.