From ca5850e34172247f02a2ad9275a60fbfa728998d Mon Sep 17 00:00:00 2001 From: Mihail Geshoski Date: Sat, 31 Oct 2020 22:52:06 +0800 Subject: [PATCH] MDL-70063 block_tag_youtube: Update category config to use category ID 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. --- blocks/tag_youtube/block_tag_youtube.php | 114 +++++++++--------- blocks/tag_youtube/edit_form.php | 22 +++- .../tag_youtube/lang/en/block_tag_youtube.php | 2 + blocks/tag_youtube/upgrade.txt | 6 + 4 files changed, 88 insertions(+), 56 deletions(-) diff --git a/blocks/tag_youtube/block_tag_youtube.php b/blocks/tag_youtube/block_tag_youtube.php index 51a33d57f1b..c8ec5fca633 100644 --- a/blocks/tag_youtube/block_tag_youtube.php +++ b/blocks/tag_youtube/block_tag_youtube.php @@ -51,9 +51,6 @@ class block_tag_youtube extends block_base { 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() { @@ -341,62 +338,71 @@ class block_tag_youtube extends block_base { 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') - ); + /** + * 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. + * + * @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 + */ + 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 { + throw new \moodle_exception('apierror', 'block_tag_youtube'); + } } /** - * Provide conversion from old numeric categories available in youtube API - * to the new ones available in the Google API + * Method that provides mapping between the video category names and their translations. * - * @param int $oldcat old category code - * @return mixed new category code or 0 (if no match found) - * - * 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 that maps the video category names with their translations */ - 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]; - } else { - return $oldcat; - } + 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'), + ]; } /** diff --git a/blocks/tag_youtube/edit_form.php b/blocks/tag_youtube/edit_form.php index 92b54d9348c..75e5c0dc623 100644 --- a/blocks/tag_youtube/edit_form.php +++ b/blocks/tag_youtube/edit_form.php @@ -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')); @@ -38,10 +40,26 @@ class block_tag_youtube_edit_form extends block_edit_form { $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); } diff --git a/blocks/tag_youtube/lang/en/block_tag_youtube.php b/blocks/tag_youtube/lang/en/block_tag_youtube.php index 7b3fd69dd68..defa7bdfa15 100644 --- a/blocks/tag_youtube/lang/en/block_tag_youtube.php +++ b/blocks/tag_youtube/lang/en/block_tag_youtube.php @@ -32,12 +32,14 @@ $string['comedy'] = 'Comedy'; $string['configtitle'] = 'YouTube block title'; $string['education'] = 'Education'; $string['entertainment'] = 'Entertainment'; +$string['categoryerror'] = 'Failed to obtain the list of categories.
{$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'; diff --git a/blocks/tag_youtube/upgrade.txt b/blocks/tag_youtube/upgrade.txt index ae3d80dc16f..9824a12cf43 100644 --- a/blocks/tag_youtube/upgrade.txt +++ b/blocks/tag_youtube/upgrade.txt @@ -1,5 +1,11 @@ This files describes API changes in the block tag_youtube code. +=== 3.11 === + +* 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