mirror of
https://github.com/moodle/moodle.git
synced 2025-08-04 08:26:37 +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
466
media/classes/manager.php
Normal file
466
media/classes/manager.php
Normal file
|
@ -0,0 +1,466 @@
|
|||
<?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/>.
|
||||
|
||||
/**
|
||||
* Manager for media files
|
||||
*
|
||||
* @package core_media
|
||||
* @copyright 2016 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Manager for media files.
|
||||
*
|
||||
* Used in file resources, media filter, and any other places that need to
|
||||
* output embedded media.
|
||||
*
|
||||
* Usage:
|
||||
* $manager = core_media_manager::instance();
|
||||
*
|
||||
*
|
||||
* @package core_media
|
||||
* @copyright 2016 Marina Glancy
|
||||
* @author 2011 The Open University
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class core_media_manager {
|
||||
/**
|
||||
* Option: Disable text link fallback.
|
||||
*
|
||||
* Use this option if you are going to print a visible link anyway so it is
|
||||
* pointless to have one as fallback.
|
||||
*
|
||||
* To enable, set value to true.
|
||||
*/
|
||||
const OPTION_NO_LINK = 'nolink';
|
||||
|
||||
/**
|
||||
* Option: When embedding, if there is no matching embed, do not use the
|
||||
* default link fallback player; instead return blank.
|
||||
*
|
||||
* This is different from OPTION_NO_LINK because this option still uses the
|
||||
* fallback link if there is some kind of embedding. Use this option if you
|
||||
* are going to check if the return value is blank and handle it specially.
|
||||
*
|
||||
* To enable, set value to true.
|
||||
*/
|
||||
const OPTION_FALLBACK_TO_BLANK = 'embedorblank';
|
||||
|
||||
/**
|
||||
* Option: Enable players which are only suitable for use when we trust the
|
||||
* user who embedded the content.
|
||||
*
|
||||
* At present, this option enables the SWF player.
|
||||
*
|
||||
* To enable, set value to true.
|
||||
*/
|
||||
const OPTION_TRUSTED = 'trusted';
|
||||
|
||||
/**
|
||||
* Option: Put a div around the output (if not blank) so that it displays
|
||||
* as a block using the 'resourcecontent' CSS class.
|
||||
*
|
||||
* To enable, set value to true.
|
||||
*/
|
||||
const OPTION_BLOCK = 'block';
|
||||
|
||||
/**
|
||||
* Option: When the request for media players came from a text filter this option will contain the
|
||||
* original HTML snippet, usually one of the tags: <a> or <video> or <audio>
|
||||
*
|
||||
* Players that support other HTML5 features such as tracks may find them in this option.
|
||||
*/
|
||||
const OPTION_ORIGINAL_TEXT = 'originaltext';
|
||||
|
||||
/** @var array Array of available 'player' objects */
|
||||
private $players;
|
||||
|
||||
/** @var string Regex pattern for links which may contain embeddable content */
|
||||
private $embeddablemarkers;
|
||||
|
||||
/** @var core_media_manager caches a singleton instance */
|
||||
static protected $instance;
|
||||
|
||||
/**
|
||||
* Returns a singleton instance of a manager
|
||||
*
|
||||
* @return core_media_manager
|
||||
*/
|
||||
public static function instance() {
|
||||
if (self::$instance === null) {
|
||||
self::$instance = new self();
|
||||
}
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets cached singleton instance. To be used after $CFG->media_plugins_sortorder is modified
|
||||
*/
|
||||
public static function reset_caches() {
|
||||
self::$instance = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the list of core_media_player objects currently in use to render
|
||||
* items.
|
||||
*
|
||||
* The list is in rank order (highest first) and does not include players
|
||||
* which are disabled.
|
||||
*
|
||||
* @return core_media_player[] Array of core_media_player objects in rank order
|
||||
*/
|
||||
protected function get_players() {
|
||||
// Save time by only building the list once.
|
||||
if (!$this->players) {
|
||||
// Get raw list of players.
|
||||
$allplayers = $this->get_players_raw();
|
||||
$sortorder = \core\plugininfo\media::get_enabled_plugins();
|
||||
|
||||
$this->players = [];
|
||||
foreach ($sortorder as $key) {
|
||||
if (array_key_exists($key, $allplayers)) {
|
||||
$this->players[] = $allplayers[$key];
|
||||
}
|
||||
}
|
||||
}
|
||||
return $this->players;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a raw list of player objects that includes objects regardless
|
||||
* of whether they are disabled or not, and without sorting.
|
||||
*
|
||||
* You can override this in a subclass if you need to add additional_
|
||||
* players.
|
||||
*
|
||||
* The return array is be indexed by player name to make it easier to
|
||||
* remove players in a subclass.
|
||||
*
|
||||
* @return array $players Array of core_media_player objects in any order
|
||||
*/
|
||||
protected function get_players_raw() {
|
||||
$plugins = core_plugin_manager::instance()->get_plugins_of_type('media');
|
||||
$rv = [];
|
||||
foreach ($plugins as $name => $dir) {
|
||||
$classname = "media_" . $name . "_plugin";
|
||||
if (class_exists($classname)) {
|
||||
$rv[$name] = new $classname();
|
||||
}
|
||||
}
|
||||
return $rv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a media file (audio or video) using suitable embedded player.
|
||||
*
|
||||
* See embed_alternatives function for full description of parameters.
|
||||
* This function calls through to that one.
|
||||
*
|
||||
* When using this function you can also specify width and height in the
|
||||
* URL by including ?d=100x100 at the end. If specified in the URL, this
|
||||
* will override the $width and $height parameters.
|
||||
*
|
||||
* @param moodle_url $url Full URL of media file
|
||||
* @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
|
||||
*/
|
||||
public function embed_url(moodle_url $url, $name = '', $width = 0, $height = 0,
|
||||
$options = array()) {
|
||||
|
||||
// Get width and height from URL if specified (overrides parameters in
|
||||
// function call).
|
||||
$rawurl = $url->out(false);
|
||||
if (preg_match('/[?#]d=([\d]{1,4}%?)x([\d]{1,4}%?)/', $rawurl, $matches)) {
|
||||
$width = $matches[1];
|
||||
$height = $matches[2];
|
||||
$url = new moodle_url(str_replace($matches[0], '', $rawurl));
|
||||
}
|
||||
|
||||
// Defer to array version of function.
|
||||
return $this->embed_alternatives(array($url), $name, $width, $height, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders media files (audio or video) using suitable embedded player.
|
||||
* The list of URLs should be alternative versions of the same content in
|
||||
* multiple formats. If there is only one format it should have a single
|
||||
* entry.
|
||||
*
|
||||
* If the media files are not in a supported format, this will give students
|
||||
* a download link to each format. The download link uses the filename
|
||||
* unless you supply the optional name parameter.
|
||||
*
|
||||
* Width and height are optional. If specified, these are suggested sizes
|
||||
* and should be the exact values supplied by the user, if they come from
|
||||
* user input. These will be treated as relating to the size of the video
|
||||
* content, not including any player control bar.
|
||||
*
|
||||
* For audio files, height will be ignored. For video files, a few formats
|
||||
* work if you specify only width, but in general if you specify width
|
||||
* you must specify height as well.
|
||||
*
|
||||
* The $options array is passed through to the core_media_player classes
|
||||
* that render the object tag. The keys can contain values from
|
||||
* core_media::OPTION_xx.
|
||||
*
|
||||
* @param array $alternatives 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
|
||||
*/
|
||||
public function embed_alternatives($alternatives, $name = '', $width = 0, $height = 0,
|
||||
$options = array()) {
|
||||
|
||||
// Get list of player plugins.
|
||||
$players = $this->get_players();
|
||||
|
||||
// Set up initial text which will be replaced by first player that
|
||||
// supports any of the formats.
|
||||
$out = core_media_player::PLACEHOLDER;
|
||||
|
||||
// Loop through all players that support any of these URLs.
|
||||
foreach ($players as $player) {
|
||||
$supported = $player->list_supported_urls($alternatives, $options);
|
||||
if ($supported) {
|
||||
// Embed.
|
||||
$text = $player->embed($supported, $name, $width, $height, $options);
|
||||
|
||||
// Put this in place of the 'fallback' slot in the previous text.
|
||||
$out = str_replace(core_media_player::PLACEHOLDER, $text, $out);
|
||||
|
||||
// Check if we need to continue looking for players.
|
||||
if (strpos($out, core_media_player::PLACEHOLDER) === false) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($options[self::OPTION_FALLBACK_TO_BLANK]) || $out !== core_media_player::PLACEHOLDER) {
|
||||
// Fallback to the link. Exception: in case of OPTION_FALLBACK_TO_BLANK and no other player matched do not fallback.
|
||||
$text = $this->fallback_to_link($alternatives, $name, $options);
|
||||
$out = str_replace(core_media_player::PLACEHOLDER, $text, $out);
|
||||
}
|
||||
|
||||
// Remove 'fallback' slot from final version and return it.
|
||||
$out = str_replace(core_media_player::PLACEHOLDER, '', $out);
|
||||
if (!empty($options[self::OPTION_BLOCK]) && $out !== '') {
|
||||
$out = html_writer::tag('div', $out, array('class' => 'resourcecontent'));
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns links to the specified URLs unless OPTION_NO_LINK is passed.
|
||||
*
|
||||
* @param array $urls URLs of media files
|
||||
* @param string $name Display name; '' to use default
|
||||
* @param array $options Options array
|
||||
* @return string HTML code for embed
|
||||
*/
|
||||
protected function fallback_to_link($urls, $name, $options) {
|
||||
// If link is turned off, return empty.
|
||||
if (!empty($options[core_media_manager::OPTION_NO_LINK])) {
|
||||
return '';
|
||||
}
|
||||
|
||||
// Build up link content.
|
||||
$output = '';
|
||||
foreach ($urls as $url) {
|
||||
if (strval($name) !== '' && $output === '') {
|
||||
$title = $name;
|
||||
} else {
|
||||
$title = core_media_manager::instance()->get_filename($url);
|
||||
}
|
||||
$printlink = html_writer::link($url, $title, array('class' => 'mediafallbacklink'));
|
||||
if ($output) {
|
||||
// Where there are multiple available formats, there are fallback links
|
||||
// for all formats, separated by /.
|
||||
$output .= ' / ';
|
||||
}
|
||||
$output .= $printlink;
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a file can be embedded. If this returns true you will get
|
||||
* an embedded player; if this returns false, you will just get a download
|
||||
* link.
|
||||
*
|
||||
* This is a wrapper for can_embed_urls.
|
||||
*
|
||||
* @param moodle_url $url URL of media file
|
||||
* @param array $options Options (same as when embedding)
|
||||
* @return bool True if file can be embedded
|
||||
*/
|
||||
public function can_embed_url(moodle_url $url, $options = array()) {
|
||||
return $this->can_embed_urls(array($url), $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a file can be embedded. If this returns true you will get
|
||||
* an embedded player; if this returns false, you will just get a download
|
||||
* link.
|
||||
*
|
||||
* @param array $urls URL of media file and any alternatives (moodle_url)
|
||||
* @param array $options Options (same as when embedding)
|
||||
* @return bool True if file can be embedded
|
||||
*/
|
||||
public function can_embed_urls(array $urls, $options = array()) {
|
||||
// Check all players to see if any of them support it.
|
||||
foreach ($this->get_players() as $player) {
|
||||
// First player that supports it, return true.
|
||||
if ($player->list_supported_urls($urls, $options)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a list of markers that can be used in a regular expression when
|
||||
* searching for URLs that can be embedded by any player type.
|
||||
*
|
||||
* This string is used to improve peformance of regex matching by ensuring
|
||||
* that the (presumably C) regex code can do a quick keyword check on the
|
||||
* URL part of a link to see if it matches one of these, rather than having
|
||||
* to go into PHP code for every single link to see if it can be embedded.
|
||||
*
|
||||
* @return string String suitable for use in regex such as '(\.mp4|\.flv)'
|
||||
*/
|
||||
public function get_embeddable_markers() {
|
||||
if (empty($this->embeddablemarkers)) {
|
||||
$markers = '';
|
||||
foreach ($this->get_players() as $player) {
|
||||
foreach ($player->get_embeddable_markers() as $marker) {
|
||||
if ($markers !== '') {
|
||||
$markers .= '|';
|
||||
}
|
||||
$markers .= preg_quote($marker);
|
||||
}
|
||||
}
|
||||
$this->embeddablemarkers = $markers;
|
||||
}
|
||||
return $this->embeddablemarkers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a string containing multiple URLs separated by #, this will split
|
||||
* it into an array of moodle_url objects suitable for using when calling
|
||||
* embed_alternatives.
|
||||
*
|
||||
* Note that the input string should NOT be html-escaped (i.e. if it comes
|
||||
* from html, call html_entity_decode first).
|
||||
*
|
||||
* @param string $combinedurl String of 1 or more alternatives separated by #
|
||||
* @param int $width Output variable: width (will be set to 0 if not specified)
|
||||
* @param int $height Output variable: height (0 if not specified)
|
||||
* @return array Array of 1 or more moodle_url objects
|
||||
*/
|
||||
public function split_alternatives($combinedurl, &$width, &$height) {
|
||||
$urls = explode('#', $combinedurl);
|
||||
$width = 0;
|
||||
$height = 0;
|
||||
$returnurls = array();
|
||||
|
||||
foreach ($urls as $url) {
|
||||
$matches = null;
|
||||
|
||||
// You can specify the size as a separate part of the array like
|
||||
// #d=640x480 without actually including a url in it.
|
||||
if (preg_match('/^d=([\d]{1,4})x([\d]{1,4})$/i', $url, $matches)) {
|
||||
$width = $matches[1];
|
||||
$height = $matches[2];
|
||||
continue;
|
||||
}
|
||||
|
||||
// Can also include the ?d= as part of one of the URLs (if you use
|
||||
// more than one they will be ignored except the last).
|
||||
if (preg_match('/\?d=([\d]{1,4})x([\d]{1,4})$/i', $url, $matches)) {
|
||||
$width = $matches[1];
|
||||
$height = $matches[2];
|
||||
|
||||
// Trim from URL.
|
||||
$url = str_replace($matches[0], '', $url);
|
||||
}
|
||||
|
||||
// Clean up url.
|
||||
$url = clean_param($url, PARAM_URL);
|
||||
if (empty($url)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Turn it into moodle_url object.
|
||||
$returnurls[] = new moodle_url($url);
|
||||
}
|
||||
|
||||
return $returnurls;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the file extension for a URL.
|
||||
* @param moodle_url $url URL
|
||||
*/
|
||||
public function get_extension(moodle_url $url) {
|
||||
// Note: Does not use core_text (. is UTF8-safe).
|
||||
$filename = self::get_filename($url);
|
||||
$dot = strrpos($filename, '.');
|
||||
if ($dot === false) {
|
||||
return '';
|
||||
} else {
|
||||
return strtolower(substr($filename, $dot + 1));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the filename from the moodle_url.
|
||||
* @param moodle_url $url URL
|
||||
* @return string Filename only (not escaped)
|
||||
*/
|
||||
public function get_filename(moodle_url $url) {
|
||||
// Use the 'file' parameter if provided (for links created when
|
||||
// slasharguments was off). If not present, just use URL path.
|
||||
$path = $url->get_param('file');
|
||||
if (!$path) {
|
||||
$path = $url->get_path();
|
||||
}
|
||||
|
||||
// Remove everything before last / if present. Does not use textlib as / is UTF8-safe.
|
||||
$slash = strrpos($path, '/');
|
||||
if ($slash !== false) {
|
||||
$path = substr($path, $slash + 1);
|
||||
}
|
||||
return $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Guesses MIME type for a moodle_url based on file extension.
|
||||
* @param moodle_url $url URL
|
||||
* @return string MIME type
|
||||
*/
|
||||
public function get_mimetype(moodle_url $url) {
|
||||
return mimeinfo('type', $this->get_filename($url));
|
||||
}
|
||||
|
||||
}
|
249
media/classes/player.php
Normal file
249
media/classes/player.php
Normal file
|
@ -0,0 +1,249 @@
|
|||
<?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/>.
|
||||
|
||||
/**
|
||||
* Base class for media players
|
||||
*
|
||||
* @package core_media
|
||||
* @copyright 2016 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Base class for media players.
|
||||
*
|
||||
* Media players return embed HTML for a particular way of playing back audio
|
||||
* or video (or another file type).
|
||||
*
|
||||
* In order to make the code more lightweight, this is not a plugin type
|
||||
* (players cannot have their own settings, database tables, capabilities, etc).
|
||||
* These classes are used only by core_media_renderer in outputrenderers.php.
|
||||
* If you add a new class here (in core code) you must modify the
|
||||
* get_players_raw function in that file to include it.
|
||||
*
|
||||
* If a Moodle installation wishes to add extra player objects they can do so
|
||||
* by overriding that renderer in theme, and overriding the get_players_raw
|
||||
* function. The new player class should then of course be defined within the
|
||||
* custom theme or other suitable location, not in this file.
|
||||
*
|
||||
* @package core_media
|
||||
* @copyright 2016 Marina Glancy
|
||||
* @author 2011 The Open University
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
abstract class core_media_player {
|
||||
/**
|
||||
* Placeholder text used to indicate where the fallback content is placed
|
||||
* within a result.
|
||||
*/
|
||||
const PLACEHOLDER = '<!--FALLBACK-->';
|
||||
|
||||
/**
|
||||
* Generates code required to embed the player.
|
||||
*
|
||||
* The returned code contains a placeholder comment '<!--FALLBACK-->'
|
||||
* (constant core_media_player::PLACEHOLDER) which indicates the location
|
||||
* where fallback content should be placed in the event that this type of
|
||||
* player is not supported by user browser.
|
||||
*
|
||||
* The $urls parameter includes one or more alternative media formats that
|
||||
* are supported by this player. It does not include formats that aren't
|
||||
* supported (see list_supported_urls).
|
||||
*
|
||||
* The $options array contains key-value pairs. See OPTION_xx constants
|
||||
* for documentation of standard option(s).
|
||||
*
|
||||
* @param array $urls URLs of media files
|
||||
* @param string $name Display name; '' to use default
|
||||
* @param int $width Optional width; 0 to use default
|
||||
* @param int $height Optional height; 0 to use default
|
||||
* @param array $options Options array
|
||||
* @return string HTML code for embed
|
||||
*/
|
||||
public abstract function embed($urls, $name, $width, $height, $options);
|
||||
|
||||
/**
|
||||
* Gets the list of file extensions supported by this media player.
|
||||
*
|
||||
* Note: This is only required for the default implementations of
|
||||
* list_supported_urls(), get_embeddable_markers() and supports().
|
||||
* If you override these functions to determine
|
||||
* supported URLs in some way other than by extension, then this function
|
||||
* is not necessary.
|
||||
*
|
||||
* @return array Array of strings (extension not including dot e.g. '.mp3')
|
||||
*/
|
||||
public function get_supported_extensions() {
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Lists keywords that must be included in a url that can be embedded with
|
||||
* this player. Any such keywords should be added to the array.
|
||||
*
|
||||
* For example if this player supports FLV and F4V files then it should add
|
||||
* '.flv' and '.f4v' to the array. (The check is not case-sensitive.)
|
||||
*
|
||||
* Default handling calls the get_supported_extensions function, so players
|
||||
* only need to override this if they don't implement get_supported_extensions.
|
||||
*
|
||||
* This is used to improve performance when matching links in the media filter.
|
||||
*
|
||||
* @return array Array of keywords to add to the embeddable markers list
|
||||
*/
|
||||
public function get_embeddable_markers() {
|
||||
return $this->get_supported_extensions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns human-readable string of supported file/link types for the "Manage media players" page
|
||||
* @param array $usedextensions extensions that should NOT be highlighted
|
||||
* @return string
|
||||
*/
|
||||
public function supports($usedextensions = []) {
|
||||
$out = [];
|
||||
if ($extensions = $this->get_supported_extensions()) {
|
||||
$video = $audio = $other = [];
|
||||
foreach ($extensions as $key => $extension) {
|
||||
$displayextension = $extension;
|
||||
if (!in_array($extension, $usedextensions)) {
|
||||
$displayextension = '<strong>'.$extension.'</strong>';
|
||||
}
|
||||
if (file_extension_in_typegroup('file.'.$extension, 'audio')) {
|
||||
$audio[] = $displayextension;
|
||||
} else if (file_extension_in_typegroup('file.'.$extension, 'video')) {
|
||||
$video[] = $displayextension;
|
||||
} else {
|
||||
$other[] = $displayextension;
|
||||
}
|
||||
}
|
||||
if ($video) {
|
||||
$out[] = get_string('videoextensions', 'core_media', join(', ', $video));
|
||||
}
|
||||
if ($audio) {
|
||||
$out[] = get_string('audioextensions', 'core_media', join(', ', $audio));
|
||||
}
|
||||
if ($other) {
|
||||
$out[] = get_string('extensions', 'core_media', join(', ', $other));
|
||||
}
|
||||
}
|
||||
return join('<br>', $out);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the ranking of this player. This is an integer used to decide which
|
||||
* player to use (after applying other considerations such as which ones
|
||||
* the user has disabled).
|
||||
*
|
||||
* This function returns the default rank that can be adjusted by the administrator
|
||||
* on the Manage media players page.
|
||||
*
|
||||
* @return int Rank (higher is better)
|
||||
*/
|
||||
public abstract function get_rank();
|
||||
|
||||
/**
|
||||
* Returns if the current player is enabled.
|
||||
*
|
||||
* @deprecated since Moodle 3.2
|
||||
* @return bool True if player is enabled
|
||||
*/
|
||||
public function is_enabled() {
|
||||
debugging('Function core_media_player::is_enabled() is deprecated without replacement', DEBUG_DEVELOPER);
|
||||
|
||||
$enabled = \core\plugininfo\media::get_enabled_plugins();
|
||||
|
||||
if ($enabled && preg_match('/^media_(.*)_plugin$/', get_class($this), $matches)) {
|
||||
return array_key_exists($matches[1], $enabled);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a list of URLs, returns a reduced array containing only those URLs
|
||||
* which are supported by this player. (Empty if none.)
|
||||
* @param array $urls Array of moodle_url
|
||||
* @param array $options Options (same as will be passed to embed)
|
||||
* @return array Array of supported moodle_url
|
||||
*/
|
||||
public function list_supported_urls(array $urls, array $options = array()) {
|
||||
$extensions = $this->get_supported_extensions();
|
||||
$result = array();
|
||||
foreach ($urls as $url) {
|
||||
$ext = core_media_manager::instance()->get_extension($url);
|
||||
if (in_array('.' . $ext, $extensions) || in_array($ext, $extensions)) {
|
||||
$result[] = $url;
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains suitable name for media. Uses specified name if there is one,
|
||||
* otherwise makes one up.
|
||||
* @param string $name User-specified name ('' if none)
|
||||
* @param array $urls Array of moodle_url used to make up name
|
||||
* @return string Name
|
||||
*/
|
||||
protected function get_name($name, $urls) {
|
||||
// If there is a specified name, use that.
|
||||
if ($name) {
|
||||
return $name;
|
||||
}
|
||||
|
||||
// Get filename of first URL.
|
||||
$url = reset($urls);
|
||||
$name = core_media_manager::instance()->get_filename($url);
|
||||
|
||||
// If there is more than one url, strip the extension as we could be
|
||||
// referring to a different one or several at once.
|
||||
if (count($urls) > 1) {
|
||||
$name = preg_replace('~\.[^.]*$~', '', $name);
|
||||
}
|
||||
|
||||
return $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares by rank order, highest first. Used for sort functions.
|
||||
* @deprecated since Moodle 3.2
|
||||
* @param core_media_player $a Player A
|
||||
* @param core_media_player $b Player B
|
||||
* @return int Negative if A should go before B, positive for vice versa
|
||||
*/
|
||||
public static function compare_by_rank(core_media_player $a, core_media_player $b) {
|
||||
debugging('Function core_media_player::compare_by_rank() is deprecated without replacement', DEBUG_DEVELOPER);
|
||||
return $b->get_rank() - $a->get_rank();
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility function that sets width and height to defaults if not specified
|
||||
* as a parameter to the function (will be specified either if, (a) the calling
|
||||
* code passed it, or (b) the URL included it).
|
||||
* @param int $width Width passed to function (updated with final value)
|
||||
* @param int $height Height passed to function (updated with final value)
|
||||
*/
|
||||
protected static function pick_video_size(&$width, &$height) {
|
||||
global $CFG;
|
||||
if (!$width) {
|
||||
$width = $CFG->media_default_width;
|
||||
$height = $CFG->media_default_height;
|
||||
}
|
||||
}
|
||||
}
|
107
media/classes/player_external.php
Normal file
107
media/classes/player_external.php
Normal file
|
@ -0,0 +1,107 @@
|
|||
<?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/>.
|
||||
|
||||
/**
|
||||
* Base class for players which handle external links
|
||||
*
|
||||
* @package core_media
|
||||
* @copyright 2016 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Base class for players which handle external links (YouTube etc).
|
||||
*
|
||||
* As opposed to media files.
|
||||
*
|
||||
* @package core_media
|
||||
* @copyright 2016 Marina Glancy
|
||||
* @author 2011 The Open University
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
abstract class core_media_player_external extends core_media_player {
|
||||
/**
|
||||
* Array of matches from regular expression - subclass can assume these
|
||||
* will be valid when the embed function is called, to save it rerunning
|
||||
* the regex.
|
||||
* @var array
|
||||
*/
|
||||
protected $matches;
|
||||
|
||||
/**
|
||||
* Part of a regular expression, including ending ~ symbol (note: these
|
||||
* regexes use ~ instead of / because URLs and HTML code typically include
|
||||
* / symbol and makes harder to read if you have to escape it).
|
||||
* Matches the end part of a link after you have read the 'important' data
|
||||
* including optional #d=400x300 at end of url, plus content of <a> tag,
|
||||
* up to </a>.
|
||||
* @var string
|
||||
*/
|
||||
const END_LINK_REGEX_PART = '[^#]*(#d=([\d]{1,4})x([\d]{1,4}))?~si';
|
||||
|
||||
public function embed($urls, $name, $width, $height, $options) {
|
||||
return $this->embed_external(reset($urls), $name, $width, $height, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains HTML code to embed the link.
|
||||
* @param moodle_url $url Single URL to embed
|
||||
* @param string $name Display name; '' to use default
|
||||
* @param int $width Optional width; 0 to use default
|
||||
* @param int $height Optional height; 0 to use default
|
||||
* @param array $options Options array
|
||||
* @return string HTML code for embed
|
||||
*/
|
||||
protected abstract function embed_external(moodle_url $url, $name, $width, $height, $options);
|
||||
|
||||
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) {
|
||||
return array();
|
||||
}
|
||||
$url = reset($urls);
|
||||
|
||||
// Check against regex.
|
||||
if (preg_match($this->get_regex(), $url->out(false), $this->matches)) {
|
||||
return array($url);
|
||||
}
|
||||
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns regular expression used to match URLs that this player handles
|
||||
* @return string PHP regular expression e.g. '~^https?://example.org/~'
|
||||
*/
|
||||
protected function get_regex() {
|
||||
return '~^unsupported~';
|
||||
}
|
||||
|
||||
/**
|
||||
* Annoyingly, preg_match $matches result does not always have the same
|
||||
* number of parameters - it leaves out optional ones at the end. WHAT.
|
||||
* Anyway, this function can be used to fix it.
|
||||
* @param array $matches Array that should be adjusted
|
||||
* @param int $count Number of capturing groups (=6 to make $matches[6] work)
|
||||
*/
|
||||
protected static function fix_match_count(&$matches, $count) {
|
||||
for ($i = count($matches); $i <= $count; $i++) {
|
||||
$matches[$i] = false;
|
||||
}
|
||||
}
|
||||
}
|
130
media/classes/player_native.php
Normal file
130
media/classes/player_native.php
Normal file
|
@ -0,0 +1,130 @@
|
|||
<?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/>.
|
||||
|
||||
/**
|
||||
* Base class for players which return native HTML5 <video> or <audio> tags
|
||||
*
|
||||
* @package core_media
|
||||
* @copyright 2016 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Base class for players which return native HTML5 <video> or <audio> tags
|
||||
*
|
||||
* @package core_media
|
||||
* @copyright 2016 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
abstract class core_media_player_native extends core_media_player {
|
||||
/**
|
||||
* Extracts a value for an attribute
|
||||
*
|
||||
* @param string $tag html tag which properties are extracted, for example "<video ...>....</video>"
|
||||
* @param string $attrname name of the attribute we are looking for
|
||||
* @param string $type one of PARAM_* constants to clean the attribute value
|
||||
* @return string|null
|
||||
*/
|
||||
public static function get_attribute($tag, $attrname, $type = PARAM_RAW) {
|
||||
if (preg_match('/^<[^>]*\b' . $attrname . '="(.*?)"/is', $tag, $matches)) {
|
||||
return clean_param(htmlspecialchars_decode($matches[1]), $type);
|
||||
} else if (preg_match('~^<[^>]*\b' . $attrname . '[ />]"~is', $tag, $matches)) {
|
||||
// Some attributes may not have value, for example this is valid: <video controls>.
|
||||
return clean_param("true", $type);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an attribute from the media tags
|
||||
*
|
||||
* @param string $tag html tag which properties are extracted, for example "<video ...>....</video>"
|
||||
* @param string|array $attrname
|
||||
* @return string
|
||||
*/
|
||||
public static function remove_attributes($tag, $attrname) {
|
||||
if (is_array($attrname)) {
|
||||
$attrname = join('|', $attrname);
|
||||
}
|
||||
while (preg_match('/^(<[^>]*\b)(' . $attrname . ')=".*?"(.*)$/is', $tag, $matches)) {
|
||||
$tag = $matches[1] . $matches[3];
|
||||
}
|
||||
while (preg_match('~^(<[^>]*\b)(' . $attrname . ')([ />].*)$~is', $tag, $matches)) {
|
||||
// Some attributes may not have value, for example: <video controls>.
|
||||
$tag = $matches[1] . $matches[3];
|
||||
}
|
||||
return $tag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds attributes to the media tags
|
||||
*
|
||||
* @param string $tag html tag which properties are extracted, for example "<video ...>....</video>"
|
||||
* @param array $attributes key-value pairs of attributes to be added
|
||||
* @return string
|
||||
*/
|
||||
public static function add_attributes($tag, $attributes) {
|
||||
$tag = self::remove_attributes($tag, array_keys($attributes));
|
||||
if (!preg_match('/^(<.*?)(>.*)$/s', $tag, $matches)) {
|
||||
return $tag;
|
||||
}
|
||||
$rv = $matches[1];
|
||||
foreach ($attributes as $name => $value) {
|
||||
$rv .= " $name=\"".s($value).'"';
|
||||
}
|
||||
$rv .= $matches[2];
|
||||
return $rv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces all embedded <source> tags and src attribute
|
||||
*
|
||||
* @param string $tag html tag which properties are extracted, for example "<video ...>....</video>"
|
||||
* @param string $sources replacement string (expected to contain <source> tags)
|
||||
* @return string
|
||||
*/
|
||||
public static function replace_sources($tag, $sources) {
|
||||
$tag = self::remove_attributes($tag, 'src');
|
||||
$tag = preg_replace(['~</?source\b[^>]*>~i'], '', $tag);
|
||||
if (preg_match('/^(<.*?>)([^\0]*)$/ms', $tag, $matches)) {
|
||||
$tag = $matches[1].$sources.$matches[2];
|
||||
}
|
||||
return $tag;
|
||||
}
|
||||
|
||||
public function get_supported_extensions() {
|
||||
return file_get_typegroup('extension', ['html_video', 'html_audio']);
|
||||
}
|
||||
|
||||
public function list_supported_urls(array $urls, array $options = array()) {
|
||||
$extensions = $this->get_supported_extensions();
|
||||
$result = array();
|
||||
foreach ($urls as $url) {
|
||||
$ext = core_media_manager::instance()->get_extension($url);
|
||||
if (in_array('.' . $ext, $extensions) && core_useragent::supports_html5($ext)) {
|
||||
// Unfortunately html5 video does not handle fallback properly.
|
||||
// https://www.w3.org/Bugs/Public/show_bug.cgi?id=10975
|
||||
// That means we need to do browser detect and not use html5 on
|
||||
// browsers which do not support the given type, otherwise users
|
||||
// will not even see the fallback link.
|
||||
$result[] = $url;
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
107
media/player/html5audio/classes/plugin.php
Normal file
107
media/player/html5audio/classes/plugin.php
Normal file
|
@ -0,0 +1,107 @@
|
|||
<?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_html5audio'
|
||||
*
|
||||
* @package media_html5audio
|
||||
* @copyright 2016 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Player that creates HTML5 <audio> tag.
|
||||
*
|
||||
* @package media_html5audio
|
||||
* @copyright 2016 Marina Glancy
|
||||
* @author 2011 The Open University
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class media_html5audio_plugin extends core_media_player_native {
|
||||
public function embed($urls, $name, $width, $height, $options) {
|
||||
|
||||
if (array_key_exists(core_media_manager::OPTION_ORIGINAL_TEXT, $options) &&
|
||||
preg_match('/^<(video|audio)\b/i', $options[core_media_manager::OPTION_ORIGINAL_TEXT], $matches)) {
|
||||
// We already had media tag, do nothing here.
|
||||
return $options[core_media_manager::OPTION_ORIGINAL_TEXT];
|
||||
}
|
||||
|
||||
// Build array of source tags.
|
||||
$sources = array();
|
||||
foreach ($urls as $url) {
|
||||
$params = ['src' => $url];
|
||||
$ext = core_media_manager::instance()->get_extension($url);
|
||||
if ($ext !== 'aac') {
|
||||
// Some browsers get confused by mimetype on source for AAC files.
|
||||
$mimetype = core_media_manager::instance()->get_mimetype($url);
|
||||
$params['type'] = $mimetype;
|
||||
}
|
||||
$sources[] = html_writer::empty_tag('source', $params);
|
||||
}
|
||||
|
||||
$sources = implode("\n", $sources);
|
||||
$title = $this->get_name($name, $urls);
|
||||
// Escape title but prevent double escaping.
|
||||
$title = s(preg_replace(['/&/', '/>/', '/</'], ['&', '>', '<'], $title));
|
||||
|
||||
// Default to not specify size (so it can be changed in css).
|
||||
$size = '';
|
||||
if ($width) {
|
||||
$size = 'width="' . $width . '"';
|
||||
}
|
||||
|
||||
$fallback = core_media_player::PLACEHOLDER;
|
||||
|
||||
return <<<OET
|
||||
<audio controls="true" $size class="mediaplugin mediaplugin_html5audio" preload="none" title="$title">
|
||||
$sources
|
||||
$fallback
|
||||
</audio>
|
||||
OET;
|
||||
}
|
||||
|
||||
public function get_supported_extensions() {
|
||||
return file_get_typegroup('extension', 'html_audio');
|
||||
}
|
||||
|
||||
public function list_supported_urls(array $urls, array $options = array()) {
|
||||
$extensions = $this->get_supported_extensions();
|
||||
$result = array();
|
||||
foreach ($urls as $url) {
|
||||
$ext = core_media_manager::instance()->get_extension($url);
|
||||
if (in_array('.' . $ext, $extensions) && core_useragent::supports_html5($ext)) {
|
||||
// Unfortunately html5 video does not handle fallback properly.
|
||||
// https://www.w3.org/Bugs/Public/show_bug.cgi?id=10975
|
||||
// That means we need to do browser detect and not use html5 on
|
||||
// browsers which do not support the given type, otherwise users
|
||||
// will not even see the fallback link.
|
||||
$result[] = $url;
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default rank
|
||||
* @return int
|
||||
*/
|
||||
public function get_rank() {
|
||||
return 20;
|
||||
}
|
||||
}
|
||||
|
26
media/player/html5audio/lang/en/media_html5audio.php
Normal file
26
media/player/html5audio/lang/en/media_html5audio.php
Normal file
|
@ -0,0 +1,26 @@
|
|||
<?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_html5audio'
|
||||
*
|
||||
* @package media_html5audio
|
||||
* @copyright 2016 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
$string['pluginname'] = 'HTML 5 audio';
|
||||
$string['pluginname_help'] = 'Audio files played by browser native audio player. (Format support depends on browser.)';
|
BIN
media/player/html5audio/pix/icon.png
Normal file
BIN
media/player/html5audio/pix/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.7 KiB |
130
media/player/html5audio/tests/player_test.php
Normal file
130
media/player/html5audio/tests/player_test.php
Normal file
|
@ -0,0 +1,130 @@
|
|||
<?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/>.
|
||||
|
||||
/**
|
||||
* Test classes for handling embedded media.
|
||||
*
|
||||
* @package media_html5audio
|
||||
* @copyright 2016 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Test script for media embedding.
|
||||
*
|
||||
* @package media_html5audio
|
||||
* @copyright 2016 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class media_html5audio_testcase extends advanced_testcase {
|
||||
|
||||
/**
|
||||
* Pre-test setup. Preserves $CFG.
|
||||
*/
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// Reset $CFG and $SERVER.
|
||||
$this->resetAfterTest();
|
||||
|
||||
// Consistent initial setup: all players disabled.
|
||||
\core\plugininfo\media::set_enabled_plugins('html5audio');
|
||||
|
||||
// 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() {
|
||||
$sortorder = \core\plugininfo\media::get_enabled_plugins();
|
||||
$this->assertEquals(['html5audio' => 'html5audio'], $sortorder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method get_supported_extensions()
|
||||
*/
|
||||
public function test_supported_extensions() {
|
||||
$nativeextensions = file_get_typegroup('extension', 'html_audio');
|
||||
|
||||
// Make sure that the list of extensions from the setting is exactly the same as html_audio group.
|
||||
$player = new media_html5audio_plugin();
|
||||
$this->assertEmpty(array_diff($player->get_supported_extensions(), $nativeextensions));
|
||||
$this->assertEmpty(array_diff($nativeextensions, $player->get_supported_extensions()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test embedding without media filter (for example for displaying file resorce).
|
||||
*/
|
||||
public function test_embed_url() {
|
||||
global $CFG;
|
||||
|
||||
$url = new moodle_url('http://example.org/1.wav');
|
||||
|
||||
$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->assertRegExp('~mediaplugin_html5audio~', $content);
|
||||
$this->assertRegExp('~</audio>~', $content);
|
||||
$this->assertRegExp('~title="Test & file"~', $content);
|
||||
// Do not set default width/height (it's an audio after all).
|
||||
$this->assertNotRegExp('~width=~', $content);
|
||||
$this->assertNotRegExp('~height=~', $content);
|
||||
|
||||
// This plugin ignores size settings.
|
||||
$this->assertNotRegExp('~width=~', $content);
|
||||
$this->assertNotRegExp('~height=~', $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() {
|
||||
$url = new moodle_url('http://example.org/some_filename.wav');
|
||||
$text = html_writer::link($url, 'Watch this one');
|
||||
$content = format_text($text, FORMAT_HTML);
|
||||
|
||||
$this->assertRegExp('~mediaplugin_html5audio~', $content);
|
||||
$this->assertRegExp('~</audio>~', $content);
|
||||
$this->assertRegExp('~title="Watch this one"~', $content);
|
||||
$this->assertNotRegExp('~<track\b~i', $content);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that mediaplugin filter does not work on <audio> tags.
|
||||
*/
|
||||
public function test_embed_media() {
|
||||
$url = new moodle_url('http://example.org/some_filename.wav');
|
||||
$trackurl = new moodle_url('http://example.org/some_filename.vtt');
|
||||
$text = '<audio controls="true"><source src="'.$url.'"/><source src="somethinginvalid"/>' .
|
||||
'<track src="'.$trackurl.'">Unsupported text</audio>';
|
||||
$content = format_text($text, FORMAT_HTML);
|
||||
|
||||
$this->assertNotRegExp('~mediaplugin_html5audio~', $content);
|
||||
$this->assertEquals(clean_text($text, FORMAT_HTML), $content);
|
||||
}
|
||||
}
|
29
media/player/html5audio/version.php
Normal file
29
media/player/html5audio/version.php
Normal 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_html5audio
|
||||
* @copyright 2016 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2016052300; // The current plugin version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2016051900; // Requires this Moodle version
|
||||
$plugin->component = 'media_html5audio'; // Full name of the plugin (used for diagnostics).
|
150
media/player/html5video/classes/plugin.php
Normal file
150
media/player/html5video/classes/plugin.php
Normal file
|
@ -0,0 +1,150 @@
|
|||
<?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_html5video'
|
||||
*
|
||||
* @package media_html5video
|
||||
* @copyright 2016 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Player that creates HTML5 <video> tag.
|
||||
*
|
||||
* @package media_html5video
|
||||
* @copyright 2016 Marina Glancy
|
||||
* @author 2011 The Open University
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class media_html5video_plugin extends core_media_player_native {
|
||||
public function embed($urls, $name, $width, $height, $options) {
|
||||
|
||||
if (array_key_exists(core_media_manager::OPTION_ORIGINAL_TEXT, $options) &&
|
||||
preg_match('/^<(video|audio)\b/i', $options[core_media_manager::OPTION_ORIGINAL_TEXT], $matches)) {
|
||||
// We already had media tag, do nothing here.
|
||||
return $options[core_media_manager::OPTION_ORIGINAL_TEXT];
|
||||
}
|
||||
|
||||
// Special handling to make videos play on Android devices pre 2.3.
|
||||
// Note: I tested and 2.3.3 (in emulator) works without, is 533.1 webkit.
|
||||
$oldandroid = core_useragent::is_webkit_android() &&
|
||||
!core_useragent::check_webkit_android_version('533.1');
|
||||
|
||||
// Build array of source tags.
|
||||
$sources = array();
|
||||
foreach ($urls as $url) {
|
||||
$mimetype = core_media_manager::instance()->get_mimetype($url);
|
||||
$source = html_writer::empty_tag('source', array('src' => $url, 'type' => $mimetype));
|
||||
if ($mimetype === 'video/mp4') {
|
||||
if ($oldandroid) {
|
||||
// Old Android fails if you specify the type param.
|
||||
$source = html_writer::empty_tag('source', array('src' => $url));
|
||||
}
|
||||
|
||||
// Better add m4v as first source, it might be a bit more
|
||||
// compatible with problematic browsers.
|
||||
array_unshift($sources, $source);
|
||||
} else {
|
||||
$sources[] = $source;
|
||||
}
|
||||
}
|
||||
|
||||
$sources = implode("\n", $sources);
|
||||
$title = $this->get_name($name, $urls);
|
||||
// Escape title but prevent double escaping.
|
||||
$title = s(preg_replace(['/&/', '/>/', '/</'], ['&', '>', '<'], $title));
|
||||
|
||||
self::pick_video_size($width, $height);
|
||||
if (!$height) {
|
||||
// Let browser choose height automatically.
|
||||
$size = "width=\"$width\"";
|
||||
} else {
|
||||
$size = "width=\"$width\" height=\"$height\"";
|
||||
}
|
||||
|
||||
$sillyscript = '';
|
||||
$idtag = '';
|
||||
if ($oldandroid) {
|
||||
// Old Android does not support 'controls' option.
|
||||
$id = 'core_media_html5v_' . md5(time() . '_' . rand());
|
||||
$idtag = 'id="' . $id . '"';
|
||||
$sillyscript = <<<OET
|
||||
<script type="text/javascript">
|
||||
document.getElementById('$id').addEventListener('click', function() {
|
||||
this.play();
|
||||
}, false);
|
||||
</script>
|
||||
OET;
|
||||
}
|
||||
|
||||
$fallback = core_media_player::PLACEHOLDER;
|
||||
return <<<OET
|
||||
<span class="mediaplugin mediaplugin_html5video">
|
||||
<video $idtag controls="true" $size preload="metadata" title="$title">
|
||||
$sources
|
||||
$fallback
|
||||
</video>
|
||||
$sillyscript
|
||||
</span>
|
||||
OET;
|
||||
}
|
||||
|
||||
public function get_supported_extensions() {
|
||||
return file_get_typegroup('extension', 'html_video');
|
||||
}
|
||||
|
||||
public function list_supported_urls(array $urls, array $options = array()) {
|
||||
$extensions = $this->get_supported_extensions();
|
||||
$result = array();
|
||||
foreach ($urls as $url) {
|
||||
$ext = core_media_manager::instance()->get_extension($url);
|
||||
if (in_array('.' . $ext, $extensions) && core_useragent::supports_html5($ext)) {
|
||||
// Unfortunately html5 video does not handle fallback properly.
|
||||
// https://www.w3.org/Bugs/Public/show_bug.cgi?id=10975
|
||||
// That means we need to do browser detect and not use html5 on
|
||||
// browsers which do not support the given type, otherwise users
|
||||
// will not even see the fallback link.
|
||||
$result[] = $url;
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility function that sets width and height to defaults if not specified
|
||||
* as a parameter to the function (will be specified either if, (a) the calling
|
||||
* code passed it, or (b) the URL included it).
|
||||
* @param int $width Width passed to function (updated with final value)
|
||||
* @param int $height Height passed to function (updated with final value)
|
||||
*/
|
||||
protected static function pick_video_size(&$width, &$height) {
|
||||
global $CFG;
|
||||
if (!$width) {
|
||||
$width = $CFG->media_default_width;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Default rank
|
||||
* @return int
|
||||
*/
|
||||
public function get_rank() {
|
||||
return 50;
|
||||
}
|
||||
}
|
26
media/player/html5video/lang/en/media_html5video.php
Normal file
26
media/player/html5video/lang/en/media_html5video.php
Normal file
|
@ -0,0 +1,26 @@
|
|||
<?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_html5video'
|
||||
*
|
||||
* @package media_html5video
|
||||
* @copyright 2016 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
$string['pluginname'] = 'HTML 5 video';
|
||||
$string['pluginname_help'] = 'Video files played by browser native video player. (Format support depends on browser.)';
|
BIN
media/player/html5video/pix/icon.png
Normal file
BIN
media/player/html5video/pix/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 169 B |
131
media/player/html5video/tests/player_test.php
Normal file
131
media/player/html5video/tests/player_test.php
Normal file
|
@ -0,0 +1,131 @@
|
|||
<?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/>.
|
||||
|
||||
/**
|
||||
* Test classes for handling embedded media.
|
||||
*
|
||||
* @package media_html5video
|
||||
* @copyright 2016 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Test script for media embedding.
|
||||
*
|
||||
* @package media_html5video
|
||||
* @copyright 2016 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class media_html5video_testcase extends advanced_testcase {
|
||||
|
||||
/**
|
||||
* Pre-test setup. Preserves $CFG.
|
||||
*/
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// Reset $CFG and $SERVER.
|
||||
$this->resetAfterTest();
|
||||
|
||||
// Consistent initial setup: all players disabled.
|
||||
\core\plugininfo\media::set_enabled_plugins('html5video');
|
||||
|
||||
// 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() {
|
||||
$sortorder = \core\plugininfo\media::get_enabled_plugins();
|
||||
$this->assertEquals(['html5video' => 'html5video'], $sortorder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method get_supported_extensions()
|
||||
*/
|
||||
public function test_supported_extensions() {
|
||||
$nativeextensions = file_get_typegroup('extension', 'html_video');
|
||||
|
||||
// Make sure that the list of extensions from the setting is exactly the same as html_video group.
|
||||
$player = new media_html5video_plugin();
|
||||
$this->assertEmpty(array_diff($player->get_supported_extensions(), $nativeextensions));
|
||||
$this->assertEmpty(array_diff($nativeextensions, $player->get_supported_extensions()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test embedding without media filter (for example for displaying file resorce).
|
||||
*/
|
||||
public function test_embed_url() {
|
||||
global $CFG;
|
||||
|
||||
$url = new moodle_url('http://example.org/1.webm');
|
||||
|
||||
$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->assertRegExp('~mediaplugin_html5video~', $content);
|
||||
$this->assertRegExp('~</video>~', $content);
|
||||
$this->assertRegExp('~title="Test & file"~', $content);
|
||||
$this->assertRegExp('~width="' . $CFG->media_default_width . '"~', $content);
|
||||
$this->assertNotRegExp('~height=~', $content); // Allow to set automatic height.
|
||||
|
||||
// Repeat sending the specific size to the manager.
|
||||
$content = $manager->embed_url($url, 'New file', 123, 50, $embedoptions);
|
||||
$this->assertRegExp('~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() {
|
||||
global $CFG;
|
||||
$url = new moodle_url('http://example.org/some_filename.mp4');
|
||||
$text = html_writer::link($url, 'Watch this one');
|
||||
$content = format_text($text, FORMAT_HTML);
|
||||
|
||||
$this->assertRegExp('~mediaplugin_html5video~', $content);
|
||||
$this->assertRegExp('~</video>~', $content);
|
||||
$this->assertRegExp('~title="Watch this one"~', $content);
|
||||
$this->assertNotRegExp('~<track\b~i', $content);
|
||||
$this->assertRegExp('~width="' . $CFG->media_default_width . '"~', $content);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that mediaplugin filter does not work on <video> tags.
|
||||
*/
|
||||
public function test_embed_media() {
|
||||
$url = new moodle_url('http://example.org/some_filename.mp4');
|
||||
$trackurl = new moodle_url('http://example.org/some_filename.vtt');
|
||||
$text = '<video controls="true"><source src="'.$url.'"/><source src="somethinginvalid"/>' .
|
||||
'<track src="'.$trackurl.'">Unsupported text</video>';
|
||||
$content = format_text($text, FORMAT_HTML);
|
||||
|
||||
$this->assertNotRegExp('~mediaplugin_html5video~', $content);
|
||||
$this->assertEquals(clean_text($text, FORMAT_HTML), $content);
|
||||
}
|
||||
}
|
29
media/player/html5video/version.php
Normal file
29
media/player/html5video/version.php
Normal 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_html5video
|
||||
* @copyright 2016 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2016052300; // The current plugin version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2016051900; // Requires this Moodle version
|
||||
$plugin->component = 'media_html5video'; // Full name of the plugin (used for diagnostics).
|
100
media/player/swf/classes/plugin.php
Normal file
100
media/player/swf/classes/plugin.php
Normal file
|
@ -0,0 +1,100 @@
|
|||
<?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_swf'
|
||||
*
|
||||
* @package media_swf
|
||||
* @copyright 2016 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Media player for Flash SWF files.
|
||||
*
|
||||
* This player contains additional security restriction: it will only be used
|
||||
* if you add option core_media_player_swf::ALLOW = true.
|
||||
*
|
||||
* Code should only set this option if it has verified that the data was
|
||||
* embedded by a trusted user (e.g. in trust text).
|
||||
*
|
||||
* @package media_swf
|
||||
* @copyright 2016 Marina Glancy
|
||||
* @author 2011 The Open University
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class media_swf_plugin extends core_media_player {
|
||||
public function embed($urls, $name, $width, $height, $options) {
|
||||
self::pick_video_size($width, $height);
|
||||
|
||||
$firsturl = reset($urls);
|
||||
$url = $firsturl->out(true);
|
||||
|
||||
$fallback = core_media_player::PLACEHOLDER;
|
||||
$output = <<<OET
|
||||
<span class="mediaplugin mediaplugin_swf">
|
||||
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="$width" height="$height">
|
||||
<param name="movie" value="$url" />
|
||||
<param name="autoplay" value="true" />
|
||||
<param name="loop" value="false" />
|
||||
<param name="controller" value="true" />
|
||||
<param name="scale" value="aspect" />
|
||||
<param name="base" value="." />
|
||||
<param name="allowscriptaccess" value="never" />
|
||||
<param name="allowfullscreen" value="true" />
|
||||
<!--[if !IE]><!-->
|
||||
<object type="application/x-shockwave-flash" data="$url" width="$width" height="$height">
|
||||
<param name="controller" value="true" />
|
||||
<param name="autoplay" value="true" />
|
||||
<param name="loop" value="false" />
|
||||
<param name="scale" value="aspect" />
|
||||
<param name="base" value="." />
|
||||
<param name="allowscriptaccess" value="never" />
|
||||
<param name="allowfullscreen" value="true" />
|
||||
<!--<![endif]-->
|
||||
$fallback
|
||||
<!--[if !IE]><!-->
|
||||
</object>
|
||||
<!--<![endif]-->
|
||||
</object>
|
||||
</span>
|
||||
OET;
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
public function get_supported_extensions() {
|
||||
return array('.swf');
|
||||
}
|
||||
|
||||
public function list_supported_urls(array $urls, array $options = array()) {
|
||||
// Not supported unless the creator is trusted.
|
||||
if (empty($options[core_media_manager::OPTION_TRUSTED])) {
|
||||
return array();
|
||||
}
|
||||
return parent::list_supported_urls($urls, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Default rank
|
||||
* @return int
|
||||
*/
|
||||
public function get_rank() {
|
||||
return 30;
|
||||
}
|
||||
}
|
26
media/player/swf/lang/en/media_swf.php
Normal file
26
media/player/swf/lang/en/media_swf.php
Normal file
|
@ -0,0 +1,26 @@
|
|||
<?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_swf'
|
||||
*
|
||||
* @package media_swf
|
||||
* @copyright 2016 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
$string['pluginname'] = 'Flash animation';
|
||||
$string['pluginname_help'] = 'For security reasons this format is only embedded within trusted text.';
|
BIN
media/player/swf/pix/icon.png
Normal file
BIN
media/player/swf/pix/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 554 B |
151
media/player/swf/tests/player_test.php
Normal file
151
media/player/swf/tests/player_test.php
Normal file
|
@ -0,0 +1,151 @@
|
|||
<?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/>.
|
||||
|
||||
/**
|
||||
* Test classes for handling embedded media.
|
||||
*
|
||||
* @package media_swf
|
||||
* @copyright 2016 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Test script for media embedding.
|
||||
*
|
||||
* @package media_swf
|
||||
* @copyright 2016 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class media_swf_testcase extends advanced_testcase {
|
||||
|
||||
/**
|
||||
* Pre-test setup. Preserves $CFG.
|
||||
*/
|
||||
public function setUp() {
|
||||
global $CFG;
|
||||
parent::setUp();
|
||||
|
||||
// Reset $CFG and $SERVER.
|
||||
$this->resetAfterTest();
|
||||
|
||||
// We need trusttext for embedding swf.
|
||||
$CFG->enabletrusttext = true;
|
||||
|
||||
// Consistent initial setup: all players disabled.
|
||||
\core\plugininfo\media::set_enabled_plugins('swf');
|
||||
|
||||
// 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() {
|
||||
$sortorder = \core\plugininfo\media::get_enabled_plugins();
|
||||
$this->assertEquals(['swf' => 'swf'], $sortorder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test embedding without media filter (for example for displaying file resorce).
|
||||
*/
|
||||
public function test_embed_url() {
|
||||
global $CFG;
|
||||
|
||||
$url = new moodle_url('http://example.org/1.swf');
|
||||
|
||||
$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->assertRegExp('~mediaplugin_swf~', $content);
|
||||
$this->assertRegExp('~</object>~', $content);
|
||||
$this->assertRegExp('~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->assertRegExp('~width="123" height="50"~', $content);
|
||||
|
||||
// Not working without trust!
|
||||
$embedoptions = array(
|
||||
core_media_manager::OPTION_BLOCK => true,
|
||||
);
|
||||
$this->assertFalse($manager->can_embed_url($url, $embedoptions));
|
||||
$content = $manager->embed_url($url, 'Test & file', 0, 0, $embedoptions);
|
||||
$this->assertNotRegExp('~mediaplugin_swf~', $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() {
|
||||
global $CFG;
|
||||
$url = new moodle_url('http://example.org/some_filename.swf');
|
||||
$text = html_writer::link($url, 'Watch this one');
|
||||
$content = format_text($text, FORMAT_HTML, ['trusted' => true]);
|
||||
|
||||
$this->assertRegExp('~mediaplugin_swf~', $content);
|
||||
$this->assertRegExp('~</object>~', $content);
|
||||
$this->assertRegExp('~width="' . $CFG->media_default_width . '" height="' .
|
||||
$CFG->media_default_height . '"~', $content);
|
||||
|
||||
// Not working without trust!
|
||||
$content = format_text($text, FORMAT_HTML);
|
||||
$this->assertNotRegExp('~mediaplugin_swf~', $content);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that mediaplugin filter adds player code on top of <video> tags.
|
||||
*
|
||||
* filter_mediaplugin is enabled by default.
|
||||
*/
|
||||
public function test_embed_media() {
|
||||
global $CFG;
|
||||
$url = new moodle_url('http://example.org/some_filename.swf');
|
||||
$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, ['trusted' => true]);
|
||||
|
||||
$this->assertRegExp('~mediaplugin_swf~', $content);
|
||||
$this->assertRegExp('~</object>~', $content);
|
||||
$this->assertRegExp('~width="' . $CFG->media_default_width . '" height="' .
|
||||
$CFG->media_default_height . '"~', $content);
|
||||
// Video tag, unsupported text and tracks are removed.
|
||||
$this->assertNotRegExp('~</video>~', $content);
|
||||
$this->assertNotRegExp('~<source\b~', $content);
|
||||
$this->assertNotRegExp('~Unsupported text~', $content);
|
||||
$this->assertNotRegExp('~<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, ['trusted' => true]);
|
||||
$this->assertRegExp('~mediaplugin_swf~', $content);
|
||||
$this->assertRegExp('~</object>~', $content);
|
||||
$this->assertRegExp('~width="123" height="35"~', $content);
|
||||
}
|
||||
}
|
29
media/player/swf/version.php
Normal file
29
media/player/swf/version.php
Normal 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_swf
|
||||
* @copyright 2016 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2016052300; // The current plugin version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2016051900; // Requires this Moodle version
|
||||
$plugin->component = 'media_swf'; // Full name of the plugin (used for diagnostics).
|
79
media/player/vimeo/classes/plugin.php
Normal file
79
media/player/vimeo/classes/plugin.php
Normal file
|
@ -0,0 +1,79 @@
|
|||
<?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_vimeo'
|
||||
*
|
||||
* @package media_vimeo
|
||||
* @copyright 2016 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Player that embeds Vimeo links.
|
||||
*
|
||||
* @package media_vimeo
|
||||
* @copyright 2016 Marina Glancy
|
||||
* @author 2011 The Open University
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class media_vimeo_plugin extends core_media_player_external {
|
||||
protected function embed_external(moodle_url $url, $name, $width, $height, $options) {
|
||||
$videoid = $this->matches[1];
|
||||
$info = s($name);
|
||||
|
||||
// Note: resizing via url is not supported, user can click the fullscreen
|
||||
// button instead. iframe embedding is not xhtml strict but it is the only
|
||||
// option that seems to work on most devices.
|
||||
self::pick_video_size($width, $height);
|
||||
|
||||
$output = <<<OET
|
||||
<span class="mediaplugin mediaplugin_vimeo">
|
||||
<iframe title="$info" src="https://player.vimeo.com/video/$videoid"
|
||||
width="$width" height="$height" frameborder="0"
|
||||
webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
|
||||
</span>
|
||||
OET;
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns regular expression to match vimeo URLs.
|
||||
* @return string
|
||||
*/
|
||||
protected function get_regex() {
|
||||
// Initial part of link.
|
||||
$start = '~^https?://vimeo\.com/';
|
||||
// Middle bit: either watch?v= or v/.
|
||||
$middle = '([0-9]+)';
|
||||
return $start . $middle . core_media_player_external::END_LINK_REGEX_PART;
|
||||
}
|
||||
|
||||
public function get_embeddable_markers() {
|
||||
return array('vimeo.com/');
|
||||
}
|
||||
|
||||
/**
|
||||
* Default rank
|
||||
* @return int
|
||||
*/
|
||||
public function get_rank() {
|
||||
return 1010;
|
||||
}
|
||||
}
|
26
media/player/vimeo/lang/en/media_vimeo.php
Normal file
26
media/player/vimeo/lang/en/media_vimeo.php
Normal file
|
@ -0,0 +1,26 @@
|
|||
<?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_vimeo'
|
||||
*
|
||||
* @package media_vimeo
|
||||
* @copyright 2016 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
$string['pluginname'] = 'Vimeo';
|
||||
$string['pluginname_help'] = 'Vimeo video sharing site.';
|
BIN
media/player/vimeo/pix/icon.png
Normal file
BIN
media/player/vimeo/pix/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.2 KiB |
134
media/player/vimeo/tests/player_test.php
Normal file
134
media/player/vimeo/tests/player_test.php
Normal file
|
@ -0,0 +1,134 @@
|
|||
<?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/>.
|
||||
|
||||
/**
|
||||
* Test classes for handling embedded media.
|
||||
*
|
||||
* @package media_vimeo
|
||||
* @copyright 2016 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Test script for media embedding.
|
||||
*
|
||||
* @package media_vimeo
|
||||
* @copyright 2016 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class media_vimeo_testcase extends advanced_testcase {
|
||||
|
||||
/**
|
||||
* Pre-test setup. Preserves $CFG.
|
||||
*/
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// Reset $CFG and $SERVER.
|
||||
$this->resetAfterTest();
|
||||
|
||||
// Consistent initial setup: all players disabled.
|
||||
\core\plugininfo\media::set_enabled_plugins('vimeo');
|
||||
|
||||
// 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() {
|
||||
$sortorder = \core\plugininfo\media::get_enabled_plugins();
|
||||
$this->assertEquals(['vimeo' => 'vimeo'], $sortorder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test embedding without media filter (for example for displaying URL resorce).
|
||||
*/
|
||||
public function test_embed_url() {
|
||||
global $CFG;
|
||||
|
||||
$url = new moodle_url('http://vimeo.com/1176321');
|
||||
|
||||
$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->assertRegExp('~mediaplugin_vimeo~', $content);
|
||||
$this->assertRegExp('~</iframe>~', $content);
|
||||
$this->assertRegExp('~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->assertRegExp('~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() {
|
||||
global $CFG;
|
||||
$url = new moodle_url('http://vimeo.com/1176321');
|
||||
$text = html_writer::link($url, 'Watch this one');
|
||||
$content = format_text($text, FORMAT_HTML);
|
||||
|
||||
$this->assertRegExp('~mediaplugin_vimeo~', $content);
|
||||
$this->assertRegExp('~</iframe>~', $content);
|
||||
$this->assertRegExp('~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() {
|
||||
global $CFG;
|
||||
$url = new moodle_url('http://vimeo.com/1176321');
|
||||
$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->assertRegExp('~mediaplugin_vimeo~', $content);
|
||||
$this->assertRegExp('~</iframe>~', $content);
|
||||
$this->assertRegExp('~width="' . $CFG->media_default_width . '" height="' .
|
||||
$CFG->media_default_height . '"~', $content);
|
||||
// Video tag, unsupported text and tracks are removed.
|
||||
$this->assertNotRegExp('~</video>~', $content);
|
||||
$this->assertNotRegExp('~<source\b~', $content);
|
||||
$this->assertNotRegExp('~Unsupported text~', $content);
|
||||
$this->assertNotRegExp('~<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->assertRegExp('~mediaplugin_vimeo~', $content);
|
||||
$this->assertRegExp('~</iframe>~', $content);
|
||||
$this->assertRegExp('~width="123" height="35"~', $content);
|
||||
}
|
||||
}
|
29
media/player/vimeo/version.php
Normal file
29
media/player/vimeo/version.php
Normal 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_vimeo
|
||||
* @copyright 2016 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2016052300; // The current plugin version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2016051900; // Requires this Moodle version
|
||||
$plugin->component = 'media_vimeo'; // Full name of the plugin (used for diagnostics).
|
191
media/player/youtube/classes/plugin.php
Normal file
191
media/player/youtube/classes/plugin.php
Normal file
|
@ -0,0 +1,191 @@
|
|||
<?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) {
|
||||
|
||||
$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);
|
||||
|
||||
if ($this->isplaylist) {
|
||||
|
||||
$site = $this->matches[1];
|
||||
$playlist = $this->matches[3];
|
||||
|
||||
return <<<OET
|
||||
<span class="mediaplugin mediaplugin_youtube">
|
||||
<iframe width="$width" height="$height" src="https://$site/embed/videoseries?list=$playlist" frameborder="0" allowfullscreen="1"></iframe>
|
||||
</span>
|
||||
OET;
|
||||
} 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&";
|
||||
}
|
||||
|
||||
return <<<OET
|
||||
<span class="mediaplugin mediaplugin_youtube">
|
||||
<iframe title="$info" width="$width" height="$height"
|
||||
src="https://www.youtube.com/embed/$videoid?{$params}rel=0&wmode=transparent" frameborder="0" allowfullscreen="1"></iframe>
|
||||
</span>
|
||||
OET;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 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\.)?(' . $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;
|
||||
}
|
||||
}
|
28
media/player/youtube/lang/en/media_youtube.php
Normal file
28
media/player/youtube/lang/en/media_youtube.php
Normal file
|
@ -0,0 +1,28 @@
|
|||
<?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'] = 'YouTube video sharing site, video and playlist links supported.';
|
||||
$string['supportsvideo'] = 'YouTube videos';
|
||||
$string['supportsplaylist'] = 'YouTube playlists';
|
BIN
media/player/youtube/pix/icon.png
Normal file
BIN
media/player/youtube/pix/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 348 B |
190
media/player/youtube/tests/player_test.php
Normal file
190
media/player/youtube/tests/player_test.php
Normal file
|
@ -0,0 +1,190 @@
|
|||
<?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/>.
|
||||
|
||||
/**
|
||||
* Test classes for handling embedded media.
|
||||
*
|
||||
* @package media_youtube
|
||||
* @copyright 2016 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* 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 media_youtube_testcase extends advanced_testcase {
|
||||
|
||||
/**
|
||||
* Pre-test setup. Preserves $CFG.
|
||||
*/
|
||||
public function setUp() {
|
||||
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() {
|
||||
$sortorder = \core\plugininfo\media::get_enabled_plugins();
|
||||
$this->assertEquals(['youtube' => 'youtube'], $sortorder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test supported link types
|
||||
*/
|
||||
public function test_supported() {
|
||||
$manager = core_media_manager::instance();
|
||||
|
||||
// Format: youtube.
|
||||
$url = new moodle_url('http://www.youtube.com/watch?v=vyrwMmsufJc');
|
||||
$t = $manager->embed_url($url);
|
||||
$this->assertContains('</iframe>', $t);
|
||||
$url = new moodle_url('http://www.youtube.com/v/vyrwMmsufJc');
|
||||
$t = $manager->embed_url($url);
|
||||
$this->assertContains('</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->assertContains('</iframe>', $t);
|
||||
$this->assertContains('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->assertContains('</iframe>', $t);
|
||||
$this->assertContains('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->assertContains('</iframe>', $t);
|
||||
$this->assertContains('list=PLxcO_MFWQBDcyn9xpbmx601YSDlDcTcr0', $t);
|
||||
$this->assertContains('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->assertContains('</iframe>', $t);
|
||||
$this->assertNotContains('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->assertContains('</iframe>', $t);
|
||||
$this->assertNotContains('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->assertContains('</iframe>', $t);
|
||||
$url = new moodle_url('http://www.youtube.com/playlist?list=PL6E18E2927047B662');
|
||||
$t = $manager->embed_url($url);
|
||||
$this->assertContains('</iframe>', $t);
|
||||
$url = new moodle_url('http://www.youtube.com/p/PL6E18E2927047B662');
|
||||
$t = $manager->embed_url($url);
|
||||
$this->assertContains('</iframe>', $t);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Test embedding without media filter (for example for displaying URL resorce).
|
||||
*/
|
||||
public function test_embed_url() {
|
||||
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->assertRegExp('~mediaplugin_youtube~', $content);
|
||||
$this->assertRegExp('~</iframe>~', $content);
|
||||
$this->assertRegExp('~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->assertRegExp('~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() {
|
||||
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->assertRegExp('~mediaplugin_youtube~', $content);
|
||||
$this->assertRegExp('~</iframe>~', $content);
|
||||
$this->assertRegExp('~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() {
|
||||
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->assertRegExp('~mediaplugin_youtube~', $content);
|
||||
$this->assertRegExp('~</iframe>~', $content);
|
||||
$this->assertRegExp('~width="' . $CFG->media_default_width . '" height="' .
|
||||
$CFG->media_default_height . '"~', $content);
|
||||
// Video tag, unsupported text and tracks are removed.
|
||||
$this->assertNotRegExp('~</video>~', $content);
|
||||
$this->assertNotRegExp('~<source\b~', $content);
|
||||
$this->assertNotRegExp('~Unsupported text~', $content);
|
||||
$this->assertNotRegExp('~<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->assertRegExp('~mediaplugin_youtube~', $content);
|
||||
$this->assertRegExp('~</iframe>~', $content);
|
||||
$this->assertRegExp('~width="123" height="35"~', $content);
|
||||
}
|
||||
}
|
29
media/player/youtube/version.php
Normal file
29
media/player/youtube/version.php
Normal 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 = 2016052300; // The current plugin version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2016051900; // Requires this Moodle version
|
||||
$plugin->component = 'media_youtube'; // Full name of the plugin (used for diagnostics).
|
Loading…
Add table
Add a link
Reference in a new issue