Skip to content

Commit

Permalink
MDL-70063 block_tag_youtube: Update category config to use category ID
Browse files Browse the repository at this point in the history
In YouTube Data API v3, the API call to fetch the videos related to a
certain category expects the category ID to be passed to the
videoCategoryId parameter, instead of the category name. Therefore, the
category config should store the category ID.
  • Loading branch information
Mihail Geshoski committed Nov 11, 2020
1 parent a8e089a commit 918b60d
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 56 deletions.
114 changes: 60 additions & 54 deletions blocks/tag_youtube/block_tag_youtube.php
Expand Up @@ -51,9 +51,6 @@ public function has_config() {

function specialization() {
$this->title = !empty($this->config->title) ? $this->config->title : get_string('pluginname', 'block_tag_youtube');
// Convert numeric categories (old YouTube API) to
// textual ones (new Google Data API)
$this->config->category = !empty($this->config->category) ? $this->category_map_old2new($this->config->category) : '0';
}

function instance_allow_multiple() {
Expand Down Expand Up @@ -341,64 +338,73 @@ protected function render_items($videosdata) {
return $text;
}

function get_categories() {
// TODO: Right now using sticky categories from
// http://gdata.youtube.com/schemas/2007/categories.cat
// This should be performed from time to time by the block insead
// and cached somewhere, avoiding deprecated ones and observing regions
return array (
'0' => get_string('anycategory', 'block_tag_youtube'),
'Film' => get_string('filmsanimation', 'block_tag_youtube'),
'Autos' => get_string('autosvehicles', 'block_tag_youtube'),
'Music' => get_string('music', 'block_tag_youtube'),
'Animals'=> get_string('petsanimals', 'block_tag_youtube'),
'Sports' => get_string('sports', 'block_tag_youtube'),
'Travel' => get_string('travel', 'block_tag_youtube'),
'Games' => get_string('gadgetsgames', 'block_tag_youtube'),
'Comedy' => get_string('comedy', 'block_tag_youtube'),
'People' => get_string('peopleblogs', 'block_tag_youtube'),
'News' => get_string('newspolitics', 'block_tag_youtube'),
'Entertainment' => get_string('entertainment', 'block_tag_youtube'),
'Education' => get_string('education', 'block_tag_youtube'),
'Howto' => get_string('howtodiy', 'block_tag_youtube'),
'Tech' => get_string('scienceandtech', 'block_tag_youtube')
);
}

/**
* Provide conversion from old numeric categories available in youtube API
* to the new ones available in the Google API
*
* @param int $oldcat old category code
* @return mixed new category code or 0 (if no match found)
* Method that returns an array containing all relevant video categories obtained through an API call, where the
* array index represents the category ID and the array value represents the category name.
*
* TODO: Someday this should be applied on upgrade for all the existing
* block instances so we won't need the mapping any more. That would imply
* to implement restore handling to perform the conversion of old blocks.
* @return array The array containing the relevant video categories
* @throws moodle_exception If the API key is not set
* @throws Google_Service_Exception If an error occurs while obtaining the categories through the API call
*/
function category_map_old2new($oldcat) {
$oldoptions = array (
0 => '0',
1 => 'Film',
2 => 'Autos',
23 => 'Comedy',
24 => 'Entertainment',
10 => 'Music',
25 => 'News',
22 => 'People',
15 => 'Animals',
26 => 'Howto',
17 => 'Sports',
19 => 'Travel',
20 => 'Games'
);
if (array_key_exists($oldcat, $oldoptions)) {
return $oldoptions[$oldcat];
public function get_categories() {
// Get the default categories and it's translations.
$categorytranslations = $this->category_map_translation();

if ($service = $this->get_service()) {
// Call the API to fetch the youtube video categories.
// This API call requires the regionCode parameter which instructs the API to return the list of video
// categories available in the specified country. Currently 'us' is hardcoded as the returned categories
// for this region correspond to the previously used (legacy) hardcoded list of categories.
// TODO: We should improve this in the future and avoid hardcoding this value.
$response = $service->videoCategories->listVideoCategories('snippet', ['regionCode' => 'us']);
$categoryitems = $response['modelData']['items'];

// Return an array with the relevant categories.
return array_reduce($categoryitems, function($categories, $category) use ($categorytranslations) {
$categoryid = $category['id'];
$categoryname = $category['snippet']['title'];
// Videos can be associated with this category.
if ($category['snippet']['assignable']) {
// If the category name can be mapped with a translation, add it to the categories array.
if (array_key_exists($categoryname, $categorytranslations)) {
$categories[$categoryid] = $categorytranslations[$categoryname];
} else { // Otherwise, display the untranslated category name and show a debugging message.
$categories[$categoryid] = $categoryname;
debugging("The category '{$categoryname}' does not have a translatable language string.");
}
}
return $categories;
}, []);
} else {
return $oldcat;
throw new \moodle_exception('apierror', 'block_tag_youtube');
}
}

/**
* Method that provides mapping between the video category names and their translations.
*
* @return array The array that maps the video category names with their translations
*/
private function category_map_translation() {
return [
'Film & Animation' => get_string('filmsanimation', 'block_tag_youtube'),
'Autos & Vehicles' => get_string('autosvehicles', 'block_tag_youtube'),
'Music' => get_string('music', 'block_tag_youtube'),
'Pets & Animals' => get_string('petsanimals', 'block_tag_youtube'),
'Sports' => get_string('sports', 'block_tag_youtube'),
'Travel & Events' => get_string('travel', 'block_tag_youtube'),
'Gaming' => get_string('gadgetsgames', 'block_tag_youtube'),
'People & Blogs' => get_string('peopleblogs', 'block_tag_youtube'),
'Comedy' => get_string('comedy', 'block_tag_youtube'),
'Entertainment' => get_string('entertainment', 'block_tag_youtube'),
'News & Politics' => get_string('newspolitics', 'block_tag_youtube'),
'Howto & Style' => get_string('howtodiy', 'block_tag_youtube'),
'Education' => get_string('education', 'block_tag_youtube'),
'Science & Technology' => get_string('scienceandtech', 'block_tag_youtube'),
'Nonprofits & Activism' => get_string('nonprofitactivism', 'block_tag_youtube'),
];
}

/**
* Return the plugin config settings for external functions.
*
Expand Down
22 changes: 20 additions & 2 deletions blocks/tag_youtube/edit_form.php
Expand Up @@ -30,6 +30,8 @@
*/
class block_tag_youtube_edit_form extends block_edit_form {
protected function specific_definition($mform) {
global $OUTPUT;

$mform->addElement('header', 'configheader', get_string('blocksettings', 'block'));

$mform->addElement('text', 'config_title', get_string('configtitle', 'block_tag_youtube'));
Expand All @@ -38,10 +40,26 @@ protected function specific_definition($mform) {
$mform->addElement('text', 'config_numberofvideos', get_string('numberofvideos', 'block_tag_youtube'), array('size' => 5));
$mform->setType('config_numberofvideos', PARAM_INT);

$categorychoices = $this->block->get_categories();
$mform->addElement('select', 'config_category', get_string('category', 'block_tag_youtube'), $categorychoices);
// Category setting.
$categorychoices = ['0' => get_string('anycategory', 'block_tag_youtube')];
$categoryerror = '';

try {
// Get all video categories through an API call and add them to the category list.
$categorychoices += $this->block->get_categories();
} catch (Exception $e) {
$categoryerror = $e->getMessage();
}
$mform->addElement('select', 'config_category', get_string('category', 'block_tag_youtube'),
$categorychoices);
$mform->setDefault('config_category', 0);

if ($categoryerror) {
$notification = $OUTPUT->notification(get_string('categoryerror', 'block_tag_youtube', $categoryerror),
'error');
$mform->addElement('static', 'config_category_error', '', $notification);
}

$mform->addElement('text', 'config_playlist', get_string('includeonlyvideosfromplaylist', 'block_tag_youtube'));
$mform->setType('config_playlist', PARAM_ALPHANUM);
}
Expand Down
2 changes: 2 additions & 0 deletions blocks/tag_youtube/lang/en/block_tag_youtube.php
Expand Up @@ -32,12 +32,14 @@
$string['configtitle'] = 'YouTube block title';
$string['education'] = 'Education';
$string['entertainment'] = 'Entertainment';
$string['categoryerror'] = 'Failed to obtain the list of categories. <br> {$a}';
$string['filmsanimation'] = 'Films & Animation';
$string['gadgetsgames'] = 'Gadgets & Games';
$string['howtodiy'] = 'How-to & DIY';
$string['includeonlyvideosfromplaylist'] = 'Include only videos from the playlist with id';
$string['music'] = 'Music';
$string['newspolitics'] = 'News & Politics';
$string['nonprofitactivism'] = 'Nonprofits & Activism';
$string['numberofvideos'] = 'Number of videos';
$string['peopleblogs'] = 'People & Blogs';
$string['petsanimals'] = 'Pets & Animals';
Expand Down
6 changes: 6 additions & 0 deletions blocks/tag_youtube/upgrade.txt
@@ -1,5 +1,11 @@
This files describes API changes in the block tag_youtube code.

=== 3.9.4 ===

* The config category now stores the category ID, instead of a string representation of the category name.
In YouTube Data API v3, the API call to fetch the videos related to a certain category expects the category ID to be
passed to the videoCategoryId parameter, instead of the category name.

=== 3.0 ===

* Due to the final YouTube API v2.0 deprecation we needed to adapt the current
Expand Down

0 comments on commit 918b60d

Please sign in to comment.