Test Failed
Push — master ( b17e1e...f735d6 )
by Vojta
03:17 queued 50s
created

Plugin   A

Complexity

Total Complexity 26

Size/Duplication

Total Lines 445
Duplicated Lines 2.47 %

Coupling/Cohesion

Components 1
Dependencies 8

Test Coverage

Coverage 73.26%

Importance

Changes 0
Metric Value
wmc 26
lcom 1
cbo 8
dl 11
loc 445
ccs 137
cts 187
cp 0.7326
rs 10
c 0
b 0
f 0

17 Methods

Rating   Name   Duplication   Size   Complexity  
A pluginDetails() 0 10 1
A boot() 11 11 1
A registerMarkupTags() 0 54 2
A getStringLoaderFunctions() 0 12 1
A getTextFilters() 0 16 1
A getLocalizedFilters() 0 20 1
A getArrayFilters() 0 12 1
A getTimeFilters() 0 13 1
A getSortByField() 0 12 1
A getMailFilters() 0 8 1
B getPhpFunctions() 0 58 1
A getConfigFunction() 0 8 1
A getSessionFunction() 0 8 1
A getTransFunction() 0 8 1
A getVarDumpFunction() 0 12 1
B hideEmail() 0 37 7
A getFileRevision() 0 18 3

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php namespace VojtaSvoboda\TwigExtensions;
2
3
use App;
4
use Backend;
5
use Carbon\Carbon;
6
use Snilius\Twig\SortByFieldExtension;
7
use System\Classes\PluginBase;
8
use Twig_Extension_StringLoader;
9
use Twig_Extensions_Extension_Array;
10
use Twig_Extensions_Extension_Date;
11
use Twig_Extensions_Extension_Intl;
12
use Twig_Extensions_Extension_Text;
13
use VojtaSvoboda\TwigExtensions\Classes\TimeDiffTranslator;
14
15
/**
16
 * Twig Extensions Plugin.
17
 *
18
 * @see http://twig.sensiolabs.org/doc/extensions/index.html#extensions-install
19
 */
20
class Plugin extends PluginBase
21
{
22
    /**
23
     * @var boolean Determine if this plugin should have elevated privileges.
24
     */
25
    public $elevated = true;
26
27
    /**
28
     * Returns information about this plugin.
29
     *
30
     * @return array
31
     */
32
    public function pluginDetails()
33
    {
34
        return [
35
            'name'        => 'Twig Extensions',
36
            'description' => 'Add more Twig filters to your templates.',
37
            'author'      => 'Vojta Svoboda',
38
            'icon'        => 'icon-plus',
39
            'homepage'    => 'https://github.com/vojtasvoboda/oc-twigextensions-plugin',
40
        ];
41
    }
42
43 View Code Duplication
    public function boot()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
44
    {
45
        $this->app->singleton('time_diff_translator', function ($app) {
46
            $loader = $app->make('translation.loader');
47
            $locale = $app->config->get('app.locale');
48
            $translator = $app->make(TimeDiffTranslator::class, [$loader, $locale]);
49
            $translator->setFallback($app->config->get('app.fallback_locale'));
50
51
            return $translator;
52
        });
53
    }
54
55
    /**
56
     * Add Twig extensions.
57
     *
58
     * @see Text extensions http://twig.sensiolabs.org/doc/extensions/text.html
59 1
     * @see Intl extensions http://twig.sensiolabs.org/doc/extensions/intl.html
60
     * @see Array extension http://twig.sensiolabs.org/doc/extensions/array.html
61 1
     * @see Time extension http://twig.sensiolabs.org/doc/extensions/date.html
62 1
     *
63
     * @return array
64
     */
65 1
    public function registerMarkupTags()
66
    {
67
        $filters = [];
68 1
        $functions = [];
69
70
        // init Twig
71 1
        $twig = $this->app->make('twig.environment');
72
73
        // add String Loader functions
74 1
        $functions += $this->getStringLoaderFunctions($twig);
75
76
        // add Config function
77 1
        $functions += $this->getConfigFunction();
78
79
        // add Session function
80 1
        $functions += $this->getSessionFunction();
81
82
        // add Trans function
83 1
        $functions += $this->getTransFunction();
84
85
        // add var_dump function
86 1
        $functions += $this->getVarDumpFunction();
87 1
88 1
        // add Text extensions
89
        $filters += $this->getTextFilters($twig);
90
91 1
        // add Intl extensions if php5-intl installed
92
        if (class_exists('IntlDateFormatter')) {
93
            $filters += $this->getLocalizedFilters($twig);
94 1
        }
95
96
        // add Array extensions
97 1
        $filters += $this->getArrayFilters();
98
99
        // add Time extensions
100 1
        $filters += $this->getTimeFilters($twig);
101
102
        // add Sort by Field extensions
103 1
        $filters += $this->getSortByField();
104
105
        // add Mail filters
106 1
        $filters += $this->getMailFilters();
107 1
108 1
        // add PHP functions
109
        $filters += $this->getPhpFunctions();
110
111
        // add File Version filter
112
        $filters += $this->getFileRevision();
113
114
        return [
115
            'filters'   => $filters,
116
            'functions' => $functions,
117
        ];
118 1
    }
119
120 1
    /**
121 1
     * Returns String Loader functions.
122
     *
123
     * @param \Twig_Environment $twig
124
     *
125 1
     * @return array
126 1
     */
127
    private function getStringLoaderFunctions($twig)
128 1
    {
129
        $stringLoader = new Twig_Extension_StringLoader();
130
        $stringLoaderFunc = $stringLoader->getFunctions();
131
132
        return [
133
            'template_from_string' => function ($template) use ($twig, $stringLoaderFunc) {
134
                $callable = $stringLoaderFunc[0]->getCallable();
135
                return $callable($twig, $template);
136
            }
137
        ];
138 3
    }
139
140 1
    /**
141 1
     * Returns Text filters.
142
     *
143
     * @param \Twig_Environment $twig
144
     *
145 3
     * @return array
146 3
     */
147 1
    private function getTextFilters($twig)
148
    {
149 1
        $textExtension = new Twig_Extensions_Extension_Text();
150 1
        $textFilters = $textExtension->getFilters();
151
152 1
        return [
153
            'truncate' => function ($value, $length = 30, $preserve = false, $separator = '...') use ($twig, $textFilters) {
154
                $callable = $textFilters[0]->getCallable();
155
                return $callable($twig, $value, $length, $preserve, $separator);
156
            },
157
            'wordwrap' => function ($value, $length = 80, $separator = "\n", $preserve = false) use ($twig, $textFilters) {
158
                $callable = $textFilters[1]->getCallable();
159
                return $callable($twig, $value, $length, $separator, $preserve);
160
            }
161
        ];
162 1
    }
163
164 1
    /**
165 1
     * Returns Intl filters.
166
     *
167
     * @param \Twig_Environment $twig
168
     *
169
     * @return array
170
     */
171 1
    private function getLocalizedFilters($twig)
172
    {
173
        $intlExtension = new Twig_Extensions_Extension_Intl();
174
        $intlFilters = $intlExtension->getFilters();
175 1
176
        return [
177
            'localizeddate' => function ($date, $dateFormat = 'medium', $timeFormat = 'medium', $locale = null, $timezone = null, $format = null) use ($twig, $intlFilters) {
178
                $callable = $intlFilters[0]->getCallable();
179
                return $callable($twig, $date, $dateFormat, $timeFormat, $locale, $timezone, $format);
180 1
            },
181
            'localizednumber' => function ($number, $style = 'decimal', $type = 'default', $locale = null) use ($twig, $intlFilters) {
182
                $callable = $intlFilters[1]->getCallable();
183
                return $callable($number, $style, $type, $locale);
184
            },
185
            'localizedcurrency' => function ($number, $currency = null, $locale = null) use ($twig, $intlFilters) {
186
                $callable = $intlFilters[2]->getCallable();
187
                return $callable($number, $currency, $locale);
188 2
            }
189
        ];
190 1
    }
191 1
192
    /**
193
     * Returns Array filters.
194
     *
195 2
     * @return array
196 2
     */
197
    private function getArrayFilters()
198 1
    {
199
        $arrayExtension = new Twig_Extensions_Extension_Array();
200
        $arrayFilters = $arrayExtension->getFilters();
201
202
        return [
203
            'shuffle' => function ($array) use ($arrayFilters) {
204
                $callable = $arrayFilters[0]->getCallable();
205
                return $callable($array);
206
            }
207
        ];
208 1
    }
209
210 1
    /**
211 1
     * Returns Date filters.
212 1
     *
213
     * @param \Twig_Environment $twig
214
     *
215
     * @return array
216
     */
217
    private function getTimeFilters($twig)
218
    {
219 1
        $translator = $this->app->make('time_diff_translator');
220
        $timeExtension = new Twig_Extensions_Extension_Date($translator);
221
        $timeFilters = $timeExtension->getFilters();
222
223
        return [
224
            'time_diff' => function ($date, $now = null) use ($twig, $timeFilters) {
225
                $callable = $timeFilters[0]->getCallable();
226
                return $callable($twig, $date, $now);
227 1
            }
228
        ];
229
    }
230
231 1
    /**
232
     * Returns Sort by Field filters.
233 1
     *
234
     * @return array
235
     */
236
    private function getSortByField()
237
    {
238
        $extension = new SortByFieldExtension();
239
        $filters = $extension->getFilters();
240
241 1
        return [
242
            'sortbyfield' => function ($array, $sort_by = null, $direction = 'asc') use ($filters) {
243
                $callable = $filters[0]->getCallable();
244
                return $callable($array, $sort_by, $direction);
245 1
            }
246 1
        ];
247 1
    }
248
249 1
    /**
250 1
     * Returns mail filters.
251
     *
252 1
     * @return array
253 1
     */
254
    private function getMailFilters()
255 1
    {
256 1
        return [
257
            'mailto' => function ($string, $link = true, $protected = true, $text = null, $class = "") {
258 1
                return $this->hideEmail($string, $link, $protected, $text, $class);
259 1
            }
260
        ];
261 1
    }
262 1
263
    /**
264 1
     * Returns plain PHP functions.
265 1
     *
266
     * @return array
267 1
     */
268 1
    private function getPhpFunctions()
269
    {
270 1
        return [
271 1
            'strftime' => function ($time, $format = '%d.%m.%Y %H:%M:%S') {
272
                $timeObj = new Carbon($time);
273 1
                return strftime($format, $timeObj->getTimestamp());
274 1
            },
275
            'uppercase' => function ($string) {
276 1
                return mb_convert_case($string, MB_CASE_UPPER, "UTF-8");
277 1
            },
278
            'lowercase' => function ($string) {
279 1
                return mb_convert_case($string, MB_CASE_LOWER, "UTF-8");
280 1
            },
281
            'ucfirst' => function ($string) {
282 1
                return mb_convert_case($string, MB_CASE_TITLE, "UTF-8");
283 1
            },
284
            'lcfirst' => function ($string) {
285 1
                return lcfirst($string);
286 1
            },
287 1
            'ltrim' => function ($string, $charlist = " \t\n\r\0\x0B") {
288
                return ltrim($string, $charlist);
289 1
            },
290 1
            'rtrim' => function ($string, $charlist = " \t\n\r\0\x0B") {
291 1
                return rtrim($string, $charlist);
292
            },
293
            'str_repeat' => function ($string, $multiplier = 1) {
294
                return str_repeat($string, $multiplier);
295
            },
296
            'plural' => function ($string, $count = 2) {
297
                return str_plural($string, $count);
298
            },
299 1
            'strpad' => function ($string, $pad_length, $pad_string = ' ') {
300
                return str_pad($string, $pad_length, $pad_string, $pad_type = STR_PAD_BOTH);
301
            },
302
            'leftpad' => function ($string, $pad_length, $pad_string = ' ') {
303 1
                return str_pad($string, $pad_length, $pad_string, $pad_type = STR_PAD_LEFT);
304 1
            },
305 1
            'rightpad' => function ($string, $pad_length, $pad_string = ' ') {
306
                return str_pad($string, $pad_length, $pad_string, $pad_type = STR_PAD_RIGHT);
307
            },
308
            'rtl' => function ($string) {
309
                return strrev($string);
310
            },
311
            'str_replace' => function ($string, $search, $replace) {
312
                return str_replace($search, $replace, $string);
313 1
            },
314
            'strip_tags' => function ($string, $allow = '') {
315
                return strip_tags($string, $allow);
316
            },
317 1
            'var_dump' => function ($expression) {
318 1
                ob_start();
319 1
                var_dump($expression);
320
                $result = ob_get_clean();
321
322
                return $result;
323
            },
324
        ];
325
    }
326
327 1
    /**
328
     * Works like the config() helper function.
329
     *
330
     * @return array
331 1
     */
332 1
    private function getConfigFunction()
333 1
    {
334
        return [
335
            'config' => function ($key = null, $default = null) {
336
                return config($key, $default);
337
            },
338
        ];
339
    }
340
341 1
    /**
342
     * Works like the session() helper function.
343
     *
344
     * @return array
345 1
     */
346 1
    private function getSessionFunction()
347 1
    {
348
        return [
349 1
            'session' => function ($key = null) {
350 1
                return session($key);
351 1
            },
352
        ];
353
    }
354
355
    /**
356
     * Works like the trans() helper function.
357
     *
358
     * @return array
359
     */
360
    private function getTransFunction()
361
    {
362
        return [
363
            'trans' => function ($key = null, $parameters = []) {
364
                return trans($key, $parameters);
365
            },
366 1
        ];
367
    }
368
369 1
    /**
370 1
     * Dumps information about a variable.
371 1
     *
372 1
     * @return array
373
     */
374
    private function getVarDumpFunction()
375 1
    {
376 1
        return [
377
            'var_dump' => function ($expression) {
378
                ob_start();
379
                var_dump($expression);
380 1
                $result = ob_get_clean();
381 1
382 1
                return $result;
383 1
            },
384 1
        ];
385 1
    }
386 1
387 1
    /**
388 1
     * Create protected link with mailto:
389 1
     *
390 1
     * @param string $email Email to render.
391 1
     * @param bool $link If email should be rendered as link.
392 1
     * @param bool $protected If email should be protected.
393 1
     * @param string $text Link text. Render email by default.
394 1
     *
395
     * @see http://www.maurits.vdschee.nl/php_hide_email/
396 1
     *
397 1
     * @return string
398
     */
399 1
    private function hideEmail($email, $link = true, $protected = true, $text = null, $class = "")
400
    {
401
        // email link text
402
        $linkText = $email;
403
        if ($text !== null) {
404
            $linkText = $text;
405
        }
406
407
        // if we want just unprotected link
408
        if (!$protected) {
409
            return $link ? '<a href="mailto:' . $email . '">' . $linkText . '</a>' : $linkText;
410
        }
411
412
        // turn on protection
413
        $character_set = '+-.0123456789@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz';
414 1
        $key = str_shuffle($character_set);
415
        $cipher_text = '';
416
        $id = 'e' . rand(1, 999999999);
417
        for ($i = 0; $i < strlen($email); $i += 1) {
418
            $cipher_text .= $key[strpos($character_set, $email[$i])];
419
        }
420
        $script = 'var a="' . $key . '";var b=a.split("").sort().join("");var c="' . $cipher_text . '";var d=""; var cl="'.$class.'";';
421
        $script .= 'for(var e=0;e<c.length;e++)d+=b.charAt(a.indexOf(c.charAt(e)));';
422
        $script .= 'var y = d;';
423
        if ($text !== null) {
424
            $script .= 'var y = "'.$text.'";';
425
        }
426 1
        if ($link) {
427 1
            $script .= 'document.getElementById("' . $id . '").innerHTML="<a class=\""+cl+"\" href=\\"mailto:"+d+"\\">"+y+"</a>"';
428
        } else {
429
            $script .= 'document.getElementById("' . $id . '").innerHTML=y';
430
        }
431
        $script = "eval(\"" . str_replace(array("\\", '"'), array("\\\\", '\"'), $script) . "\")";
432
        $script = '<script type="text/javascript">/*<![CDATA[*/' . $script . '/*]]>*/</script>';
433
434
        return '<span id="' . $id . '">[javascript protected email address]</span>' . $script;
435
    }
436
437
    /**
438
     * Appends this pattern: ? . {last modified date}
439
     * to an assets filename to force browser to reload
440
     * cached modified file.
441
     *
442
     * See: https://github.com/vojtasvoboda/oc-twigextensions-plugin/issues/25
443
     *
444
     * @return array
445
     */
446
    private function getFileRevision()
447
    {
448
        return [
449
            'revision' => function ($filename, $format = null) {
450
                // Remove http/web address from the file name if there is one to load it locally
451
                $prefix = url('/');
452
                $filename_ = trim(preg_replace('/^' . preg_quote($prefix, '/') . '/', '', $filename), '/');
453
                if (file_exists($filename_)) {
454
                    $timestamp = filemtime($filename_);
455
                    $prepend = ($format) ? date($format, $timestamp) : $timestamp;
456
457
                    return $filename . "?" . $prepend;
458
                }
459
460
                return $filename;
461
            },
462
        ];
463
    }
464
}
465