Completed
Push — master ( d3f21c...2ab792 )
by Mikael
03:28
created

TShortcode   A

Complexity

Total Complexity 24

Size/Duplication

Total Lines 413
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 0

Test Coverage

Coverage 55.26%

Importance

Changes 4
Bugs 0 Features 1
Metric Value
wmc 24
c 4
b 0
f 1
lcom 1
cbo 0
dl 0
loc 413
ccs 63
cts 114
cp 0.5526
rs 10

5 Methods

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