course MDL-24250 fixed notice about undefined constant.
[moodle.git] / filter / mediaplugin / filter.php
CommitLineData
4317f92f 1<?php
35716b86
PS
2
3// This file is part of Moodle - http://moodle.org/
6de17fde 4//
35716b86
PS
5// Moodle is free software: you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
6de17fde 9//
35716b86
PS
10// Moodle is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
6de17fde 14//
35716b86
PS
15// You should have received a copy of the GNU General Public License
16// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
17
18/**
19 * Media plugin filtering
20 *
21 * This filter will replace any links to a media file with
22 * a media plugin that plays that media inline
23 *
24 * @package filter
25 * @subpackage mediaplugin
26 * @copyright 2004 onwards Martin Dougiamas {@link http://moodle.com}
27 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
28 */
6de17fde 29
35716b86 30defined('MOODLE_INTERNAL') || die();
6de17fde 31
7e64d361 32require_once($CFG->libdir.'/filelib.php');
33
35716b86 34class filter_mediaplugin extends moodle_text_filter {
ccc161f8 35 private $eolas_fix_applied = false;
9e3f34d1 36 function filter($text) {
82afb587 37 global $CFG, $PAGE;
9e3f34d1 38 // You should never modify parameters passed to a method or function, it's BAD practice. Create a copy instead.
39 // The reason is that you must always be able to refer to the original parameter that was passed.
40 // For this reason, I changed $text = preg_replace(..,..,$text) into $newtext = preg.... (NICOLAS CONNAULT)
41 // Thanks to Pablo Etcheverry for pointing this out! MDL-10177
42
43 // We're using the UFO technique for flash to attain XHTML Strict 1.0
44 // See: http://www.bobbyvandersluis.com/ufo/
45 if (!is_string($text)) {
46 // non string data can not be filtered anyway
47 return $text;
48 }
49 $newtext = $text; // fullclone is slow and not needed here
50
51 if ($CFG->filter_mediaplugin_enable_mp3) {
3a42ad12 52 $search = '/<a[^>]*?href="([^<]+\.mp3)"[^>]*>.*?<\/a>/is';
35716b86 53 $newtext = preg_replace_callback($search, 'filter_mediaplugin_mp3_callback', $newtext);
9e3f34d1 54 }
55
56 if ($CFG->filter_mediaplugin_enable_swf) {
3a42ad12 57 $search = '/<a[^>]*?href="([^<]+\.swf)(\?d=([\d]{1,3}%?)x([\d]{1,3}%?))?"[^>]*>.*?<\/a>/is';
35716b86 58 $newtext = preg_replace_callback($search, 'filter_mediaplugin_swf_callback', $newtext);
9e3f34d1 59 }
60
61 if ($CFG->filter_mediaplugin_enable_flv) {
3a42ad12 62 $search = '/<a[^>]*?href="([^<]+\.flv)(\?d=([\d]{1,3}%?)x([\d]{1,3}%?))?"[^>]*>.*?<\/a>/is';
35716b86 63 $newtext = preg_replace_callback($search, 'filter_mediaplugin_flv_callback', $newtext);
9e3f34d1 64 }
65
66 if ($CFG->filter_mediaplugin_enable_mov) {
3a42ad12 67 $search = '/<a[^>]*?href="([^<]+\.mov)(\?d=([\d]{1,3}%?)x([\d]{1,3}%?))?"[^>]*>.*?<\/a>/is';
35716b86 68 $newtext = preg_replace_callback($search, 'filter_mediaplugin_qt_callback', $newtext);
46936592 69
3a42ad12 70 $search = '/<a[^>]*?href="([^<]+\.mp4)(\?d=([\d]{1,4}%?)x([\d]{1,4}%?))?"[^>]*>.*?<\/a>/is';
35716b86 71 $newtext = preg_replace_callback($search, 'filter_mediaplugin_qt_callback', $newtext);
46936592 72
3a42ad12 73 $search = '/<a[^>]*?href="([^<]+\.m4v)(\?d=([\d]{1,4}%?)x([\d]{1,4}%?))?"[^>]*>.*?<\/a>/is';
35716b86 74 $newtext = preg_replace_callback($search, 'filter_mediaplugin_qt_callback', $newtext);
a184479a 75
3a42ad12 76 $search = '/<a[^>]*?href="([^<]+\.m4a)(\?d=([\d]{1,4}%?)x([\d]{1,4}%?))?"[^>]*>.*?<\/a>/is';
35716b86 77 $newtext = preg_replace_callback($search, 'filter_mediaplugin_qt_callback', $newtext);
9e3f34d1 78 }
79
80 if ($CFG->filter_mediaplugin_enable_wmv) {
3a42ad12 81 $search = '/<a[^>]*?href="([^<]+\.wmv)(\?d=([\d]{1,3}%?)x([\d]{1,3}%?))?"[^>]*>.*?<\/a>/is';
35716b86 82 $newtext = preg_replace_callback($search, 'filter_mediaplugin_wmp_callback', $newtext);
9e3f34d1 83 }
84
85 if ($CFG->filter_mediaplugin_enable_mpg) {
3a42ad12 86 $search = '/<a[^>]*?href="([^<]+\.mpe?g)(\?d=([\d]{1,3}%?)x([\d]{1,3}%?))?"[^>]*>.*?<\/a>/is';
35716b86 87 $newtext = preg_replace_callback($search, 'filter_mediaplugin_qt_callback', $newtext);
9e3f34d1 88 }
89
90 if ($CFG->filter_mediaplugin_enable_avi) {
3a42ad12 91 $search = '/<a[^>]*?href="([^<]+\.avi)(\?d=([\d]{1,3}%?)x([\d]{1,3}%?))?"[^>]*>.*?<\/a>/is';
35716b86 92 $newtext = preg_replace_callback($search, 'filter_mediaplugin_wmp_callback', $newtext);
9e3f34d1 93 }
94
95 if ($CFG->filter_mediaplugin_enable_ram) {
3a42ad12 96 $search = '/<a[^>]*?href="([^<]+\.ram)"[^>]*>.*?<\/a>/is';
35716b86 97 $newtext = preg_replace_callback($search, 'filter_mediaplugin_real_callback', $newtext);
9e3f34d1 98 }
99
100 if ($CFG->filter_mediaplugin_enable_rpm) {
3a42ad12 101 $search = '/<a[^>]*?href="([^<]+\.rpm)"[^>]*>.*?<\/a>/is';
35716b86 102 $newtext = preg_replace_callback($search, 'filter_mediaplugin_real_callback', $newtext);
9e3f34d1 103 }
104
105 if ($CFG->filter_mediaplugin_enable_rm) {
3a42ad12 106 $search = '/<a[^>]*?href="([^<]+\.rm)"[^>]*>.*?<\/a>/is';
35716b86 107 $newtext = preg_replace_callback($search, 'filter_mediaplugin_real_callback', $newtext);
9e3f34d1 108 }
109
110 if (!empty($CFG->filter_mediaplugin_enable_youtube)) {
4842422f
AD
111 //see MDL-23903 for description of recent changes to this regex
112 //$search = '/<a.*?href="([^<]*)youtube.com\/watch\?v=([^"]*)"[^>]*>(.*?)<\/a>/is';
113 $search = '/<a[^>]*href="([^<]*?)youtube.com\/watch\?v=([^"]*)"[^>]*>(.*?)<\/a>/is';
35716b86 114 $newtext = preg_replace_callback($search, 'filter_mediaplugin_youtube_callback', $newtext);
9e3f34d1 115
116 $search = '/<a.*?href="([^<]*)youtube.com\/v\/([^"]*)"[^>]*>(.*?)<\/a>/is';
35716b86 117 $newtext = preg_replace_callback($search, 'filter_mediaplugin_youtube_callback', $newtext);
9e3f34d1 118 }
119
224eccbf 120 if (!empty($CFG->filter_mediaplugin_enable_img)) {
3a42ad12 121 $search = '/<a[^>]*?href="([^<]+\.jpg)"[^>]*>(.*?)<\/a>/is';
35716b86 122 $newtext = preg_replace_callback($search, 'filter_mediaplugin_img_callback', $newtext);
3a42ad12 123 $search = '/<a[^>]*?href="([^<]+\.png)"[^>]*>(.*?)<\/a>/is';
35716b86 124 $newtext = preg_replace_callback($search, 'filter_mediaplugin_img_callback', $newtext);
3a42ad12 125 $search = '/<a[^>]*?href="([^<]+\.gif)"[^>]*>(.*?)<\/a>/is';
35716b86 126 $newtext = preg_replace_callback($search, 'filter_mediaplugin_img_callback', $newtext);
c159f28b 127 }
128
9e3f34d1 129 if (empty($newtext) or $newtext === $text) {
130 // error or not filtered
131 unset($newtext);
132 return $text;
133 }
134
135 if (!$this->eolas_fix_applied) {
9dec75db 136 $PAGE->requires->js('/filter/mediaplugin/eolas_fix.js');
9e3f34d1 137 $this->eolas_fix_applied = true;
138 }
139
140 return $newtext;
d07851e1 141 }
6de17fde 142}
143
7e64d361 144///===========================
145/// callback filter functions
146
35716b86 147function filter_mediaplugin_mp3_callback($link) {
088ccb43
PS
148 global $CFG, $OUTPUT, $PAGE;
149
150 $c = $OUTPUT->filter_mediaplugin_colors(); // You can set this up in your theme/xxx/config.php
7e64d361 151
152 static $count = 0;
153 $count++;
154 $id = 'filter_mp3_'.time().$count; //we need something unique because it might be stored in text cache
155
156 $url = addslashes_js($link[1]);
157
3a42ad12
RW
158 $playerpath = $CFG->wwwroot.'/filter/mediaplugin/mp3player.swf';
159 $audioplayerpath = $CFG->wwwroot .'/filter/mediaplugin/flowplayer.audio.swf';
160 $colors = explode('&', $c);
161 $playercolors = array();
162 foreach ($colors as $color) {
163 $color = explode('=', $color);
164 $playercolors[$color[0]] = $color[1];
165 }
82afb587 166
3a42ad12
RW
167 $output = <<<OET
168 <span class="mediaplugin mediaplugin_mp3" id="$id"></span>
169 <noscript>
170 <object width="100" height="15" id="nonjsmp3plugin" name="undefined" data="$playerpath" type="application/x-shockwave-flash">
171 <param name="movie" value="$playerpath" />
172 <param name="allowfullscreen" value="false" />
173 <param name="allowscriptaccess" value="always" />
174 <param name="flashvars" value='config={"plugins": {"controls": {
175 "fullscreen": false,
176 "height": 15,
177 "autoHide": false,
178 "all": false,
179 "play": true,
180 "pause": true,
181 "scrubber": true
182 },
183 "audio": {"url": "$audioplayerpath"}
184 },
185 "clip":{"url":"$url",
186 "autoPlay": false},
187 "content":{"url":"$playerpath"}}}' />
188 </object>
189 </noscript>
190OET;
191
192 $jsoutput = create_flowplayer($id, $url, 'mp3', $playercolors);
193 $output .= $jsoutput;
82afb587 194
195 return $output;
7e64d361 196}
197
35716b86 198function filter_mediaplugin_swf_callback($link) {
82afb587 199 global $PAGE;
7e64d361 200 static $count = 0;
201 $count++;
202 $id = 'filter_swf_'.time().$count; //we need something unique because it might be stored in text cache
203
204 $width = empty($link[3]) ? '400' : $link[3];
205 $height = empty($link[4]) ? '300' : $link[4];
206 $url = addslashes_js($link[1]);
207
82afb587 208 $args = Array();
209 $args['movie'] = $url;
210 $args['width'] = $width;
211 $args['height'] = $height;
212 $args['majorversion'] = 6;
213 $args['build'] = 40;
214 $args['allowscriptaccess'] = 'never';
215 $args['quality'] = 'high';
82afb587 216
10eaeca8 217 $jsoutput = create_ufo_inline($id, $args);
35716b86 218
a845d68b 219 $output = $link[0].'<span class="mediaplugin mediaplugin_swf" id="'.$id.'">('.get_string('flashanimation', 'filter_mediaplugin').')</span>'.$jsoutput;
82afb587 220
221 return $output;
7e64d361 222}
223
35716b86 224function filter_mediaplugin_flv_callback($link) {
82afb587 225 global $CFG, $PAGE;
7e64d361 226
227 static $count = 0;
228 $count++;
229 $id = 'filter_flv_'.time().$count; //we need something unique because it might be stored in text cache
230
231 $width = empty($link[3]) ? '480' : $link[3];
232 $height = empty($link[4]) ? '360' : $link[4];
233 $url = addslashes_js($link[1]);
234
3a42ad12
RW
235 $playerpath = $CFG->wwwroot.'/filter/mediaplugin/flvplayer.swf';
236
237 $output = <<<EOT
238 <span class="mediaplugin mediaplugin_flv" id="$id"></span>
239 <noscript>
240 <object width="800" height="600" id="undefined" name="undefined" data="$playerpath" type="application/x-shockwave-flash">
241 <param name="movie" value="$playerpath" />
242 <param name="allowfullscreen" value="true" />
243 <param name="allowscriptaccess" value="always" />
244 <param name="flashvars" value='config={"clip":{"url":"$url",
245 "autoPlay": false},
246 "content":{"url":"$playerpath"}}}' />
247 </object>
248 </noscript>
249EOT;
250
251 $jsoutput = create_flowplayer($id, $url, 'flv');
252 $output .= $jsoutput;
82afb587 253 return $output;
7e64d361 254}
255
35716b86 256function filter_mediaplugin_real_callback($link, $autostart=false) {
7e64d361 257 $url = addslashes_js($link[1]);
258 $mimetype = mimeinfo('type', $url);
259 $autostart = $autostart ? 'true' : 'false';
260
261// embed kept for now see MDL-8674
262 return $link[0].
263'<span class="mediaplugin mediaplugin_real">
264<script type="text/javascript">
265//<![CDATA[
266document.write(\'<object classid="clsid:CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA" width="240" height="180">\\
267 <param name="src" value="'.$url.'" />\\
268 <param name="autostart" value="'.$autostart.'" />\\
269 <param name="controls" value="imagewindow" />\\
270 <param name="console" value="video" />\\
271 <param name="loop" value="true" />\\
7c59f3be 272 <embed src="'.$url.'" width="240" height="180" loop="true" type="'.$mimetype.'" controls="imagewindow" console="video" autostart="'.$autostart.'" />\\
7e64d361 273 </object><br />\\
274 <object classid="clsid:CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA" width="240" height="30">\\
275 <param name="src" value="'.$url.'" />\\
276 <param name="autostart" value="'.$autostart.'" />\\
277 <param name="controls" value="ControlPanel" />\\
278 <param name="console" value="video" />\\
279 <embed src="'.$url.'" width="240" height="30" controls="ControlPanel" type="'.$mimetype.'" console="video" autostart="'.$autostart.'" />\\
280 </object>\');
281//]]>
282</script></span>';
283}
284
4d8bccf4 285/**
286 * Change links to Youtube into embedded Youtube videos
287 */
35716b86 288function filter_mediaplugin_youtube_callback($link, $autostart=false) {
4d8bccf4 289
290 $site = addslashes_js($link[1]);
291 $url = addslashes_js($link[2]);
4842422f 292 $info = addslashes_js(strip_tags($link[3]));//strip out html tags as they won't work in the title attribute
4d8bccf4 293
4317f92f
PS
294 return '<object title="'.$info.'"
295 class="mediaplugin mediaplugin_youtube" type="application/x-shockwave-flash"
4d8bccf4 296 data="'.$site.'youtube.com/v/'.$url.'&amp;fs=1&amp;rel=0" width="425" height="344">'.
6188deb8 297 '<param name="movie" value="'.$site.'youtube.com/v/'.$url.'&amp;fs=1&amp;rel=0" />'.
4d8bccf4 298 '<param name="FlashVars" value="playerMode=embedded" />'.
299 '<param name="wmode" value="transparent" />'.
300 '<param name="allowFullScreen" value="true" />'.
e2cf2d7f 301 '</object>';
4d8bccf4 302}
303
c159f28b 304/**
305 * Change links to images into embedded images
306 */
35716b86 307function filter_mediaplugin_img_callback($link, $autostart=false) {
c159f28b 308 $url = addslashes_js($link[1]);
309 $info = addslashes_js($link[2]);
310
311 return '<img class="mediaplugin mediaplugin_img" alt="" title="'.$info.'" src="'.$url.'" />';
312}
313
7e64d361 314/**
315 * Embed video using window media player if available
316 */
35716b86 317function filter_mediaplugin_wmp_callback($link, $autostart=false) {
7e64d361 318 $url = $link[1];
319 if (empty($link[3]) or empty($link[4])) {
320 $mpsize = '';
321 $size = 'width="300" height="260"';
322 $autosize = 'true';
323 } else {
324 $size = 'width="'.$link[3].'" height="'.$link[4].'"';
325 $mpsize = $size;
326 $autosize = 'false';
327 }
328 $mimetype = mimeinfo('type', $url);
329 $autostart = $autostart ? 'true' : 'false';
330
331 return $link[0].
332'<span class="mediaplugin mediaplugin_wmp">
333<object classid="CLSID:6BF52A52-394A-11d3-B153-00C04F79FAA6" '.$mpsize.'
334 standby="Loading Microsoft(R) Windows(R) Media Player components..."
335 type="application/x-oleobject">
336 <param name="Filename" value="'.$url.'" />
337 <param name="src" value="'.$url.'" />
338 <param name="url" value="'.$url.'" />
339 <param name="ShowControls" value="true" />
340 <param name="AutoRewind" value="true" />
341 <param name="AutoStart" value="'.$autostart.'" />
342 <param name="Autosize" value="'.$autosize.'" />
343 <param name="EnableContextMenu" value="true" />
344 <param name="TransparentAtStart" value="false" />
345 <param name="AnimationAtStart" value="false" />
346 <param name="ShowGotoBar" value="false" />
347 <param name="EnableFullScreenControls" value="true" />
348<!--[if !IE]>-->
349 <object data="'.$url.'" type="'.$mimetype.'" '.$size.'>
350 <param name="src" value="'.$url.'" />
351 <param name="controller" value="true" />
352 <param name="autoplay" value="'.$autostart.'" />
353 <param name="autostart" value="'.$autostart.'" />
354 <param name="resize" value="scale" />
355 </object>
356<!--<![endif]-->
357</object></span>';
358}
359
35716b86 360function filter_mediaplugin_qt_callback($link, $autostart=false) {
7e64d361 361 $url = $link[1];
362 if (empty($link[3]) or empty($link[4])) {
1387d5eb 363 $size = 'width="440" height="315"';
7e64d361 364 } else {
365 $size = 'width="'.$link[3].'" height="'.$link[4].'"';
366 }
367 $mimetype = mimeinfo('type', $url);
368 $autostart = $autostart ? 'true' : 'false';
369
370 return $link[0].
371'<span class="mediaplugin mediaplugin_qt">
372<object classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B"
373 codebase="http://www.apple.com/qtactivex/qtplugin.cab" '.$size.'>
374 <param name="pluginspage" value="http://www.apple.com/quicktime/download/" />
375 <param name="src" value="'.$url.'" />
d42df9da 376 <param name="controller" value="true" />
7e64d361 377 <param name="loop" value="true" />
378 <param name="autoplay" value="'.$autostart.'" />
379 <param name="autostart" value="'.$autostart.'" />
380 <param name="scale" value="aspect" />
381<!--[if !IE]>-->
382 <object data="'.$url.'" type="'.$mimetype.'" '.$size.'>
383 <param name="src" value="'.$url.'" />
384 <param name="pluginurl" value="http://www.apple.com/quicktime/download/" />
385 <param name="controller" value="true" />
386 <param name="loop" value="true" />
387 <param name="autoplay" value="'.$autostart.'" />
388 <param name="autostart" value="'.$autostart.'" />
389 <param name="scale" value="aspect" />
390 </object>
391<!--<![endif]-->
392</object></span>';
393}
6de17fde 394
4317f92f 395