Completed
Push — format-currency ( fa34aa )
by Wouter
61:53
created

TemplateModifiers::formatNumber()   B

Complexity

Conditions 5
Paths 12

Size

Total Lines 22
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 22
rs 8.6737
cc 5
eloc 10
nc 12
nop 2
1
<?php
2
3
namespace Frontend\Core\Engine;
4
5
/*
6
 * This file is part of Fork CMS.
7
 *
8
 * For the full copyright and license information, please view the license
9
 * file that was distributed with this source code.
10
 */
11
12
use Frontend\Core\Engine\Model as FrontendModel;
13
use Frontend\Core\Engine\Block\Widget as FrontendBlockWidget;
14
use Frontend\Modules\Profiles\Engine\Model as FrontendProfilesModel;
15
use Common\Core\Twig\Extensions\BaseTwigModifiers;
16
17
/**
18
 * Contains all Frontend-related custom modifiers
19
 */
20
class TemplateModifiers extends BaseTwigModifiers
21
{
22
    /**
23
     * Format a number as a float
24
     *    syntax: {{ $number|formatfloat($decimals) }}
25
     *
26
     * @param float $number   The number to format.
27
     * @param int   $decimals The number of decimals.
28
     *
29
     * @return string
30
     */
31
    public static function formatFloat($number, $decimals = 2)
32
    {
33
        return number_format((float) $number, (int) $decimals, '.', ' ');
34
    }
35
36
    /**
37
     * Format a number
38
     *    syntax: {{ $string|formatnumber($decimals) }}
39
     *
40
     * @param float $string The number to format.
41
     * @param int $decimals The number of decimals
42
     *
43
     * @return string
44
     */
45
    public static function formatNumber($string, $decimals = null)
46
    {
47
        // redefine
48
        $string = (float) $string;
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $string. This often makes code more readable.
Loading history...
49
50
        // get setting
51
        $format = FrontendModel::get('fork.settings')->get('Core', 'number_format');
52
53
        // get amount of decimals
54
        if ($decimals === null) {
55
            $decimals = (mb_strpos($string, '.') ? mb_strlen(mb_substr($string, mb_strpos($string, '.') + 1)) : 0);
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $decimals. This often makes code more readable.
Loading history...
56
        }
57
58
        // get separators
59
        $separators = explode('_', $format);
60
        $separatorSymbols = array('comma' => ',', 'dot' => '.', 'space' => ' ', 'nothing' => '');
61
        $decimalSeparator = (isset($separators[0], $separatorSymbols[$separators[0]]) ? $separatorSymbols[$separators[0]] : null);
62
        $thousandsSeparator = (isset($separators[1], $separatorSymbols[$separators[1]]) ? $separatorSymbols[$separators[1]] : null);
63
64
        // format the number
65
        return number_format($string, $decimals, $decimalSeparator, $thousandsSeparator);
66
    }
67
68
    /**
69
     * Get the navigation html
70
     *    syntax: {{ getnavigation($type, $parentId, $depth, $excludeIds-splitted-by-dash, $template) }}
71
     *
72
     * @param string $type       The type of navigation, possible values are: page, footer.
73
     * @param int    $parentId   The parent wherefore the navigation should be build.
74
     * @param int    $depth      The maximum depth that has to be build.
75
     * @param string $excludeIds Which pageIds should be excluded (split them by -).
76
     * @param string $template        The template that will be used.
77
     *
78
     * @return string
79
     */
80
    public static function getNavigation(
81
        $type = 'page',
82
        $parentId = 0,
83
        $depth = null,
84
        $excludeIds = null,
85
        $template = '/Core/Layout/Templates/Navigation.html.twig'
86
    ) {
87
        // build excludeIds
88
        if ($excludeIds !== null) {
89
            $excludeIds = (array) explode('-', $excludeIds);
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $excludeIds. This often makes code more readable.
Loading history...
90
        }
91
92
        // get HTML
93
        try {
94
            $return = (string) Navigation::getNavigationHTML($type, $parentId, $depth, $excludeIds, $template);
0 ignored issues
show
Bug introduced by
It seems like $excludeIds defined by parameter $excludeIds on line 84 can also be of type null; however, Frontend\Core\Engine\Nav...on::getNavigationHTML() does only seem to accept array, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
95
        } catch (Exception $e) {
96
            // if something goes wrong just return as fallback
97
            return '';
98
        }
99
100
        // return the var
101
        if ($return != '') {
102
            return $return;
103
        }
104
105
        // fallback
106
        return '';
107
    }
108
109
    /**
110
     * Formats a timestamp as a string that indicates the time ago
111
     *    syntax: {{ $string|timeago }}.
112
     *
113
     * @param string $string A UNIX-timestamp that will be formatted as a time-ago-string.
114
     *
115
     * @return string
116
     */
117
    public static function timeAgo($string = null)
118
    {
119
        $string = (int) $string;
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $string. This often makes code more readable.
Loading history...
120
121
        // invalid timestamp
122
        if ($string == 0) {
123
            return '';
124
        }
125
126
        // return
127
        return '<abbr title="'.\SpoonDate::getDate(
128
            FrontendModel::get('fork.settings')->get('Core', 'date_format_long').', '.FrontendModel::get('fork.settings')->get(
129
                'Core',
130
                'time_format'
131
            ),
132
            $string,
133
            FRONTEND_LANGUAGE
134
        ).'">'.\SpoonDate::getTimeAgo($string, FRONTEND_LANGUAGE).'</abbr>';
135
    }
136
137
    /**
138
     * Get a given field for a page-record
139
     *    syntax: {{ getpageinfo($pageId, $field, $language) }}
140
     *
141
     * @param int    $pageId   The id of the page to build the URL for.
142
     * @param string $field    The field to get.
143
     * @param string $language The language to use, if not provided we will use the loaded language.
144
     *
145
     * @return string
146
     */
147
    public static function getPageInfo($pageId, $field = 'title', $language = null)
148
    {
149
        // redefine
150
        $field = (string) $field;
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $field. This often makes code more readable.
Loading history...
151
        $language = ($language !== null) ? (string) $language : null;
0 ignored issues
show
Unused Code introduced by
$language is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
Coding Style introduced by
Consider using a different name than the parameter $language. This often makes code more readable.
Loading history...
152
153
        // get page
154
        $page = Navigation::getPageInfo((int) $pageId);
155
156
        // validate
157
        if (empty($page)) {
158
            return '';
159
        }
160
        if (!isset($page[$field])) {
161
            return '';
162
        }
163
164
        // return page info
165
        return $page[$field];
166
    }
167
168
    /**
169
     * Fetch the path for an include (theme file if available, core file otherwise)
170
     *    syntax: {{ getpath($file) }}
171
     *
172
     * @param string $file The base path.
173
     *
174
     * @return string
175
     */
176
    public static function getPath($file)
177
    {
178
        return Theme::getPath($file);
179
    }
180
181
    /**
182
     * Get the subnavigation html
183
     *   syntax: {{ getsubnavigation($type, $parentId, $startdepth, $enddepth, $excludeIds-splitted-by-dash, $template) }}
184
     *
185
     *   NOTE: When supplying more than 1 ID to exclude, the single quotes around the dash-separated list are mandatory.
186
     *
187
     * @param string $type       The type of navigation, possible values are: page, footer.
188
     * @param int    $pageId     The parent wherefore the navigation should be build.
189
     * @param int    $startDepth The depth to start from.
190
     * @param int    $endDepth   The maximum depth that has to be build.
191
     * @param string $excludeIds Which pageIds should be excluded (split them by -).
192
     * @param string $template        The template that will be used.
193
     *
194
     * @return string
195
     */
196
    public static function getSubNavigation(
197
        $type = 'page',
198
        $pageId = 0,
199
        $startDepth = 1,
200
        $endDepth = null,
201
        $excludeIds = null,
202
        $template = '/Core/Layout/Templates/Navigation.html.twig'
203
    ) {
204
        // build excludeIds
205
        if ($excludeIds !== null) {
206
            $excludeIds = (array) explode('-', $excludeIds);
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $excludeIds. This often makes code more readable.
Loading history...
207
        }
208
209
        // get info about the given page
210
        $pageInfo = Navigation::getPageInfo($pageId);
211
212
        // validate page info
213
        if ($pageInfo === false) {
214
            return '';
215
        }
216
217
        // split URL into chunks
218
        $chunks = (array) explode('/', $pageInfo['full_url']);
219
220
        // remove language chunk
221
        $hasMultiLanguages = FrontendModel::getContainer()->getParameter('site.multilanguage');
222
        $chunks = ($hasMultiLanguages) ? (array) array_slice($chunks, 2) : (array) array_slice($chunks, 1);
223
        if (count($chunks) == 0) {
224
            $chunks[0] = '';
225
        }
226
227
        // init var
228
        $parentURL = '';
229
230
        // build url
231
        for ($i = 0; $i < $startDepth - 1; ++$i) {
232
            $parentURL .= $chunks[$i] . '/';
233
        }
234
235
        // get parent ID
236
        $parentID = Navigation::getPageId($parentURL);
237
238
        try {
239
            // get HTML
240
            $return = (string) Navigation::getNavigationHTML(
241
                $type,
242
                $parentID,
243
                $endDepth,
244
                $excludeIds,
0 ignored issues
show
Bug introduced by
It seems like $excludeIds defined by parameter $excludeIds on line 201 can also be of type null; however, Frontend\Core\Engine\Nav...on::getNavigationHTML() does only seem to accept array, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
245
                (string) $template
246
            );
247
        } catch (Exception $e) {
248
            return '';
249
        }
250
251
        // return the var
252
        if ($return != '') {
253
            return $return;
254
        }
255
256
        // fallback
257
        return;
258
    }
259
260
    /**
261
     * Get the URL for a given pageId & language
262
     *    syntax: {{ geturl($pageId, $language) }}
263
     *
264
     * @param int    $pageId   The id of the page to build the URL for.
265
     * @param string $language The language to use, if not provided we will use the loaded language.
266
     *
267
     * @return string
268
     */
269
    public static function getURL($pageId, $language = null)
270
    {
271
        $language = ($language !== null) ? (string) $language : null;
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $language. This often makes code more readable.
Loading history...
272
273
        return Navigation::getURL((int) $pageId, $language);
274
    }
275
276
    /**
277
     * Get the URL for a give module & action combination
278
     *    syntax: {{ geturlforblock($module, $action, $language) }}
279
     *
280
     * @param string $module   The module wherefore the URL should be build.
281
     * @param string $action   A specific action wherefore the URL should be build, otherwise the default will be used.
282
     * @param string $language The language to use, if not provided we will use the loaded language.
283
     *
284
     * @return string
285
     */
286
    public static function getURLForBlock($module, $action = null, $language = null)
287
    {
288
        $action = ($action !== null) ? (string) $action : null;
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $action. This often makes code more readable.
Loading history...
289
        $language = ($language !== null) ? (string) $language : null;
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $language. This often makes code more readable.
Loading history...
290
291
        return Navigation::getURLForBlock((string) $module, $action, $language);
292
    }
293
294
    /**
295
     * Fetch an URL based on an extraId
296
     *    syntax: {{ geturlforextraid($extraId, $language) }}
297
     *
298
     * @param int    $extraId  The id of the extra.
299
     * @param string $language The language to use, if not provided we will use the loaded language.
300
     *
301
     * @return string
302
     */
303
    public static function getURLForExtraId($extraId, $language = null)
304
    {
305
        $language = ($language !== null) ? (string) $language : null;
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $language. This often makes code more readable.
Loading history...
306
307
        return Navigation::getURLForExtraId((int) $extraId, $language);
308
    }
309
310
    /**
311
     * Parse a widget straight from the template, rather than adding it through pages.
312
     *    syntax: {{ parsewidget($module, $action, $id) }}
313
     *
314
     * @internal if your widget outputs random data you should cache it inside the widget
315
     * Fork checks the output and if the output of the widget is random it will loop until the random data
316
     * is the same as in the previous iteration
317
     *
318
     * @param string $module The module whose module we want to execute.
319
     * @param string $action The action to execute.
320
     * @param string $id     The widget id (saved in data-column).
321
     *
322
     * @return string|null
323
     */
324
    public static function parseWidget($module, $action, $id = null)
325
    {
326
        $data = $id !== null ? serialize(array('id' => $id)) : null;
327
328
        // create new widget instance and return parsed content
329
        $extra = new FrontendBlockWidget(Model::get('kernel'), $module, $action, $data);
330
331
        // set parseWidget because we will need it to skip setting headers in the display
332
        Model::getContainer()->set('parseWidget', true);
1 ignored issue
show
Documentation introduced by
true is of type boolean, but the function expects a object.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
333
334
        try {
335
            $extra->execute();
336
            $content = $extra->getContent();
337
            Model::getContainer()->set('parseWidget', null);
1 ignored issue
show
Documentation introduced by
null is of type null, but the function expects a object.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
338
339
            return $content;
340
        } catch (Exception $e) {
341
            // if we are debugging, we want to see the exception
342
            if (Model::getContainer()->getParameter('kernel.debug')) {
343
                throw $e;
344
            }
345
346
            return;
347
        }
348
    }
349
350
    /**
351
     * Output a profile setting
352
     *    syntax: {{ profilesetting($string, $name) }}
353
     *
354
     * @param string $string  The variable
355
     * @param string $name The name of the setting
356
     *
357
     * @return string
358
     */
359
    public static function profileSetting($string, $name)
360
    {
361
        $profile = FrontendProfilesModel::get((int) $string);
362
        if ($profile === false) {
363
            return '';
364
        }
365
366
        // convert into array
367
        $profile = $profile->toArray();
368
369
        // @remark I know this is dirty, but I couldn't find a better way.
370
        if (in_array($name, array('display_name', 'registered_on', 'full_url')) && isset($profile[$name])) {
371
            return $profile[$name];
372
        } elseif (isset($profile['settings'][$name])) {
373
            return $profile['settings'][$name];
374
        } else {
375
            return '';
376
        }
377
    }
378
379
    /**
380
     * Get the value for a user-setting
381
     *    syntax {{ usersetting($setting, $userId) }}
382
     *
383
     * @param string $string     The string passed from the template.
384
     * @param string $setting The name of the setting you want.
385
     * @param int    $userId  The userId, if not set by $string.
386
     *
387
     * @return string
388
     */
389
    public static function userSetting($string = null, $setting, $userId = null)
390
    {
391
        $userId = ($string !== null) ? (int) $string : (int) $userId;
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $userId. This often makes code more readable.
Loading history...
392
        $setting = (string) $setting;
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $setting. This often makes code more readable.
Loading history...
393
394
        // validate
395
        if ($userId === 0) {
396
            throw new Exception('Invalid user id');
397
        }
398
399
        // get user
400
        $user = User::getBackendUser($userId);
401
402
        // return
403
        return (string) $user->getSetting($setting);
404
    }
405
406
    /**
407
     * Translate a string.
408
     *    syntax {{ $string|trans }}
409
     *
410
     * @param string $string The string that you want to apply this method on.
411
     *
412
     * @return string The string, to translate.
413
     */
414
    public static function trans($string)
415
    {
416
        if (strpos($string, '.') === false) {
417
            return $string;
418
        }
419
        list($action, $string) = explode('.', $string);
420
421
        if (!in_array($action, array('lbl', 'act', 'err', 'msg'))) {
422
            return $string;
423
        }
424
425
        return Language::$action($string);
426
    }
427
428
    /**
429
     * Formats plain text as HTML, links will be detected, paragraphs will be inserted
430
     *    syntax: {{ $string|cleanupPlainText }}.
431
     *
432
     * @param string $string The text to cleanup.
433
     *
434
     * @return string
435
     */
436
    public static function cleanupPlainText($string)
437
    {
438
        // redefine
439
        $string = (string) $string;
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $string. This often makes code more readable.
Loading history...
440
441
        // detect links
442
        $string = \SpoonFilter::replaceURLsWithAnchors(
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $string. This often makes code more readable.
Loading history...
443
            $string,
444
            FrontendModel::get('fork.settings')->get('Core', 'seo_nofollow_in_comments', false)
445
        );
446
447
        // replace newlines
448
        $string = str_replace("\r", '', $string);
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $string. This often makes code more readable.
Loading history...
449
        $string = preg_replace('/(?<!.)(\r\n|\r|\n){3,}$/m', '', $string);
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $string. This often makes code more readable.
Loading history...
450
451
        // replace br's into p's
452
        $string = '<p>'.str_replace("\n", '</p><p>', $string).'</p>';
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $string. This often makes code more readable.
Loading history...
453
454
        // cleanup
455
        $string = str_replace("\n", '', $string);
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $string. This often makes code more readable.
Loading history...
456
        $string = str_replace('<p></p>', '', $string);
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $string. This often makes code more readable.
Loading history...
457
458
        // return
459
        return $string;
460
    }
461
462
    /**
463
     * Returns the count of the count of the array.
464
     *
465
     * @param array $data
466
     *
467
     * @return int
468
     */
469
    public static function count(array $data)
470
    {
471
        return count($data);
472
    }
473
}
474