xref: /dokuwiki/_test/tests/Parsing/ParserMode/MediaTest.php (revision 884caed926ca0aa0af6ce3f34ae3aa7317a3361a)
1<?php
2
3namespace dokuwiki\test\Parsing\ParserMode;
4
5use Doku_Renderer_xhtml;
6use dokuwiki\Parsing\ParserMode\Media;
7
8/**
9 * Tests for the {@see Media} parser mode: `{{...}}` media embeds.
10 *
11 * Covers the parser-level dispatch (internalmedia/externalmedia calls with the right argument tuple),
12 * audio/video rendering through the XHTML renderer, and various title / alignment / cache flag cases.
13 *
14 * @group parser_media
15 * @author  Michael Große <grosse@cosmocode.de>
16*/
17class MediaTest extends ParserTestBase
18{
19    function testInternal() {
20        $this->P->addMode('media', new Media());
21        $this->P->parse('Foo {{img.gif}} Bar');
22        $calls = [
23            ['document_start', []],
24            ['p_open', []],
25            ['cdata', ["\n" . 'Foo ']],
26            ['internalmedia', ['img.gif', null, null, null, null, 'cache', 'details']],
27            ['cdata', [' Bar']],
28            ['p_close', []],
29            ['document_end', []],
30        ];
31        $this->assertCalls($calls, $this->H->calls);
32    }
33
34    function testInternalLinkOnly() {
35        $this->P->addMode('media', new Media());
36        $this->P->parse('Foo {{img.gif?linkonly}} Bar');
37        $calls = [
38            ['document_start', []],
39            ['p_open', []],
40            ['cdata', ["\n" . 'Foo ']],
41            ['internalmedia', ['img.gif', null, null, null, null, 'cache', 'linkonly']],
42            ['cdata', [' Bar']],
43            ['p_close', []],
44            ['document_end', []],
45        ];
46        $this->assertCalls($calls, $this->H->calls);
47    }
48
49    function testNotImage() {
50        $this->P->addMode('media', new Media());
51        $this->P->parse('Foo {{foo.txt?10x10|Some File}} Bar');
52        $calls = [
53            ['document_start', []],
54            ['p_open', []],
55            ['cdata', ["\n" . 'Foo ']],
56            ['internalmedia', ['foo.txt', 'Some File', null, 10, 10, 'cache', 'details']],
57            ['cdata', [' Bar']],
58            ['p_close', []],
59            ['document_end', []],
60        ];
61        $this->assertCalls($calls, $this->H->calls);
62    }
63
64    function testInternalLAlign() {
65        $this->P->addMode('media', new Media());
66        $this->P->parse('Foo {{img.gif }} Bar');
67        $calls = [
68            ['document_start', []],
69            ['p_open', []],
70            ['cdata', ["\n" . 'Foo ']],
71            ['internalmedia', ['img.gif', null, 'left', null, null, 'cache', 'details']],
72            ['cdata', [' Bar']],
73            ['p_close', []],
74            ['document_end', []],
75        ];
76        $this->assertCalls($calls, $this->H->calls);
77    }
78
79    function testInternalRAlign() {
80        $this->P->addMode('media', new Media());
81        $this->P->parse('Foo {{ img.gif}} Bar');
82        $calls = [
83            ['document_start', []],
84            ['p_open', []],
85            ['cdata', ["\n" . 'Foo ']],
86            ['internalmedia', ['img.gif', null, 'right', null, null, 'cache', 'details']],
87            ['cdata', [' Bar']],
88            ['p_close', []],
89            ['document_end', []],
90        ];
91        $this->assertCalls($calls, $this->H->calls);
92    }
93
94    function testInternalCenter() {
95        $this->P->addMode('media', new Media());
96        $this->P->parse('Foo {{ img.gif }} Bar');
97        $calls = [
98            ['document_start', []],
99            ['p_open', []],
100            ['cdata', ["\n" . 'Foo ']],
101            ['internalmedia', ['img.gif', null, 'center', null, null, 'cache', 'details']],
102            ['cdata', [' Bar']],
103            ['p_close', []],
104            ['document_end', []],
105        ];
106        $this->assertCalls($calls, $this->H->calls);
107    }
108
109    function testInternalParams() {
110        $this->P->addMode('media', new Media());
111        $this->P->parse('Foo {{img.gif?50x100nocache}} Bar');
112        $calls = [
113            ['document_start', []],
114            ['p_open', []],
115            ['cdata', ["\n" . 'Foo ']],
116            ['internalmedia', ['img.gif', null, null, '50', '100', 'nocache', 'details']],
117            ['cdata', [' Bar']],
118            ['p_close', []],
119            ['document_end', []],
120        ];
121        $this->assertCalls($calls, $this->H->calls);
122    }
123
124    function testInternalTitle() {
125        $this->P->addMode('media', new Media());
126        $this->P->parse('Foo {{img.gif?50x100|Some Image}} Bar');
127        $calls = [
128            ['document_start', []],
129            ['p_open', []],
130            ['cdata', ["\n" . 'Foo ']],
131            ['internalmedia', ['img.gif', 'Some Image', null, '50', '100', 'cache', 'details']],
132            ['cdata', [' Bar']],
133            ['p_close', []],
134            ['document_end', []],
135        ];
136        $this->assertCalls($calls, $this->H->calls);
137    }
138
139    function testExternal() {
140        $this->P->addMode('media', new Media());
141        $this->P->parse('Foo {{http://www.google.com/img.gif}} Bar');
142        $calls = [
143            ['document_start', []],
144            ['p_open', []],
145            ['cdata', ["\n" . 'Foo ']],
146            ['externalmedia', ['http://www.google.com/img.gif', null, null, null, null, 'cache', 'details']],
147            ['cdata', [' Bar']],
148            ['p_close', []],
149            ['document_end', []],
150        ];
151        $this->assertCalls($calls, $this->H->calls);
152    }
153
154    function testExternalParams() {
155        $this->P->addMode('media', new Media());
156        $this->P->parse('Foo {{http://www.google.com/img.gif?50x100nocache}} Bar');
157        $calls = [
158            ['document_start', []],
159            ['p_open', []],
160            ['cdata', ["\n" . 'Foo ']],
161            ['externalmedia',
162                ['http://www.google.com/img.gif', null, null, '50', '100', 'nocache', 'details']],
163            ['cdata', [' Bar']],
164            ['p_close', []],
165            ['document_end', []],
166        ];
167        $this->assertCalls($calls, $this->H->calls);
168    }
169
170    function testExternalTitle() {
171        $this->P->addMode('media', new Media());
172        $this->P->parse('Foo {{http://www.google.com/img.gif?50x100|Some Image}} Bar');
173        $calls = [
174            ['document_start', []],
175            ['p_open', []],
176            ['cdata', ["\n" . 'Foo ']],
177            ['externalmedia',
178                ['http://www.google.com/img.gif', 'Some Image', null, '50', '100', 'cache', 'details']],
179            ['cdata', [' Bar']],
180            ['p_close', []],
181            ['document_end', []],
182        ];
183        $this->assertCalls($calls, $this->H->calls);
184    }
185
186    function testNested() {
187        $this->P->addMode('media', new Media());
188        $this->P->parse('Foo {{img.gif|{{foo.gif|{{bar.gif|Bar}}}}}} Bar');
189        $calls = [
190            ['document_start', []],
191            ['p_open', []],
192            ['cdata', ["\n" . 'Foo ']],
193            ['internalmedia',
194                ['img.gif', '{{foo.gif|{{bar.gif|Bar', null, null, null, 'cache', 'details']],
195            ['cdata', ['}}}} Bar']],
196            ['p_close', []],
197            ['document_end', []],
198        ];
199        $this->assertCalls($calls, $this->H->calls);
200    }
201
202
203    function testVideoOGVExternal() {
204        $file = 'http://some.where.far/away.ogv';
205        $parser_response = p_get_instructions('{{' . $file . '}}');
206
207        $calls = [
208            ['document_start',[]],
209            ['p_open',[]],
210            ['externalmedia',[$file,null,null,null,null,'cache','details']],
211            ['cdata',[null]],
212            ['p_close',[]],
213            ['document_end',[]],
214        ];
215        $this->assertCalls($calls, $parser_response);
216
217        $Renderer = new Doku_Renderer_xhtml();
218        $url = $Renderer->externalmedia($file,null,null,null,null,'cache','details',true);
219        //print_r("url: " . $url);
220        $video = '<video class="media" width="320" height="240" controls="controls">';
221        $this->assertEquals($video, substr($url,0,66));
222        $source = '<source src="http://some.where.far/away.ogv" type="video/ogg" />';
223        $this->assertEquals($source, substr($url,67,64));
224        // work around random token
225        $a_first_part = '<a href="' . \DOKU_BASE . 'lib/exe/fetch.php?tok=';
226        $a_second_part = '&amp;media=http%3A%2F%2Fsome.where.far%2Faway.ogv" class="media mediafile mf_ogv" title="http://some.where.far/away.ogv">';
227
228        $substr_start = 132;
229        $substr_len = strlen($a_first_part);
230        $this->assertEquals($a_first_part, substr($url, $substr_start, $substr_len));
231
232        $substr_start = strpos($url, '&amp;media', $substr_start + $substr_len);
233        $this->assertNotSame(false, $substr_start, 'Substring not found.');
234        $substr_len = strlen($a_second_part);
235        $this->assertEquals($a_second_part, substr($url, $substr_start, $substr_len));
236
237        $rest = 'away.ogv</a></video>'."\n";
238        $substr_start = strlen($url) - strlen($rest);
239        $this->assertEquals($rest, substr($url, $substr_start));
240    }
241
242    /**
243     * unknown extension of external media file
244     */
245    function testVideoVIDExternal() {
246        $file = 'http://some.where.far/away.vid';
247        $parser_response = p_get_instructions('{{' . $file . '}}');
248
249        $calls = [
250            ['document_start', []],
251            ['p_open', []],
252            ['externalmedia', [$file, null, null, null, null, 'cache', 'details']],
253            ['cdata', [null]],
254            ['p_close', []],
255            ['document_end', []],
256        ];
257        $this->assertCalls($calls, $parser_response);
258
259        $Renderer = new Doku_Renderer_xhtml();
260        $url = $Renderer->externalmedia($file, null, null, null, null, 'cache', 'details', true);
261        // work around random token
262        $a_first_part = '<a href="' . \DOKU_BASE . 'lib/exe/fetch.php?tok=';
263        $a_second_part = '&amp;media=http%3A%2F%2Fsome.where.far%2Faway.vid" class="media mediafile mf_vid" title="http://some.where.far/away.vid">';
264
265        $substr_start = 0;
266        $substr_len = strlen($a_first_part);
267        $this->assertEquals($a_first_part, substr($url, $substr_start, $substr_len));
268
269        $substr_start = strpos($url, '&amp;media', $substr_start + $substr_len);
270        $this->assertNotSame(false, $substr_start, 'Substring not found.');
271        $substr_len = strlen($a_second_part);
272        $this->assertEquals($a_second_part, substr($url, $substr_start, $substr_len));
273
274        $rest = 'away.vid</a>';
275        $substr_start = strlen($url) - strlen($rest);
276        $this->assertEquals($rest, substr($url, $substr_start));
277    }
278
279
280    function testVideoOGVInternal() {
281        $file = 'wiki:kind_zu_katze.ogv';
282        $parser_response = p_get_instructions('{{' . $file . '}}');
283
284        $calls = [
285            ['document_start',[]],
286            ['p_open',[]],
287            ['internalmedia',[$file,null,null,null,null,'cache','details']],
288            ['cdata',[null]],
289            ['p_close',[]],
290            ['document_end',[]],
291        ];
292        $this->assertCalls($calls, $parser_response);
293
294        $Renderer = new Doku_Renderer_xhtml();
295        $url = $Renderer->externalmedia($file,null,null,null,null,'cache','details',true);
296
297        $video = '<video class="media" width="320" height="240" controls="controls" poster="' . \DOKU_BASE . 'lib/exe/fetch.php?media=wiki:kind_zu_katze.png">';
298        $substr_start = 0;
299        $substr_len = strlen($video);
300        $this->assertEquals($video, substr($url, $substr_start, $substr_len));
301
302        // find $source_webm in $url
303        $source_webm = '<source src="' . \DOKU_BASE . 'lib/exe/fetch.php?media=wiki:kind_zu_katze.webm" type="video/webm" />';
304        $substr_start = strpos($url, $source_webm, $substr_start + $substr_len);
305        $this->assertNotSame(false, $substr_start, 'Substring not found.');
306
307        // find $source_ogv in $url
308        $source_ogv = '<source src="' . \DOKU_BASE . 'lib/exe/fetch.php?media=wiki:kind_zu_katze.ogv" type="video/ogg" />';
309        $substr_start = strpos($url, $source_ogv, $substr_start + strlen($source_webm));
310        $this->assertNotSame(false, $substr_start, 'Substring not found.');
311
312        // find $a_webm in $url
313        $a_webm = '<a href="' . \DOKU_BASE . 'lib/exe/fetch.php?media=wiki:kind_zu_katze.webm" class="media mediafile mf_webm" title="wiki:kind_zu_katze.webm (99.1'."\xC2\xA0".'KB)">kind_zu_katze.webm</a>';
314        $substr_start = strpos($url, $a_webm, $substr_start + strlen($source_ogv));
315        $this->assertNotSame(false, $substr_start, 'Substring not found.');
316
317        // find $a_webm in $url
318        $a_ogv = '<a href="' . \DOKU_BASE . 'lib/exe/fetch.php?media=wiki:kind_zu_katze.ogv" class="media mediafile mf_ogv" title="wiki:kind_zu_katze.ogv (44.8'."\xC2\xA0".'KB)">kind_zu_katze.ogv</a>';
319        $substr_start = strpos($url, $a_ogv, $substr_start + strlen($a_webm));
320        $this->assertNotSame(false, $substr_start, 'Substring not found.');
321
322        $rest = '</video>'."\n";
323        $substr_start = strlen($url) - strlen($rest);
324        $this->assertEquals($rest, substr($url, $substr_start));
325    }
326
327    function testVideoInternalTitle() {
328        $file = 'wiki:kind_zu_katze.ogv';
329        $title = 'Single quote: \' Ampersand: &';
330
331        $Renderer = new Doku_Renderer_xhtml();
332        $url = $Renderer->externalmedia($file, $title, null, null, null, 'cache', 'details', true);
333
334        // make sure the title is escaped just once
335        $this->assertEquals(hsc($title), substr($url, 28, 37));
336    }
337
338    function testSimpleLinkText() {
339        $file = 'wiki:dokuwiki-128.png';
340        $parser_response = p_get_instructions('{{' . $file . '|This is a simple text.}}');
341
342        $calls = [
343            ['document_start',[]],
344            ['p_open',[]],
345            ['internalmedia',[$file,'This is a simple text.',null,null,null,'cache','details']],
346            ['cdata',[null]],
347            ['p_close',[]],
348            ['document_end',[]],
349        ];
350        $this->assertCalls($calls, $parser_response);
351    }
352
353    function testLinkTextWithWavedBrackets_1() {
354        $file = 'wiki:dokuwiki-128.png';
355        $parser_response = p_get_instructions('{{' . $file . '|We got a { here.}}');
356
357        $calls = [
358            ['document_start',[]],
359            ['p_open',[]],
360            ['internalmedia',[$file,'We got a { here.',null,null,null,'cache','details']],
361            ['cdata',[null]],
362            ['p_close',[]],
363            ['document_end',[]],
364        ];
365        $this->assertCalls($calls, $parser_response);
366    }
367
368    function testLinkTextWithWavedBrackets_2() {
369        $file = 'wiki:dokuwiki-128.png';
370        $parser_response = p_get_instructions('{{' . $file . '|We got a } here.}}');
371
372        $calls = [
373            ['document_start',[]],
374            ['p_open',[]],
375            ['internalmedia',[$file,'We got a } here.',null,null,null,'cache','details']],
376            ['cdata',[null]],
377            ['p_close',[]],
378            ['document_end',[]],
379        ];
380        $this->assertCalls($calls, $parser_response);
381    }
382
383    function testAlignFromWhitespace() {
384        // DW's historical whitespace-inside-braces alignment still works.
385        $file = 'wiki:image.png';
386        $parser_response = p_get_instructions('{{ ' . $file . '}}');
387        $calls = [
388            ['document_start', []],
389            ['p_open', []],
390            ['internalmedia', [$file, null, 'right', null, null, 'cache', 'details']],
391            ['cdata', [null]],
392            ['p_close', []],
393            ['document_end', []],
394        ];
395        $this->assertCalls($calls, $parser_response);
396    }
397
398    function testAlignFromParameter() {
399        $file = 'wiki:image.png';
400        $parser_response = p_get_instructions('{{' . $file . '?left}}');
401        $calls = [
402            ['document_start', []],
403            ['p_open', []],
404            ['internalmedia', [$file, null, 'left', null, null, 'cache', 'details']],
405            ['cdata', [null]],
406            ['p_close', []],
407            ['document_end', []],
408        ];
409        $this->assertCalls($calls, $parser_response);
410    }
411
412    function testAlignParameterBeatsWhitespace() {
413        // Explicit ?center wins over whitespace-derived 'left' (trailing space).
414        $file = 'wiki:image.png';
415        $parser_response = p_get_instructions('{{' . $file . '?center }}');
416        $calls = [
417            ['document_start', []],
418            ['p_open', []],
419            ['internalmedia', [$file, null, 'center', null, null, 'cache', 'details']],
420            ['cdata', [null]],
421            ['p_close', []],
422            ['document_end', []],
423        ];
424        $this->assertCalls($calls, $parser_response);
425    }
426
427    function testLinkTextWithWavedBrackets_3() {
428        $file = 'wiki:dokuwiki-128.png';
429        $parser_response = p_get_instructions('{{' . $file . '|We got a { and a } here.}}');
430
431        $calls = [
432            ['document_start',[]],
433            ['p_open',[]],
434            ['internalmedia',[$file,'We got a { and a } here.',null,null,null,'cache','details']],
435            ['cdata',[null]],
436            ['p_close',[]],
437            ['document_end',[]],
438        ];
439        $this->assertCalls($calls, $parser_response);
440    }
441}
442