MDL-62660 tool_dataprivacy: Add scheduled task to expire data requests
[moodle.git] / blocks / tag_youtube / block_tag_youtube.php
blob9c79fe8d982ddf987c6a320659aacc8390457fb2
1 <?php
2 // This file is part of Moodle - http://moodle.org/
3 //
4 // Moodle is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // Moodle is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
17 /**
18 * Tag youtube block
20 * @package block_tag_youtube
21 * @copyright 1999 onwards Martin Dougiamas (http://dougiamas.com)
22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
25 define('DEFAULT_NUMBER_OF_VIDEOS', 5);
27 class block_tag_youtube extends block_base {
29 /**
30 * @var Google_Service_Youtube
32 protected $service = null;
34 function init() {
35 $this->title = get_string('pluginname','block_tag_youtube');
36 $this->config = new stdClass();
39 function applicable_formats() {
40 return array('tag' => true);
43 /**
44 * It can be configured.
46 * @return bool
48 public function has_config() {
49 return true;
52 function specialization() {
53 $this->title = !empty($this->config->title) ? $this->config->title : get_string('pluginname', 'block_tag_youtube');
54 // Convert numeric categories (old YouTube API) to
55 // textual ones (new Google Data API)
56 $this->config->category = !empty($this->config->category) ? $this->category_map_old2new($this->config->category) : '0';
59 function instance_allow_multiple() {
60 return true;
63 function get_content() {
64 global $CFG;
66 //note: do NOT include files at the top of this file
67 require_once($CFG->libdir . '/filelib.php');
69 if ($this->content !== NULL) {
70 return $this->content;
73 $this->content = new stdClass();
74 $this->content->footer = '';
76 if (!$this->get_service()) {
77 $this->content->text = $this->get_error_message();
78 return $this->content;
81 $text = '';
82 if(!empty($this->config->playlist)){
83 //videos from a playlist
84 $text = $this->get_videos_by_playlist();
86 else{
87 if(!empty($this->config->category)){
88 //videos from category with tag
89 $text = $this->get_videos_by_tag_and_category();
91 else {
92 //videos with tag
93 $text = $this->get_videos_by_tag();
97 $this->content->text = $text;
99 return $this->content;
102 function get_videos_by_playlist(){
104 if (!$service = $this->get_service()) {
105 return $this->get_error_message();
108 $numberofvideos = DEFAULT_NUMBER_OF_VIDEOS;
109 if( !empty($this->config->numberofvideos)) {
110 $numberofvideos = $this->config->numberofvideos;
113 try {
114 $response = $service->playlistItems->listPlaylistItems('id,snippet', array(
115 'playlistId' => $this->config->playlist,
116 'maxResults' => $numberofvideos
118 } catch (Google_Service_Exception $e) {
119 debugging('Google service exception: ' . $e->getMessage(), DEBUG_DEVELOPER);
120 return $this->get_error_message(get_string('requesterror', 'block_tag_youtube'));
123 return $this->render_items($response);
126 function get_videos_by_tag(){
128 if (!$service = $this->get_service()) {
129 return $this->get_error_message();
132 $tagid = optional_param('id', 0, PARAM_INT); // tag id - for backware compatibility
133 $tag = optional_param('tag', '', PARAM_TAG); // tag
134 $tc = optional_param('tc', 0, PARAM_INT); // Tag collection id.
136 if ($tagid) {
137 $tagobject = core_tag_tag::get($tagid);
138 } else if ($tag) {
139 $tagobject = core_tag_tag::get_by_name($tc, $tag);
142 if (empty($tagobject)) {
143 return '';
146 $querytag = urlencode($tagobject->name);
148 $numberofvideos = DEFAULT_NUMBER_OF_VIDEOS;
149 if ( !empty($this->config->numberofvideos) ) {
150 $numberofvideos = $this->config->numberofvideos;
153 try {
154 $response = $service->search->listSearch('id,snippet', array(
155 'q' => $querytag,
156 'type' => 'video',
157 'maxResults' => $numberofvideos
159 } catch (Google_Service_Exception $e) {
160 debugging('Google service exception: ' . $e->getMessage(), DEBUG_DEVELOPER);
161 return $this->get_error_message(get_string('requesterror', 'block_tag_youtube'));
164 return $this->render_items($response);
167 function get_videos_by_tag_and_category(){
169 if (!$service = $this->get_service()) {
170 return $this->get_error_message();
173 $tagid = optional_param('id', 0, PARAM_INT); // tag id - for backware compatibility
174 $tag = optional_param('tag', '', PARAM_TAG); // tag
175 $tc = optional_param('tc', 0, PARAM_INT); // Tag collection id.
177 if ($tagid) {
178 $tagobject = core_tag_tag::get($tagid);
179 } else if ($tag) {
180 $tagobject = core_tag_tag::get_by_name($tc, $tag);
183 if (empty($tagobject)) {
184 return '';
187 $querytag = urlencode($tagobject->name);
189 $numberofvideos = DEFAULT_NUMBER_OF_VIDEOS;
190 if( !empty($this->config->numberofvideos)) {
191 $numberofvideos = $this->config->numberofvideos;
194 try {
195 $response = $service->search->listSearch('id,snippet', array(
196 'q' => $querytag,
197 'type' => 'video',
198 'maxResults' => $numberofvideos,
199 'videoCategoryId' => $this->config->category
201 } catch (Google_Service_Exception $e) {
202 debugging('Google service exception: ' . $e->getMessage(), DEBUG_DEVELOPER);
203 return $this->get_error_message(get_string('requesterror', 'block_tag_youtube'));
206 return $this->render_items($response);
210 * Sends a request to fetch data.
212 * @see block_tag_youtube::service
213 * @deprecated since Moodle 2.8.8, 2.9.2 and 3.0 MDL-49085 - please do not use this function any more.
214 * @param string $request
215 * @throws coding_exception
217 public function fetch_request($request) {
218 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.');
220 $c = new curl(array('cache' => true, 'module_cache'=>'tag_youtube'));
221 $c->setopt(array('CURLOPT_TIMEOUT' => 3, 'CURLOPT_CONNECTTIMEOUT' => 3));
223 $response = $c->get($request);
225 $xml = new SimpleXMLElement($response);
226 return $this->render_video_list($xml);
230 * Renders the video list.
232 * @see block_tag_youtube::render_items
233 * @deprecated since Moodle 2.8.8, 2.9.2 and 3.0 MDL-49085 - please do not use this function any more.
234 * @param SimpleXMLElement $xml
235 * @throws coding_exception
237 function render_video_list(SimpleXMLElement $xml){
238 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.');
242 * Returns an error message.
244 * Useful when the block is not properly set or something goes wrong.
246 * @param string $message The message to display.
247 * @return string HTML
249 protected function get_error_message($message = null) {
250 global $OUTPUT;
252 if (empty($message)) {
253 $message = get_string('apierror', 'block_tag_youtube');
255 return $OUTPUT->notification($message);
259 * Gets the youtube service object.
261 * @return Google_Service_YouTube
263 protected function get_service() {
264 global $CFG;
266 if (!$apikey = get_config('block_tag_youtube', 'apikey')) {
267 return false;
270 // Wrapped in an if in case we call different get_videos_* multiple times.
271 if (!isset($this->service)) {
272 require_once($CFG->libdir . '/google/lib.php');
273 $client = get_google_client();
274 $client->setDeveloperKey($apikey);
275 $client->setScopes(array(Google_Service_YouTube::YOUTUBE_READONLY));
276 $this->service = new Google_Service_YouTube($client);
279 return $this->service;
283 * Renders the list of items.
285 * @param array $videosdata
286 * @return string HTML
288 protected function render_items($videosdata) {
290 if (!$videosdata || empty($videosdata->items)) {
291 if (!empty($videosdata->error)) {
292 debugging('Error fetching data from youtube: ' . $videosdata->error->message, DEBUG_DEVELOPER);
294 return '';
297 // If we reach that point we already know that the API key is set.
298 $service = $this->get_service();
300 $text = html_writer::start_tag('ul', array('class' => 'yt-video-entry unlist img-text'));
301 foreach ($videosdata->items as $video) {
303 // Link to the video included in the playlist if listing a playlist.
304 if (!empty($video->snippet->resourceId)) {
305 $id = $video->snippet->resourceId->videoId;
306 $playlist = '&list=' . $video->snippet->playlistId;
307 } else {
308 $id = $video->id->videoId;
309 $playlist = '';
312 $thumbnail = $video->snippet->getThumbnails()->getDefault();
313 $url = 'http://www.youtube.com/watch?v=' . $id . $playlist;
315 $videodetails = $service->videos->listVideos('id,contentDetails', array('id' => $id));
316 if ($videodetails && !empty($videodetails->items)) {
318 // We fetch by id so we just use the first one.
319 $details = $videodetails->items[0];
320 $start = new DateTime('@0');
321 $start->add(new DateInterval($details->contentDetails->duration));
322 $seconds = $start->format('U');
325 $text .= html_writer::start_tag('li');
327 $imgattrs = array('class' => 'youtube-thumb', 'src' => $thumbnail->url, 'alt' => $video->snippet->title);
328 $thumbhtml = html_writer::empty_tag('img', $imgattrs);
329 $link = html_writer::tag('a', $thumbhtml, array('href' => $url));
330 $text .= html_writer::tag('div', $link, array('class' => 'clearfix'));
332 $text .= html_writer::tag('span', html_writer::tag('a', $video->snippet->title, array('href' => $url)));
334 if (!empty($seconds)) {
335 $text .= html_writer::tag('div', format_time($seconds));
337 $text .= html_writer::end_tag('li');
339 $text .= html_writer::end_tag('ul');
341 return $text;
344 function get_categories() {
345 // TODO: Right now using sticky categories from
346 // http://gdata.youtube.com/schemas/2007/categories.cat
347 // This should be performed from time to time by the block insead
348 // and cached somewhere, avoiding deprecated ones and observing regions
349 return array (
350 '0' => get_string('anycategory', 'block_tag_youtube'),
351 'Film' => get_string('filmsanimation', 'block_tag_youtube'),
352 'Autos' => get_string('autosvehicles', 'block_tag_youtube'),
353 'Music' => get_string('music', 'block_tag_youtube'),
354 'Animals'=> get_string('petsanimals', 'block_tag_youtube'),
355 'Sports' => get_string('sports', 'block_tag_youtube'),
356 'Travel' => get_string('travel', 'block_tag_youtube'),
357 'Games' => get_string('gadgetsgames', 'block_tag_youtube'),
358 'Comedy' => get_string('comedy', 'block_tag_youtube'),
359 'People' => get_string('peopleblogs', 'block_tag_youtube'),
360 'News' => get_string('newspolitics', 'block_tag_youtube'),
361 'Entertainment' => get_string('entertainment', 'block_tag_youtube'),
362 'Education' => get_string('education', 'block_tag_youtube'),
363 'Howto' => get_string('howtodiy', 'block_tag_youtube'),
364 'Tech' => get_string('scienceandtech', 'block_tag_youtube')
369 * Provide conversion from old numeric categories available in youtube API
370 * to the new ones available in the Google API
372 * @param int $oldcat old category code
373 * @return mixed new category code or 0 (if no match found)
375 * TODO: Someday this should be applied on upgrade for all the existing
376 * block instances so we won't need the mapping any more. That would imply
377 * to implement restore handling to perform the conversion of old blocks.
379 function category_map_old2new($oldcat) {
380 $oldoptions = array (
381 0 => '0',
382 1 => 'Film',
383 2 => 'Autos',
384 23 => 'Comedy',
385 24 => 'Entertainment',
386 10 => 'Music',
387 25 => 'News',
388 22 => 'People',
389 15 => 'Animals',
390 26 => 'Howto',
391 17 => 'Sports',
392 19 => 'Travel',
393 20 => 'Games'
395 if (array_key_exists($oldcat, $oldoptions)) {
396 return $oldoptions[$oldcat];
397 } else {
398 return $oldcat;