first commit

This commit is contained in:
CHIEFSOFT\ameye
2024-09-30 18:11:26 -04:00
commit e592ca6823
27270 changed files with 5002257 additions and 0 deletions
+215
View File
@@ -0,0 +1,215 @@
<?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/>.
/**
* Main class for plugin 'media_youtube'
*
* @package media_youtube
* @copyright 2016 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
/**
* Player that creates youtube embedding.
*
* @package media_youtube
* @author 2011 The Open University
* @copyright 2016 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class media_youtube_plugin extends core_media_player_external {
/**
* Stores whether the playlist regex was matched last time when
* {@link list_supported_urls()} was called
* @var bool
*/
protected $isplaylist = false;
public function list_supported_urls(array $urls, array $options = array()) {
// These only work with a SINGLE url (there is no fallback).
if (count($urls) == 1) {
$url = reset($urls);
// Check against regex.
if (preg_match($this->get_regex(), $url->out(false), $this->matches)) {
$this->isplaylist = false;
return array($url);
}
// Check against playlist regex.
if (preg_match($this->get_regex_playlist(), $url->out(false), $this->matches)) {
$this->isplaylist = true;
return array($url);
}
}
return array();
}
protected function embed_external(moodle_url $url, $name, $width, $height, $options) {
global $OUTPUT;
$nocookie = get_config('media_youtube', 'nocookie');
$info = trim($name ?? '');
if (empty($info) or strpos($info, 'http') === 0) {
$info = get_string('pluginname', 'media_youtube');
}
$info = s($info);
self::pick_video_size($width, $height);
// Template context.
$context = [
'width' => $width,
'height' => $height,
'title' => $info
];
if ($this->isplaylist) {
$site = $this->matches[1];
$playlist = $this->matches[3];
$params = ['list' => $playlist];
// Handle no cookie option.
if (!$nocookie) {
$embedurl = new moodle_url("https://$site/embed/videoseries", $params);
} else {
$embedurl = new moodle_url('https://www.youtube-nocookie.com/embed/videoseries', $params );
}
$context['embedurl'] = $embedurl->out(false);
// Return the rendered template.
return $OUTPUT->render_from_template('media_youtube/embed', $context);
} else {
$videoid = end($this->matches);
$params = [];
$start = self::get_start_time($url);
if ($start > 0) {
$params['start'] = $start;
}
$listid = $url->param('list');
// Check for non-empty but valid playlist ID.
if (!empty($listid) && !preg_match('/[^a-zA-Z0-9\-_]/', $listid)) {
// This video is part of a playlist, and we want to embed it as such.
$params['list'] = $listid;
}
// Add parameters to object to be passed to the mustache template.
$params['rel'] = 0;
$params['wmode'] = 'transparent';
// Handle no cookie option.
if (!$nocookie) {
$embedurl = new moodle_url('https://www.youtube.com/embed/' . $videoid, $params );
} else {
$embedurl = new moodle_url('https://www.youtube-nocookie.com/embed/' . $videoid, $params );
}
$context['embedurl'] = $embedurl->out(false);
// Return the rendered template.
return $OUTPUT->render_from_template('media_youtube/embed', $context);
}
}
/**
* Check for start time parameter. Note that it's in hours/mins/secs in the URL,
* but the embedded player takes only a number of seconds as the "start" parameter.
* @param moodle_url $url URL of video to be embedded.
* @return int Number of seconds video should start at.
*/
protected static function get_start_time($url) {
$matches = array();
$seconds = 0;
$rawtime = $url->param('t');
if (empty($rawtime)) {
$rawtime = $url->param('start');
}
if (is_numeric($rawtime)) {
// Start time already specified as a number of seconds; ensure it's an integer.
$seconds = $rawtime;
} else if (preg_match('/(\d+?h)?(\d+?m)?(\d+?s)?/i', $rawtime ?? '', $matches)) {
// Convert into a raw number of seconds, as that's all embedded players accept.
for ($i = 1; $i < count($matches); $i++) {
if (empty($matches[$i])) {
continue;
}
$part = str_split($matches[$i], strlen($matches[$i]) - 1);
switch ($part[1]) {
case 'h':
$seconds += 3600 * $part[0];
break;
case 'm':
$seconds += 60 * $part[0];
break;
default:
$seconds += $part[0];
}
}
}
return intval($seconds);
}
/**
* Returns regular expression used to match URLs for single youtube video
* @return string PHP regular expression e.g. '~^https?://example.org/~'
*/
protected function get_regex() {
// Regex for standard youtube link.
$link = '(youtube(-nocookie)?\.com/(?:watch\?v=|v/))';
// Regex for shortened youtube link.
$shortlink = '((youtu|y2u)\.be/)';
// Initial part of link.
$start = '~^https?://((www|m)\.)?(' . $link . '|' . $shortlink . ')';
// Middle bit: Video key value.
$middle = '([a-z0-9\-_]+)';
return $start . $middle . core_media_player_external::END_LINK_REGEX_PART;
}
/**
* Returns regular expression used to match URLs for youtube playlist
* @return string PHP regular expression e.g. '~^https?://example.org/~'
*/
protected function get_regex_playlist() {
// Initial part of link.
$start = '~^https?://(www\.youtube(-nocookie)?\.com)/';
// Middle bit: either view_play_list?p= or p/ (doesn't work on youtube) or playlist?list=.
$middle = '(?:view_play_list\?p=|p/|playlist\?list=)([a-z0-9\-_]+)';
return $start . $middle . core_media_player_external::END_LINK_REGEX_PART;
}
public function get_embeddable_markers() {
return array('youtube.com', 'youtube-nocookie.com', 'youtu.be', 'y2u.be');
}
/**
* Default rank
* @return int
*/
public function get_rank() {
return 1001;
}
}
@@ -0,0 +1,46 @@
<?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/>.
/**
* Privacy provider implementation for media_youtube.
*
* @package media_youtube
* @copyright 2018 Mihail Geshoski <mihail@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace media_youtube\privacy;
defined('MOODLE_INTERNAL') || die();
/**
* Privacy provider implementation for media_youtube.
*
* @copyright 2018 Mihail Geshoski <mihail@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements \core_privacy\local\metadata\null_provider {
/**
* Get the language string identifier with the component's language
* file to explain why this plugin stores no data.
*
* @return string
*/
public static function get_reason(): string {
return 'privacy:metadata';
}
}
@@ -0,0 +1,31 @@
<?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/>.
/**
* Strings for plugin 'media_youtube'
*
* @package media_youtube
* @copyright 2016 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
$string['pluginname'] = 'YouTube';
$string['pluginname_help'] = 'The video-sharing website youtube.com. Video and playlist links are supported.';
$string['privacy:metadata'] = 'The Youtube media plugin does not store any personal data.';
$string['supportsvideo'] = 'YouTube videos';
$string['supportsplaylist'] = 'YouTube playlists';
$string['nocookie'] = 'Use no cookie domain';
$string['nocookie_desc'] = 'Use youtube-nocookie.com domain for embedding videos. This reduces the number of third party cookies used in embedding. This domain is also not blocked by some adblockers.';
Binary file not shown.

After

Width:  |  Height:  |  Size: 348 B

+36
View File
@@ -0,0 +1,36 @@
<?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 file for plugin 'media_youtube'
*
* @package media_youtube
* @copyright 2023 Matt Porritt <matt.porritt@moodle.com
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
if ($ADMIN->fulltree) {
// Add the settings page.
$settings->add(new admin_setting_heading('media_youtube_settings',
get_string('pluginname', 'media_youtube'),
get_string('pluginname_help', 'media_youtube')));
// Add a settings checkbox to enable or disable no cookie YouTube links.
$settings->add(new admin_setting_configcheckbox('media_youtube/nocookie',
new lang_string('nocookie', 'media_youtube'),
new lang_string('nocookie_desc', 'media_youtube'), 0));
}
@@ -0,0 +1,41 @@
{{!
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/>.
}}
{{!
@template media_youtube/embed
This template will render the YouTube embeded player.
Variables required for this template:
* title: The title of the video.
* width: The width of the video.
* height: The height of the video.
* embedurl: The URL to the video.
Example context (json):
{
"title": "YouTube video",
"width": 640,
"height": 360,
"embedurl": "https://www.youtube.com/embed/9bZkp7q19f0?rel=0&amp;wmode=transparent"
}
}}
<span class="mediaplugin mediaplugin_youtube">
<iframe title="{{title}}" width="{{width}}" height="{{height}}" style="border:0;"
src="{{{embedurl}}}" allow="fullscreen" loading="lazy"></iframe>
</span>
+210
View File
@@ -0,0 +1,210 @@
<?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/>.
namespace media_youtube;
use core_media_manager;
/**
* Test script for media embedding.
*
* @package media_youtube
* @copyright 2016 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class player_test extends \advanced_testcase {
/**
* Pre-test setup. Preserves $CFG.
*/
public function setUp(): void {
parent::setUp();
// Reset $CFG and $SERVER.
$this->resetAfterTest();
// Consistent initial setup: all players disabled.
\core\plugininfo\media::set_enabled_plugins('youtube');
// Pretend to be using Firefox browser (must support ogg for tests to work).
\core_useragent::instance(true, 'Mozilla/5.0 (X11; Linux x86_64; rv:46.0) Gecko/20100101 Firefox/46.0 ');
}
/**
* Test that plugin is returned as enabled media plugin.
*/
public function test_is_installed(): void {
$sortorder = \core\plugininfo\media::get_enabled_plugins();
$this->assertEquals(['youtube' => 'youtube'], $sortorder);
}
/**
* Test supported link types
*/
public function test_supported(): void {
$manager = core_media_manager::instance();
// Format: youtube.
$url = new \moodle_url('http://www.youtube.com/watch?v=vyrwMmsufJc');
$t = $manager->embed_url($url);
$this->assertStringContainsString('</iframe>', $t);
$url = new \moodle_url('http://www.youtube.com/v/vyrwMmsufJc');
$t = $manager->embed_url($url);
$this->assertStringContainsString('</iframe>', $t);
$url = new \moodle_url('http://m.youtube.com/watch?v=vyrwMmsufJc');
$t = $manager->embed_url($url);
$this->assertStringContainsString('</iframe>', $t);
// Format: youtube video within playlist.
$url = new \moodle_url('https://www.youtube.com/watch?v=dv2f_xfmbD8&index=4&list=PLxcO_MFWQBDcyn9xpbmx601YSDlDcTcr0');
$t = $manager->embed_url($url);
$this->assertStringContainsString('</iframe>', $t);
$this->assertStringContainsString('list=PLxcO_MFWQBDcyn9xpbmx601YSDlDcTcr0', $t);
// Format: youtube video with start time.
$url = new \moodle_url('https://www.youtube.com/watch?v=JNJMF1l3udM&t=1h11s');
$t = $manager->embed_url($url);
$this->assertStringContainsString('</iframe>', $t);
$this->assertStringContainsString('start=3611', $t);
// Format: youtube video within playlist with start time.
$url = new \moodle_url('https://www.youtube.com/watch?v=dv2f_xfmbD8&index=4&list=PLxcO_MFWQBDcyn9xpbmx601YSDlDcTcr0&t=1m5s');
$t = $manager->embed_url($url);
$this->assertStringContainsString('</iframe>', $t);
$this->assertStringContainsString('list=PLxcO_MFWQBDcyn9xpbmx601YSDlDcTcr0', $t);
$this->assertStringContainsString('start=65', $t);
// Format: youtube video with invalid parameter values (injection attempts).
$url = new \moodle_url('https://www.youtube.com/watch?v=dv2f_xfmbD8&index=4&list=PLxcO_">');
$t = $manager->embed_url($url);
$this->assertStringContainsString('</iframe>', $t);
$this->assertStringNotContainsString('list=PLxcO_', $t); // We shouldn't get a list param as input was invalid.
$url = new \moodle_url('https://www.youtube.com/watch?v=JNJMF1l3udM&t=">');
$t = $manager->embed_url($url);
$this->assertStringContainsString('</iframe>', $t);
$this->assertStringNotContainsString('start=', $t); // We shouldn't get a start param as input was invalid.
// Format: youtube playlist.
$url = new \moodle_url('http://www.youtube.com/view_play_list?p=PL6E18E2927047B662');
$t = $manager->embed_url($url);
$this->assertStringContainsString('</iframe>', $t);
$url = new \moodle_url('http://www.youtube.com/playlist?list=PL6E18E2927047B662');
$t = $manager->embed_url($url);
$this->assertStringContainsString('</iframe>', $t);
$url = new \moodle_url('http://www.youtube.com/p/PL6E18E2927047B662');
$t = $manager->embed_url($url);
$this->assertStringContainsString('</iframe>', $t);
}
/**
* Test embedding without media filter (for example for displaying URL resorce).
*/
public function test_embed_url(): void {
global $CFG;
$url = new \moodle_url('http://www.youtube.com/v/vyrwMmsufJc');
$manager = core_media_manager::instance();
$embedoptions = array(
core_media_manager::OPTION_TRUSTED => true,
core_media_manager::OPTION_BLOCK => true,
);
$this->assertTrue($manager->can_embed_url($url, $embedoptions));
$content = $manager->embed_url($url, 'Test & file', 0, 0, $embedoptions);
$this->assertMatchesRegularExpression('~mediaplugin_youtube~', $content);
$this->assertMatchesRegularExpression('~</iframe>~', $content);
$this->assertMatchesRegularExpression('~width="' . $CFG->media_default_width . '" height="' .
$CFG->media_default_height . '"~', $content);
// Repeat sending the specific size to the manager.
$content = $manager->embed_url($url, 'New file', 123, 50, $embedoptions);
$this->assertMatchesRegularExpression('~width="123" height="50"~', $content);
}
/**
* Test that mediaplugin filter replaces a link to the supported file with media tag.
*
* filter_mediaplugin is enabled by default.
*/
public function test_embed_link(): void {
global $CFG;
$url = new \moodle_url('http://www.youtube.com/v/vyrwMmsufJc');
$text = \html_writer::link($url, 'Watch this one');
$content = format_text($text, FORMAT_HTML);
$this->assertMatchesRegularExpression('~mediaplugin_youtube~', $content);
$this->assertMatchesRegularExpression('~</iframe>~', $content);
$this->assertMatchesRegularExpression('~width="' . $CFG->media_default_width . '" height="' .
$CFG->media_default_height . '"~', $content);
}
/**
* Test that mediaplugin filter adds player code on top of <video> tags.
*
* filter_mediaplugin is enabled by default.
*/
public function test_embed_media(): void {
global $CFG;
$url = new \moodle_url('http://www.youtube.com/v/vyrwMmsufJc');
$trackurl = new \moodle_url('http://example.org/some_filename.vtt');
$text = '<video controls="true"><source src="'.$url.'"/>' .
'<track src="'.$trackurl.'">Unsupported text</video>';
$content = format_text($text, FORMAT_HTML);
$this->assertMatchesRegularExpression('~mediaplugin_youtube~', $content);
$this->assertMatchesRegularExpression('~</iframe>~', $content);
$this->assertMatchesRegularExpression('~width="' . $CFG->media_default_width . '" height="' .
$CFG->media_default_height . '"~', $content);
// Video tag, unsupported text and tracks are removed.
$this->assertDoesNotMatchRegularExpression('~</video>~', $content);
$this->assertDoesNotMatchRegularExpression('~<source\b~', $content);
$this->assertDoesNotMatchRegularExpression('~Unsupported text~', $content);
$this->assertDoesNotMatchRegularExpression('~<track\b~i', $content);
// Video with dimensions and source specified as src attribute without <source> tag.
$text = '<video controls="true" width="123" height="35" src="'.$url.'">Unsupported text</video>';
$content = format_text($text, FORMAT_HTML);
$this->assertMatchesRegularExpression('~mediaplugin_youtube~', $content);
$this->assertMatchesRegularExpression('~</iframe>~', $content);
$this->assertMatchesRegularExpression('~width="123" height="35"~', $content);
}
/**
* Test that YouTube media plugin renders embed code correctly
* when the "nocookie" config options is set to true.
*
* @covers \media_youtube_plugin::embed_external
*/
public function test_youtube_nocookie(): void {
// Turn on the no cookie option.
set_config('nocookie', true, 'media_youtube');
// Test that the embed code contains the no cookie domain.
$url = new \moodle_url('http://www.youtube.com/v/vyrwMmsufJc');
$text = \html_writer::link($url, 'Watch this one');
$content = format_text($text, FORMAT_HTML);
$this->assertMatchesRegularExpression('~youtube-nocookie~', $content);
// Next test for a playlist.
$url = new \moodle_url('https://www.youtube.com/playlist?list=PL59FEE129ADFF2B12');
$text = \html_writer::link($url, 'Great Playlist');
$content = format_text($text, FORMAT_HTML);
$this->assertMatchesRegularExpression('~youtube-nocookie~', $content);
}
}
+29
View File
@@ -0,0 +1,29 @@
<?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/>.
/**
* Version details
*
* @package media_youtube
* @copyright 2016 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$plugin->version = 2024042200; // The current plugin version (Date: YYYYMMDDXX).
$plugin->requires = 2024041600; // Requires this Moodle version.
$plugin->component = 'media_youtube'; // Full name of the plugin (used for diagnostics).