TShortcode   A
last analyzed

Complexity

Total Complexity 40

Size/Duplication

Total Lines 549
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 0

Test Coverage

Coverage 36.13%

Importance

Changes 0
Metric Value
wmc 40
lcom 1
cbo 0
dl 0
loc 549
ccs 43
cts 119
cp 0.3613
rs 9.2
c 0
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
A shortCodeInit() 0 18 3
B shortCodeYoutube() 0 39 6
A shortCodeCodepen() 0 39 4
C shortCodeFigure() 0 51 10
A shortCodeAsciinema() 0 28 4
A shortCodeBook() 0 27 2
C shortCode() 0 93 11

How to fix   Complexity   

Complex Class

Complex classes like TShortcode often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use TShortcode, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Anax\TextFilter;
4
5
/**
6
 * Shortcode to format when working with text.
7
 *
8
 */
9
trait TShortcode
10
{
11
    /**
12
     * Shortcode to quicker format text as HTML.
13
     *
14
     * @param string $text text to be converted.
15
     *
16
     * @return string the formatted text.
17
     */
18 1
    public function shortCode($text)
19
    {
20
        /* Needs PHP 7
21
        $patternsAndCallbacks = [
22
            "/\[(FIGURE)[\s+](.+)\]/" => function ($match) {
23
                return self::ShortCodeFigure($matches[2]);
24
            },
25
            "/(```([\w]*))\n([^`]*)```[\n]{1}/s" => function ($match) {
26
                return $this->syntaxHighlightGeSHi($matches[3], $matches[2]);
27
            },
28
        ];
29
30
        return preg_replace_callback_array($patternsAndCallbacks, $text);
31
        */
32
33
        $patterns = [
34 1
            "/\[(FIGURE)[\s+](.+)\]/",
35
            //'/\[(YOUTUBE) src=(.+) width=(.+) caption=(.+)\]/',
36
            "/\[(YOUTUBE)[\s+](.+)\]/",
37
            "/\[(CODEPEN)[\s+](.+)\]/",
38
            "/\[(ASCIINEMA)[\s+](.+)\]/",
39
            "/\[(BOOK)[\s+](.+)\]/",
40
            //"/(```)([\w]*)\n([.]*)```[\n]{1}/s",
41
            "/(```)([\w]*)\n(.*?)```\n/s",
42
            '/\[(INFO)\]/',
43
            '/\[(\/INFO)\]/',
44
            '/\[(WARNING)\]/',
45
            '/\[(\/WARNING)\]/',
46
        ];
47
48 1
        return preg_replace_callback(
49 1
            $patterns,
50
            function ($matches) {
51 1
                switch ($matches[1]) {
52 1
                    case "FIGURE":
53 1
                        return self::shortCodeFigure($matches[2]);
54
                    break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
55
56
                    case "YOUTUBE":
57
                        return self::shortCodeYoutube($matches[2]);
58
                    break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
59
60
                    case "CODEPEN":
61
                        return self::shortCodeCodepen($matches[2]);
62
                    break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
63
64
                    case "ASCIINEMA":
65
                        return self::shortCodeAsciinema($matches[2]);
66
                    break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
67
68
                    case "BOOK":
69
                        return self::shortCodeBook($matches[2]);
70
                    break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
71
72
                    case "```":
73
                        //return $this->syntaxHighlightGeSHi($matches[3], $matches[2]);
74
                        return $this->syntaxHighlightJs($matches[3], $matches[2]);
0 ignored issues
show
Bug introduced by
It seems like syntaxHighlightJs() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
75
                    break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
76
77
                    case 'INFO':
78
                        return <<<EOD
79
<div class="info">
80
    <span class="icon fa-stack fa-lg">
81
        <i class="fa fa-circle fa-stack-2x"></i>
82
        <i class="fa fa-info fa-stack-1x fa-inverse" aria-hidden="true"></i>
83
    </span>
84
    <div markdown=1>
85
EOD;
86
                        break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
87
88
                    case 'WARNING':
89
                        return <<<EOD
90
<div class="warning">
91
    <span class="icon fa-stack fa-lg">
92
        <i class="fa fa-circle fa-stack-2x"></i>
93
        <i class="fa fa-exclamation-triangle fa-stack-1x fa-inverse" aria-hidden="true"></i>
94
    </span>
95
    <div markdown=1>
96
EOD;
97
                        break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
98
99
                    case '/INFO':
100
                    case '/WARNING':
101
                        return "</div></div>";
102
                        break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
103
104
                    default:
105
                        return "{$matches[1]} is unknown shortcode.";
106
                }
107 1
            },
108 1
            $text
109
        );
110
    }
111
112
113
114
    /**
115
     * Init shortcode handling by preparing the option list to an array,
116
     * for those using arguments.
117
     *
118
     * @param string $options for the shortcode.
119
     *
120
     * @return array with all the options.
121
     */
122 1
    public static function shortCodeInit($options)
123
    {
124 1
        preg_match_all('/[a-zA-Z0-9]+="[^"]+"|\S+/', $options, $matches);
125
126 1
        $res = array();
127 1
        foreach ($matches[0] as $match) {
128 1
            $pos = strpos($match, '=');
129 1
            if ($pos === false) {
130
                $res[$match] = true;
131
            } else {
132 1
                $key = substr($match, 0, $pos);
133 1
                $val = trim(substr($match, $pos+1), '"');
134 1
                $res[$key] = $val;
135
            }
136
        }
137
138 1
        return $res;
139
    }
140
141
142
143
    /**
144
     * Shortcode for [YOUTUBE].
145
     *
146
     * Usage example: [YOUTUBE src=id-for-the-tube width=630 caption=""]
147
     *
148
     * @param string $options for the shortcode.
149
     *
150
     * @return array with all the options.
151
     */
152
    public static function shortCodeYoutube($options)
153
    {
154
        $options= array_merge(
155
            [
156
                "id"    => null,
157
                "class" => null,
158
                "src" => null,
159
                "list" => null,
160
                "time" => null,
161
                "width" => 600,
162
                "ratio" => 16/9,
163
                "caption" => null,
164
            ],
165
            self::ShortCodeInit($options)
166
        );
167
        extract($options, EXTR_SKIP);
168
169
        $id = $id ? " id=\"$id\"" : null;
170
        $class = $class ? " class=\"figure $class\"" : " class=\"figure\"";
171
        $list = $list ? "?listType=playlist&amp;list=$list" : null;
172
        $time = $time ? "#t=$time" : null;
173
        $height = ceil($width / $ratio);
174
175
        //$caption = t("Figure: !CAPTION", ["!CAPTION" => $caption]);
176
        if ($caption) {
177
            $caption = "<figcaption markdown=1>{$caption}</figcaption>";
178
        }
179
180
        // @codingStandardsIgnoreStart
181
        $html = <<<EOD
182
<figure{$id}{$class}>
183
<iframe width="$width" height="$height" src="https://www.youtube.com/embed/{$src}{$list}{$time}" frameborder="0" allowfullscreen></iframe>
184
{$caption}
185
</figure>
186
EOD;
187
        // @codingStandardsIgnoreEnd
188
189
        return $html;
190
    }
191
192
193
194
    /**
195
     * Shortcode for [CODEPEN].
196
     *
197
     * Usage example: [CODEPEN src=id-for-the-tube width=630 caption=""]
198
     *
199
     * @param string $options for the shortcode.
200
     *
201
     * @return array with all the options.
202
     */
203
    public static function shortCodeCodepen($options)
204
    {
205
        $options= array_merge(
206
            [
207
                "id"    => null,
208
                "class" => null,
209
                "src" => null,
210
                "user" => null,
211
                "title" => null,
212
                "tab" => "result",
213
                "theme" => 0,
214
                "height" => 300,
215
                "width" => "100%",
216
                "caption" => null,
217
            ],
218
            self::ShortCodeInit($options)
219
        );
220
        extract($options, EXTR_SKIP);
221
222
        $id = $id ? " id=\"$id\"" : null;
223
        $class = $class ? " class=\"figure figure-codepen $class\"" : " class=\"figure figure-codepen\"";
224
225
        //$caption = t("Figure: !CAPTION", ["!CAPTION" => $caption]);
226
        if ($caption) {
227
            $caption = "<figcaption markdown=1>{$caption}</figcaption>";
228
        }
229
230
        // @codingStandardsIgnoreStart
231
        $html = <<<EOD
232
<figure{$id}{$class} width="$width">
233
<p data-height="$height" data-theme-id="$theme" data-slug-hash="$src" data-default-tab="$tab" data-user="$user" data-embed-version="2" data-pen-title="$title" class="codepen">See the <a href="https://codepen.io/$user/pen/$src/">Pen</a> on <a href="https://codepen.io">CodePen</a>.</p>
234
{$caption}
235
</figure>
236
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>
237
EOD;
238
        // @codingStandardsIgnoreEnd
239
240
        return $html;
241
    }
242
243
244
245
    /**
246
     * Shortcode for <figure>.
247
     *
248
     * Usage example: [FIGURE src="img/home/me.jpg" caption="Me" alt="Bild på mig" nolink="nolink"]
249
     *
250
     * @param string $options for the shortcode.
251
     *
252
     * @return array with all the options.
253
     */
254 1
    public static function shortCodeFigure($options)
255
    {
256
        // Merge incoming options with default and expose as variables
257 1
        $options= array_merge(
258
            [
259 1
                "id"    => null,
260
                "class" => null,
261
                "src"   => null,
262
                "title" => null,
263
                "alt"   => null,
264
                "caption" => null,
265
                "href"  => null,
266
                "nolink" => false,
267
            ],
268 1
            self::ShortCodeInit($options)
269
        );
270 1
        extract($options, EXTR_SKIP);
271
272 1
        $id = $id ? " id=\"$id\"" : null;
273 1
        $class = $class ? " class=\"figure $class\"" : " class=\"figure\"";
274 1
        $title = $title ? " title=\"$title\"" : null;
275
276 1
        if (!$alt && $caption) {
277 1
            $alt = $caption;
278
        }
279
280 1
        if (!$href) {
281 1
            $pos = strpos($src, "?");
282 1
            $href = $pos ? substr($src, 0, $pos) : $src;
283
        }
284
285 1
        $start = null;
286 1
        $end = null;
287 1
        if (!$nolink) {
288 1
            $start = "<a href=\"{$href}\">";
289 1
            $end = "</a>";
290
        }
291
292 1
        if ($caption) {
293 1
            $caption = "<figcaption markdown=1>{$caption}</figcaption>";
294
        }
295
296
        $html = <<<EOD
297 1
<figure{$id}{$class}>
298 1
{$start}<img src="{$src}" alt="{$alt}"{$title}/>{$end}
299 1
{$caption}
300
</figure>
301
EOD;
302
303 1
        return $html;
304
    }
305
306
307
308
    /**
309
     * Shortcode for [asciinema].
310
     *
311
     * @param string $code the code to process.
0 ignored issues
show
Bug introduced by
There is no parameter named $code. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
312
     * @param string $options for the shortcode.
313
     * @return array with all the options.
314
     */
315
    public static function shortCodeAsciinema($options)
316
    {
317
        // Merge incoming options with default and expose as variables
318
        $options= array_merge(
319
            [
320
                "id" => null,
321
                "class" => null,
322
                "src" => null,
323
                "title" => null,
324
                "caption" => null,
325
            ],
326
            self::ShortCodeInit($options)
327
        );
328
        extract($options, EXTR_SKIP);
329
330
        $id = $id ? " id=\"$id\"" : null;
331
        $class = $class ? " class=\"figure asciinema $class\"" : " class=\"figure asciinema\"";
332
        $title = $title ? " title=\"$title\"" : null;
333
334
        $html = <<<EOD
335
<figure{$id}{$class}$title>
336
<script type="text/javascript" src="https://asciinema.org/a/{$src}.js" id="asciicast-{$src}" async></script>
337
<figcaption markdown=1>{$caption}</figcaption>
338
</figure>
339
EOD;
340
341
        return $html;
342
    }
343
344
345
346
    /**
347
     * Shortcode for [book].
348
     *
349
     * @param string $code the code to process.
0 ignored issues
show
Bug introduced by
There is no parameter named $code. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
350
     * @param string $options for the shortcode.
351
     * @return array with all the options.
352
     */
353
    public static function shortCodeBook($options)
354
    {
355
        // Merge incoming options with default and expose as variables
356
        $options= array_merge(
357
            [
358
                "isbn" => null,
359
            ],
360
            self::ShortCodeInit($options)
361
        );
362
        extract($options, EXTR_SKIP);
363
364
        $stores = [
365
            "BTH" => "http://bth.summon.serialssolutions.com/?#!/search?ho=t&amp;q={$isbn}",
366
            "Libris" => "http://libris.kb.se/hitlist?q={$isbn}",
367
            "Google Books" => "http://books.google.com/books?q={$isbn}",
368
            "Bokus" => "http://www.bokus.com/bok/{$isbn}",
369
            "Adlibris" => "http://www.adlibris.com/se/product.aspx?isbn={$isbn}",
370
            "Amazon" => "http://www.amazon.com/s/ref=nb_ss?url=field-keywords={$isbn}",
371
            "Barnes&Noble" => "http://search.barnesandnoble.com/booksearch/ISBNInquiry.asp?r=1&IF=N&EAN={$isbn}",
372
        ];
373
374
        $html = null;
375
        foreach ($stores as $key => $val) {
376
            $html .= "<a href='$val'>$key</a> &bull; ";
377
        }
378
        return substr($html, 0, -8);
379
    }
380
381
382
383
    /**
384
     * Shortcode for including a SVG-image inside a <figure>.
385
     *
386
     * @param string $code the code to process.
387
     * @param string $options for the shortcode.
388
     * @return array with all the options.
389
     */
390
/*    public static function ShortCodeSVGFigure($options) {
391
        // Merge incoming options with default and expose as variables
392
        $options= array_merge(
393
            [
394
                "id"    => null,
395
                "class" => null,
396
                "src"   => null,
397
                "title" => null,
398
                "alt"   => null,
399
                "caption" => null,
400
                "href"  => null,
401
                "nolink" => false,
402
                //'path' => null,
403
            ],
404
            self::ShortCodeInit($options)
405
        );
406
        extract($options, EXTR_SKIP);
407
408
        $id = $id ? " id=\"$id\"" : null;
409
        $class = $class ? " class=\"figure $class\"" : " class=\"figure\"";
410
        $title = $title ? " title=\"$title\"" : null;
411
412
        if (!$alt && $caption) {
413
            $alt = $caption;
414
        }
415
416
        if (!$href) {
417
            $pos = strpos($src, "?");
418
            $href = $pos ? substr($src, 0, $pos) : $src;
419
        }
420
421
        $start = null;
422
        $end = null;
423
        if (!$nolink) {
424
            $start = "<a href=\"{$href}\">";
425
            $end = "</a>";
426
        }
427
428
        // Import the file containing the svg-image
429
        /*
430
        $svg = null;
431
432
        if($path[0] != '/') {
433
        $path = self::$dir . '/' . $path;
434
        }
435
436
        if(is_file($path)) {
437
        $svg = file_get_contents($path);
438
        }
439
        else {
440
        $svg = "No such file: $path";
441
        }
442
        $html = <<<EOD
443
        <figure{$id}{$class}>
444
        {$svg}
445
        <figcaption markdown=1>{$caption}</figcaption>
446
        </figure>
447
        EOD;*/
448
/*
449
        $html = <<<EOD
450
<figure{$id}{$class}>
451
{$start}<img src="{$src}" alt="{$alt}"{$title}/>{$end}
452
<figcaption markdown=1>{$caption}</figcaption>
453
</figure>
454
EOD;
455
456
        return $html;*/
457
/*    }
458
*/
459
460
461
462
/**
463
 * Shorttags to to quicker format text as HTML.
464
 *
465
 * @param string text text to be converted.
466
 * @return string the formatted text.
467
 */
468
/*public static function ShortTags($text) {
469
  $callback = function($matches) {
470
    switch($matches[1]) {
471
      case 'IMG':
472
        $caption = t('Image: ');
473
        $pos = strpos($matches[2], '?');
474
        $href = $pos ? substr($matches[2], 0, $pos) : $matches[2];
475
        $src = htmlspecialchars($matches[2]);
476
        return <<<EOD
477
<figure>
478
<a href='{$href}'><img src='{$src}' alt='{$matches[3]}' /></a>
479
<figcaption markdown=1>{$caption}{$matches[3]}</figcaption>
480
</figure>
481
EOD;
482
483
      case 'IMG2':
484
        $caption = null; //t('Image: ');
485
        $pos = strpos($matches[2], '?');
486
        $href = $pos ? substr($matches[2], 0, $pos) : $matches[2];
487
        $src = htmlspecialchars($matches[2]);
488
        return <<<EOD
489
<figure class="{$matches[4]}">
490
<a href='{$href}'><img src='{$src}' alt='{$matches[3]}' /></a>
491
<figcaption markdown=1>{$caption}{$matches[3]}</figcaption>
492
</figure>
493
EOD;
494
      case 'BOOK':
495
        $isbn = $matches[2];
496
        $stores = array(
497
          'BTH' => "http://bth.summon.serialssolutions.com/?#!/search?ho=t&amp;q={$isbn}",
498
          'Libris' => "http://libris.kb.se/hitlist?q={$isbn}",
499
          'Google Books' => "http://books.google.com/books?q={$isbn}",
500
          'Bokus' => "http://www.bokus.com/bok/{$isbn}",
501
          'Adlibris' => "http://www.adlibris.com/se/product.aspx?isbn={$isbn}",
502
          'Amazon' => "http://www.amazon.com/s/ref=nb_ss?url=field-keywords={$isbn}",
503
          'Barnes&Noble' => "http://search.barnesandnoble.com/booksearch/ISBNInquiry.asp?r=1&IF=N&EAN={$isbn}",
504
        );
505
        $html = null;
506
        foreach($stores as $key => $val) {
507
          $html .= "<a href='$val'>$key</a> &bull; ";
508
        }
509
        return substr($html, 0, -8);
510
      break;
511
512
      case 'YOUTUBE':
513
        $caption = t('Figure: ');
514
        $height = ceil($matches[3] / (16/9));
515
        return <<<EOD
516
<figure>
517
<iframe width='{$matches[3]}' height='{$height}' src="http://www.youtube.com/embed/{$matches[2]}" frameborder="0"
518
allowfullscreen></iframe>
519
<figcaption>{$caption}{$matches[4]}</figcaption>
520
</figure>
521
EOD;
522
      break;
523
524
      case 'syntax=': return CTextFilter::SyntaxHighlightGeSHi($matches[3], $matches[2]); break;
525
      case '```': return CTextFilter::SyntaxHighlightGeSHi($matches[3], $matches[2]); break;
526
      //case 'syntax=': return "<pre>" . highlight_string($matches[3], true) . "</pre>"; break;
527
      //case 'INCL':  include($matches[2]); break;
528
      case 'INFO':  return "<div class='info' markdown=1>"; break;
529
      case '/INFO': return "</div>"; break;
530
      case 'BASEURL': return CLydia::Instance()->request->base_url; break;
531
      case 'FIGURE': return CTextFilter::ShortCodeFigure($matches[2]); break;
532
      case 'FIGURE-SVG': return CTextFilter::ShortCodeSVGFigure($matches[2]); break;
533
      case 'ASCIINEMA': return CTextFilter::ShortCodeAsciinema($matches[2]); break;
534
      default: return "{$matches[1]} IS UNKNOWN SHORTTAG."; break;
535
    }
536
  };
537
  $patterns = array(
538
    '#\[(BASEURL)\]#',
539
    //'/\[(AUTHOR) name=(.+) email=(.+) url=(.+)\]/',
540
    '/\[(FIGURE)[\s+](.+)\]/',
541
    '/\[(FIGURE-SVG)[\s+](.+)\]/',
542
    '/\[(ASCIINEMA)[\s+](.+)\]/',
543
    '/\[(IMG) src=(.+) alt=(.+)\]/',
544
    '/\[(IMG2) src=(.+) alt="(.+)" class="(.+)"\]/',
545
    '/\[(BOOK) isbn=(.+)\]/',
546
    '/\[(YOUTUBE) src=(.+) width=(.+) caption=(.+)\]/',
547
    '/~~~(syntax=)(php|html|html5|css|sql|javascript|bash)\n([^~]+)\n~~~/s',
548
    '/(```)(php|html|html5|css|sql|javascript|bash|text|txt|python)\n([^`]+)\n```/s',
549
    //'/\[(INCL)/s*([^\]+)/',
550
    '#\[(INFO)\]#', '#\[(/INFO)\]#',
551
  );
552
553
  $ret = preg_replace_callback($patterns, $callback, $text);
554
  return $ret;
555
}
556
*/
557
}
558