Test Failed
Push — master ( 2a5a24...724d17 )
by Mikael
11:58
created

src/TextFilter/TShortcode.php (3 issues)

Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace Mos\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 1
            "/\[(YOUTUBE)[\s+](.+)\]/",
37 1
            "/\[(ASCIINEMA)[\s+](.+)\]/",
38 1
            "/\[(BOOK)[\s+](.+)\]/",
39 1
            //"/(```)([\w]*)\n([.]*)```[\n]{1}/s",
40 1
            "/(```)([\w]*)\n(.*?)```\n/s",
41 1
            '/\[(INFO)\]/',
42
            '/\[(\/INFO)\]/',
43 1
            '/\[(WARNING)\]/',
44 1
            '/\[(\/WARNING)\]/',
45 1
        ];
46 1
47 1
        return preg_replace_callback(
48 1
            $patterns,
49
            function ($matches) {
50
                switch ($matches[1]) {
51
                    case "FIGURE":
52
                        return self::shortCodeFigure($matches[2]);
53
                    break;
54
55
                    case "YOUTUBE":
56
                        return self::shortCodeYoutube($matches[2]);
57
                    break;
58
59
                    case "ASCIINEMA":
60
                        return self::shortCodeAsciinema($matches[2]);
61
                    break;
0 ignored issues
show
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...
62
63
                    case "BOOK":
64
                        return self::shortCodeBook($matches[2]);
65
                    break;
0 ignored issues
show
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...
66
67
                    case "```":
68
                        //return $this->syntaxHighlightGeSHi($matches[3], $matches[2]);
69
                        return $this->syntaxHighlightJs($matches[3], $matches[2]);
70
                    break;
0 ignored issues
show
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 'INFO':
73
                        return <<<EOD
74
<div class="info">
75 1
    <span class="icon fa-stack fa-lg">
76
        <i class="fa fa-circle fa-stack-2x"></i>
77 1
        <i class="fa fa-info fa-stack-1x fa-inverse" aria-hidden="true"></i>
78
    </span>
79
    <div markdown=1>
80
EOD;
81
                        break;
82
83
                    case 'WARNING':
84
                        return <<<EOD
85
<div class="warning">
86
    <span class="icon fa-stack fa-lg">
87
        <i class="fa fa-circle fa-stack-2x"></i>
88
        <i class="fa fa-exclamation-triangle fa-stack-1x fa-inverse" aria-hidden="true"></i>
89
    </span>
90 1
    <div markdown=1>
91
EOD;
92 1
                        break;
93
94 1
                    case '/INFO':
95 1
                    case '/WARNING':
96 1
                        return "</div></div>";
97 1
                        break;
98
99
                    default:
100 1
                        return "{$matches[1]} is unknown shortcode.";
101 1
                }
102 1
            },
103
            $text
104 1
        );
105
    }
106 1
107
108
109
    /**
110
     * Init shortcode handling by preparing the option list to an array,
111
     * for those using arguments.
112
     *
113
     * @param string $options for the shortcode.
114
     *
115
     * @return array with all the options.
116
     */
117
    public static function shortCodeInit($options)
118
    {
119
        preg_match_all('/[a-zA-Z0-9]+="[^"]+"|\S+/', $options, $matches);
120
121
        $res = array();
122
        foreach ($matches[0] as $match) {
123
            $pos = strpos($match, '=');
124
            if ($pos === false) {
125
                $res[$match] = true;
126
            } else {
127
                $key = substr($match, 0, $pos);
128
                $val = trim(substr($match, $pos+1), '"');
129
                $res[$key] = $val;
130
            }
131
        }
132
133
        return $res;
134
    }
135
136
137
138
    /**
139
     * Shortcode for [YOUTUBE].
140
     *
141
     * Usage example: [YOUTUBE src=id-for-the-tube width=630 caption=""]
142
     *
143
     * @param string $options for the shortcode.
144
     *
145
     * @return array with all the options.
146
     */
147
    public static function shortCodeYoutube($options)
148
    {
149
        $options= array_merge(
150
            [
151
                "id"    => null,
152
                "class" => null,
153
                "src" => null,
154
                "list" => null,
155
                "time" => null,
156
                "width" => 600,
157
                "ratio" => 16/9,
158
                "caption" => null,
159 1
            ],
160
            self::ShortCodeInit($options)
161
        );
162 1
        extract($options, EXTR_SKIP);
163
164 1
        $id = $id ? " id=\"$id\"" : null;
165 1
        $class = $class ? " class=\"figure $class\"" : " class=\"figure\"";
166 1
        $list = $list ? "?listType=playlist&amp;list=$list" : null;
167 1
        $time = $time ? "#t=$time" : null;
168 1
        $height = ceil($width / $ratio);
169 1
170 1
        //$caption = t("Figure: !CAPTION", ["!CAPTION" => $caption]);
171 1
        if ($caption) {
172 1
            $caption = "<figcaption markdown=1>{$caption}</figcaption>";
173 1
        }
174 1
175 1
        // @codingStandardsIgnoreStart
176
        $html = <<<EOD
177 1
<figure{$id}{$class}>
178 1
<iframe width="$width" height="$height" src="https://www.youtube.com/embed/{$src}{$list}{$time}" frameborder="0" allowfullscreen></iframe>
179 1
{$caption}
180
</figure>
181 1
EOD;
182 1
        // @codingStandardsIgnoreEnd
183 1
184
        return $html;
185 1
    }
186 1
187 1
188 1
189
    /**
190 1
     * Shortcode for <figure>.
191 1
     *
192 1
     * Usage example: [FIGURE src="img/home/me.jpg" caption="Me" alt="Bild på mig" nolink="nolink"]
193 1
     *
194 1
     * @param string $options for the shortcode.
195 1
     *
196
     * @return array with all the options.
197
     */
198 1
    public static function shortCodeFigure($options)
199 1
    {
200 1
        // Merge incoming options with default and expose as variables
201 1
        $options= array_merge(
202 1
            [
203
                "id"    => null,
204 1
                "class" => null,
205
                "src"   => null,
206
                "title" => null,
207
                "alt"   => null,
208
                "caption" => null,
209
                "href"  => null,
210
                "nolink" => false,
211
            ],
212
            self::ShortCodeInit($options)
213
        );
214
        extract($options, EXTR_SKIP);
215
216
        $id = $id ? " id=\"$id\"" : null;
217
        $class = $class ? " class=\"figure $class\"" : " class=\"figure\"";
218
        $title = $title ? " title=\"$title\"" : null;
219
220
        if (!$alt && $caption) {
221
            $alt = $caption;
222
        }
223
224
        if (!$href) {
225
            $pos = strpos($src, "?");
226
            $href = $pos ? substr($src, 0, $pos) : $src;
227
        }
228
229
        $start = null;
230
        $end = null;
231
        if (!$nolink) {
232
            $start = "<a href=\"{$href}\">";
233
            $end = "</a>";
234
        }
235
236
        if ($caption) {
237
            $caption = "<figcaption markdown=1>{$caption}</figcaption>";
238
        }
239
240
        $html = <<<EOD
241
<figure{$id}{$class}>
242
{$start}<img src="{$src}" alt="{$alt}"{$title}/>{$end}
243
{$caption}
244
</figure>
245
EOD;
246
247
        return $html;
248
    }
249
250
251
252
    /**
253
     * Shortcode for [asciinema].
254
     *
255
     * @param string $code the code to process.
256
     * @param string $options for the shortcode.
257
     * @return array with all the options.
258
     */
259
    public static function shortCodeAsciinema($options)
260
    {
261
        // Merge incoming options with default and expose as variables
262
        $options= array_merge(
263
            [
264
                "id" => null,
265
                "class" => null,
266
                "src" => null,
267
                "title" => null,
268
                "caption" => null,
269
            ],
270
            self::ShortCodeInit($options)
271
        );
272
        extract($options, EXTR_SKIP);
273
274
        $id = $id ? " id=\"$id\"" : null;
275
        $class = $class ? " class=\"figure asciinema $class\"" : " class=\"figure asciinema\"";
276
        $title = $title ? " title=\"$title\"" : null;
277
278
        $html = <<<EOD
279
<figure{$id}{$class}$title>
280
<script type="text/javascript" src="https://asciinema.org/a/{$src}.js" id="asciicast-{$src}" async></script>
281
<figcaption markdown=1>{$caption}</figcaption>
282
</figure>
283
EOD;
284
285
        return $html;
286
    }
287
288
289
290
    /**
291
     * Shortcode for [book].
292
     *
293
     * @param string $code the code to process.
294
     * @param string $options for the shortcode.
295
     * @return array with all the options.
296
     */
297
    public static function shortCodeBook($options)
298
    {
299
        // Merge incoming options with default and expose as variables
300
        $options= array_merge(
301
            [
302
                "isbn" => null,
303
            ],
304
            self::ShortCodeInit($options)
305
        );
306
        extract($options, EXTR_SKIP);
307
308
        $stores = [
309
            "BTH" => "http://bth.summon.serialssolutions.com/?#!/search?ho=t&amp;q={$isbn}",
310
            "Libris" => "http://libris.kb.se/hitlist?q={$isbn}",
311
            "Google Books" => "http://books.google.com/books?q={$isbn}",
312
            "Bokus" => "http://www.bokus.com/bok/{$isbn}",
313
            "Adlibris" => "http://www.adlibris.com/se/product.aspx?isbn={$isbn}",
314
            "Amazon" => "http://www.amazon.com/s/ref=nb_ss?url=field-keywords={$isbn}",
315
            "Barnes&Noble" => "http://search.barnesandnoble.com/booksearch/ISBNInquiry.asp?r=1&IF=N&EAN={$isbn}",
316
        ];
317
318
        $html = null;
319
        foreach ($stores as $key => $val) {
320
            $html .= "<a href='$val'>$key</a> &bull; ";
321
        }
322
        return substr($html, 0, -8);
323
    }
324
325
326
327
    /**
328
     * Shortcode for including a SVG-image inside a <figure>.
329
     *
330
     * @param string $code the code to process.
331
     * @param string $options for the shortcode.
332
     * @return array with all the options.
333
     */
334
/*    public static function ShortCodeSVGFigure($options) {
335
        // Merge incoming options with default and expose as variables
336
        $options= array_merge(
337
            [
338
                "id"    => null,
339
                "class" => null,
340
                "src"   => null,
341
                "title" => null,
342
                "alt"   => null,
343
                "caption" => null,
344
                "href"  => null,
345
                "nolink" => false,
346
                //'path' => null,
347
            ],
348
            self::ShortCodeInit($options)
349
        );
350
        extract($options, EXTR_SKIP);
351
352
        $id = $id ? " id=\"$id\"" : null;
353
        $class = $class ? " class=\"figure $class\"" : " class=\"figure\"";
354
        $title = $title ? " title=\"$title\"" : null;
355
356
        if (!$alt && $caption) {
357
            $alt = $caption;
358
        }
359
360
        if (!$href) {
361
            $pos = strpos($src, "?");
362
            $href = $pos ? substr($src, 0, $pos) : $src;
363
        }
364
365
        $start = null;
366
        $end = null;
367
        if (!$nolink) {
368
            $start = "<a href=\"{$href}\">";
369
            $end = "</a>";
370
        }
371
372
        // Import the file containing the svg-image
373
        /*
374
        $svg = null;
375
376
        if($path[0] != '/') {
377
        $path = self::$dir . '/' . $path;
378
        }
379
380
        if(is_file($path)) {
381
        $svg = file_get_contents($path);
382
        }
383
        else {
384
        $svg = "No such file: $path";
385
        }
386
        $html = <<<EOD
387
        <figure{$id}{$class}>
388
        {$svg}
389
        <figcaption markdown=1>{$caption}</figcaption>
390
        </figure>
391
        EOD;*/
392
/*
393
        $html = <<<EOD
394
<figure{$id}{$class}>
395
{$start}<img src="{$src}" alt="{$alt}"{$title}/>{$end}
396
<figcaption markdown=1>{$caption}</figcaption>
397
</figure>
398
EOD;
399
400
        return $html;*/
401
/*    }
402
*/
403
404
405
406
/**
407
 * Shorttags to to quicker format text as HTML.
408
 *
409
 * @param string text text to be converted.
410
 * @return string the formatted text.
411
 */
412
/*public static function ShortTags($text) {
413
  $callback = function($matches) {
414
    switch($matches[1]) {
415
      case 'IMG':
416
        $caption = t('Image: ');
417
        $pos = strpos($matches[2], '?');
418
        $href = $pos ? substr($matches[2], 0, $pos) : $matches[2];
419
        $src = htmlspecialchars($matches[2]);
420
        return <<<EOD
421
<figure>
422
<a href='{$href}'><img src='{$src}' alt='{$matches[3]}' /></a>
423
<figcaption markdown=1>{$caption}{$matches[3]}</figcaption>
424
</figure>
425
EOD;
426
427
      case 'IMG2':
428
        $caption = null; //t('Image: ');
429
        $pos = strpos($matches[2], '?');
430
        $href = $pos ? substr($matches[2], 0, $pos) : $matches[2];
431
        $src = htmlspecialchars($matches[2]);
432
        return <<<EOD
433
<figure class="{$matches[4]}">
434
<a href='{$href}'><img src='{$src}' alt='{$matches[3]}' /></a>
435
<figcaption markdown=1>{$caption}{$matches[3]}</figcaption>
436
</figure>
437
EOD;
438
      case 'BOOK':
439
        $isbn = $matches[2];
440
        $stores = array(
441
          'BTH' => "http://bth.summon.serialssolutions.com/?#!/search?ho=t&amp;q={$isbn}",
442
          'Libris' => "http://libris.kb.se/hitlist?q={$isbn}",
443
          'Google Books' => "http://books.google.com/books?q={$isbn}",
444
          'Bokus' => "http://www.bokus.com/bok/{$isbn}",
445
          'Adlibris' => "http://www.adlibris.com/se/product.aspx?isbn={$isbn}",
446
          'Amazon' => "http://www.amazon.com/s/ref=nb_ss?url=field-keywords={$isbn}",
447
          'Barnes&Noble' => "http://search.barnesandnoble.com/booksearch/ISBNInquiry.asp?r=1&IF=N&EAN={$isbn}",
448
        );
449
        $html = null;
450
        foreach($stores as $key => $val) {
451
          $html .= "<a href='$val'>$key</a> &bull; ";
452
        }
453
        return substr($html, 0, -8);
454
      break;
455
456
      case 'YOUTUBE':
457
        $caption = t('Figure: ');
458
        $height = ceil($matches[3] / (16/9));
459
        return <<<EOD
460
<figure>
461
<iframe width='{$matches[3]}' height='{$height}' src="http://www.youtube.com/embed/{$matches[2]}" frameborder="0"
462
allowfullscreen></iframe>
463
<figcaption>{$caption}{$matches[4]}</figcaption>
464
</figure>
465
EOD;
466
      break;
467
      
468
      case 'syntax=': return CTextFilter::SyntaxHighlightGeSHi($matches[3], $matches[2]); break;
469
      case '```': return CTextFilter::SyntaxHighlightGeSHi($matches[3], $matches[2]); break;
470
      //case 'syntax=': return "<pre>" . highlight_string($matches[3], true) . "</pre>"; break;
471
      //case 'INCL':  include($matches[2]); break;
472
      case 'INFO':  return "<div class='info' markdown=1>"; break;
473
      case '/INFO': return "</div>"; break;
474
      case 'BASEURL': return CLydia::Instance()->request->base_url; break;
475
      case 'FIGURE': return CTextFilter::ShortCodeFigure($matches[2]); break;
476
      case 'FIGURE-SVG': return CTextFilter::ShortCodeSVGFigure($matches[2]); break;
477
      case 'ASCIINEMA': return CTextFilter::ShortCodeAsciinema($matches[2]); break;
478
      default: return "{$matches[1]} IS UNKNOWN SHORTTAG."; break;
479
    }
480
  };
481
  $patterns = array(
482
    '#\[(BASEURL)\]#',
483
    //'/\[(AUTHOR) name=(.+) email=(.+) url=(.+)\]/',
484
    '/\[(FIGURE)[\s+](.+)\]/',
485
    '/\[(FIGURE-SVG)[\s+](.+)\]/',
486
    '/\[(ASCIINEMA)[\s+](.+)\]/',
487
    '/\[(IMG) src=(.+) alt=(.+)\]/',
488
    '/\[(IMG2) src=(.+) alt="(.+)" class="(.+)"\]/',
489
    '/\[(BOOK) isbn=(.+)\]/',
490
    '/\[(YOUTUBE) src=(.+) width=(.+) caption=(.+)\]/',
491
    '/~~~(syntax=)(php|html|html5|css|sql|javascript|bash)\n([^~]+)\n~~~/s',
492
    '/(```)(php|html|html5|css|sql|javascript|bash|text|txt|python)\n([^`]+)\n```/s',
493
    //'/\[(INCL)/s*([^\]+)/',
494
    '#\[(INFO)\]#', '#\[(/INFO)\]#',
495
  );
496
497
  $ret = preg_replace_callback($patterns, $callback, $text);
498
  return $ret;
499
}
500
*/
501
}
502