Merge branch 'MDL-29276' of git://github.com/mouneyrac/moodle
[moodle.git] / filter / mediaplugin / filter.php
bloba94d298dbc66ed1ae8cfc85952bfe0a77e32e4bc
1 <?php
2 // This file is part of Moodle - http://moodle.org/
3 //
4 // Moodle is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // Moodle is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
17 /**
18 * Media plugin filtering
20 * This filter will replace any links to a media file with
21 * a media plugin that plays that media inline
23 * @package filter
24 * @subpackage mediaplugin
25 * @copyright 2004 onwards Martin Dougiamas {@link http://moodle.com}
26 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
29 defined('MOODLE_INTERNAL') || die();
31 require_once($CFG->libdir.'/filelib.php');
33 if (!defined('FILTER_MEDIAPLUGIN_VIDEO_WIDTH')) {
34 /**
35 * Default media width, some plugins may use automatic sizes or accept resize parameters.
36 * This can be defined in config.php.
38 define('FILTER_MEDIAPLUGIN_VIDEO_WIDTH', 400);
41 if (!defined('FILTER_MEDIAPLUGIN_VIDEO_HEIGHT')) {
42 /**
43 * Default video height, plugins that know aspect ration
44 * should calculate it themselves using the FILTER_MEDIAPLUGIN_VIDEO_HEIGHT
45 * This can be defined in config.php.
47 define('FILTER_MEDIAPLUGIN_VIDEO_HEIGHT', 300);
51 //TODO: we should use /u modifier in regex, unfortunately it may not work properly on some misconfigured servers, see lib/filter/urltolink/filter.php ...
53 //TODO: we should migrate to proper config_plugin settings ...
56 /**
57 * Automatic media embedding filter class.
59 * It is highly recommended to configure servers to be compatible with our slasharguments,
60 * otherwise the "?d=600x400" may not work.
62 * @package filter
63 * @subpackage mediaplugin
64 * @copyright 2004 onwards Martin Dougiamas {@link http://moodle.com}
65 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
67 class filter_mediaplugin extends moodle_text_filter {
69 function filter($text, array $options = array()) {
70 global $CFG;
72 if (!is_string($text) or empty($text)) {
73 // non string data can not be filtered anyway
74 return $text;
76 if (stripos($text, '</a>') === false) {
77 // performance shortcut - all regexes bellow end with the </a> tag,
78 // if not present nothing can match
79 return $text;
82 $newtext = $text; // we need to return the original value if regex fails!
84 // YouTube and Vimeo are great because the files are not served by Moodle server
86 if (!empty($CFG->filter_mediaplugin_enable_youtube)) {
87 $search = '/<a\s[^>]*href="(https?:\/\/www\.youtube(-nocookie)?\.com)\/watch\?v=([a-z0-9\-_]+)[^"#]*(#d=([\d]{1,4})x([\d]{1,4}))?"[^>]*>([^>]*)<\/a>/is';
88 $newtext = preg_replace_callback($search, 'filter_mediaplugin_youtube_callback', $newtext);
90 $search = '/<a\s[^>]*href="(https?:\/\/www\.youtube(-nocookie)?\.com)\/v\/([a-z0-9\-_]+)[^"#]*(#d=([\d]{1,4})x([\d]{1,4}))?[^>]*>([^>]*)<\/a>/is';
91 $newtext = preg_replace_callback($search, 'filter_mediaplugin_youtube_callback', $newtext);
93 $search = '/<a\s[^>]*href="(https?:\/\/www\.youtube(-nocookie)?\.com)\/view_play_list\?p=([a-z0-9\-_]+)[^"#]*(#d=([\d]{1,4})x([\d]{1,4}))?[^>]*>([^>]*)<\/a>/is';
94 $newtext = preg_replace_callback($search, 'filter_mediaplugin_youtube_playlist_callback', $newtext);
96 $search = '/<a\s[^>]*href="(https?:\/\/www\.youtube(-nocookie)?\.com)\/p\/([a-z0-9\-_]+)[^"#]*(#d=([\d]{1,4})x([\d]{1,4}))?[^>]*>([^>]*)<\/a>/is';
97 $newtext = preg_replace_callback($search, 'filter_mediaplugin_youtube_playlist_callback', $newtext);
100 if (!empty($CFG->filter_mediaplugin_enable_vimeo)) {
101 $search = '/<a\s[^>]*href="http:\/\/vimeo\.com\/([0-9]+)[^"#]*(#d=([\d]{1,4})x([\d]{1,4}))?[^>]*>([^>]*)<\/a>/is';
102 $newtext = preg_replace_callback($search, 'filter_mediaplugin_vimeo_callback', $newtext);
106 // HTML 5 audio and video tags are the future! If only if vendors decided to use just one audio and video format...
108 if (!empty($CFG->filter_mediaplugin_enable_html5audio)) {
109 $search = '/<a\s[^>]*href="([^"#\?]+\.(ogg|oga|aac|m4a)([#\?][^"]*)?)"[^>]*>([^>]*)<\/a>/is';
110 $newtext = preg_replace_callback($search, 'filter_mediaplugin_html5audio_callback', $newtext);
113 if (!empty($CFG->filter_mediaplugin_enable_html5video)) {
114 $search = '/<a\s[^>]*href="([^"#\?]+\.(m4v|webm|ogv|mp4)([#\?][^"]*)?)"[^>]*>([^>]*)<\/a>/is';
115 $newtext = preg_replace_callback($search, 'filter_mediaplugin_html5video_callback', $newtext);
119 // Flash stuff
121 if (!empty($CFG->filter_mediaplugin_enable_mp3)) {
122 $search = '/<a\s[^>]*href="([^"#\?]+\.mp3)"[^>]*>([^>]*)<\/a>/is';
123 $newtext = preg_replace_callback($search, 'filter_mediaplugin_mp3_callback', $newtext);
126 if ((!empty($options['noclean']) or !empty($CFG->allowobjectembed)) and !empty($CFG->filter_mediaplugin_enable_swf)) {
127 $search = '/<a\s[^>]*href="([^"#\?]+\.swf)([#\?]d=([\d]{1,4})x([\d]{1,4}))?"[^>]*>([^>]*)<\/a>/is';
128 $newtext = preg_replace_callback($search, 'filter_mediaplugin_swf_callback', $newtext);
131 if (!empty($CFG->filter_mediaplugin_enable_flv)) {
132 $search = '/<a\s[^>]*href="([^"#\?]+\.(flv|f4v)([#\?][^"]*)?)"[^>]*>([^>]*)<\/a>/is';
133 $newtext = preg_replace_callback($search, 'filter_mediaplugin_flv_callback', $newtext);
137 // The rest of legacy formats - these should not be used if possible
139 if (!empty($CFG->filter_mediaplugin_enable_wmp)) {
140 $search = '/<a\s[^>]*href="([^"#\?]+\.(wmv|avi))(\?d=([\d]{1,4})x([\d]{1,4}))?"[^>]*>([^>]*)<\/a>/is';
141 $newtext = preg_replace_callback($search, 'filter_mediaplugin_wmp_callback', $newtext);
144 if (!empty($CFG->filter_mediaplugin_enable_qt)) {
145 // HTML5 filtering may steal mpeg 4 formats
146 $search = '/<a\s[^>]*href="([^"#\?]+\.(mpg|mpeg|mov|mp4|m4v|m4a))(\?d=([\d]{1,4})x([\d]{1,4}))?"[^>]*>([^>]*)<\/a>/is';
147 $newtext = preg_replace_callback($search, 'filter_mediaplugin_qt_callback', $newtext);
150 if (!empty($CFG->filter_mediaplugin_enable_rm)) {
151 // hopefully nobody is using this any more!!
152 // rpm is redhat packaging format these days, it is better to prevent these in default installs
154 $search = '/<a\s[^>]*href="([^"#\?]+\.(ra|ram|rm|rv))"[^>]*>([^>]*)<\/a>/is';
155 $newtext = preg_replace_callback($search, 'filter_mediaplugin_real_callback', $newtext);
159 if (empty($newtext) or $newtext === $text) {
160 // error or not filtered
161 unset($newtext);
162 return $text;
166 return $newtext;
171 ///===========================
172 /// utility functions
176 * Parse list of alternative URLs
177 * @param string $url urls separated with '#', size specified as ?d=640x480 or #d=640x480
178 * @return array (urls, width, height)
180 function filter_mediaplugin_parse_alternatives($url, $defaultwidth = 0, $defaultheight = 0) {
181 $urls = explode('#', $url);
182 $width = $defaultwidth;
183 $height = $defaultheight;
184 $returnurls = array();
186 foreach ($urls as $url) {
187 $matches = null;
189 if (preg_match('/^d=([\d]{1,4})x([\d]{1,4})$/i', $url, $matches)) { // #d=640x480
190 $width = $matches[1];
191 $height = $matches[2];
192 continue;
194 if (preg_match('/\?d=([\d]{1,4})x([\d]{1,4})$/i', $url, $matches)) { // old style file.ext?d=640x480
195 $width = $matches[1];
196 $height = $matches[2];
197 $url = str_replace($matches[0], '', $url);
200 $url = str_replace('&amp;', '&', $url);
201 $url = clean_param($url, PARAM_URL);
202 if (empty($url)) {
203 continue;
206 $returnurls[] = $url;
209 return array($returnurls, $width, $height);
213 * Should the current tag be ignored in this filter?
214 * @param string $tag
215 * @return bool
217 function filter_mediaplugin_ignore($tag) {
218 if (preg_match('/class="[^"]*nomediaplugin/i', $tag)) {
219 return true;
220 } else {
221 false;
225 ///===========================
226 /// callback filter functions
230 * Replace audio links with audio tag.
232 * @param array $link
233 * @return string
235 function filter_mediaplugin_html5audio_callback(array $link) {
236 global $CFG;
238 if (filter_mediaplugin_ignore($link[0])) {
239 return $link[0];
242 $info = trim($link[4]);
243 if (empty($info) or strpos($info, 'http') === 0) {
244 $info = get_string('fallbackaudio', 'filter_mediaplugin');
247 list($urls, $ignorewidth, $ignoredheight) = filter_mediaplugin_parse_alternatives($link[1]);
249 $fallbackurl = null;
250 $fallbackmime = null;
251 $sources = array();
252 $fallbacklink = null;
254 foreach ($urls as $url) {
255 $mimetype = mimeinfo('type', $url);
256 if (strpos($mimetype, 'audio/') !== 0) {
257 continue;
259 $sources[] = html_writer::tag('source', '', array('src' => $url, 'type' => $mimetype));
261 if ($fallbacklink === null) {
262 $fallbacklink = html_writer::link($url.'#', $info); // the extra '#' prevents linking in mp3 filter bellow
264 if ($fallbackurl === null) {
265 if ($mimetype === 'audio/mp3' or $mimetype === 'audio/aac') {
266 $fallbackurl = str_replace('&', '&amp;', $url);
267 $fallbackmime = $mimetype;
271 if (!$sources) {
272 return $link[0];
275 if ($fallbackmime !== null) {
276 // fallback to quicktime
277 $fallback = <<<OET
278 <object classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B" codebase="http://www.apple.com/qtactivex/qtplugin.cab" width="200" height="20">
279 <param name="pluginspage" value="http://www.apple.com/quicktime/download/" />
280 <param name="src" value="$fallbackurl" />
281 <param name="controller" value="true" />
282 <param name="loop" value="false" />
283 <param name="autoplay" value="false" />
284 <param name="autostart" value="false" />
285 <param name="scale" value="aspect" />
286 $fallbacklink
287 <!--[if !IE]>-->
288 <object data="$fallbackurl" type="$fallbackmime" width="200" height="20">
289 <param name="src" value="$fallbackurl" />
290 <param name="pluginurl" value="http://www.apple.com/quicktime/download/" />
291 <param name="controller" value="true" />
292 <param name="loop" value="false" />
293 <param name="autoplay" value="false" />
294 <param name="autostart" value="false" />
295 <param name="scale" value="aspect" />
296 $fallbacklink
297 </object>
298 <!--<![endif]-->
299 </object>
300 OET;
301 } else {
302 $fallback = $fallbacklink;
305 $sources = implode("\n", $sources);
306 $title = s($info);
308 // audio players are supposed to be inline elements
309 $output = <<<OET
310 <audio controls="true" width="200" class="mediaplugin mediaplugin_html5audio" preload="no" title="$title">
311 $sources
312 $fallback
313 </audio>
314 OET;
316 return $output;
320 * Replace ogg video links with video tag.
322 * Please note this is not going to work in all browsers,
323 * it is also not xhtml strict.
325 * @param array $link
326 * @return string
328 function filter_mediaplugin_html5video_callback(array $link) {
330 if (filter_mediaplugin_ignore($link[0])) {
331 return $link[0];
334 $info = trim($link[4]);
335 if (empty($info) or strpos($info, 'http') === 0) {
336 $info = get_string('fallbackvideo', 'filter_mediaplugin');
339 list($urls, $width, $height) = filter_mediaplugin_parse_alternatives($link[1], FILTER_MEDIAPLUGIN_VIDEO_WIDTH, 0);
341 $fallbackurl = null;
342 $fallbackmime = null;
343 $sources = array();
344 $fallbacklink = null;
346 foreach ($urls as $url) {
347 $mimetype = mimeinfo('type', $url);
348 if (strpos($mimetype, 'video/') !== 0) {
349 continue;
351 $source = html_writer::tag('source', '', array('src' => $url, 'type' => $mimetype));
352 if ($mimetype === 'video/mp4') {
353 // better add m4v as first source, it might be a bit more compatible with problematic browsers
354 array_unshift($sources, $source);
355 } else {
356 $sources[] = $source;
359 if ($fallbacklink === null) {
360 $fallbacklink = html_writer::link($url.'#', $info); // the extra '#' prevents linking in mp3 filter bellow
362 if ($fallbackurl === null) {
363 if ($mimetype === 'video/mp4') {
364 $fallbackurl = str_replace('&', '&amp;', $url);
365 $fallbackmime = $mimetype;
369 if (!$sources) {
370 return $link[0];
373 if ($fallbackmime !== null) {
374 $qtheight = ($height == 0) ? FILTER_MEDIAPLUGIN_VIDEO_HEIGHT : ($height + 15);
375 // fallback to quicktime
376 $fallback = <<<OET
377 <object classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B" codebase="http://www.apple.com/qtactivex/qtplugin.cab" width="$width" height="$qtheight">
378 <param name="pluginspage" value="http://www.apple.com/quicktime/download/" />
379 <param name="src" value="$fallbackurl" />
380 <param name="controller" value="true" />
381 <param name="loop" value="false" />
382 <param name="autoplay" value="false" />
383 <param name="autostart" value="false" />
384 <param name="scale" value="aspect" />
385 $fallbacklink
386 <!--[if !IE]>-->
387 <object data="$fallbackurl" type="$fallbackmime" width="$width" height="$qtheight">
388 <param name="src" value="$fallbackurl" />
389 <param name="pluginurl" value="http://www.apple.com/quicktime/download/" />
390 <param name="controller" value="true" />
391 <param name="loop" value="false" />
392 <param name="autoplay" value="false" />
393 <param name="autostart" value="false" />
394 <param name="scale" value="aspect" />
395 $fallbacklink
396 </object>
397 <!--<![endif]-->
398 </object>
399 OET;
400 } else {
401 $fallback = $fallbacklink;
404 $sources = implode("\n", $sources);
405 $title = s($info);
407 if (empty($height)) {
408 // automatic height
409 $size = "width=\"$width\"";
410 } else {
411 $size = "width=\"$width\" height=\"$height\"";
414 $output = <<<OET
415 <span class="mediaplugin mediaplugin_html5video">
416 <video controls="true" $size preload="metadata" title="$title">
417 $sources
418 $fallback
419 </video>
420 </span>
421 OET;
423 return $output;
427 * Replace mp3 links with small audio player.
429 * @param $link
430 * @return string
432 function filter_mediaplugin_mp3_callback($link) {
433 static $count = 0;
435 if (filter_mediaplugin_ignore($link[0])) {
436 return $link[0];
439 $count++;
440 $id = 'filter_mp3_'.time().'_'.$count; //we need something unique because it might be stored in text cache
442 $url = $link[1];
443 $rawurl = str_replace('&amp;', '&', $url);
445 $info = trim($link[2]);
446 if (empty($info) or strpos($info, 'http') === 0) {
447 $info = get_string('mp3audio', 'filter_mediaplugin');
450 $printlink = html_writer::link($rawurl, $info, array('class'=>'mediafallbacklink'));
452 //note: when flash or javascript not available only the $printlink is displayed,
453 // audio players are supposed to be inline elements
455 $output = html_writer::tag('span', $printlink, array('id'=>$id, 'class'=>'mediaplugin mediaplugin_mp3'));
456 $output .= html_writer::script(js_writer::function_call('M.util.add_audio_player', array($id, $rawurl, true))); // we can not use standard JS init because this may be cached
458 return $output;
462 * Replace swf links with embedded flash objects.
464 * Please note this is not a secure and is recommended to be disabled on production systems.
466 * @deprecated
467 * @param $link
468 * @return string
470 function filter_mediaplugin_swf_callback($link) {
472 if (filter_mediaplugin_ignore($link[0])) {
473 return $link[0];
476 $width = empty($link[3]) ? FILTER_MEDIAPLUGIN_VIDEO_WIDTH : $link[3];
477 $height = empty($link[4]) ? FILTER_MEDIAPLUGIN_VIDEO_HEIGHT : $link[4];
479 $url = $link[1];
480 $rawurl = str_replace('&amp;', '&', $url);
482 $info = trim($link[5]);
483 if (empty($info) or strpos($info, 'http') === 0) {
484 $info = get_string('flashanimation', 'filter_mediaplugin');
487 $printlink = html_writer::link($rawurl, $info, array('class'=>'mediafallbacklink'));
489 $output = <<<OET
490 <span class="mediaplugin mediaplugin_swf">
491 <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="$width" height="$height">
492 <param name="movie" value="$url" />
493 <param name="autoplay" value="true" />
494 <param name="loop" value="true" />
495 <param name="controller" value="true" />
496 <param name="scale" value="aspect" />
497 <param name="base" value="." />
498 <param name="allowscriptaccess" value="never" />
499 <!--[if !IE]>-->
500 <object type="application/x-shockwave-flash" data="$url" width="$width" height="$height">
501 <param name="controller" value="true" />
502 <param name="autoplay" value="true" />
503 <param name="loop" value="true" />
504 <param name="scale" value="aspect" />
505 <param name="base" value="." />
506 <param name="allowscriptaccess" value="never" />
507 <!--<![endif]-->
508 $printlink
509 <!--[if !IE]>-->
510 </object>
511 <!--<![endif]-->
512 </object>
513 </span>
514 OET;
516 return $output;
521 * Replace flv links with flow player.
523 * @param $link
524 * @return string
526 function filter_mediaplugin_flv_callback($link) {
527 static $count = 0;
529 if (filter_mediaplugin_ignore($link[0])) {
530 return $link[0];
533 $count++;
534 $id = 'filter_flv_'.time().'_'.$count; //we need something unique because it might be stored in text cache
536 list($urls, $width, $height) = filter_mediaplugin_parse_alternatives($link[1], 0, 0);
538 $autosize = false;
539 if (!$width and !$height) {
540 $width = FILTER_MEDIAPLUGIN_VIDEO_WIDTH;
541 $height = FILTER_MEDIAPLUGIN_VIDEO_HEIGHT;
542 $autosize = true;
545 $flashurl = null;
546 $sources = array();
548 foreach ($urls as $url) {
549 $mimetype = mimeinfo('type', $url);
550 if (strpos($mimetype, 'video/') !== 0) {
551 continue;
553 $source = html_writer::tag('source', '', array('src' => $url, 'type' => $mimetype));
554 if ($mimetype === 'video/mp4') {
555 // better add m4v as first source, it might be a bit more compatible with problematic browsers
556 array_unshift($sources, $source);
557 } else {
558 $sources[] = $source;
561 if ($flashurl === null) {
562 $flashurl = str_replace('&', '&amp;', $url);
565 if (!$sources) {
566 return $link[0];
569 $info = trim($link[4]);
570 if (empty($info) or strpos($info, 'http') === 0) {
571 $info = get_string('fallbackvideo', 'filter_mediaplugin');
573 $printlink = html_writer::link($flashurl.'#', $info, array('class'=>'mediafallbacklink')); // the '#' prevents the QT filter
575 $title = s($info);
577 if (count($sources) > 1) {
578 $sources = implode("\n", $sources);
580 // html 5 fallback
581 $printlink = <<<OET
582 <video controls="true" width="$width" height="$height" preload="metadata" title="$title">
583 $sources
584 $printlink
585 </video>
586 <noscript><br />
587 $printlink
588 </noscript>
589 OET;
592 // note: no need to print "this is flv link" because it is printed automatically if JS or Flash not available
594 $output = html_writer::tag('span', $printlink, array('id'=>$id, 'class'=>'mediaplugin mediaplugin_flv'));
595 $output .= html_writer::script(js_writer::function_call('M.util.add_video_player', array($id, $flashurl, $width, $height, $autosize))); // we can not use standard JS init because this may be cached
597 return $output;
601 * Replace real media links with real player.
603 * Note: hopefully nobody is using this obsolete format any more.
605 * @deprectated
606 * @param $link
607 * @return string
609 function filter_mediaplugin_real_callback($link) {
611 if (filter_mediaplugin_ignore($link[0])) {
612 return $link[0];
615 $url = $link[1];
616 $rawurl = str_replace('&amp;', '&', $url);
618 //Note: the size is hardcoded intentionally because this does not work anyway!
620 $width = FILTER_MEDIAPLUGIN_VIDEO_WIDTH;
621 $height = FILTER_MEDIAPLUGIN_VIDEO_HEIGHT;
623 $info = trim($link[3]);
624 if (empty($info) or strpos($info, 'http') === 0) {
625 $info = get_string('fallbackvideo', 'filter_mediaplugin');
627 $printlink = html_writer::link($rawurl, $info, array('class'=>'mediafallbacklink'));
629 return <<<OET
630 <span class="mediaplugin mediaplugin_real">
631 $printlink <br />
632 <object title="$info" classid="clsid:CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA" data="$url" width="$width" height="$height"">
633 <param name="src" value="$url" />
634 <param name="controls" value="All" />
635 <!--[if !IE]>-->
636 <object title="$info" type="audio/x-pn-realaudio-plugin" data="$url" width="$width" height="$height">
637 <param name="src" value="$url" />
638 <param name="controls" value="All" />
639 <!--<![endif]-->
640 <!--[if !IE]>-->
641 </object>
642 <!--<![endif]-->
643 </object>
644 </span>
645 OET;
649 * Change links to YouTube into embedded YouTube videos
651 * Note: resizing via url is not supported, user can click the fullscreen button instead
653 * @param $link
654 * @return string
656 function filter_mediaplugin_youtube_callback($link) {
657 global $CFG;
659 if (filter_mediaplugin_ignore($link[0])) {
660 return $link[0];
663 $site = $link[1];
664 $videoid = $link[3];
666 $info = trim($link[7]);
667 if (empty($info) or strpos($info, 'http') === 0) {
668 $info = get_string('siteyoutube', 'filter_mediaplugin');
670 $info = s($info);
672 $width = empty($link[5]) ? FILTER_MEDIAPLUGIN_VIDEO_WIDTH : $link[5];
673 $height = empty($link[6]) ? FILTER_MEDIAPLUGIN_VIDEO_HEIGHT : $link[6];
675 if (empty($CFG->xmlstrictheaders)) {
676 return <<<OET
677 <iframe title="$info" width="$width" height="$height" src="$site/embed/$videoid?rel=0" frameborder="0" allowfullscreen></iframe>
678 OET;
681 //NOTE: we can not use any link fallback because it breaks built-in player on iOS devices
683 $output = <<<OET
684 <span class="mediaplugin mediaplugin_youtube">
685 <object title="$info" type="application/x-shockwave-flash" data="$site/v/$videoid&amp;fs=1&amp;rel=0" width="$width" height="$height">
686 <param name="movie" value="$site/v/$videoid&amp;fs=1&amp;rel=0" />
687 <param name="FlashVars" value="playerMode=embedded" />
688 <param name="allowFullScreen" value="true" />
689 </object>
690 </span>
691 OET;
693 return $output;
697 * Change YouTube playlist into embedded YouTube playlist videos
699 * Note: resizing via url is not supported, user can click the fullscreen button instead
701 * @param $link
702 * @return string
704 function filter_mediaplugin_youtube_playlist_callback($link) {
705 global $CFG;
707 if (filter_mediaplugin_ignore($link[0])) {
708 return $link[0];
711 $site = $link[1];
712 $playlist = $link[3];
714 $info = trim($link[7]);
715 if (empty($info) or strpos($info, 'http') === 0) {
716 $info = get_string('siteyoutube', 'filter_mediaplugin');
718 $printlink = html_writer::link("$site/view_play_list\?p=$playlist", $info, array('class'=>'mediafallbacklink'));
719 $info = s($info);
721 $width = empty($link[5]) ? FILTER_MEDIAPLUGIN_VIDEO_WIDTH : $link[5];
722 $height = empty($link[6]) ? FILTER_MEDIAPLUGIN_VIDEO_HEIGHT : $link[6];
724 // TODO: iframe HTML 5 video not implemented and object does work on iOS devices
726 $output = <<<OET
727 <span class="mediaplugin mediaplugin_youtube">
728 <object title="$info" type="application/x-shockwave-flash" data="$site/p/$playlist&amp;fs=1&amp;rel=0" width="$width" height="$height">
729 <param name="movie" value="$site/v/$playlist&amp;fs=1&amp;rel=0" />
730 <param name="FlashVars" value="playerMode=embedded" />
731 <param name="allowFullScreen" value="true" />
732 $printlink</object>
733 </span>
734 OET;
736 return $output;
740 * Change links to Vimeo into embedded Vimeo videos
742 * @param $link
743 * @return string
745 function filter_mediaplugin_vimeo_callback($link) {
746 global $CFG;
748 if (filter_mediaplugin_ignore($link[0])) {
749 return $link[0];
752 $videoid = $link[1];
753 $info = s(strip_tags($link[5]));
755 //Note: resizing via url is not supported, user can click the fullscreen button instead
756 // iframe embedding is not xhtml strict but it is the only option that seems to work on most devices
758 $width = empty($link[3]) ? FILTER_MEDIAPLUGIN_VIDEO_WIDTH : $link[3];
759 $height = empty($link[4]) ? FILTER_MEDIAPLUGIN_VIDEO_HEIGHT : $link[4];
761 $output = <<<OET
762 <span class="mediaplugin mediaplugin_vimeo">
763 <iframe title="$info" src="http://player.vimeo.com/video/$videoid" width="$width" height="$height" frameborder="0"></iframe>
764 </span>
765 OET;
767 return $output;
771 * Embed video using window media player if available
773 * This does not work much outside of IE, hopefully not many ppl use it these days.
775 * @param $link
776 * @return string
778 function filter_mediaplugin_wmp_callback($link) {
780 if (filter_mediaplugin_ignore($link[0])) {
781 return $link[0];
784 $url = $link[1];
785 $rawurl = str_replace('&amp;', '&', $url);
787 $info = trim($link[6]);
788 if (empty($info) or strpos($info, 'http') === 0) {
789 $info = get_string('fallbackvideo', 'filter_mediaplugin');
791 $printlink = html_writer::link($rawurl, $info, array('class'=>'mediafallbacklink'));
793 if (empty($link[4]) or empty($link[5])) {
794 $mpsize = '';
795 $size = 'width="'.FILTER_MEDIAPLUGIN_VIDEO_WIDTH.'" height="'.(FILTER_MEDIAPLUGIN_VIDEO_HEIGHT+64).'"';
796 $autosize = 'true';
797 } else {
798 $size = 'width="'.$link[4].'" height="'.($link[5] + 15).'"';
799 $mpsize = 'width="'.$link[4].'" height="'.($link[5] + 64).'"';
800 $autosize = 'false';
802 $mimetype = mimeinfo('type', $url);
806 return <<<OET
807 <span class="mediaplugin mediaplugin_wmp">
808 $printlink <br />
809 <object classid="CLSID:6BF52A52-394A-11d3-B153-00C04F79FAA6" $mpsize standby="Loading Microsoft(R) Windows(R) Media Player components..." type="application/x-oleobject">
810 <param name="Filename" value="$url" />
811 <param name="src" value="$url" />
812 <param name="url" value="$url" />
813 <param name="ShowControls" value="true" />
814 <param name="AutoRewind" value="true" />
815 <param name="AutoStart" value="false" />
816 <param name="Autosize" value="$autosize" />
817 <param name="EnableContextMenu" value="true" />
818 <param name="TransparentAtStart" value="false" />
819 <param name="AnimationAtStart" value="false" />
820 <param name="ShowGotoBar" value="false" />
821 <param name="EnableFullScreenControls" value="true" />
822 <param name="uimode" value="full" />
823 <!--[if !IE]>-->
824 <object data="$url" type="$mimetype" $size>
825 <param name="src" value="$url" />
826 <param name="controller" value="true" />
827 <param name="autoplay" value="false" />
828 <param name="autostart" value="false" />
829 <param name="resize" value="scale" />
830 </object>
831 <!--<![endif]-->
832 </object></span>
833 OET;
837 * Replace quicktime links with quicktime player.
839 * You need to install a quicktime player, it is not available for all browsers+OS combinations.
841 * @param $link
842 * @return string
844 function filter_mediaplugin_qt_callback($link) {
846 if (filter_mediaplugin_ignore($link[0])) {
847 return $link[0];
850 $url = $link[1];
851 $rawurl = str_replace('&amp;', '&', $url);
853 $info = trim($link[6]);
854 if (empty($info) or strpos($info, 'http') === 0) {
855 $info = get_string('fallbackvideo', 'filter_mediaplugin');
857 $printlink = html_writer::link($rawurl, $info, array('class'=>'mediafallbacklink'));
859 if (empty($link[4]) or empty($link[5])) {
860 $size = 'width="'.FILTER_MEDIAPLUGIN_VIDEO_WIDTH.'" height="'.(FILTER_MEDIAPLUGIN_VIDEO_HEIGHT+15).'"';
861 } else {
862 $size = 'width="'.$link[4].'" height="'.($link[5]+15).'"';
864 $mimetype = mimeinfo('type', $url);
866 // this is the safest fallback for incomplete or missing browser support for this format
867 return <<<OET
868 <span class="mediaplugin mediaplugin_qt">
869 $printlink <br />
870 <object classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B" codebase="http://www.apple.com/qtactivex/qtplugin.cab" $size>
871 <param name="pluginspage" value="http://www.apple.com/quicktime/download/" />
872 <param name="src" value="$url" />
873 <param name="controller" value="true" />
874 <param name="loop" value="true" />
875 <param name="autoplay" value="false" />
876 <param name="autostart" value="false" />
877 <param name="scale" value="aspect" />
878 <!--[if !IE]>-->
879 <object data="$url" type="$mimetype" $size>
880 <param name="src" value="$url" />
881 <param name="pluginurl" value="http://www.apple.com/quicktime/download/" />
882 <param name="controller" value="true" />
883 <param name="loop" value="true" />
884 <param name="autoplay" value="false" />
885 <param name="autostart" value="false" />
886 <param name="scale" value="aspect" />
887 </object>
888 <!--<![endif]-->
889 </object></span>
890 OET;