Completed
Push — develop ( 59ebb8...02877b )
by Schlaefer
04:24
created

BbcodeParserTest::testLinkAutoIgnoreLocalFiles()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 6
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * Saito - The Threaded Web Forum
7
 *
8
 * @copyright Copyright (c) the Saito Project Developers
9
 * @link https://github.com/Schlaefer/Saito
10
 * @license http://opensource.org/licenses/MIT
11
 */
12
13
namespace BbcodeParser\Test\Lib;
14
15
use App\View\Helper\ParserHelper;
16
use Cake\Cache\Cache;
17
use Cake\Core\Configure;
18
use Cake\View\View;
19
use Plugin\BbcodeParser\Lib;
20
use Plugin\BbcodeParser\src\Lib\Parser;
21
use Saito\Markup\MarkupSettings;
22
use Saito\Test\SaitoTestCase;
23
use Saito\User\Userlist;
24
use Saito\User\Userlist\UserlistModel;
25
26
class BbcodeParserTest extends SaitoTestCase
27
{
28
29
    /**
30
     * @var Parser
31
     */
32
    protected $_Parser = null;
33
34
    /** @var MarkupSettings */
35
    protected $MarkupSettings;
36
37 View Code Duplication
    public function testBold()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
38
    {
39
        $input = '[b]bold[/b]';
40
        $expected = ['strong' => [], 'bold', '/strong'];
41
        $result = $this->_Parser->parse($input);
42
        $this->assertHtml($expected, $result);
43
    }
44
45 View Code Duplication
    public function testEmphasis()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
46
    {
47
        $input = '[i]italic[/i]';
48
        $expected = ['em' => [], 'italic', '/em'];
49
        $result = $this->_Parser->parse($input);
50
        $this->assertHtml($expected, $result);
51
    }
52
53 View Code Duplication
    public function testQuoteblock()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
54
    {
55
        $input = '[quote]foo bar[/quote]';
56
        $expected = ['blockquote' => [], 'foo bar', '/blockquote'];
57
        $result = $this->_Parser->parse($input);
58
        $this->assertHtml($expected, $result);
59
    }
60
61
    public function testStrike()
62
    {
63
        $expected = ['del' => [], 'text', '/del'];
64
65
        // [strike]
66
        $input = '[strike]text[/strike]';
67
        $result = $this->_Parser->parse($input);
68
        $this->assertHtml($expected, $result);
69
70
        // [s]
71
        $input = '[s]text[/s]';
72
        $result = $this->_Parser->parse($input);
73
        $this->assertHtml($expected, $result);
74
    }
75
76
    public function testSpoiler()
77
    {
78
        $input = 'pre [spoiler] te "\' xt[/spoiler]';
79
        $expected = [
80
            'pre',
81
            [
82
                'div' => [
83
                    'class' => 'richtext-spoiler',
84
                    'style' => 'display: inline;'
85
                ]
86
            ],
87
            ['script' => true],
88
            'preg:/(.*?)"string":" te &quot;&#039; xt"(.*?)(?=<)/',
89
            '/script',
90
            [
91
                'a' => [
92
                    'href' => '#',
93
                    'class' => 'richtext-spoiler-link',
94
                    'onclick'
95
                ]
96
            ],
97
            'preg:/.*▇ Spoiler ▇.*?(?=<)/',
98
            '/a',
99
            '/div'
100
        ];
101
        $result = $this->_Parser->parse($input);
102
        $this->assertHtml($expected, $result);
103
    }
104
105
    public function testList()
106
    {
107
        $input = "[list]\n[*]fooo\n[*]bar\n[/list]";
108
        $expected = [
109
            ['ul' => []],
110
            ['li' => []],
111
            'fooo',
112
            ['br' => []],
113
            '/li',
114
            ['li' => []],
115
            'bar',
116
            ['br' => []],
117
            '/li',
118
            '/ul'
119
        ];
120
        $result = $this->_Parser->parse($input);
121
        $this->assertHtml($expected, $result);
122
    }
123
124
    public function testMaskLinkWithoutProtocol()
125
    {
126
        $input = '[url=thetempe.st/station]purge[/url]';
127
        $expected = [
128
            'a' => [
129
                'href' => 'http://thetempe.st/station',
130
                'rel' => 'external',
131
                'target' => '_blank'
132
            ],
133
            'purge',
134
            '/a'
135
        ];
136
        $result = $this->_Parser->parse($input);
137
        $this->assertHtml($expected, $result);
138
    }
139
140
    public function testParserEngineCaching()
141
    {
142
        $input = '[img=]foo.png[/img]';
143
        $result = $this->_Parser->parse($input, ['multimedia' => true]);
144
        $this->assertContains('<img src', $result);
145
        $result = $this->_Parser->parse($input, ['multimedia' => false]);
146
        $this->assertNotContains('<img src', $result);
147
    }
148
149
    public function testLink()
150
    {
151
        $input = '[url=http://cgi.ebay.de/ws/eBayISAPI.dll?ViewItem&item=250678480561&ssPageName=ADME:X:RTQ:DE:1123]test[/url]';
152
        $expected = "<a href='http://cgi.ebay.de/ws/eBayISAPI.dll?ViewItem&amp;item=250678480561&amp;ssPageName=ADME:X:RTQ:DE:1123' rel='external' target='_blank'>test</a> <span class='richtext-linkInfo'>[ebay.de]</span>";
153
        $result = $this->_Parser->parse($input);
154
        $this->assertEquals($expected, $result);
155
156
        /*
157
         * external server
158
         */
159
        $input = '[url]http://heise.de/foobar[/url]';
160
        $expected = [
161
            'a' => [
162
                'href' => 'http://heise.de/foobar',
163
                'rel' => 'external',
164
                'target' => '_blank'
165
            ],
166
            'http://heise.de/foobar',
167
            '/a'
168
        ];
169
        $result = $this->_Parser->parse($input);
170
        $this->assertHtml($expected, $result);
171
172
        $input = '[link]http://heise.de/foobar[/link]';
173
        $expected = [
174
            'a' => [
175
                'href' => 'http://heise.de/foobar',
176
                'rel' => 'external',
177
                'target' => '_blank'
178
            ],
179
            'http://heise.de/foobar',
180
            '/a'
181
        ];
182
        $result = $this->_Parser->parse($input);
183
        $this->assertHtml($expected, $result);
184
185
        // masked link
186
        $input = '[url=http://heise.de/foobar]foobar[/url]';
187
        $expected = [
188
            'a' => [
189
                'href' => 'http://heise.de/foobar',
190
                'rel' => 'external',
191
                'target' => '_blank'
192
            ],
193
            'foobar',
194
            '/a',
195
            'span' => ['class' => 'richtext-linkInfo'],
196
            '[heise.de]',
197
            '/span'
198
        ];
199
        $result = $this->_Parser->parse($input);
200
        $this->assertHtml($expected, $result);
201
202
        // masked link with no label
203
        $input = '[url=http://heise.de/foobar  label=none ]foobar[/url]';
204
        $expected = [
205
            'a' => [
206
                'href' => 'http://heise.de/foobar',
207
                'rel' => 'external',
208
                'target' => '_blank',
209
            ],
210
            'foobar',
211
            '/a',
212
        ];
213
        $result = $this->_Parser->parse($input);
214
        $this->assertHtml($expected, $result);
215
216
        /*
217
         * local server
218
         */
219
        $input = '[url=http://macnemo.de/foobar]foobar[/url]';
220
        $expected = "<a href='http://macnemo.de/foobar'>foobar</a>";
221
        $result = $this->_Parser->parse($input);
222
        $this->assertEquals($expected, $result);
223
224
        $input = '[url]/foobar[/url]';
225
        $expected = [
226
            'a' => [
227
                'href' => '/foobar',
228
            ],
229
            'preg:/\/foobar/',
230
            '/a',
231
        ];
232
        $result = $this->_Parser->parse($input);
233
        $this->assertHtml($expected, $result);
234
235
        // test lokaler server with absolute url
236
        $input = '[url=/foobar]foobar[/url]';
237
        $expected = "<a href='/foobar'>foobar</a>";
238
        $result = $this->_Parser->parse($input);
239
        $this->assertEquals($expected, $result);
240
241
        // test 'http://' only
242
        $input = '[url=http://]foobar[/url]';
243
        $expected = "<a href='http://'>foobar</a>";
244
        $result = $this->_Parser->parse($input);
245
        $this->assertEquals($expected, $result);
246
247
        // test for co.uk
248
        $input = '[url=http://heise.co.uk/foobar]foobar[/url]';
249
        $expected = [
250
            'a' => [
251
                'href' => 'http://heise.co.uk/foobar',
252
                'rel' => 'external',
253
                'target' => '_blank'
254
            ],
255
            'foobar',
256
            '/a',
257
            'span' => ['class' => 'richtext-linkInfo'],
258
            '[heise.co.uk]',
259
            '/span'
260
        ];
261
        $result = $this->_Parser->parse($input);
262
        $this->assertHtml($expected, $result);
263
    }
264
265
    public function testHashLinkSuccess()
266
    {
267
        // inline content ([i])
268
        $input = "[i]#2234[/i]";
269
        $expected = [
270
            'em' => [],
271
            'a' => [
272
                'href' => '/hash/2234'
273
            ],
274
            '#2234',
275
            '/a',
276
            '/em'
277
        ];
278
        $result = $this->_Parser->parse($input);
279
        $this->assertHtml($expected, $result);
280
281
        // lists
282
        $input = "[list][*]#2234[/list]";
283
        $expected = [
284
            'ul' => true,
285
            'li' => true,
286
            'a' => [
287
                'href' => '/hash/2234'
288
            ],
289
            '#2234',
290
            '/a',
291
            '/li',
292
            '/ul'
293
        ];
294
        $result = $this->_Parser->parse($input);
295
        $this->assertHtml($expected, $result);
296
    }
297
298
    public function testHashLinkFailure()
299
    {
300
        // don't hash code
301
        $input = '[code]#2234[/code]';
302
        $result = $this->_Parser->parse($input);
303
        $this->assertNotContains('>#2234</a>', $result);
304
305
        // not a valid hash
306
        $input = '#2234t';
307
        $result = $this->_Parser->parse($input);
308
        $this->assertEquals('#2234t', $result);
309
    }
310
311
    public function testAtLinkKnownUsers()
312
    {
313
        $input = '@Alice @Bob @Bobby Junior @Bobby Tables @Dr. No';
314
        $expected =
315
            "<a href='/at/Alice'>@Alice</a>" .
316
            " @Bob " .
317
            "<a href='/at/Bobby+Junior'>@Bobby Junior</a>" .
318
            " @Bobby Tables " .
319
            "<a href='/at/Dr.+No'>@Dr. No</a>";
320
321
        $result = $this->_Parser->parse($input);
322
        $this->assertEquals(
323
            $expected,
324
            $result,
325
            '@User string is not replaced with link to user profile.'
326
        );
327
328
        $input = '[code]@Alice[/code]';
329
        $result = $this->_Parser->parse($input);
330
        $this->assertNotContains('>@Alice</a>', $result);
331
    }
332
333
    public function testAtLinkKnownUsersLinebreak()
334
    {
335
        $input = "@Alice\nfoo";
336
        $result = $this->_Parser->parse($input);
337
        $expected = [
338
            'a' => ['href' => '/at/Alice'],
339
            '@Alice',
340
            '/a',
341
            'br' => true
342
        ];
343
        $this->assertHtml($expected, $result);
344
    }
345
346 View Code Duplication
    public function testLinkEmptyUrl()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
347
    {
348
        $input = '[url=][/url]';
349
        $expected = "<a href=''></a>";
350
        $result = $this->_Parser->parse($input);
351
        $this->assertEquals($expected, $result);
352
    }
353
354 View Code Duplication
    public function testEditMarker()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
355
    {
356
        $input = 'pre [e] post';
357
        $expected = [
358
            'pre ',
359
            'span' => [
360
                'class' => 'richtext-editMark'
361
            ],
362
            '/span',
363
            ' post'
364
        ];
365
        $result = $this->_Parser->parse($input);
366
        $this->assertHtml($expected, $result);
367
    }
368
369
    /*
370
     * without obfuscator
371
     *
372
    public function testEmail() {
373
        /*
374
            // mailto:
375
            $input = '[email]mailto:[email protected][/email]';
376
            $expected = "<a href='mailto:[email protected]'>mailto:[email protected]</a>";
377
            $result = $this->Bbcode->parse($input);
378
            $this->assertEquals($expected, $result);
379
380
            // mailto: mask
381
            $input = '[email=mailto:[email protected]]Mail[/email]';
382
            $expected = "<a href='mailto:[email protected]'>Mail</a>";
383
            $result = $this->Bbcode->parse($input);
384
            $this->assertEquals($expected, $result);
385
386
            // no mailto:
387
            $input = '[email][email protected][/email]';
388
            $expected = "<a href='mailto:[email protected]'>[email protected]</a>";
389
            $result = $this->Bbcode->parse($input);
390
            $this->assertEquals($expected, $result);
391
392
            // no mailto: mask
393
            $input = '[[email protected]]Mail[/email]';
394
            $expected = "<a href='mailto:[email protected]'>Mail</a>";
395
            $result = $this->Bbcode->parse($input);
396
            $this->assertEquals($expected, $result);
397
    }
398
            */
399
400 View Code Duplication
    public function testEmailMailto()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
401
    {
402
        $MO = $this->getMockBuilder('MailObfuscator')
403
            ->setMethods(['link'])
404
            ->getMock();
405
        $MO->expects($this->once(4))
0 ignored issues
show
Unused Code introduced by
The call to BbcodeParserTest::once() has too many arguments starting with 4.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
406
            ->method('link')
407
            ->with('[email protected]', null);
408
        $this->_Helper->MailObfuscator = $MO;
0 ignored issues
show
Bug introduced by
The property _Helper does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
409
410
        $input = '[email]mailto:[email protected][/email]';
411
        $this->_Parser->parse($input);
412
    }
413
414 View Code Duplication
    public function testEmailMailtoMask()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
415
    {
416
        $MO = $this->getMockBuilder('MailObfuscator')
417
            ->setMethods(['link'])
418
            ->getMock();
419
        $MO->expects($this->once(4))
0 ignored issues
show
Unused Code introduced by
The call to BbcodeParserTest::once() has too many arguments starting with 4.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
420
            ->method('link')
421
            ->with('[email protected]', 'Mail');
422
        $this->_Helper->MailObfuscator = $MO;
423
424
        $input = '[email=mailto:[email protected]]Mail[/email]';
425
        $this->_Parser->parse($input);
426
    }
427
428 View Code Duplication
    public function testEmailNoMailto()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
429
    {
430
        $MO = $this->getMockBuilder('MailObfuscator')
431
            ->setMethods(['link'])
432
            ->getMock();
433
        $MO->expects($this->once(4))
0 ignored issues
show
Unused Code introduced by
The call to BbcodeParserTest::once() has too many arguments starting with 4.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
434
            ->method('link')
435
            ->with('[email protected]', null);
436
        $this->_Helper->MailObfuscator = $MO;
437
438
        $input = '[email][email protected][/email]';
439
        $this->_Parser->parse($input);
440
    }
441
442 View Code Duplication
    public function testEmailNoMailtoMask()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
443
    {
444
        $MO = $this->getMockBuilder('MailObfuscator')
445
            ->setMethods(['link'])
446
            ->getMock();
447
        $MO->expects($this->once(4))
0 ignored issues
show
Unused Code introduced by
The call to BbcodeParserTest::once() has too many arguments starting with 4.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
448
            ->method('link')
449
            ->with('[email protected]', 'Mail');
450
        $this->_Helper->MailObfuscator = $MO;
451
452
        $input = '[[email protected]]Mail[/email]';
453
        $this->_Parser->parse($input);
454
    }
455
456
    public function testFlash()
457
    {
458
        $bbcode = '[flash_video]//www.youtube.com/v/MrBRPYlrGF8?version=3&amp;hl=en_US|560|315[/flash_video]';
459
        $expected = <<<EOF
460
			<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="560" height="315">
461
									<param name="movie" value="//www.youtube.com/v/MrBRPYlrGF8?version=3&amp;amp;hl=en_US"></param>
462
									<embed src="//www.youtube.com/v/MrBRPYlrGF8?version=3&amp;amp;hl=en_US" width="560" height="315" type="application/x-shockwave-flash" wmode="opaque" style="width:560px; height:315px;" id="VideoPlayback" flashvars=""> </embed> </object>
463
EOF;
464
        $actual = $this->_Parser->parse(
465
            $bbcode,
466
            ['video_domains_allowed' => 'youtube']
467
        );
468
        $this->assertEquals(trim($expected), trim($actual));
469
    }
470
471
    public function testFloat()
472
    {
473
        $expected = [
474
            ['div' => ['class' => 'clearfix']],
475
            '/div',
476
            ['div' => ['class' => 'richtext-float']],
477
            'text',
478
            '/div',
479
            'more'
480
        ];
481
482
        $input = '[float]text[/float]more';
483
        $result = $this->_Parser->parse($input);
484
        $this->assertHtml($expected, $result);
485
    }
486
487
    public function testLinkAuto()
488
    {
489
        $input = 'http://heise.de/foobar';
490
        $expected = "<a href='http://heise.de/foobar' rel='external' target='_blank'>http://heise.de/foobar</a>";
491
        $result = $this->_Parser->parse($input);
492
        $this->assertEquals($expected, $result);
493
494
        // autolink surrounded by text
495
        $input = 'some http://heise.de/foobar text';
496
        $expected = "some <a href='http://heise.de/foobar' rel='external' target='_blank'>http://heise.de/foobar</a> text";
497
        $result = $this->_Parser->parse($input);
498
        $this->assertEquals($expected, $result);
499
500
        // no autolink in [code]
501
        $input = '[code]http://heise.de/foobar[/code]';
502
        $needle = 'heise.de/foobar</a>';
503
        $result = $this->_Parser->parse($input);
504
        $this->assertNotContains($result, $needle);
505
506
        // no autolink in [url]
507
        $input = '[url=http://a.com/]http://b.de/[/url]';
508
        $result = $this->_Parser->parse($input);
509
        $this->assertRegExp(
510
            '#href=["\']http://a.com/["\'][^>]*?>http://b.de/#',
511
            $result
512
        );
513
514
        // email autolink
515
        $input = 'text [email protected] test';
516
        // $expected = "text <a href='mailto:[email protected]'>[email protected]</a> test";
517
        $result = $this->_Parser->parse($input);
518
        // $this->assertEquals($expected, $result);
519
        // @bogus weak test
520
        $this->assertRegExp('/^text .*href=".* test$/sm', $result);
521
522
        //# in list
523
        $input = <<<EOF
524
[list]
525
[*] http://heise.de
526
[/list]
527
EOF;
528
        $result = $this->_Parser->parse($input);
529
        $expected = "<a href='http://heise.de";
530
        $this->assertTextContains($expected, $result);
531
    }
532
533
    public function testLinkAutoWithoutHttpPrefix()
534
    {
535
        $input = 'some www.example.com/foobar text';
536
        $expected = [
537
            'some ',
538
            'a' => [
539
                'href' => 'http://www.example.com/foobar',
540
                'rel' => 'external',
541
                'target' => '_blank',
542
            ],
543
            'http://www.example.com/foobar',
544
            '/a',
545
            ' text'
546
        ];
547
        $result = $this->_Parser->parse($input);
548
        $this->assertHtml($expected, $result);
549
    }
550
551
    public function testLinkAutoUrlWithinParentheses()
552
    {
553
        $input = 'some (www.example.com/foobar) text';
554
        $expected = [
555
            'some (',
556
            'a' => [
557
                'href' => 'http://www.example.com/foobar',
558
                'rel' => 'external',
559
                'target' => '_blank',
560
            ],
561
            'http://www.example.com/foobar',
562
            '/a',
563
            ') text'
564
        ];
565
        $result = $this->_Parser->parse($input);
566
        $this->assertHtml($expected, $result);
567
    }
568
569
    public function testLinkAutoSurroundingChars()
570
    {
571
        $input = 'text http://example.com/?foo,,, text';
572
        $result = $this->_Parser->parse($input);
573
        $expected = [
574
            'text ',
575
            'a' => [
576
                'href' => 'http://example.com/?foo,,',
577
                'rel' => 'external',
578
                'target' => '_blank',
579
            ],
580
            'http://example.com/?foo,,',
581
            '/a',
582
            ', text'
583
        ];
584
        $this->assertHtml($expected, $result);
585
586
        // Question mark
587
        $input = 'question http://example.com/? Text';
588
        $result = $this->_Parser->parse($input);
589
        $expected = [
590
            'question ',
591
            'a' => [
592
                'href' => 'http://example.com/',
593
                'rel' => 'external',
594
                'target' => '_blank',
595
            ],
596
            'http://example.com/',
597
            '/a',
598
            '? Text'
599
        ];
600
        $this->assertHtml($expected, $result);
601
602
        // No Question mark but url
603
        $input = 'no question http://example.com/?foo=bar text';
604
        $result = $this->_Parser->parse($input);
605
        $expected = [
606
            'no question ',
607
            'a' => [
608
                'href' => 'http://example.com/?foo=bar',
609
                'rel' => 'external',
610
                'target' => '_blank',
611
            ],
612
            'http://example.com/?foo=bar',
613
            '/a',
614
            ' text'
615
        ];
616
        $this->assertHtml($expected, $result);
617
    }
618
619
    public function testLinkAutoIgnoreLocalFiles()
620
    {
621
        $input = 'a file:///foo.bar b file://foo c file:// d file:///';
622
        $result = $this->_Parser->parse($input);
623
        $this->assertEquals($input, $result);
624
    }
625
626
    public function testReturnText()
627
    {
628
        $in = 'test [b]test[b] test';
629
        $expected = 'test test test';
630
        $actual = $this->_Parser->parse($in, ['return' => 'text']);
631
        $this->assertEquals($expected, $actual);
632
    }
633
634
    public function testShortenLink()
635
    {
636
        $maxLength = 15;
637
        $this->MarkupSettings->setSingle('text_word_maxlength', $maxLength);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Saito\Markup\MarkupSettings as the method setSingle() does only exist in the following sub-classes of Saito\Markup\MarkupSettings: BbcodeParser\Test\Lib\an.../BbcodeParserTest.php$0. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
638
639
        $input = '[url]http://this/url/is/32/chars/long[/url]';
640
        $expected = "<a href='http://this/url/is/32/chars/long' rel='external' target='_blank'>http:// … /long</a>";
641
642
        $result = $this->_Parser->parse($input);
643
        $this->assertEquals($expected, $result);
644
645
        $input = 'http://this/url/is/32/chars/long';
646
        $expected = "<a href='http://this/url/is/32/chars/long' rel='external' target='_blank'>http:// … /long</a>";
647
        $result = $this->_Parser->parse($input);
648
        $this->assertEquals($expected, $result);
649
    }
650
651
    public function testIframe()
652
    {
653
        //* test allowed domain
654
        $input = '[iframe height=349 width=560 ' .
655
            'src=http://www.youtube.com/embed/HdoW3t_WorU ' .
656
            'frameborder=0][/iframe]';
657
        $expected = [
658
            [
659
                'div' => [
660
                    'class' => 'embed-responsive embed-responsive-16by9',
661
                ],
662
                'iframe' => [
663
                    'class' => 'embed-responsive-item',
664
                    'src' => 'http://www.youtube.com/embed/HdoW3t_WorU?&amp;wmode=Opaque',
665
                    'height' => '349',
666
                    'width' => '560',
667
                    'frameborder' => '0'
668
                ]
669
            ],
670
            '/iframe',
671
        ];
672
        $result = $this->_Parser->parse(
673
            $input,
674
            ['video_domains_allowed' => 'youtube | vimeo']
675
        );
676
        $this->assertHtml($expected, $result);
677
678
        //* test forbidden domains
679
        $input = '[iframe height=349 width=560 ' .
680
            'src=http://www.youtubescam.com/embed/HdoW3t_WorU ' .
681
            'frameborder=0][/iframe]';
682
        $pattern = '/src/i';
683
        $result = $this->_Parser->parse(
684
            $input,
685
            ['video_domains_allowed' => 'youtube | vimeo']
686
        );
687
        $this->assertNotRegExp($pattern, $result);
688
    }
689
690
    public function testIframeAllDomainsAllowed()
691
    {
692
        $input = '[iframe height=349 width=560 ' .
693
            'src=http://www.youtubescam.com/embed/HdoW3t_WorU ' .
694
            '][/iframe]';
695
        $expected = 'src="http://www.youtubescam.com/embed/HdoW3t_WorU';
696
        $this->MarkupSettings->setSingle('video_domains_allowed', '*');
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Saito\Markup\MarkupSettings as the method setSingle() does only exist in the following sub-classes of Saito\Markup\MarkupSettings: BbcodeParser\Test\Lib\an.../BbcodeParserTest.php$0. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
697
        $result = $this->_Parser->parse($input);
698
        $this->assertContains($expected, $result);
699
    }
700
701
    public function testIframeNoDomainAllowed()
702
    {
703
        $input = '[iframe height=349 width=560 ' .
704
            'src=http://www.youtubescam.com/embed/HdoW3t_WorU ' .
705
            '][/iframe]';
706
        $expected = '/src/i';
707
        $result = $this->_Parser->parse(
708
            $input,
709
            ['video_domains_allowed' => '']
710
        );
711
        $this->assertNotRegExp($expected, $result);
712
    }
713
714 View Code Duplication
    public function testExternalImageAbsoluteAutoLinked()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
715
    {
716
        // test for standard URIs
717
        $input = '[img]http://foo.bar/img/macnemo.png[/img]';
718
        $expected = [
719
            'a' => [
720
                'href' => 'http://foo.bar/img/macnemo.png',
721
                // 'rel' => 'external',
722
                'target' => '_blank',
723
            ],
724
            'img' => [
725
                'src' => 'http://foo.bar/img/macnemo.png',
726
                'alt' => ''
727
            ]
728
        ];
729
        $result = $this->_Parser->parse($input);
730
        $this->assertHtml($expected, $result);
731
    }
732
733 View Code Duplication
    public function testExternalImageRelativeAutoLinked()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
734
    {
735
        // test for standard URIs
736
        $input = '[img]/somewhere/macnemo.png[/img]';
737
        $expected = [
738
            'a' => [
739
                'href' => '/somewhere/macnemo.png',
740
                'target' => '_blank',
741
            ],
742
            'img' => [
743
                'src' => '/somewhere/macnemo.png',
744
                'alt' => ''
745
            ]
746
        ];
747
        $result = $this->_Parser->parse($input);
748
        $this->assertHtml($expected, $result);
749
    }
750
751
    /**
752
     * test scaling with 1 parameter
753
     */
754
    public function testExternalImageAbsoluteAutoLinkedScaledByOne()
755
    {
756
        // test for standard URIs
757
        $input = '[img=50]http://foo.bar/img/macnemo.png[/img]';
758
        $expected = [
759
            'a' => [
760
                'href' => 'http://foo.bar/img/macnemo.png',
761
                'target' => '_blank',
762
            ],
763
            'img' => [
764
                'src' => 'http://foo.bar/img/macnemo.png',
765
                'alt' => '',
766
                'width' => '50',
767
            ]
768
        ];
769
        $result = $this->_Parser->parse($input);
770
        $this->assertHtml($expected, $result);
771
    }
772
773
    /**
774
     * test scaling with 2 parameter
775
     */
776
    public function testExternalImageAbsoluteAutoLinkedScaledByTwo()
777
    {
778
        // test for standard URIs
779
        $input = '[img=50x100]http://foo.bar/img/macnemo.png[/img]';
780
        $expected = [
781
            'a' => [
782
                'href' => 'http://foo.bar/img/macnemo.png',
783
                'target' => '_blank',
784
            ],
785
            'img' => [
786
                'src' => 'http://foo.bar/img/macnemo.png',
787
                'alt' => '',
788
                'height' => '100',
789
                'width' => '50',
790
            ]
791
        ];
792
        $result = $this->_Parser->parse($input);
793
        $this->assertHtml($expected, $result);
794
    }
795
796
    public function testExternalImageWithHttpsEnforced()
797
    {
798
        $_SERVER['HTTPS'] = true;
799
        $input = '[img=]http://foo.bar/img/macnemo.png[/img]';
800
        $expected = [
801
            'a' => [
802
                'href' => 'https://foo.bar/img/macnemo.png',
803
                'target' => '_blank',
804
            ],
805
            'img' => [
806
                'src' => 'https://foo.bar/img/macnemo.png',
807
                'alt' => '',
808
            ]
809
        ];
810
        $result = $this->_Parser->parse($input);
811
        $this->assertHtml($expected, $result);
812
        unset($_SERVER['HTTPS']);
813
    }
814
815
    public function testImageNestedInExternalLink()
816
    {
817
        $input = '[url=http://heise.de][img]http://heise.de/img.png[/img][/url]';
818
819
        /*
820
        $expected = "<a href='http://heise.de' rel='external' target='_blank'><img src=\"http://heise.de/img.png\" class=\"external_image\" style=\"\" width=\"auto\" height=\"auto\" alt=\"\" /></a>";
821
        */
822
        $expected = [
823
            [
824
                'a' => [
825
                    'href' => 'http://heise.de',
826
                    'rel' => 'external',
827
                    'target' => '_blank',
828
                ]
829
            ],
830
            [
831
                'img' => [
832
                    'src' => 'http://heise.de/img.png',
833
                    'alt' => '',
834
                ]
835
            ],
836
            '/a'
837
        ];
838
        $result = $this->_Parser->parse($input);
839
        $this->assertHtml($expected, $result);
840
    }
841
842
    /**
843
     * [uploads]<image>[/uploads]
844
     */
845
    public function testInternalImageAutoLinked()
846
    {
847
        //// internal image
848
        $input = '[upload]test.png[/upload]';
849
        $expected = [
850
            [
851
                'a' => [
852
                    'href' => '/useruploads/test.png',
853
                    'target' => '_blank',
854
                ],
855
                'img' => [
856
                    'alt' => '',
857
                    'src' => '/useruploads/test.png',
858
                ],
859
            ],
860
        ];
861
        $result = $this->_Parser->parse($input);
862
        $this->assertHtml($expected, $result);
863
864
        //// internal image with attributes
865
        $input = '[upload width=50 height=60]test.png[/upload]';
866
        $expected = [
867
            [
868
                'a' => [
869
                    'href' => '/useruploads/test.png',
870
                    'target' => '_blank',
871
                ],
872
                'img' =>
873
                    [
874
                        'alt' => '',
875
                        'src' => '/useruploads/test.png',
876
                        'width' => '50',
877
                        'height' => '60',
878
                    ]
879
            ]
880
        ];
881
        $result = $this->_Parser->parse($input);
882
        $this->assertHtml($expected, $result);
883
884
        // nested image does not have [domain.info]
885
        $input = '[url=http://heise.de][upload]test.png[/upload][/url]';
886
        $expected = "/richtext-linkInfo/";
887
        $result = $this->_Parser->parse($input);
888
        $this->assertNotRegExp($expected, $result);
889
    }
890
891
    public function testInternalImageExternallyLinked()
892
    {
893
        //// internal image
894
        $input = '[url=http://foo.de][upload]test.png[/upload][/url]';
895
        $expected = [
896
            [
897
                'a' => [
898
                    'href' => 'http://foo.de',
899
                    'rel' => 'external',
900
                    'target' => '_blank',
901
                ],
902
                'img' => [
903
                    'src' => '/useruploads/test.png',
904
                    'alt' => '',
905
                ]
906
            ],
907
        ];
908
        $result = $this->_Parser->parse($input);
909
        $this->assertHtml($expected, $result);
910
    }
911
912 View Code Duplication
    public function testUploadTypeImage()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
913
    {
914
        //// internal image
915
        $input = '[img src=upload]test.png[/img]';
916
        $expected = [
917
            [
918
                'a' => [
919
                    'href' => '/useruploads/test.png',
920
                    'target' => '_blank',
921
                ],
922
                'img' => [
923
                    'src' => '/useruploads/test.png',
924
                    'alt' => '',
925
                ]
926
            ],
927
        ];
928
        $result = $this->_Parser->parse($input);
929
        $this->assertHtml($expected, $result);
930
    }
931
932 View Code Duplication
    public function testUploadTypeAudio()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
933
    {
934
        //// internal image
935
        $input = '[audio src=upload]test.mp3[/audio]';
936
        $expected = [
937
            'audio' => [
938
                'controls' => 'controls',
939
                'preload' => 'auto',
940
                'src' => '/useruploads/test.mp3',
941
                'x-webkit-airplay' => 'allow',
942
            ]
943
        ];
944
        $result = $this->_Parser->parse($input);
945
        $this->assertHtml($expected, $result);
946
    }
947
948 View Code Duplication
    public function testUploadTypeVideo()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
949
    {
950
        $input = '[video src=upload]test.mp4[/video]';
951
        $expected = [
952
            'video' => [
953
                'controls' => 'controls',
954
                'preload' => 'auto',
955
                'src' => '/useruploads/test.mp4',
956
                'x-webkit-airplay' => 'allow',
957
            ]
958
        ];
959
        $result = $this->_Parser->parse($input);
960
        $this->assertHtml($expected, $result);
961
    }
962
963
    public function testUploadTypeFile()
964
    {
965
        $input = '[file src=upload]test.txt[/file]';
966
        $expected = [
967
            'a' => [
968
                'href' => '/useruploads/test.txt',
969
                'target' => '_blank',
970
            ],
971
            'test.txt',
972
            '/a'
973
        ];
974
        $result = $this->_Parser->parse($input);
975
        $this->assertHtml($expected, $result);
976
    }
977
978 View Code Duplication
    public function testUploadTypeFileSrcNotValid()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
979
    {
980
        $input = '[file src=foo]test.txt[/file]';
981
        $expected = [
982
            'div' => [
983
                'class' => 'richtext-imessage',
984
            ],
985
        ];
986
        $result = $this->_Parser->parse($input);
987
        $this->assertHtml($expected, $result);
988
    }
989
990
    public function testUploadTypeFileNoSource()
991
    {
992
        $input = '[file]test.txt[/file]';
993
        $result = $this->_Parser->parse($input);
994
        $this->assertHtml($input, $result);
0 ignored issues
show
Documentation introduced by
$input is of type string, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
995
    }
996
997
    public function testSmiliesNoSmiliesInCodeTag()
998
    {
999
        $input = '[code text]:)[/code]';
1000
        $needle = '<img';
1001
        $result = $this->_Parser->parse($input, ['cache' => false]);
1002
        $this->assertNotContains($needle, $result);
1003
    }
1004
1005 View Code Duplication
    public function testCodeNestedTags()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1006
    {
1007
        $input = '[code][b]text[b][/code]';
1008
        $expected = [
1009
            [
1010
                'div' => ['class' => 'geshi-wrapper']
1011
            ],
1012
            'preg:/.*?\[b\]text\[b\].*/',
1013
        ];
1014
        $result = $this->_Parser->parse($input);
1015
        $this->assertHtml($expected, $result);
1016
    }
1017
1018 View Code Duplication
    public function testCodeWhitespace()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1019
    {
1020
        $input = "[code]\ntest\n[/code]";
1021
        $expected = "/>test</";
1022
        $result = $this->_Parser->parse($input);
1023
        $this->assertRegExp($expected, $result);
1024
    }
1025
1026 View Code Duplication
    public function testCodeSimple()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1027
    {
1028
        $input = '[code]text[/code]';
1029
        $result = $this->_Parser->parse($input);
1030
        $expected = 'lang="text"';
1031
        $this->assertContains($expected, $result);
1032
    }
1033
1034 View Code Duplication
    public function testCodeLangAttribute()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1035
    {
1036
        $input = '[code=php]text[/code]';
1037
        $result = $this->_Parser->parse($input);
1038
        $expected = 'lang="php"';
1039
        $this->assertContains($expected, $result);
1040
    }
1041
1042
    /**
1043
     * tests that citation marks are not replaced in code-blocks
1044
     */
1045
    public function testCodeNoCitationMark()
1046
    {
1047
        // [code]<citation mark>[/code] should not be cited
1048
        $input = h(
1049
            "[code]\n" . $this->_Helper->getConfig('quote_symbol') . "\n[/code]"
1050
        );
1051
        $expected = '`span class=.*?richtext-citation`';
1052
        $result = $this->_Parser->parse($input);
1053
        $this->assertNotRegExp($expected, $result);
1054
    }
1055
1056
    public function testCodeDetaginize()
1057
    {
1058
        $input = '[code bash]pre http://example.com post[/code]';
1059
        $result = $this->_Parser->parse($input);
1060
        $this->assertNotContains('autoLink', $result);
1061
    }
1062
1063
    public function testQuote()
1064
    {
1065
        $_qs = $this->MarkupSettings->get('quote_symbol');
1066
        $input = $_qs . ' fo [b]test[/b] ba';
1067
        $result = $this->_Parser->parse($input);
1068
        $expected = [
1069
            'span' => ['class' => 'richtext-citation'],
1070
            $_qs . ' fo ',
1071
            'strong' => [],
1072
            'test',
1073
            '/strong',
1074
            ' ba',
1075
            '/span'
1076
        ];
1077
        $this->assertHtml($expected, $result);
1078
    }
1079
1080 View Code Duplication
    public function testHtml5Video()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1081
    {
1082
        //* setup
1083
        $bbcodeImg = Configure::read('Saito.Settings.bbcode_img');
1084
        Configure::write('Saito.Settings.bbcode_img', true);
1085
1086
        //* @td write video tests
1087
        $url = 'http://example.com/audio.mp4';
1088
        $input = "[video]{$url}[/video]";
1089
        $result = $this->_Parser->parse($input);
1090
        $expected = [
1091
            'video' => [
1092
                'src' => $url,
1093
                'preload' => 'auto',
1094
                'controls' => 'controls',
1095
                'x-webkit-airplay' => 'allow'
1096
            ],
1097
        ];
1098
        $this->assertHtml($expected, $result);
1099
1100
        //* teardown
1101
        Configure::write('Saito.Settings.bbcode_img', $bbcodeImg);
1102
    }
1103
1104 View Code Duplication
    public function testHr()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1105
    {
1106
        $input = '[hr][hr]';
1107
        $expected = '<hr><hr>';
1108
        $result = $this->_Parser->parse($input);
1109
        $this->assertEquals($result, $expected);
1110
    }
1111
1112 View Code Duplication
    public function testHrShort()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1113
    {
1114
        $input = '[---][---]';
1115
        $expected = '<hr><hr>';
1116
        $result = $this->_Parser->parse($input);
1117
        $this->assertEquals($result, $expected);
1118
    }
1119
1120 View Code Duplication
    public function testEmbedNoReplacement()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1121
    {
1122
        $input = '[embed]http://no.provider/unreplaced[/embed]';
1123
1124
        $result = $this->_Parser->parse($input);
1125
1126
        $expected = [
1127
            'div' => [
1128
                'class' => 'js-embed',
1129
                'data-embed' => '{&quot;url&quot;:&quot;http:\/\/no.provider\/unreplaced&quot;}',
1130
                'id' => 'embed-10478631dd9f8f00da95953f63f6e5f3',
1131
            ],
1132
            '/div',
1133
        ];
1134
1135
        $this->assertHtml($expected, $result);
1136
    }
1137
1138
    public function testEmbedDisabledWithoutAutolinking()
1139
    {
1140
        $this->MarkupSettings->setSingle('autolink', false);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Saito\Markup\MarkupSettings as the method setSingle() does only exist in the following sub-classes of Saito\Markup\MarkupSettings: BbcodeParser\Test\Lib\an.../BbcodeParserTest.php$0. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
1141
        $this->MarkupSettings->setSingle('content_embed_active', false);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Saito\Markup\MarkupSettings as the method setSingle() does only exist in the following sub-classes of Saito\Markup\MarkupSettings: BbcodeParser\Test\Lib\an.../BbcodeParserTest.php$0. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
1142
1143
        $url = 'http://foo.bar/baz';
1144
        $input = "[embed]{$url}[/embed]";
1145
1146
        $result = $this->_Parser->parse($input);
1147
1148
        $this->assertHtml($url, $result);
0 ignored issues
show
Documentation introduced by
$url is of type string, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1149
    }
1150
1151
    public function testEmbedDisabledWithAutolinking()
1152
    {
1153
        $this->MarkupSettings->setSingle('autolink', true);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Saito\Markup\MarkupSettings as the method setSingle() does only exist in the following sub-classes of Saito\Markup\MarkupSettings: BbcodeParser\Test\Lib\an.../BbcodeParserTest.php$0. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
1154
        $this->MarkupSettings->setSingle('content_embed_active', false);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Saito\Markup\MarkupSettings as the method setSingle() does only exist in the following sub-classes of Saito\Markup\MarkupSettings: BbcodeParser\Test\Lib\an.../BbcodeParserTest.php$0. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
1155
1156
        $url = 'http://foo.bar/baz';
1157
        $input = "[embed]{$url}[/embed]";
1158
1159
        $result = $this->_Parser->parse($input);
1160
1161
        $expected = [
1162
            'a' => [
1163
                'href' => $url,
1164
                'target' => '_blank',
1165
            ],
1166
            $url,
1167
            '/a',
1168
        ];
1169
1170
        $this->assertHtml($expected, $result);
1171
    }
1172
1173 View Code Duplication
    public function testHtml5Audio()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1174
    {
1175
        //* setup
1176
        $bbcodeImg = Configure::read('Saito.Settings.bbcode_img');
1177
        Configure::write('Saito.Settings.bbcode_img', true);
1178
1179
        //* simple test
1180
        $url = 'http://example.com/audio3.m4a';
1181
        $input = "[audio]{$url}[/audio]";
1182
        $result = $this->_Parser->parse($input);
1183
        $expected = [
1184
            'audio' => [
1185
                'src' => $url,
1186
                'controls' => 'controls',
1187
                'preload' => 'auto',
1188
                'x-webkit-airplay' => 'allow',
1189
            ],
1190
            '/audio',
1191
        ];
1192
        $this->assertHtml($expected, $result);
1193
1194
        //* teardown
1195
        Configure::write('Saito.Settings.bbcode_img', $bbcodeImg);
1196
    }
1197
1198
    /* ******************** Setup ********************** */
1199
1200
    public function setUp()
1201
    {
1202
        Cache::clear();
1203
1204 View Code Duplication
        if (Cache::getConfig('bbcodeParserEmbed') === null) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1205
            Cache::setConfig(
1206
                'bbcodeParserEmbed',
1207
                [
1208
                    'className' => 'File',
1209
                    'prefix' => 'saito_embed-',
1210
                    'path' => CACHE,
1211
                    'groups' => ['embed'],
1212
                    'duration' => '+1 year'
1213
1214
                ]
1215
            );
1216
        }
1217
1218
        if (isset($_SERVER['SERVER_NAME'])) {
1219
            $this->server_name = $_SERVER['SERVER_NAME'];
0 ignored issues
show
Bug introduced by
The property server_name does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
1220
        } else {
1221
            $this->server_name = false;
1222
        }
1223
1224
        if (isset($_SERVER['SERVER_PORT'])) {
1225
            $this->server_port = $_SERVER['SERVER_PORT'];
0 ignored issues
show
Bug introduced by
The property server_port does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
1226
        } else {
1227
            $this->server_port = false;
1228
        }
1229
1230
        $this->autolink = Configure::read('Saito.Settings.autolink');
0 ignored issues
show
Bug introduced by
The property autolink does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
1231
        Configure::write('Saito.Settings.autolink', true);
1232
1233
        $_SERVER['SERVER_NAME'] = 'macnemo.de';
1234
        $_SERVER['SERVER_PORT'] = '80';
1235
1236
        parent::setUp();
1237
1238
        $View = new View();
1239
1240
        //= smiley fixture
1241
        $smiliesFixture = [
1242
            [
1243
                'order' => 1,
1244
                'icon' => 'wink.png',
1245
                'image' => 'wink.png',
1246
                'title' => 'Wink',
1247
                'code' => ';)',
1248
                'type' => 'image'
1249
            ],
1250
            [
1251
                'order' => 2,
1252
                'icon' => 'smile_icon.svg',
1253
                'image' => 'smile_image.svg',
1254
                'title' => 'Smile',
1255
                'code' => ':-)',
1256
                'type' => 'image'
1257
            ],
1258
            [
1259
                'order' => 3,
1260
                'icon' => 'coffee',
1261
                'image' => 'coffee',
1262
                'title' => 'Coffee',
1263
                'code' => '[_]P',
1264
                'type' => 'font'
1265
            ],
1266
        ];
1267
        Cache::write('Saito.Smilies.data', $smiliesFixture);
1268
        $SmileyLoader = new \Saito\Smiley\SmileyLoader();
1269
1270
        //= userlist fixture
1271
        $Userlist = $this->getMockBuilder(UserlistModel::class)
1272
            ->disableOriginalConstructor()
1273
            ->setMethods(['get'])
1274
            ->getMock();
1275
        $Userlist->method('get')->willReturn(['Alice', 'Bobby Junior', 'Dr. No']);
1276
1277
        //= ParserHelper
1278
        $markupSettingsMock = new class extends MarkupSettings {
1279
            public function setSingle(string $key, $value)
1280
            {
1281
                $this->_settings[$key] = $value;
1282
            }
1283
        };
1284
        $this->MarkupSettings = new $markupSettingsMock([
1285
            'UserList' => $Userlist,
1286
            'atBaseUrl' => '/at/',
1287
            'autolink' => true,
1288
            'bbcode_img' => true,
1289
            'content_embed_active' => true,
1290
            'content_embed_media' => true,
1291
            'content_embed_text' => true,
1292
            'hashBaseUrl' => '/hash/',
1293
            'quote_symbol' => '»',
1294
            'smilies' => true,
1295
            'smiliesData' => $SmileyLoader,
1296
            'text_word_maxlength' => 100000,
1297
            'video_domains_allowed' => 'youtube',
1298
            'webroot' => ''
1299
        ]);
1300
        $this->_Helper = $ParserHelper = new ParserHelper($View);
1301
        $ParserHelper->beforeRender(null);
1302
1303
        //= Smiley Renderer
1304
        $this->_Helper->getView()->set('smiliesData', $SmileyLoader);
1305
1306
        //= Parser
1307
        $this->_Parser = new Parser($ParserHelper, $this->MarkupSettings);
1308
    }
1309
1310
    public function tearDown()
1311
    {
1312
        parent::tearDown();
1313
        if ($this->server_name) {
1314
            $_SERVER['SERVER_NAME'] = $this->server_name;
1315
        }
1316
1317
        if ($this->server_name) {
1318
            $_SERVER['SERVER_PORT'] = $this->server_port;
1319
        }
1320
1321
        Configure::write('Saito.Settings.autolink', $this->autolink);
1322
1323
        Cache::clear();
1324
        unset($this->_Parser);
1325
    }
1326
}
1327