mirror of
https://github.com/moodle/moodle.git
synced 2025-08-05 00:46:50 +02:00
MDL-38158 core_media: Convert media players to new plugin type
AMOS BEGIN MOV [siteyoutube,core_media],[pluginname,media_youtube] MOV [siteyoutube_desc,core_media],[pluginname_help,media_youtube] MOV [sitevimeo,core_media],[pluginname,media_vimeo] MOV [sitevimeo_desc,core_media],[pluginname_help,media_vimeo] MOV [html5audio,core_media],[pluginname,media_html5audio] MOV [html5audio_desc,core_media],[pluginname_help,media_html5audio] MOV [html5video,core_media],[pluginname,media_html5video] MOV [html5video_desc,core_media],[pluginname_help,media_html5video] MOV [flashanimation,core_media],[pluginname,media_swf] MOV [flashanimation_desc,core_media],[pluginname_help,media_swf] AMOS END
This commit is contained in:
parent
3c73b26c4b
commit
fab11235d8
76 changed files with 3524 additions and 4406 deletions
|
@ -36,32 +36,13 @@ if (!is_siteadmin()) {
|
|||
|
||||
// Set up page.
|
||||
$PAGE->set_context(context_system::instance());
|
||||
$PAGE->set_url(new moodle_url('/filter/mediaplugin/perftest.php'));
|
||||
$PAGE->set_url(new moodle_url('/filter/mediaplugin/dev/perftest.php'));
|
||||
$PAGE->set_heading($SITE->fullname);
|
||||
print $OUTPUT->header();
|
||||
|
||||
// Hack setup to enable all players.
|
||||
$CFG->core_media_enable_youtube = 1;
|
||||
$CFG->core_media_enable_vimeo = 1;
|
||||
$CFG->core_media_enable_mp3 = 1;
|
||||
$CFG->core_media_enable_flv = 1;
|
||||
$CFG->core_media_enable_swf = 1;
|
||||
$CFG->core_media_enable_html5audio = 1;
|
||||
$CFG->core_media_enable_html5video = 1;
|
||||
$CFG->core_media_enable_qt = 1;
|
||||
$CFG->core_media_enable_wmp = 1;
|
||||
$CFG->core_media_enable_rm = 1;
|
||||
|
||||
$CFG->filter_mediaplugin_enable_youtube = 1;
|
||||
$CFG->filter_mediaplugin_enable_vimeo = 1;
|
||||
$CFG->filter_mediaplugin_enable_mp3 = 1;
|
||||
$CFG->filter_mediaplugin_enable_flv = 1;
|
||||
$CFG->filter_mediaplugin_enable_swf = 1;
|
||||
$CFG->filter_mediaplugin_enable_html5audio = 1;
|
||||
$CFG->filter_mediaplugin_enable_html5video = 1;
|
||||
$CFG->filter_mediaplugin_enable_qt = 1;
|
||||
$CFG->filter_mediaplugin_enable_wmp = 1;
|
||||
$CFG->filter_mediaplugin_enable_rm = 1;
|
||||
// Enable all players.
|
||||
$enabledmediaplugins = \core\plugininfo\media::get_enabled_plugins();
|
||||
\core\plugininfo\media::set_enabled_plugins('vimeo,youtube,videojs,html5audio,html5video,swf');
|
||||
|
||||
// Create plugin.
|
||||
$filterplugin = new filter_mediaplugin(null, array());
|
||||
|
@ -168,6 +149,8 @@ foreach ($linksamples as $sample) {
|
|||
}
|
||||
filter_mediaplugin_perf_stop('One link (mp3)');
|
||||
|
||||
\core\plugininfo\media::set_enabled_plugins($enabledmediaplugins);
|
||||
|
||||
// End page.
|
||||
echo html_writer::end_tag('ul');
|
||||
print $OUTPUT->footer();
|
|
@ -42,10 +42,6 @@ defined('MOODLE_INTERNAL') || die();
|
|||
class filter_mediaplugin extends moodle_text_filter {
|
||||
/** @var bool True if currently filtering trusted text */
|
||||
private $trusted;
|
||||
/** @var core_media_renderer Media renderer */
|
||||
private $mediarenderer;
|
||||
/** @var string Partial regex pattern indicating possible embeddable content */
|
||||
private $embedmarkers;
|
||||
|
||||
public function filter($text, array $options = array()) {
|
||||
global $CFG, $PAGE;
|
||||
|
@ -55,16 +51,11 @@ class filter_mediaplugin extends moodle_text_filter {
|
|||
return $text;
|
||||
}
|
||||
|
||||
if (stripos($text, '</a>') === false) {
|
||||
// Performance shortcut - if not </a> tag, nothing can match.
|
||||
if (stripos($text, '</a>') === false && stripos($text, '</video>') === false && stripos($text, '</audio>') === false) {
|
||||
// Performance shortcut - if there are no </a>, </video> or </audio> tags, nothing can match.
|
||||
return $text;
|
||||
}
|
||||
|
||||
if (!$this->mediarenderer) {
|
||||
$this->mediarenderer = $PAGE->get_renderer('core', 'media');
|
||||
$this->embedmarkers = $this->mediarenderer->get_embeddable_markers();
|
||||
}
|
||||
|
||||
// Check SWF permissions.
|
||||
$this->trusted = !empty($options['noclean']) or !empty($CFG->allowobjectembed);
|
||||
|
||||
|
@ -76,32 +67,41 @@ class filter_mediaplugin extends moodle_text_filter {
|
|||
}
|
||||
|
||||
// Regex to find media extensions in an <a> tag.
|
||||
$re = '~<a\s[^>]*href="([^"]*(?:' . $this->embedmarkers . ')[^"]*)"[^>]*>([^>]*)</a>~is';
|
||||
$embedmarkers = core_media_manager::instance()->get_embeddable_markers();
|
||||
$re = '~<a\s[^>]*href="([^"]*(?:' . $embedmarkers . ')[^"]*)"[^>]*>([^>]*)</a>~is';
|
||||
|
||||
$newtext = '';
|
||||
$validtag = '';
|
||||
$tagname = '';
|
||||
$sizeofmatches = count($matches);
|
||||
|
||||
// We iterate through the given string to find valid <a> tags
|
||||
// and build them so that the callback function can check it for
|
||||
// embedded content. Then we rebuild the string.
|
||||
foreach ($matches as $idx => $tag) {
|
||||
if (preg_match('|</a>|', $tag) && !empty($validtag)) {
|
||||
if (preg_match('|</'.$tagname.'>|', $tag) && !empty($validtag)) {
|
||||
$validtag .= $tag;
|
||||
|
||||
// Given we now have a valid <a> tag to process it's time for
|
||||
// ReDoS protection. Stop processing if a word is too large.
|
||||
if (strlen($validtag) < 4096) {
|
||||
$processed = preg_replace_callback($re, array($this, 'callback'), $validtag);
|
||||
if ($tagname === 'a') {
|
||||
$processed = preg_replace_callback($re, array($this, 'callback'), $validtag);
|
||||
} else {
|
||||
// For audio and video tags we just process them without precheck for embeddable markers.
|
||||
$processed = $this->process_media_tag($validtag);
|
||||
}
|
||||
}
|
||||
// Rebuilding the string with our new processed text.
|
||||
$newtext .= !empty($processed) ? $processed : $validtag;
|
||||
// Wipe it so we can catch any more instances to filter.
|
||||
$validtag = '';
|
||||
$processed = '';
|
||||
} else if (preg_match('/<a\s[^>]*/', $tag) && $sizeofmatches > 1) {
|
||||
// Looking for a starting <a> tag.
|
||||
} else if (preg_match('/<(a|video|audio)\s[^>]*/', $tag, $tagmatches) && $sizeofmatches > 1 &&
|
||||
(empty($validtag) || $tagname === strtolower($tagmatches[1]))) {
|
||||
// Looking for a starting tag. Ignore tags embedded into each other.
|
||||
$validtag = $tag;
|
||||
$tagname = strtolower($tagmatches[1]);
|
||||
} else {
|
||||
// If we have a validtag add to that to process later,
|
||||
// else add straight onto our newtext string.
|
||||
|
@ -124,6 +124,8 @@ class filter_mediaplugin extends moodle_text_filter {
|
|||
* @return string
|
||||
*/
|
||||
private function callback(array $matches) {
|
||||
$mediamanager = core_media_manager::instance();
|
||||
|
||||
global $CFG, $PAGE;
|
||||
// Check if we ignore it.
|
||||
if (preg_match('/class="[^"]*nomediaplugin/i', $matches[0])) {
|
||||
|
@ -137,30 +139,79 @@ class filter_mediaplugin extends moodle_text_filter {
|
|||
}
|
||||
|
||||
// Split provided URL into alternatives.
|
||||
$urls = core_media::split_alternatives($matches[1], $width, $height);
|
||||
$urls = $mediamanager->split_alternatives($matches[1], $width, $height);
|
||||
|
||||
$options = array();
|
||||
$options = [core_media_manager::OPTION_ORIGINAL_TEXT => $matches[0]];
|
||||
return $this->embed_alternatives($urls, $name, $width, $height, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders media files (audio or video) using suitable embedded player.
|
||||
*
|
||||
* Wrapper for {@link core_media_manager::embed_alternatives()}
|
||||
*
|
||||
* @param array $urls Array of moodle_url to media files
|
||||
* @param string $name Optional user-readable name to display in download link
|
||||
* @param int $width Width in pixels (optional)
|
||||
* @param int $height Height in pixels (optional)
|
||||
* @param array $options Array of key/value pairs
|
||||
* @return string HTML content of embed
|
||||
*/
|
||||
protected function embed_alternatives($urls, $name, $width, $height, $options) {
|
||||
|
||||
// Allow SWF (or not).
|
||||
if ($this->trusted) {
|
||||
$options[core_media::OPTION_TRUSTED] = true;
|
||||
$options[core_media_manager::OPTION_TRUSTED] = true;
|
||||
}
|
||||
|
||||
// We could test whether embed is possible using can_embed, but to save
|
||||
// time, let's just embed it with the 'fallback to blank' option which
|
||||
// does most of the same stuff anyhow.
|
||||
$options[core_media::OPTION_FALLBACK_TO_BLANK] = true;
|
||||
$options[core_media_manager::OPTION_FALLBACK_TO_BLANK] = true;
|
||||
|
||||
// NOTE: Options are not passed through from filter because the 'embed'
|
||||
// code does not recognise filter options (it's a different kind of
|
||||
// option-space) as it can be used in non-filter situations.
|
||||
$result = $this->mediarenderer->embed_alternatives($urls, $name, $width, $height, $options);
|
||||
$result = core_media_manager::instance()->embed_alternatives($urls, $name, $width, $height, $options);
|
||||
|
||||
// If something was embedded, return it, otherwise return original.
|
||||
if ($result !== '') {
|
||||
return $result;
|
||||
} else {
|
||||
return $matches[0];
|
||||
return $options[core_media_manager::OPTION_ORIGINAL_TEXT];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces <video> or <audio> tag with processed contents
|
||||
*
|
||||
* @param string $fulltext complete HTML snipped "<video ...>...</video>" or "<audio ...>....</audio>"
|
||||
* @return string
|
||||
*/
|
||||
protected function process_media_tag($fulltext) {
|
||||
// Check if we ignore it.
|
||||
if (preg_match('/^<[^>]*class="[^"]*nomediaplugin/im', $fulltext)) {
|
||||
return $fulltext;
|
||||
}
|
||||
|
||||
// Find all sources both as <video src=""> and as embedded <source> tags.
|
||||
$urls = [];
|
||||
if (preg_match('/^<[^>]*\bsrc="(.*?)"/im', $fulltext, $matches)) {
|
||||
$urls[] = new moodle_url($matches[1]);
|
||||
}
|
||||
if (preg_match_all('/<source\b[^>]*\bsrc="(.*?)"/im', $fulltext, $matches)) {
|
||||
foreach ($matches[1] as $url) {
|
||||
$urls[] = new moodle_url($url);
|
||||
}
|
||||
}
|
||||
// Extract width/height/title attributes and call embed_alternatives to find a suitable media player.
|
||||
if ($urls) {
|
||||
$options = [core_media_manager::OPTION_ORIGINAL_TEXT => $fulltext];
|
||||
$width = core_media_player_native::get_attribute($fulltext, 'width', PARAM_INT);
|
||||
$height = core_media_player_native::get_attribute($fulltext, 'height', PARAM_INT);
|
||||
$name = core_media_player_native::get_attribute($fulltext, 'title');
|
||||
return $this->embed_alternatives($urls, $name, $width, $height, $options);
|
||||
}
|
||||
return $fulltext;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,4 +25,5 @@
|
|||
$string['fallbackaudio'] = 'Audio link';
|
||||
$string['fallbackvideo'] = 'Video link';
|
||||
$string['filtername'] = 'Multimedia plugins';
|
||||
|
||||
$string['linktomedia'] = 'Multimedia plugins filter engages the existing media players to convert links to media files into embedded objects. '.
|
||||
' It can also enhance <video> and <audio> tags with selected video and audio players.<br><a href="{$a}">Manage media players</a>';
|
||||
|
|
34
filter/mediaplugin/settings.php
Normal file
34
filter/mediaplugin/settings.php
Normal file
|
@ -0,0 +1,34 @@
|
|||
<?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/>.
|
||||
|
||||
/**
|
||||
* Mediaplugin filter settings
|
||||
*
|
||||
* @package filter_mediaplugin
|
||||
* @copyright 2016 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die;
|
||||
|
||||
if ($ADMIN->fulltree) {
|
||||
$url = new moodle_url('/admin/settings.php', ['section' => 'managemediaplayers']);
|
||||
$item = new admin_setting_heading('filter_mediaplugin/about',
|
||||
'',
|
||||
new lang_string('linktomedia', 'filter_mediaplugin', $url->out()));
|
||||
$settings->add($item);
|
||||
|
||||
}
|
|
@ -1,26 +1,13 @@
|
|||
/**
|
||||
* Filters
|
||||
*/
|
||||
.mediaplugin_html5audio,
|
||||
.mediaplugin_html5video,
|
||||
.mediaplugin_swf,
|
||||
.mediaplugin_flv,
|
||||
.mediaplugin_real,
|
||||
.mediaplugin_youtube,
|
||||
.mediaplugin_vimeo,
|
||||
.mediaplugin_wmp,
|
||||
.mediaplugin_qt {
|
||||
.mediaplugin {
|
||||
display: block;
|
||||
margin-top: 5px;
|
||||
margin-bottom: 5px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/*
|
||||
* mp3 player colours -this read using JS and applied to swf audio flow player
|
||||
* see http://flowplayer.org/documentation/skinning/controlbar.html?skin=default for more color properties,
|
||||
* any property that ends with '...Color' is supported here.
|
||||
*/
|
||||
.mp3flowplayer_backgroundColor {
|
||||
color: #000;
|
||||
.mediaplugin > div {
|
||||
margin: auto;
|
||||
}
|
||||
|
|
|
@ -32,22 +32,10 @@ require_once($CFG->dirroot . '/filter/mediaplugin/filter.php'); // Include the c
|
|||
class filter_mediaplugin_testcase extends advanced_testcase {
|
||||
|
||||
function test_filter_mediaplugin_link() {
|
||||
global $CFG;
|
||||
|
||||
$this->resetAfterTest(true);
|
||||
|
||||
// we need to enable the plugins somehow
|
||||
$CFG->core_media_enable_youtube = 1;
|
||||
$CFG->core_media_enable_vimeo = 1;
|
||||
$CFG->core_media_enable_mp3 = 1;
|
||||
$CFG->core_media_enable_flv = 1;
|
||||
$CFG->core_media_enable_swf = 1;
|
||||
$CFG->core_media_enable_html5audio = 1;
|
||||
$CFG->core_media_enable_html5video = 1;
|
||||
$CFG->core_media_enable_qt = 1;
|
||||
$CFG->core_media_enable_wmp = 1;
|
||||
$CFG->core_media_enable_rm = 1;
|
||||
|
||||
\core\plugininfo\media::set_enabled_plugins('vimeo,youtube,videojs,html5video,swf,html5audio');
|
||||
|
||||
$filterplugin = new filter_mediaplugin(null, array());
|
||||
|
||||
|
@ -64,7 +52,7 @@ class filter_mediaplugin_testcase extends advanced_testcase {
|
|||
'<a href="http://moodle.org/testfile/test.mp3">test mp3</a>',
|
||||
'<a href="http://moodle.org/testfile/test.ogg">test ogg</a>',
|
||||
'<a id="movie player" class="center" href="http://moodle.org/testfile/test.mpg">test mpg</a>',
|
||||
'<a href="http://moodle.org/testfile/test.ram">test</a>',
|
||||
'<a href="http://moodle.org/testfile/test.webm">test</a>',
|
||||
'<a href="http://www.youtube.com/watch?v=JghQgA2HMX8" class="href=css">test file</a>',
|
||||
'<a href="http://www.youtube-nocookie.com/watch?v=JghQgA2HMX8" class="href=css">test file</a>',
|
||||
'<a href="http://youtu.be/JghQgA2HMX8" class="href=css">test file</a>',
|
||||
|
@ -72,7 +60,7 @@ class filter_mediaplugin_testcase extends advanced_testcase {
|
|||
'<a class="youtube" href="http://www.youtube.com/watch?v=JghQgA2HMX8">test file</a>',
|
||||
'<a class="_blanktarget" href="http://moodle.org/testfile/test.flv?d=100x100">test flv</a>',
|
||||
'<a class="hrefcss" href="http://www.youtube.com/watch?v=JghQgA2HMX8">test file</a>',
|
||||
'<a class="content" href="http://moodle.org/testfile/test.avi">test mp3</a>',
|
||||
'<a class="content" href="http://moodle.org/testfile/test.ogg">test ogg</a>',
|
||||
'<a id="audio" href="http://moodle.org/testfile/test.mp3">test mp3</a>',
|
||||
'<a href="http://moodle.org/testfile/test.mp3">test mp3</a>',
|
||||
'<a href="http://moodle.org/testfile/test.mp3">test mp3</a>',
|
||||
|
@ -83,7 +71,7 @@ class filter_mediaplugin_testcase extends advanced_testcase {
|
|||
'<a class="content"
|
||||
|
||||
|
||||
href="http://moodle.org/testfile/test.avi">test mp3
|
||||
href="http://moodle.org/testfile/test.wav">test wav
|
||||
</a>',
|
||||
'<a href="http://www.youtube.com/watch?v=JghQgA2HMX8?d=200x200" >youtube\'s</a>',
|
||||
// Test a long URL under 4096 characters.
|
||||
|
@ -139,7 +127,7 @@ class filter_mediaplugin_testcase extends advanced_testcase {
|
|||
// Valid mediaurl followed by a longurl.
|
||||
$precededlongurl = '<a href="http://moodle.org/testfile/test.mp3">test.mp3</a>'. $longurl;
|
||||
$filter = $filterplugin->filter($precededlongurl);
|
||||
$this->assertEquals(1, substr_count($filter, 'M.util.add_audio_player'));
|
||||
$this->assertEquals(1, substr_count($filter, '</audio>'));
|
||||
$this->assertContains($longurl, $filter);
|
||||
|
||||
// Testing for cases where: to be filtered content has 6+ text afterwards.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue