Completed
Push — prado-3.3 ( e90646...0b76d5 )
by Fabio
23:37 queued 03:01
created

Parsedown::parse_block_elements()   F

Complexity

Conditions 95
Paths > 20000

Size

Total Lines 658

Duplication

Lines 30
Ratio 4.56 %

Importance

Changes 0
Metric Value
cc 95
nc 1274410
nop 2
dl 30
loc 658
rs 0
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
#
4
#
5
# Parsedown
6
# http://parsedown.org
7
#
8
# (c) Emanuil Rusev
9
# http://erusev.com
10
#
11
# For the full license information, view the LICENSE file that was distributed
12
# with this source code.
13
#
14
#
15
16
class Parsedown
17
{
18
    # Multiton
19
20
    static function instance($name = 'default')
21
    {
22
        if (isset(self::$instances[$name]))
23
        {
24
            return self::$instances[$name];
25
        }
26
27
        $instance = new Parsedown();
28
29
        self::$instances[$name] = $instance;
30
31
        return $instance;
32
    }
33
34
    private static $instances = array();
35
36
    #
37
    # Setters
38
    #
39
40
    # Enables GFM line breaks.
41
42
    function set_breaks_enabled($breaks_enabled)
43
    {
44
        $this->breaks_enabled = $breaks_enabled;
45
46
        return $this;
47
    }
48
49
    private $breaks_enabled = false;
50
51
    #
52
    # Synopsis
53
    #
54
55
    # Markdown is intended to be easy-to-read by humans - those of us who read
56
    # line by line, left to right, top to bottom. In order to take advantage of
57
    # this, Parsedown tries to read in a similar way. It breaks texts into
58
    # lines, it iterates through them and it looks at how they start and relate
59
    # to each other.
60
61
    #
62
    # Methods
63
    #
64
65
    function parse($text)
66
    {
67
        # standardize line breaks
68
        $text = str_replace("\r\n", "\n", $text);
69
        $text = str_replace("\r", "\n", $text);
70
71
        # replace tabs with spaces
72
        $text = str_replace("\t", '    ', $text);
73
74
        # remove surrounding line breaks
75
        $text = trim($text, "\n");
76
77
        # split text into lines
78
        $lines = explode("\n", $text);
79
80
        # convert lines into html
81
        $text = $this->parse_block_elements($lines);
82
83
        # remove trailing line breaks
84
        $text = chop($text, "\n");
85
86
        return $text;
87
    }
88
89
    #
90
    # Private
91
92
    private function parse_block_elements(array $lines, $context = '')
93
    {
94
        $blocks = array();
95
96
        $block = array(
97
            'type' => '',
98
        );
99
100
        foreach ($lines as $line)
101
        {
102
            # context
103
104
            switch ($block['type'])
105
            {
106
                case 'fenced':
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
107
108
                    if ( ! isset($block['closed']))
109
                    {
110
                        if (preg_match('/^[ ]*'.$block['fence'][0].'{3,}[ ]*$/', $line))
111
                        {
112
                            $block['closed'] = true;
113
                        }
114 View Code Duplication
                        else
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...
115
                        {
116
                            if ($block['text'] !== '')
117
                            {
118
                                $block['text'] .= "\n";
119
                            }
120
121
                            $block['text'] .= $line;
122
                        }
123
124
                        continue 2;
125
                    }
126
127
                    break;
128
129
                case 'markup':
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
130
131
                    if ( ! isset($block['closed']))
132
                    {
133
                        if (strpos($line, $block['start']) !== false) # opening tag
134
                        {
135
                            $block['depth']++;
136
                        }
137
138
                        if (strpos($line, $block['end']) !== false) # closing tag
139
                        {
140
                            if ($block['depth'] > 0)
141
                            {
142
                                $block['depth']--;
143
                            }
144
                            else
145
                            {
146
                                $block['closed'] = true;
147
                            }
148
                        }
149
150
                        $block['text'] .= "\n".$line;
151
152
                        continue 2;
153
                    }
154
155
                    break;
156
            }
157
158
            # ~
159
160
            $indentation = 0;
161
162
            while(isset($line[$indentation]) and $line[$indentation] === ' ')
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
163
            {
164
                $indentation++;
165
            }
166
167
            $outdented_line = $indentation > 0 ? ltrim($line) : $line;
168
169
            # blank
170
171
            if ($outdented_line === '')
172
            {
173
                $block['interrupted'] = true;
174
175
                continue;
176
            }
177
178
            # context
179
180
            switch ($block['type'])
181
            {
182
                case 'quote':
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
183
184
                    if ( ! isset($block['interrupted']))
185
                    {
186
                        $line = preg_replace('/^[ ]*>[ ]?/', '', $line);
187
188
                        $block['lines'] []= $line;
189
190
                        continue 2;
191
                    }
192
193
                    break;
194
195
                case 'li':
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
196
197
                    if ($block['indentation'] === $indentation and preg_match('/^'.$block['marker'].'[ ]+(.*)/', $outdented_line, $matches))
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
198
                    {
199
                        unset($block['last']);
200
201
                        $blocks []= $block;
202
203
                        $block['last'] = true;
204
                        $block['lines'] = array($matches[1]);
205
206
                        unset($block['first']);
207
                        unset($block['interrupted']);
208
209
                        continue 2;
210
                    }
211
212
                    if ( ! isset($block['interrupted']))
213
                    {
214
                        $line = preg_replace('/^[ ]{0,'.$block['baseline'].'}/', '', $line);
215
216
                        $block['lines'] []= $line;
217
218
                        continue 2;
219
                    }
220
                    elseif ($line[0] === ' ')
221
                    {
222
                        $block['lines'] []= '';
223
224
                        $line = preg_replace('/^[ ]{0,'.$block['baseline'].'}/', '', $line);
225
226
                        $block['lines'] []= $line;
227
228
                        unset($block['interrupted']);
229
230
                        continue 2;
231
                    }
232
233
                    break;
234
            }
235
236
            # indentation sensitive types
237
238
            switch ($line[0])
239
            {
240
                case ' ':
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
241
242
                    # code
243
244
                    if ($indentation >= 4)
245
                    {
246
                        $code_line = substr($line, 4);
247
248
                        if ($block['type'] === 'code')
249
                        {
250
                            if (isset($block['interrupted']))
251
                            {
252
                                $block['text'] .= "\n";
253
254
                                unset($block['interrupted']);
255
                            }
256
257
                            $block['text'] .= "\n".$code_line;
258
                        }
259
                        else
260
                        {
261
                            $blocks []= $block;
262
263
                            $block = array(
264
                                'type' => 'code',
265
                                'text' => $code_line,
266
                            );
267
                        }
268
269
                        continue 2;
270
                    }
271
272
                    break;
273
274
                case '#':
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
275
276
                    # atx heading (#)
277
278
                    if (isset($line[1]))
279
                    {
280
                        $blocks []= $block;
281
282
                        $level = 1;
283
284
                        while (isset($line[$level]) and $line[$level] === '#')
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
285
                        {
286
                            $level++;
287
                        }
288
289
                        $block = array(
290
                            'type' => 'heading',
291
                            'text' => trim($line, '# '),
292
                            'level' => $level,
293
                        );
294
295
                        continue 2;
296
                    }
297
298
                    break;
299
300
                case '-':
301
                case '=':
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
302
303
                    # setext heading (===)
304
305
                    if ($block['type'] === 'paragraph' and isset($block['interrupted']) === false)
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
306
                    {
307
                        $chopped_line = chop($line);
308
309
                        $i = 1;
310
311
                        while (isset($chopped_line[$i]))
312
                        {
313
                            if ($chopped_line[$i] !== $line[0])
314
                            {
315
                                break 2;
316
                            }
317
318
                            $i++;
319
                        }
320
321
                        $block['type'] = 'heading';
322
323
                        $block['level'] = $line[0] === '-' ? 2 : 1;
324
325
                        continue 2;
326
                    }
327
328
                    break;
329
            }
330
331
            # indentation insensitive types
332
333
            switch ($outdented_line[0])
334
            {
335
                case '<':
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
336
337
                    $position = strpos($outdented_line, '>');
338
339
                    if ($position > 1)
340
                    {
341
                        $substring = substr($outdented_line, 1, $position - 1);
342
343
                        $substring = chop($substring);
344
345
                        if (substr($substring, -1) === '/')
346
                        {
347
                            $is_self_closing = true;
348
349
                            $substring = substr($substring, 0, -1);
350
                        }
351
352
                        $position = strpos($substring, ' ');
353
354
                        if ($position)
355
                        {
356
                            $name = substr($substring, 0, $position);
357
                        }
358
                        else
359
                        {
360
                            $name = $substring;
361
                        }
362
363
                        if ( ! ctype_alpha($name))
364
                        {
365
                            break;
366
                        }
367
368
                        if (in_array($name, self::$text_level_elements))
369
                        {
370
                            break;
371
                        }
372
373
                        $blocks []= $block;
374
375
                        if (isset($is_self_closing))
376
                        {
377
                            $block = array(
378
                                'type' => 'self-closing tag',
379
                                'text' => $outdented_line,
380
                            );
381
382
                            unset($is_self_closing);
383
384
                            continue 2;
385
                        }
386
387
                        $block = array(
388
                            'type' => 'markup',
389
                            'text' => $outdented_line,
390
                            'start' => '<'.$name.'>',
391
                            'end' => '</'.$name.'>',
392
                            'depth' => 0,
393
                        );
394
395
                        if (strpos($outdented_line, $block['end']))
396
                        {
397
                            $block['closed'] = true;
398
                        }
399
400
                        continue 2;
401
                    }
402
403
                    break;
404
405
                case '>':
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
406
407
                    # quote
408
409
                    if (preg_match('/^>[ ]?(.*)/', $outdented_line, $matches))
410
                    {
411
                        $blocks []= $block;
412
413
                        $block = array(
414
                            'type' => 'quote',
415
                            'lines' => array(
416
                                $matches[1],
417
                            ),
418
                        );
419
420
                        continue 2;
421
                    }
422
423
                    break;
424
425
                case '[':
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
426
427
                    # reference
428
429
                    $position = strpos($outdented_line, ']:');
430
431
                    if ($position)
432
                    {
433
                        $reference = array();
434
435
                        $label = substr($outdented_line, 1, $position - 1);
436
                        $label = strtolower($label);
437
438
                        $substring = substr($outdented_line, $position + 2);
439
                        $substring = trim($substring);
440
441
                        if ($substring === '')
442
                        {
443
                            break;
444
                        }
445
446
                        if ($substring[0] === '<')
447
                        {
448
                            $position = strpos($substring, '>');
449
450
                            if ($position === false)
451
                            {
452
                                break;
453
                            }
454
455
                            $reference['»'] = substr($substring, 1, $position - 1);
456
457
                            $substring = substr($substring, $position + 1);
458
                        }
459
                        else
460
                        {
461
                            $position = strpos($substring, ' ');
462
463
                            if ($position === false)
464
                            {
465
                                $reference['»'] = $substring;
466
467
                                $substring = false;
468
                            }
469
                            else
470
                            {
471
                                $reference['»'] = substr($substring, 0, $position);
472
473
                                $substring = substr($substring, $position + 1);
474
                            }
475
                        }
476
477
                        if ($substring !== false)
478
                        {
479
                            if ($substring[0] !== '"' and $substring[0] !== "'" and $substring[0] !== '(')
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
480
                            {
481
                                break;
482
                            }
483
484
                            $last_char = substr($substring, -1);
485
486
                            if ($last_char !== '"' and $last_char !== "'" and $last_char !== ')')
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
487
                            {
488
                                break;
489
                            }
490
491
                            $reference['#'] = substr($substring, 1, -1);
492
                        }
493
494
                        $this->reference_map[$label] = $reference;
495
496
                        continue 2;
497
                    }
498
499
                    break;
500
501
                case '`':
502
                case '~':
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
503
504
                    # fenced code block
505
506
                    if (preg_match('/^([`]{3,}|[~]{3,})[ ]*(\S+)?[ ]*$/', $outdented_line, $matches))
507
                    {
508
                        $blocks []= $block;
509
510
                        $block = array(
511
                            'type' => 'fenced',
512
                            'text' => '',
513
                            'fence' => $matches[1],
514
                        );
515
516
                        if (isset($matches[2]))
517
                        {
518
                            $block['language'] = $matches[2];
519
                        }
520
521
                        continue 2;
522
                    }
523
524
                    break;
525
526
                case '*':
527
                case '+':
528
                case '-':
529
                case '_':
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
530
531
                    # hr
532
533
                    if (preg_match('/^([-*_])([ ]{0,2}\1){2,}[ ]*$/', $outdented_line))
534
                    {
535
                        $blocks []= $block;
536
537
                        $block = array(
538
                            'type' => 'rule',
539
                        );
540
541
                        continue 2;
542
                    }
543
544
                    # li
545
546
                    if (preg_match('/^([*+-][ ]+)(.*)/', $outdented_line, $matches))
547
                    {
548
                        $blocks []= $block;
549
550
                        $baseline = $indentation + strlen($matches[1]);
551
552
                        $block = array(
553
                            'type' => 'li',
554
                            'indentation' => $indentation,
555
                            'baseline' => $baseline,
556
                            'marker' => '[*+-]',
557
                            'first' => true,
558
                            'last' => true,
559
                            'lines' => array(),
560
                        );
561
562
                        $block['lines'] []= preg_replace('/^[ ]{0,4}/', '', $matches[2]);
563
564
                        continue 2;
565
                    }
566
            }
567
568
            # li
569
570
            if ($outdented_line[0] <= '9' and preg_match('/^(\d+[.][ ]+)(.*)/', $outdented_line, $matches))
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
571
            {
572
                $blocks []= $block;
573
574
                $baseline = $indentation + strlen($matches[1]);
575
576
                $block = array(
577
                    'type' => 'li',
578
                    'indentation' => $indentation,
579
                    'baseline' => $baseline,
580
                    'marker' => '\d+[.]',
581
                    'first' => true,
582
                    'last' => true,
583
                    'ordered' => true,
584
                    'lines' => array(),
585
                );
586
587
                $block['lines'] []= preg_replace('/^[ ]{0,4}/', '', $matches[2]);
588
589
                continue;
590
            }
591
592
            # paragraph
593
594
            if ($block['type'] === 'paragraph')
595
            {
596
                if (isset($block['interrupted']))
597
                {
598
                    $blocks []= $block;
599
600
                    $block['text'] = $line;
601
602
                    unset($block['interrupted']);
603
                }
604 View Code Duplication
                else
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...
605
                {
606
                    if ($this->breaks_enabled)
607
                    {
608
                        $block['text'] .= '  ';
609
                    }
610
611
                    $block['text'] .= "\n".$line;
612
                }
613
            }
614
            else
615
            {
616
                $blocks []= $block;
617
618
                $block = array(
619
                    'type' => 'paragraph',
620
                    'text' => $line,
621
                );
622
            }
623
        }
624
625
        $blocks []= $block;
626
627
        unset($blocks[0]);
628
629
        # $blocks » HTML
630
631
        $markup = '';
632
633
        foreach ($blocks as $block)
634
        {
635
            switch ($block['type'])
636
            {
637
                case 'paragraph':
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
638
639
                    $text = $this->parse_span_elements($block['text']);
640
641
                    if ($context === 'li' and $markup === '')
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
642
                    {
643
                        if (isset($block['interrupted']))
644
                        {
645
                            $markup .= "\n".'<p>'.$text.'</p>'."\n";
646
                        }
647
                        else
648
                        {
649
                            $markup .= $text;
650
651
                            if (isset($blocks[2]))
652
                            {
653
                                $markup .= "\n";
654
                            }
655
                        }
656
                    }
657
                    else
658
                    {
659
                        $markup .= '<p>'.$text.'</p>'."\n";
660
                    }
661
662
                    break;
663
664
                case 'quote':
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
665
666
                    $text = $this->parse_block_elements($block['lines']);
667
668
                    $markup .= '<blockquote>'."\n".$text.'</blockquote>'."\n";
669
670
                    break;
671
672
                case 'code':
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
673
674
                    $text = htmlspecialchars($block['text'], ENT_NOQUOTES, 'UTF-8');
675
676
                    $markup .= '<pre><code>'.$text.'</code></pre>'."\n";
677
678
                    break;
679
680
                case 'fenced':
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
681
682
                    $text = htmlspecialchars($block['text'], ENT_NOQUOTES, 'UTF-8');
683
684
                    $markup .= '<pre><code';
685
686
                    if (isset($block['language']))
687
                    {
688
                        $markup .= ' class="language-'.$block['language'].'"';
689
                    }
690
691
                    $markup .= '>'.$text.'</code></pre>'."\n";
692
693
                    break;
694
695
                case 'heading':
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
696
697
                    $text = $this->parse_span_elements($block['text']);
698
699
                    $markup .= '<h'.$block['level'].'>'.$text.'</h'.$block['level'].'>'."\n";
700
701
                    break;
702
703
                case 'rule':
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
704
705
                    $markup .= '<hr />'."\n";
706
707
                    break;
708
709
                case 'li':
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
710
711 View Code Duplication
                    if (isset($block['first']))
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...
712
                    {
713
                        $type = isset($block['ordered']) ? 'ol' : 'ul';
714
715
                        $markup .= '<'.$type.'>'."\n";
716
                    }
717
718
                    if (isset($block['interrupted']) and ! isset($block['last']))
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
719
                    {
720
                        $block['lines'] []= '';
721
                    }
722
723
                    $text = $this->parse_block_elements($block['lines'], 'li');
724
725
                    $markup .= '<li>'.$text.'</li>'."\n";
726
727 View Code Duplication
                    if (isset($block['last']))
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...
728
                    {
729
                        $type = isset($block['ordered']) ? 'ol' : 'ul';
730
731
                        $markup .= '</'.$type.'>'."\n";
732
                    }
733
734
                    break;
735
736
                case 'markup':
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
737
738
                    $markup .= $block['text']."\n";
739
740
                    break;
741
742
                default:
0 ignored issues
show
Coding Style introduced by
The default body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a default statement must start on the line immediately following the statement.

switch ($expr) {
    default:
        doSomething(); //right
        break;
}


switch ($expr) {
    default:

        doSomething(); //wrong
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
743
744
                    $markup .= $block['text']."\n";
745
            }
746
        }
747
748
        return $markup;
749
    }
750
751
    private function parse_span_elements($text, $markers = array("  \n", '![', '&', '*', '<', '[', '\\', '_', '`', 'http', '~~'))
752
    {
753
        if (isset($text[1]) === false or $markers === array())
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
754
        {
755
            return $text;
756
        }
757
758
        # ~
759
760
        $markup = '';
761
762
        while ($markers)
0 ignored issues
show
Bug Best Practice introduced by
The expression $markers of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
763
        {
764
            $closest_marker = null;
765
            $closest_marker_index = 0;
766
            $closest_marker_position = null;
767
768
            foreach ($markers as $index => $marker)
769
            {
770
                $marker_position = strpos($text, $marker);
771
772
                if ($marker_position === false)
773
                {
774
                    unset($markers[$index]);
775
776
                    continue;
777
                }
778
779
                if ($closest_marker === null or $marker_position < $closest_marker_position)
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
780
                {
781
                    $closest_marker = $marker;
782
                    $closest_marker_index = $index;
783
                    $closest_marker_position = $marker_position;
784
                }
785
            }
786
787
            # ~
788
789
            if ($closest_marker === null or isset($text[$closest_marker_position + 1]) === false)
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
790
            {
791
                $markup .= $text;
792
793
                break;
794
            }
795
            else
796
            {
797
                $markup .= substr($text, 0, $closest_marker_position);
798
            }
799
800
            $text = substr($text, $closest_marker_position);
801
802
            # ~
803
804
            unset($markers[$closest_marker_index]);
805
806
            # ~
807
808
            switch ($closest_marker)
809
            {
810
                case "  \n":
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
811
812
                    $markup .= '<br />'."\n";
813
814
                    $offset = 3;
815
816
                    break;
817
818
                case '![':
819
                case '[':
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
820
821
                    if (strpos($text, ']') and preg_match('/\[((?:[^][]|(?R))*)\]/', $text, $matches))
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
822
                    {
823
                        $element = array(
824
                            '!' => $text[0] === '!',
825
                            'a' => $matches[1],
826
                        );
827
828
                        $offset = strlen($matches[0]);
829
830
                        if ($element['!'])
831
                        {
832
                            $offset++;
833
                        }
834
835
                        $remaining_text = substr($text, $offset);
836
837
                        if ($remaining_text[0] === '(' and preg_match('/\([ ]*(.*?)(?:[ ]+[\'"](.+?)[\'"])?[ ]*\)/', $remaining_text, $matches))
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
838
                        {
839
                            $element['»'] = $matches[1];
840
841
                            if (isset($matches[2]))
842
                            {
843
                                $element['#'] = $matches[2];
844
                            }
845
846
                            $offset += strlen($matches[0]);
847
                        }
848
                        elseif ($this->reference_map)
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->reference_map of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
849
                        {
850
                            $reference = $element['a'];
851
852
                            if (preg_match('/^\s*\[(.*?)\]/', $remaining_text, $matches))
853
                            {
854
                                $reference = $matches[1] ? $matches[1] : $element['a'];
855
856
                                $offset += strlen($matches[0]);
857
                            }
858
859
                            $reference = strtolower($reference);
860
861
                            if (isset($this->reference_map[$reference]))
862
                            {
863
                                $element['»'] = $this->reference_map[$reference]['»'];
864
865
                                if (isset($this->reference_map[$reference]['#']))
866
                                {
867
                                    $element['#'] = $this->reference_map[$reference]['#'];
868
                                }
869
                            }
870
                            else
871
                            {
872
                                unset($element);
873
                            }
874
                        }
875
                        else
876
                        {
877
                            unset($element);
878
                        }
879
                    }
880
881
                    if (isset($element))
882
                    {
883
                        $element['»'] = str_replace('&', '&amp;', $element['»']);
884
                        $element['»'] = str_replace('<', '&lt;', $element['»']);
885
886
                        if ($element['!'])
887
                        {
888
                            $markup .= '<img alt="'.$element['a'].'" src="'.$element['»'].'"';
889
890
                            if (isset($element['#']))
891
                            {
892
                                $markup .= ' title="'.$element['#'].'"';
893
                            }
894
895
                            $markup .= ' />';
896
                        }
897
                        else
898
                        {
899
                            $element['a'] = $this->parse_span_elements($element['a'], $markers);
900
901
                            $markup .= '<a href="'.$element['»'].'"';
902
903
                            if (isset($element['#']))
904
                            {
905
                                $markup .= ' title="'.$element['#'].'"';
906
                            }
907
908
                            $markup .= '>'.$element['a'].'</a>';
909
                        }
910
911
                        unset($element);
912
                    }
913
                    else
914
                    {
915
                        $markup .= $closest_marker;
916
917
                        $offset = $closest_marker === '![' ? 2 : 1;
918
                    }
919
920
                    break;
921
922
                case '&':
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
923
924
                    if (preg_match('/^&#?\w+;/', $text, $matches))
925
                    {
926
                        $markup .= $matches[0];
927
928
                        $offset = strlen($matches[0]);
929
                    }
930
                    else
931
                    {
932
                        $markup .= '&amp;';
933
934
                        $offset = 1;
935
                    }
936
937
                    break;
938
939
                case '*':
940
                case '_':
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
941
942
                    if ($text[1] === $closest_marker and preg_match(self::$strong_regex[$closest_marker], $text, $matches))
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
943
                    {
944
                        $markers[] = $closest_marker;
945
                        $matches[1] = $this->parse_span_elements($matches[1], $markers);
946
947
                        $markup .= '<strong>'.$matches[1].'</strong>';
948
                    }
949
                    elseif (preg_match(self::$em_regex[$closest_marker], $text, $matches))
950
                    {
951
                        $markers[] = $closest_marker;
952
                        $matches[1] = $this->parse_span_elements($matches[1], $markers);
953
954
                        $markup .= '<em>'.$matches[1].'</em>';
955
                    }
956
957
                    if (isset($matches) and $matches)
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
958
                    {
959
                        $offset = strlen($matches[0]);
960
                    }
961
                    else
962
                    {
963
                        $markup .= $closest_marker;
964
965
                        $offset = 1;
966
                    }
967
968
                    break;
969
970
                case '<':
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
971
972
                    if (strpos($text, '>') !== false)
973
                    {
974
                        if ($text[1] === 'h' and preg_match('/^<(https?:[\/]{2}[^\s]+?)>/i', $text, $matches))
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
975
                        {
976
                            $element_url = $matches[1];
977
                            $element_url = str_replace('&', '&amp;', $element_url);
978
                            $element_url = str_replace('<', '&lt;', $element_url);
979
980
                            $markup .= '<a href="'.$element_url.'">'.$element_url.'</a>';
981
982
                            $offset = strlen($matches[0]);
983
                        }
984
                        elseif (strpos($text, '@') > 1 and preg_match('/<(\S+?@\S+?)>/', $text, $matches))
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
985
                        {
986
                            $markup .= '<a href="mailto:'.$matches[1].'">'.$matches[1].'</a>';
987
988
                            $offset = strlen($matches[0]);
989
                        }
990
                        elseif (preg_match('/^<\/?\w.*?>/', $text, $matches))
991
                        {
992
                            $markup .= $matches[0];
993
994
                            $offset = strlen($matches[0]);
995
                        }
996
                        else
997
                        {
998
                            $markup .= '&lt;';
999
1000
                            $offset = 1;
1001
                        }
1002
                    }
1003
                    else
1004
                    {
1005
                        $markup .= '&lt;';
1006
1007
                        $offset = 1;
1008
                    }
1009
1010
                    break;
1011
1012
                case '\\':
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
1013
1014
                    if (in_array($text[1], self::$special_characters))
1015
                    {
1016
                        $markup .= $text[1];
1017
1018
                        $offset = 2;
1019
                    }
1020
                    else
1021
                    {
1022
                        $markup .= '\\';
1023
1024
                        $offset = 1;
1025
                    }
1026
1027
                    break;
1028
1029
                case '`':
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
1030
1031
                    if (preg_match('/^(`+)[ ]*(.+?)[ ]*(?<!`)\1(?!`)/', $text, $matches))
1032
                    {
1033
                        $element_text = $matches[2];
1034
                        $element_text = htmlspecialchars($element_text, ENT_NOQUOTES, 'UTF-8');
1035
1036
                        $markup .= '<code>'.$element_text.'</code>';
1037
1038
                        $offset = strlen($matches[0]);
1039
                    }
1040
                    else
1041
                    {
1042
                        $markup .= '`';
1043
1044
                        $offset = 1;
1045
                    }
1046
1047
                    break;
1048
1049
                case 'http':
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
1050
1051
                    if (preg_match('/^https?:[\/]{2}[^\s]+\b\/*/ui', $text, $matches))
1052
                    {
1053
                        $element_url = $matches[0];
1054
                        $element_url = str_replace('&', '&amp;', $element_url);
1055
                        $element_url = str_replace('<', '&lt;', $element_url);
1056
1057
                        $markup .= '<a href="'.$element_url.'">'.$element_url.'</a>';
1058
1059
                        $offset = strlen($matches[0]);
1060
                    }
1061
                    else
1062
                    {
1063
                        $markup .= 'http';
1064
1065
                        $offset = 4;
1066
                    }
1067
1068
                    break;
1069
1070
                case '~~':
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
1071
1072
                    if (preg_match('/^~~(?=\S)(.+?)(?<=\S)~~/', $text, $matches))
1073
                    {
1074
                        $matches[1] = $this->parse_span_elements($matches[1], $markers);
1075
1076
                        $markup .= '<del>'.$matches[1].'</del>';
1077
1078
                        $offset = strlen($matches[0]);
1079
                    }
1080
                    else
1081
                    {
1082
                        $markup .= '~~';
1083
1084
                        $offset = 2;
1085
                    }
1086
1087
                    break;
1088
            }
1089
1090
            if (isset($offset))
1091
            {
1092
                $text = substr($text, $offset);
1093
            }
1094
1095
            $markers[$closest_marker_index] = $closest_marker;
1096
        }
1097
1098
        return $markup;
1099
    }
1100
1101
    #
1102
    # Fields
1103
    #
1104
1105
    private $reference_map = array();
1106
1107
    #
1108
    # Read-only
1109
1110
    private static $strong_regex = array(
1111
        '*' => '/^[*]{2}((?:[^*]|[*][^*]*[*])+?)[*]{2}(?![*])/s',
1112
        '_' => '/^__((?:[^_]|_[^_]*_)+?)__(?!_)/us',
1113
    );
1114
1115
    private static $em_regex = array(
1116
        '*' => '/^[*]((?:[^*]|[*][*][^*]+?[*][*])+?)[*](?![*])/s',
1117
        '_' => '/^_((?:[^_]|__[^_]*__)+?)_(?!_)\b/us',
1118
    );
1119
1120
    private static $special_characters = array(
1121
        '\\', '`', '*', '_', '{', '}', '[', ']', '(', ')', '>', '#', '+', '-', '.', '!',
1122
    );
1123
1124
    private static $text_level_elements = array(
1125
        'a', 'br', 'bdo', 'abbr', 'blink', 'nextid', 'acronym', 'basefont',
1126
        'b', 'em', 'big', 'cite', 'small', 'spacer', 'listing',
1127
        'i', 'rp', 'sub', 'code',          'strike', 'marquee',
1128
        'q', 'rt', 'sup', 'font',          'strong',
1129
        's', 'tt', 'var', 'mark',
1130
        'u', 'xm', 'wbr', 'nobr',
1131
                          'ruby',
1132
                          'span',
1133
                          'time',
1134
    );
1135
}
1136