Completed
Push — master ( 39af78...f32426 )
by Mikael
02:26
created

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