Test Failed
Branch master (7b1793)
by Tymoteusz
15:35
created

ExtendedTemplateService::ext_depthKeys()   C

Complexity

Conditions 7
Paths 18

Size

Total Lines 23
Code Lines 16

Duplication

Lines 23
Ratio 100 %

Importance

Changes 0
Metric Value
cc 7
eloc 16
nc 18
nop 2
dl 23
loc 23
rs 6.7272
c 0
b 0
f 0
1
<?php
2
namespace TYPO3\CMS\Core\TypoScript;
3
4
/*
5
 * This file is part of the TYPO3 CMS project.
6
 *
7
 * It is free software; you can redistribute it and/or modify it under
8
 * the terms of the GNU General Public License, either version 2
9
 * of the License, or any later version.
10
 *
11
 * For the full copyright and license information, please read the
12
 * LICENSE.txt file that was distributed with this source code.
13
 *
14
 * The TYPO3 project - inspiring people to share!
15
 */
16
17
use TYPO3\CMS\Backend\Template\DocumentTemplate;
18
use TYPO3\CMS\Backend\Utility\BackendUtility;
19
use TYPO3\CMS\Core\Database\ConnectionPool;
20
use TYPO3\CMS\Core\Database\Query\QueryBuilder;
21
use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
22
use TYPO3\CMS\Core\Exception;
23
use TYPO3\CMS\Core\Imaging\Icon;
24
use TYPO3\CMS\Core\Imaging\IconFactory;
25
use TYPO3\CMS\Core\Localization\LanguageService;
26
use TYPO3\CMS\Core\Utility\GeneralUtility;
27
use TYPO3\CMS\Core\Utility\MathUtility;
28
use TYPO3\CMS\Frontend\Configuration\TypoScript\ConditionMatching\ConditionMatcher;
29
30
/**
31
 * TSParser extension class to TemplateService
32
 * Contains functions for the TS module in TYPO3 backend
33
 */
34
class ExtendedTemplateService extends TemplateService
35
{
36
    /**
37
     * Disabled in backend context
38
     *
39
     * @var bool
40
     */
41
    public $tt_track = false;
42
43
    /**
44
     * @var array
45
     */
46
    public $categories = [
47
        'basic' => [],
48
        // Constants of superior importance for the template-layout. This is dimensions, imagefiles and enabling of various features. The most basic constants, which you would almost always want to configure.
49
        'menu' => [],
50
        // Menu setup. This includes fontfiles, sizes, background images. Depending on the menutype.
51
        'content' => [],
52
        // All constants related to the display of pagecontent elements
53
        'page' => [],
54
        // General configuration like metatags, link targets
55
        'advanced' => [],
56
        // Advanced functions, which are used very seldom.
57
        'all' => []
58
    ];
59
60
    /**
61
     * Translated categories
62
     *
63
     * @var array
64
     */
65
    protected $categoryLabels = [];
66
67
    /**
68
     * This will be filled with the available categories of the current template.
69
     *
70
     * @var array
71
     */
72
    public $subCategories = [
73
        // Standard categories:
74
        'enable' => ['Enable features', 'a'],
75
        'dims' => ['Dimensions, widths, heights, pixels', 'b'],
76
        'file' => ['Files', 'c'],
77
        'typo' => ['Typography', 'd'],
78
        'color' => ['Colors', 'e'],
79
        'links' => ['Links and targets', 'f'],
80
        'language' => ['Language specific constants', 'g'],
81
        // subcategories based on the default content elements
82
        'cheader' => ['Content: \'Header\'', 'ma'],
83
        'cheader_g' => ['Content: \'Header\', Graphical', 'ma'],
84
        'ctext' => ['Content: \'Text\'', 'mb'],
85
        'cimage' => ['Content: \'Image\'', 'md'],
86
        'ctextmedia' => ['Content: \'Textmedia\'', 'ml'],
87
        'cbullets' => ['Content: \'Bullet list\'', 'me'],
88
        'ctable' => ['Content: \'Table\'', 'mf'],
89
        'cuploads' => ['Content: \'Filelinks\'', 'mg'],
90
        'cmultimedia' => ['Content: \'Multimedia\'', 'mh'],
91
        'cmedia' => ['Content: \'Media\'', 'mr'],
92
        'cmailform' => ['Content: \'Form\'', 'mi'],
93
        'csearch' => ['Content: \'Search\'', 'mj'],
94
        'clogin' => ['Content: \'Login\'', 'mk'],
95
        'cmenu' => ['Content: \'Menu/Sitemap\'', 'mm'],
96
        'cshortcut' => ['Content: \'Insert records\'', 'mn'],
97
        'clist' => ['Content: \'List of records\'', 'mo'],
98
        'chtml' => ['Content: \'HTML\'', 'mq']
99
    ];
100
101
    /**
102
     * Tsconstanteditor
103
     *
104
     * @var int
105
     */
106
    public $ext_inBrace = 0;
107
108
    /**
109
     * Tsbrowser
110
     *
111
     * @var array
112
     */
113
    public $tsbrowser_searchKeys = [];
114
115
    /**
116
     * @var array
117
     */
118
    public $tsbrowser_depthKeys = [];
119
120
    /**
121
     * @var string
122
     */
123
    public $constantMode = '';
124
125
    /**
126
     * @var string
127
     */
128
    public $regexMode = '';
129
130
    /**
131
     * @var string
132
     */
133
    public $fixedLgd = '';
134
135
    /**
136
     * @var int
137
     */
138
    public $ext_lineNumberOffset = 0;
139
140
    /**
141
     * @var int
142
     */
143
    public $ext_expandAllNotes = 0;
144
145
    /**
146
     * @var int
147
     */
148
    public $ext_noPMicons = 0;
149
150
    /**
151
     * @var array
152
     */
153
    public $ext_listOfTemplatesArr = [];
154
155
    /**
156
     * @var string
157
     */
158
    public $ext_lineNumberOffset_mode = '';
159
160
    /**
161
     * Don't change
162
     *
163
     * @var int
164
     */
165
    public $ext_dontCheckIssetValues = 0;
166
167
    /**
168
     * @var int
169
     */
170
    public $ext_printAll = 0;
171
172
    /**
173
     * @var string
174
     */
175
    public $ext_CEformName = 'forms[0]';
176
177
    /**
178
     * @var bool
179
     */
180
    public $doNotSortCategoriesBeforeMakingForm = false;
181
182
    /**
183
     * Ts analyzer
184
     *
185
     * @var array
186
     */
187
    public $templateTitles = [];
188
189
    /**
190
     * @var array|null
191
     */
192
    protected $lnToScript = null;
193
194
    /**
195
     * @var array
196
     */
197
    public $clearList_const_temp;
198
199
    /**
200
     * @var array
201
     */
202
    public $clearList_setup_temp;
203
204
    /**
205
     * @var string
206
     */
207
    public $bType = '';
208
209
    /**
210
     * @var bool
211
     */
212
    public $linkObjects = false;
213
214
    /**
215
     * @var bool
216
     */
217
    public $changed = false;
218
219
    /**
220
     * @var int[]
221
     */
222
    protected $objReg = [];
223
224
    /**
225
     * @var array
226
     */
227
    public $raw = [];
228
229
    /**
230
     * @var int
231
     */
232
    public $rawP = 0;
233
234
    /**
235
     * @var string
236
     */
237
    public $lastComment = '';
238
239
    /**
240
     * @var array
241
     */
242
    protected $inlineJavaScript = [];
243
244
    /**
245
     * Gets the inline JavaScript.
246
     *
247
     * @return array
248
     */
249
    public function getInlineJavaScript()
250
    {
251
        return $this->inlineJavaScript;
252
    }
253
254
    /**
255
     * Substitute constant
256
     *
257
     * @param string $all
258
     * @return string
259
     */
260
    public function substituteConstants($all)
261
    {
262
        return preg_replace_callback('/\\{\\$(.[^}]+)\\}/', [$this, 'substituteConstantsCallBack'], $all);
263
    }
264
265
    /**
266
     * Call back method for preg_replace_callback in substituteConstants
267
     *
268
     * @param array $matches Regular expression matches
269
     * @return string Replacement
270
     * @see substituteConstants()
271
     */
272
    public function substituteConstantsCallBack($matches)
273
    {
274
        $marker = substr(md5($matches[0]), 0, 6);
275
        switch ($this->constantMode) {
276
            case 'const':
277
                $ret_val = isset($this->flatSetup[$matches[1]]) && !is_array($this->flatSetup[$matches[1]]) ? '##' . $marker . '_B##' . $matches[0] . '##' . $marker . '_E##' : $matches[0];
0 ignored issues
show
Bug introduced by
Are you sure $marker of type false|string can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

277
                $ret_val = isset($this->flatSetup[$matches[1]]) && !is_array($this->flatSetup[$matches[1]]) ? '##' . /** @scrutinizer ignore-type */ $marker . '_B##' . $matches[0] . '##' . $marker . '_E##' : $matches[0];
Loading history...
278
                break;
279
            case 'subst':
280
                $ret_val = isset($this->flatSetup[$matches[1]]) && !is_array($this->flatSetup[$matches[1]]) ? '##' . $marker . '_B##' . $this->flatSetup[$matches[1]] . '##' . $marker . '_E##' : $matches[0];
281
                break;
282
            case 'untouched':
283
                $ret_val = $matches[0];
284
                break;
285
            default:
286
                $ret_val = isset($this->flatSetup[$matches[1]]) && !is_array($this->flatSetup[$matches[1]]) ? $this->flatSetup[$matches[1]] : $matches[0];
287
        }
288
        return $ret_val;
289
    }
290
291
    /**
292
     * Substitute markers
293
     *
294
     * @param string $all
295
     * @return string
296
     */
297
    public function substituteCMarkers($all)
298
    {
299
        switch ($this->constantMode) {
300
            case 'const':
301
            case 'subst':
302
                $all = preg_replace(
303
                    '/##[a-z0-9]{6}_B##((?:(?!##[a-z0-9]{6}_E##).)+)?##[a-z0-9]{6}_E##/',
304
                        '<strong style="color: green;">$1</strong>',
305
                        $all
306
                );
307
                break;
308
            default:
309
        }
310
        return $all;
311
    }
312
313
    /**
314
     * Parse constants with respect to the constant-editor in this module.
315
     * In particular comments in the code are registered.
316
     *
317
     * @return array
318
     */
319
    public function generateConfig_constants()
320
    {
321
        // These vars are also set lateron...
322
        $this->setup['sitetitle'] = $this->sitetitle;
323
        // Parse constants
324
        $constants = GeneralUtility::makeInstance(Parser\TypoScriptParser::class);
325
        // Register comments!
326
        $constants->regComments = 1;
327
        $constants->setup = $this->mergeConstantsFromPageTSconfig([]);
328
        /** @var ConditionMatcher $matchObj */
329
        $matchObj = GeneralUtility::makeInstance(ConditionMatcher::class);
330
        // Matches ALL conditions in TypoScript
331
        $matchObj->setSimulateMatchResult(true);
332
        $c = 0;
333
        $cc = count($this->constants);
334
        $defaultConstants = [];
335
        foreach ($this->constants as $str) {
336
            $c++;
337
            if ($c == $cc) {
338
                $this->flatSetup = [];
339
                $this->flattenSetup($constants->setup, '');
340
                $defaultConstants = $this->flatSetup;
341
            }
342
            $constants->parse($str, $matchObj);
343
        }
344
        $this->flatSetup = [];
345
        $this->flattenSetup($constants->setup, '');
346
        $this->setup['constants'] = $constants->setup;
347
        return $this->ext_compareFlatSetups($defaultConstants);
348
    }
349
350
    /**
351
     * @param array $theSetup
352
     * @param string $theKey
353
     * @return array
354
     */
355
    public function ext_getSetup($theSetup, $theKey)
356
    {
357
        $parts = explode('.', $theKey, 2);
358
        if ((string)$parts[0] !== '' && is_array($theSetup[$parts[0] . '.'])) {
359
            if (trim($parts[1]) !== '') {
360
                return $this->ext_getSetup($theSetup[$parts[0] . '.'], trim($parts[1]));
361
            }
362
            return [$theSetup[$parts[0] . '.'], $theSetup[$parts[0]]];
363
        }
364
        if (trim($theKey) !== '') {
365
            return [[], $theSetup[$theKey]];
366
        }
367
        return [$theSetup, ''];
368
    }
369
370
    /**
371
     * Get object tree
372
     *
373
     * @param array $arr
374
     * @param string $depth_in
375
     * @param string $depthData
376
     * @param string $parentType (unused)
377
     * @param string $parentValue (unused)
378
     * @param string $alphaSort sorts the array keys / tree by alphabet when set to 1
379
     * @return array
380
     */
381
    public function ext_getObjTree($arr, $depth_in, $depthData, $parentType = '', $parentValue = '', $alphaSort = '0')
0 ignored issues
show
Unused Code introduced by
The parameter $parentType is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

381
    public function ext_getObjTree($arr, $depth_in, $depthData, /** @scrutinizer ignore-unused */ $parentType = '', $parentValue = '', $alphaSort = '0')

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $parentValue is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

381
    public function ext_getObjTree($arr, $depth_in, $depthData, $parentType = '', /** @scrutinizer ignore-unused */ $parentValue = '', $alphaSort = '0')

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
382
    {
383
        $HTML = '';
384
        if ($alphaSort == '1') {
385
            ksort($arr);
386
        }
387
        $keyArr_num = [];
388
        $keyArr_alpha = [];
389
        /** @var \TYPO3\CMS\Backend\Routing\UriBuilder $uriBuilder */
390
        $uriBuilder = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Routing\UriBuilder::class);
391
        foreach ($arr as $key => $value) {
392
            // Don't do anything with comments / linenumber registrations...
393
            if (substr($key, -2) !== '..') {
394
                $key = preg_replace('/\\.$/', '', $key);
395
                if (substr($key, -1) !== '.') {
396
                    if (MathUtility::canBeInterpretedAsInteger($key)) {
397
                        $keyArr_num[$key] = $arr[$key];
398
                    } else {
399
                        $keyArr_alpha[$key] = $arr[$key];
400
                    }
401
                }
402
            }
403
        }
404
        ksort($keyArr_num);
405
        $keyArr = $keyArr_num + $keyArr_alpha;
406
        if ($depth_in) {
407
            $depth_in = $depth_in . '.';
408
        }
409
        foreach ($keyArr as $key => $value) {
410
            $depth = $depth_in . $key;
411
            // This excludes all constants starting with '_' from being shown.
412
            if ($this->bType !== 'const' || $depth[0] !== '_') {
413
                $goto = substr(md5($depth), 0, 6);
414
                $deeper = is_array($arr[$key . '.']) && ($this->tsbrowser_depthKeys[$depth] || $this->ext_expandAllNotes);
415
                $PM = is_array($arr[$key . '.']) && !$this->ext_noPMicons ? ($deeper ? 'minus' : 'plus') : 'join';
416
                $HTML .= $depthData . '<li>';
417
                if ($PM !== 'join') {
418
                    $urlParameters = [
419
                        'id' => $GLOBALS['SOBE']->id,
420
                        'tsbr[' . $depth . ']' => $deeper ? 0 : 1
421
                    ];
422
                    if (GeneralUtility::_GP('breakPointLN')) {
0 ignored issues
show
Bug Best Practice introduced by
The expression TYPO3\CMS\Core\Utility\G...ty::_GP('breakPointLN') of type null|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
423
                        $urlParameters['breakPointLN'] = GeneralUtility::_GP('breakPointLN');
424
                    }
425
                    $aHref = (string)$uriBuilder->buildUriFromRoute('web_ts', $urlParameters) . '#' . $goto;
0 ignored issues
show
Bug introduced by
Are you sure $goto of type false|string can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

425
                    $aHref = (string)$uriBuilder->buildUriFromRoute('web_ts', $urlParameters) . '#' . /** @scrutinizer ignore-type */ $goto;
Loading history...
426
                    $HTML .= '<a class="list-tree-control' . ($PM === 'minus' ? ' list-tree-control-open' : ' list-tree-control-closed') . '" name="' . $goto . '" href="' . htmlspecialchars($aHref) . '"><i class="fa"></i></a>';
427
                }
428
                $label = $key;
429
                // Read only...
430
                if (($depth === 'types' || $depth === 'resources' || $depth === 'sitetitle') && $this->bType === 'setup') {
431
                    $label = '<span style="color: #666666;">' . $label . '</span>';
432
                } else {
433
                    if ($this->linkObjects) {
434
                        $urlParameters = [
435
                            'id' => $GLOBALS['SOBE']->id,
436
                            'sObj' => $depth
437
                        ];
438
                        if (GeneralUtility::_GP('breakPointLN')) {
0 ignored issues
show
Bug Best Practice introduced by
The expression TYPO3\CMS\Core\Utility\G...ty::_GP('breakPointLN') of type null|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
439
                            $urlParameters['breakPointLN'] = GeneralUtility::_GP('breakPointLN');
440
                        }
441
                        $aHref = (string)$uriBuilder->buildUriFromRoute('web_ts', $urlParameters);
442
                        if ($this->bType !== 'const') {
443
                            $ln = is_array($arr[$key . '.ln..']) ? 'Defined in: ' . $this->lineNumberToScript($arr[$key . '.ln..']) : 'N/A';
0 ignored issues
show
Bug introduced by
Are you sure $this->lineNumberToScript($arr[$key . '.ln..']) of type array can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

443
                            $ln = is_array($arr[$key . '.ln..']) ? 'Defined in: ' . /** @scrutinizer ignore-type */ $this->lineNumberToScript($arr[$key . '.ln..']) : 'N/A';
Loading history...
444
                        } else {
445
                            $ln = '';
446
                        }
447
                        if ($this->tsbrowser_searchKeys[$depth] & 4) {
448
                            $label = '<strong class="text-danger">' . $label . '</strong>';
449
                        }
450
                        // The key has matched the search string
451
                        $label = '<a href="' . htmlspecialchars($aHref) . '" title="' . htmlspecialchars($ln) . '">' . $label . '</a>';
452
                    }
453
                }
454
                $HTML .= '
455
					<span class="list-tree-group">
456
						<span class="list-tree-label">[' . $label . ']</span>';
457
                if (isset($arr[$key])) {
458
                    $theValue = $arr[$key];
459
                    if ($this->fixedLgd) {
460
                        $imgBlocks = ceil(1 + strlen($depthData) / 77);
461
                        $lgdChars = 68 - ceil(strlen(('[' . $key . ']')) * 0.8) - $imgBlocks * 3;
462
                        $theValue = $this->ext_fixed_lgd($theValue, $lgdChars);
0 ignored issues
show
Bug introduced by
$lgdChars of type double is incompatible with the type integer expected by parameter $chars of TYPO3\CMS\Core\TypoScrip...ervice::ext_fixed_lgd(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

462
                        $theValue = $this->ext_fixed_lgd($theValue, /** @scrutinizer ignore-type */ $lgdChars);
Loading history...
463
                    }
464
                    // The value has matched the search string
465
                    if ($this->tsbrowser_searchKeys[$depth] & 2) {
466
                        $HTML .= ' = <span class="list-tree-value text-danger">' . htmlspecialchars($theValue) . '</span>';
467
                    } else {
468
                        $HTML .= ' = <span class="list-tree-value">' . htmlspecialchars($theValue) . '</span>';
469
                    }
470
                    if ($this->ext_regComments && isset($arr[$key . '..'])) {
471
                        $comment = $arr[$key . '..'];
472
                        // Skip INCLUDE_TYPOSCRIPT comments, they are almost useless
473
                        if (!preg_match('/### <INCLUDE_TYPOSCRIPT:.*/', $comment)) {
474
                            // Remove linebreaks, replace with ' '
475
                            $comment = preg_replace('/[\\r\\n]/', ' ', $comment);
476
                            // Remove # and * if more than twice in a row
477
                            $comment = preg_replace('/[#\\*]{2,}/', '', $comment);
478
                            // Replace leading # (just if it exists) and add it again. Result: Every comment should be prefixed by a '#'.
479
                            $comment = preg_replace('/^[#\\*\\s]+/', '# ', $comment);
480
                            // Masking HTML Tags: Replace < with &lt; and > with &gt;
481
                            $comment = htmlspecialchars($comment);
482
                            $HTML .= ' <i class="text-muted">' . trim($comment) . '</i>';
483
                        }
484
                    }
485
                }
486
                $HTML .= '</span>';
487
                if ($deeper) {
488
                    $HTML .= $this->ext_getObjTree($arr[$key . '.'], $depth, $depthData, '', $arr[$key], $alphaSort);
489
                }
490
            }
491
        }
492
        if ($HTML !== '') {
493
            $HTML = '<ul class="list-tree text-monospace">' . $HTML . '</ul>';
494
        }
495
496
        return $HTML;
497
    }
498
499
    /**
500
     * Find the originating template name for an array of line numbers (TypoScript setup only!)
501
     * Given an array of linenumbers the method will try to find the corresponding template where this line originated
502
     * The linenumber indicates the *last* lineNumber that is part of the template
503
     *
504
     * lineNumbers are in sync with the calculated lineNumbers '.ln..' in TypoScriptParser
505
     *
506
     * @param array $lnArr Array with linenumbers (might have some extra symbols, for example for unsetting) to be processed
507
     * @return array The same array where each entry has been prepended by the template title if available
508
     */
509
    public function lineNumberToScript(array $lnArr)
510
    {
511
        // On the first call, construct the lnToScript array.
512
        if (!is_array($this->lnToScript)) {
513
            $this->lnToScript = [];
514
515
            // aggregatedTotalLineCount
516
            $c = 0;
517
            foreach ($this->hierarchyInfo as $templateNumber => $info) {
518
                // hierarchyInfo has the number of lines in configLines, but unfortunately this value
519
                // was calculated *before* processing of any INCLUDE instructions
520
                // for some yet unknown reason we have to add an extra +2 offset
521
                $linecountAfterIncludeProcessing = substr_count($this->config[$templateNumber], LF) + 2;
522
                $c += $linecountAfterIncludeProcessing;
523
                $this->lnToScript[$c] = $info['title'];
524
            }
525
        }
526
527
        foreach ($lnArr as $k => $ln) {
528
            foreach ($this->lnToScript as $endLn => $title) {
529
                if ($endLn >= (int)$ln) {
530
                    $lnArr[$k] = '"' . $title . '", ' . $ln;
531
                    break;
532
                }
533
            }
534
        }
535
536
        return implode('; ', $lnArr);
537
    }
538
539
    /**
540
     * @param array $arr
541
     * @param string $depth_in
542
     * @param string $searchString
543
     * @param array $keyArray
544
     * @return array
545
     * @throws Exception
546
     */
547
    public function ext_getSearchKeys($arr, $depth_in, $searchString, $keyArray)
548
    {
549
        $keyArr = [];
550 View Code Duplication
        foreach ($arr as $key => $value) {
551
            $key = preg_replace('/\\.$/', '', $key);
552
            if (substr($key, -1) !== '.') {
553
                $keyArr[$key] = 1;
554
            }
555
        }
556
        if ($depth_in) {
557
            $depth_in = $depth_in . '.';
558
        }
559
        $searchPattern = '';
560
        if ($this->regexMode) {
561
            $searchPattern = '/' . addcslashes($searchString, '/') . '/';
562
            $matchResult = @preg_match($searchPattern, '');
563
            if ($matchResult === false) {
564
                throw new Exception(sprintf('Error evaluating regular expression "%s".', $searchPattern), 1446559458);
565
            }
566
        }
567
        foreach ($keyArr as $key => $value) {
568
            $depth = $depth_in . $key;
569
            $deeper = is_array($arr[$key . '.']);
570
            if ($this->regexMode) {
571
                // The value has matched
572
                if (preg_match($searchPattern, $arr[$key])) {
573
                    $this->tsbrowser_searchKeys[$depth] += 2;
574
                }
575
                // The key has matched
576
                if (preg_match($searchPattern, $key)) {
577
                    $this->tsbrowser_searchKeys[$depth] += 4;
578
                }
579
                // Just open this subtree if the parent key has matched the search
580
                if (preg_match($searchPattern, $depth_in)) {
581
                    $this->tsbrowser_searchKeys[$depth] = 1;
582
                }
583
            } else {
584
                // The value has matched
585
                if (stristr($arr[$key], $searchString)) {
586
                    $this->tsbrowser_searchKeys[$depth] += 2;
587
                }
588
                // The key has matches
589
                if (stristr($key, $searchString)) {
590
                    $this->tsbrowser_searchKeys[$depth] += 4;
591
                }
592
                // Just open this subtree if the parent key has matched the search
593
                if (stristr($depth_in, $searchString)) {
594
                    $this->tsbrowser_searchKeys[$depth] = 1;
595
                }
596
            }
597 View Code Duplication
            if ($deeper) {
598
                $cS = count($this->tsbrowser_searchKeys);
599
                $keyArray = $this->ext_getSearchKeys($arr[$key . '.'], $depth, $searchString, $keyArray);
600
                if ($cS != count($this->tsbrowser_searchKeys)) {
601
                    $keyArray[$depth] = 1;
602
                }
603
            }
604
        }
605
        return $keyArray;
606
    }
607
608
    /**
609
     * @param int $pid
610
     * @return int
611
     */
612
    public function ext_getRootlineNumber($pid)
613
    {
614
        if ($pid) {
615
            foreach ($this->getRootLine() as $key => $val) {
616
                if ((int)$val['uid'] === (int)$pid) {
617
                    return (int)$key;
618
                }
619
            }
620
        }
621
        return -1;
622
    }
623
624
    /**
625
     * @param array $arr
626
     * @param string $depthData
627
     * @param array $keyArray
628
     * @param int $first
629
     * @return array
630
     */
631
    public function ext_getTemplateHierarchyArr($arr, $depthData, $keyArray, $first = 0)
632
    {
633
        $keyArr = [];
634 View Code Duplication
        foreach ($arr as $key => $value) {
635
            $key = preg_replace('/\\.$/', '', $key);
636
            if (substr($key, -1) !== '.') {
637
                $keyArr[$key] = 1;
638
            }
639
        }
640
        $a = 0;
641
        $c = count($keyArr);
642
        /** @var \TYPO3\CMS\Backend\Routing\UriBuilder $uriBuilder */
643
        $uriBuilder = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Routing\UriBuilder::class);
644
        /** @var IconFactory $iconFactory */
645
        $iconFactory = GeneralUtility::makeInstance(IconFactory::class);
646
        foreach ($keyArr as $key => $value) {
647
            $HTML = '';
648
            $a++;
649
            $deeper = is_array($arr[$key . '.']);
650
            $row = $arr[$key];
651
            $LN = $a == $c ? 'blank' : 'line';
652
            $BTM = $a == $c ? 'top' : '';
653
            $HTML .= $depthData;
654
            $alttext = '[' . $row['templateID'] . ']';
655
            $alttext .= $row['pid'] ? ' - ' . BackendUtility::getRecordPath($row['pid'], $GLOBALS['SOBE']->perms_clause, 20) : '';
0 ignored issues
show
Bug introduced by
Are you sure TYPO3\CMS\Backend\Utilit...BE']->perms_clause, 20) of type string|array<integer,string> can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

655
            $alttext .= $row['pid'] ? ' - ' . /** @scrutinizer ignore-type */ BackendUtility::getRecordPath($row['pid'], $GLOBALS['SOBE']->perms_clause, 20) : '';
Loading history...
656
            $icon = substr($row['templateID'], 0, 3) === 'sys'
657
                ? '<span title="' . htmlspecialchars($alttext) . '">' . $iconFactory->getIconForRecord('sys_template', $row, Icon::SIZE_SMALL)->render() . '</span>'
658
                : '<span title="' . htmlspecialchars($alttext) . '">' . $iconFactory->getIcon('mimetypes-x-content-template-static', Icon::SIZE_SMALL)->render() . '</span>';
659
            if (in_array($row['templateID'], $this->clearList_const) || in_array($row['templateID'], $this->clearList_setup)) {
660
                $urlParameters = [
661
                    'id' => $GLOBALS['SOBE']->id,
662
                    'template' => $row['templateID']
663
                ];
664
                $aHref = (string)$uriBuilder->buildUriFromRoute('web_ts', $urlParameters);
665
                $A_B = '<a href="' . htmlspecialchars($aHref) . '">';
666
                $A_E = '</a>';
667
                if (GeneralUtility::_GP('template') == $row['templateID']) {
668
                    $A_B = '<strong>' . $A_B;
669
                    $A_E .= '</strong>';
670
                }
671
            } else {
672
                $A_B = '';
673
                $A_E = '';
674
            }
675
            $HTML .= ($first ? '' : '<span class="treeline-icon treeline-icon-join' . $BTM . '"></span>') . $icon . ' ' . $A_B
676
                . htmlspecialchars(GeneralUtility::fixed_lgd_cs($row['title'], $GLOBALS['BE_USER']->uc['titleLen']))
677
                . $A_E . '&nbsp;&nbsp;';
678
            $RL = $this->ext_getRootlineNumber($row['pid']);
679
            $statusCheckedIcon = $iconFactory->getIcon('status-status-checked', Icon::SIZE_SMALL)->render();
680
            $keyArray[] = '<tr>
681
							<td class="nowrap">' . $HTML . '</td>
682
							<td align="center">' . ($row['root'] ? $statusCheckedIcon : '') . '</td>
683
							<td align="center">' . ($row['clConf'] ? $statusCheckedIcon : '') . '</td>
684
							<td align="center">' . ($row['clConst'] ? $statusCheckedIcon : '') . '</td>
685
							<td align="center">' . ($row['pid'] ?: '') . '</td>
686
							<td align="center">' . ($RL >= 0 ? $RL : '') . '</td>
687
							<td>' . ($row['next'] ? $row['next'] : '') . '</td>
688
						</tr>';
689
            if ($deeper) {
690
                $keyArray = $this->ext_getTemplateHierarchyArr($arr[$key . '.'], $depthData . ($first ? '' : '<span class="treeline-icon treeline-icon-' . $LN . '"></span>'), $keyArray);
691
            }
692
        }
693
        return $keyArray;
694
    }
695
696
    /**
697
     * Processes the flat array from TemplateService->hierarchyInfo
698
     * and turns it into a hierarchical array to show dependencies (used by TemplateAnalyzer)
699
     *
700
     * @param array $depthDataArr (empty array on external call)
701
     * @param int &$pointer Element number (1! to count()) of $this->hierarchyInfo that should be processed.
702
     * @return array Processed hierachyInfo.
703
     */
704
    public function ext_process_hierarchyInfo(array $depthDataArr, &$pointer)
705
    {
706
        $parent = $this->hierarchyInfo[$pointer - 1]['templateParent'];
707
        while ($pointer > 0 && $this->hierarchyInfo[$pointer - 1]['templateParent'] == $parent) {
708
            $pointer--;
709
            $row = $this->hierarchyInfo[$pointer];
710
            $depthDataArr[$row['templateID']] = $row;
711
            unset($this->clearList_setup_temp[$row['templateID']]);
712
            unset($this->clearList_const_temp[$row['templateID']]);
713
            $this->templateTitles[$row['templateID']] = $row['title'];
714
            if ($row['templateID'] == $this->hierarchyInfo[$pointer - 1]['templateParent']) {
715
                $depthDataArr[$row['templateID'] . '.'] = $this->ext_process_hierarchyInfo([], $pointer);
716
            }
717
        }
718
        return $depthDataArr;
719
    }
720
721
    /**
722
     * Get formatted HTML output for TypoScript either with Syntaxhiglighting or in plain mode
723
     *
724
     * @param array $config Array with simple strings of typoscript code.
725
     * @param bool $lineNumbers Prepend linNumbers to each line.
726
     * @param bool $comments Enable including comments in output.
727
     * @param bool $crop Enable cropping of long lines.
728
     * @param bool $syntaxHL Enrich output with syntaxhighlighting.
729
     * @param int $syntaxHLBlockmode
730
     * @return string
731
     */
732
    public function ext_outputTS(
733
        array $config,
734
        $lineNumbers = false,
735
        $comments = false,
736
        $crop = false,
737
        $syntaxHL = false,
738
        $syntaxHLBlockmode = 0
739
    ) {
740
        $all = '';
741
        foreach ($config as $str) {
742
            $all .= '[GLOBAL]' . LF . $str;
743
        }
744
        if ($syntaxHL) {
745
            $tsparser = GeneralUtility::makeInstance(Parser\TypoScriptParser::class);
746
            $tsparser->lineNumberOffset = $this->ext_lineNumberOffset + 1;
747
            $tsparser->parentObject = $this;
748
            return $tsparser->doSyntaxHighlight($all, $lineNumbers ? [$this->ext_lineNumberOffset + 1] : '', $syntaxHLBlockmode);
749
        }
750
        return $this->ext_formatTS($all, $lineNumbers, $comments, $crop);
751
    }
752
753
    /**
754
     * Returns a new string of max. $chars length
755
     * If the string is longer, it will be truncated and prepended with '...'
756
     * $chars must be an integer of at least 4
757
     *
758
     * @param string $string
759
     * @param int $chars
760
     * @return string
761
     */
762
    public function ext_fixed_lgd($string, $chars)
763
    {
764
        if ($chars >= 4) {
765
            if (strlen($string) > $chars) {
766
                if (strlen($string) > 24 && preg_match('/^##[a-z0-9]{6}_B##$/', substr($string, 0, 12))) {
0 ignored issues
show
Bug introduced by
It seems like substr($string, 0, 12) can also be of type false; however, parameter $subject of preg_match() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

766
                if (strlen($string) > 24 && preg_match('/^##[a-z0-9]{6}_B##$/', /** @scrutinizer ignore-type */ substr($string, 0, 12))) {
Loading history...
767
                    $string = GeneralUtility::fixed_lgd_cs(substr($string, 12, -12), ($chars - 3));
0 ignored issues
show
Bug introduced by
It seems like substr($string, 12, -12) can also be of type false; however, parameter $string of TYPO3\CMS\Core\Utility\G...Utility::fixed_lgd_cs() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

767
                    $string = GeneralUtility::fixed_lgd_cs(/** @scrutinizer ignore-type */ substr($string, 12, -12), ($chars - 3));
Loading history...
768
                    $marker = substr(md5($string), 0, 6);
769
                    return '##' . $marker . '_B##' . $string . '##' . $marker . '_E##';
0 ignored issues
show
Bug introduced by
Are you sure $marker of type false|string can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

769
                    return '##' . /** @scrutinizer ignore-type */ $marker . '_B##' . $string . '##' . $marker . '_E##';
Loading history...
770
                }
771
                return GeneralUtility::fixed_lgd_cs($string, $chars - 3);
772
            }
773
        }
774
        return $string;
775
    }
776
777
    /**
778
     * @param int $lineNumber Line Number
779
     * @param array $str
780
     * @return string
781
     */
782
    public function ext_lnBreakPointWrap($lineNumber, $str)
783
    {
784
        return '<a href="#" id="line-' . $lineNumber . '" onClick="return brPoint(' . $lineNumber . ','
785
            . ($this->ext_lineNumberOffset_mode === 'setup' ? 1 : 0) . ');">' . $str . '</a>';
0 ignored issues
show
Bug introduced by
Are you sure $str of type array can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

785
            . ($this->ext_lineNumberOffset_mode === 'setup' ? 1 : 0) . ');">' . /** @scrutinizer ignore-type */ $str . '</a>';
Loading history...
786
    }
787
788
    /**
789
     * @param string $input
790
     * @param bool $ln
791
     * @param bool $comments
792
     * @param bool $crop
793
     * @return string
794
     */
795
    public function ext_formatTS($input, $ln, $comments = true, $crop = false)
796
    {
797
        $cArr = explode(LF, $input);
798
        $n = ceil(log10(count($cArr) + $this->ext_lineNumberOffset));
799
        $lineNum = '';
800
        foreach ($cArr as $k => $v) {
801
            $lln = $k + $this->ext_lineNumberOffset + 1;
802
            if ($ln) {
803
                $lineNum = $this->ext_lnBreakPointWrap($lln, str_replace(' ', '&nbsp;', sprintf(('% ' . $n . 'd'), $lln))) . ':   ';
0 ignored issues
show
Bug introduced by
str_replace(' ', '&nbsp;...'% ' . $n . 'd', $lln)) of type string is incompatible with the type array expected by parameter $str of TYPO3\CMS\Core\TypoScrip...:ext_lnBreakPointWrap(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

803
                $lineNum = $this->ext_lnBreakPointWrap($lln, /** @scrutinizer ignore-type */ str_replace(' ', '&nbsp;', sprintf(('% ' . $n . 'd'), $lln))) . ':   ';
Loading history...
804
            }
805
            $v = htmlspecialchars($v);
806
            if ($crop) {
807
                $v = $this->ext_fixed_lgd($v, $ln ? 71 : 77);
808
            }
809
            $cArr[$k] = $lineNum . str_replace(' ', '&nbsp;', $v);
810
            $firstChar = substr(trim($v), 0, 1);
811
            if ($firstChar === '[') {
812
                $cArr[$k] = '<strong class="text-success">' . $cArr[$k] . '</strong>';
813
            } elseif ($firstChar === '/' || $firstChar === '#') {
814
                if ($comments) {
815
                    $cArr[$k] = '<span class="text-muted">' . $cArr[$k] . '</span>';
816
                } else {
817
                    unset($cArr[$k]);
818
                }
819
            }
820
        }
821
        $output = implode($cArr, '<br />') . '<br />';
0 ignored issues
show
Bug introduced by
'<br />' of type string is incompatible with the type array expected by parameter $pieces of implode(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

821
        $output = implode($cArr, /** @scrutinizer ignore-type */ '<br />') . '<br />';
Loading history...
Bug introduced by
$cArr of type array<mixed,mixed|string>|array is incompatible with the type string expected by parameter $glue of implode(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

821
        $output = implode(/** @scrutinizer ignore-type */ $cArr, '<br />') . '<br />';
Loading history...
822
        return $output;
823
    }
824
825
    /**
826
     * Get a single sys_template record attached to a single page.
827
     * If multiple template records are on this page, the first (order by sorting)
828
     * record will be returned, unless a specific template uid is specified via $templateUid
829
     *
830
     * @param int $pid The pid to select sys_template records from
831
     * @param int $templateUid Optional template uid
832
     * @return array|null Returns the template record or null if none was found
833
     */
834
    public function ext_getFirstTemplate($pid, $templateUid = 0)
835
    {
836
        if (empty($pid)) {
837
            return null;
838
        }
839
840
        // Query is taken from the runThroughTemplates($theRootLine) function in the parent class.
841
        $queryBuilder = $this->getTemplateQueryBuilder($pid)
842
            ->setMaxResults(1);
843
        if ($templateUid) {
844
            $queryBuilder->andWhere(
845
                $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($templateUid, \PDO::PARAM_INT))
846
            );
847
        }
848
        $row = $queryBuilder->execute()->fetch();
849
        BackendUtility::workspaceOL('sys_template', $row);
850
851
        return $row;
852
    }
853
854
    /**
855
     * Get an array of all template records on a page.
856
     *
857
     * @param int $pid Pid to fetch sys_template records for
858
     * @return array[] Array of template records
859
     */
860
    public function ext_getAllTemplates($pid): array
861
    {
862
        if (empty($pid)) {
863
            return [];
864
        }
865
        $result = $this->getTemplateQueryBuilder($pid)->execute();
866
        $outRes = [];
867
        while ($row = $result->fetch()) {
868
            BackendUtility::workspaceOL('sys_template', $row);
869
            if (is_array($row)) {
870
                $outRes[] = $row;
871
            }
872
        }
873
        return $outRes;
874
    }
875
876
    /**
877
     * Internal helper method to prepare the query builder for
878
     * getting sys_template records from a given pid
879
     *
880
     * @param int $pid The pid to select sys_template records from
881
     * @return QueryBuilder Returns a QueryBuilder
882
     */
883
    protected function getTemplateQueryBuilder(int $pid): QueryBuilder
884
    {
885
        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
886
            ->getQueryBuilderForTable('sys_template');
887
        $queryBuilder->getRestrictions()
888
            ->removeAll()
889
            ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
890
        $queryBuilder->select('*')
891
            ->from('sys_template')
892
            ->where(
893
                $queryBuilder->expr()->eq('pid', $queryBuilder->createNamedParameter($pid, \PDO::PARAM_INT))
894
            );
895 View Code Duplication
        if (!empty($GLOBALS['TCA']['sys_template']['ctrl']['sortby'])) {
896
            $queryBuilder->orderBy($GLOBALS['TCA']['sys_template']['ctrl']['sortby']);
897
        }
898
899
        return $queryBuilder;
900
    }
901
902
    /**
903
     * This function compares the flattened constants (default and all).
904
     * Returns an array with the constants from the whole template which may be edited by the module.
905
     *
906
     * @param array $default
907
     * @return array
908
     */
909
    public function ext_compareFlatSetups($default)
910
    {
911
        $editableComments = [];
912
        $counter = 0;
913
        foreach ($this->flatSetup as $const => $value) {
914 View Code Duplication
            if (substr($const, -2) === '..' || !isset($this->flatSetup[$const . '..'])) {
915
                continue;
916
            }
917
            $counter++;
918
            $comment = trim($this->flatSetup[$const . '..']);
919
            $c_arr = explode(LF, $comment);
920
            foreach ($c_arr as $k => $v) {
921
                $line = trim(preg_replace('/^[#\\/]*/', '', $v));
922
                if (!$line) {
923
                    continue;
924
                }
925
                $parts = explode(';', $line);
926
                foreach ($parts as $par) {
927
                    if (strstr($par, '=')) {
928
                        $keyValPair = explode('=', $par, 2);
929
                        switch (trim(strtolower($keyValPair[0]))) {
930
                            case 'type':
931
                                // Type:
932
                                $editableComments[$const]['type'] = trim($keyValPair[1]);
933
                                break;
934
                            case 'cat':
935
                                // List of categories.
936
                                $catSplit = explode('/', strtolower($keyValPair[1]));
937
                                $catSplit[0] = trim($catSplit[0]);
938
                                if (isset($this->categoryLabels[$catSplit[0]])) {
939
                                    $catSplit[0] = $this->categoryLabels[$catSplit[0]];
940
                                }
941
                                $editableComments[$const]['cat'] = $catSplit[0];
942
                                // This is the subcategory. Must be a key in $this->subCategories[].
943
                                // catSplit[2] represents the search-order within the subcat.
944
                                $catSplit[1] = trim($catSplit[1]);
945 View Code Duplication
                                if ($catSplit[1] && isset($this->subCategories[$catSplit[1]])) {
946
                                    $editableComments[$const]['subcat_name'] = $catSplit[1];
947
                                    $orderIdentifier = isset($catSplit[2]) ? trim($catSplit[2]) : $counter;
948
                                    $editableComments[$const]['subcat'] = $this->subCategories[$catSplit[1]][1]
949
                                        . '/' . $catSplit[1] . '/' . $orderIdentifier . 'z';
950
                                } elseif (isset($catSplit[2])) {
951
                                    $editableComments[$const]['subcat'] = 'x' . '/' . trim($catSplit[2]) . 'z';
952
                                } else {
953
                                    $editableComments[$const]['subcat'] = 'x' . '/' . $counter . 'z';
954
                                }
955
                                break;
956
                            case 'label':
957
                                // Label
958
                                $editableComments[$const]['label'] = trim($keyValPair[1]);
959
                                break;
960 View Code Duplication
                            case 'customcategory':
961
                                // Custom category label
962
                                $customCategory = explode('=', $keyValPair[1], 2);
963
                                if (trim($customCategory[0])) {
964
                                    $categoryKey = strtolower($customCategory[0]);
965
                                    $this->categoryLabels[$categoryKey] = $this->getLanguageService()->sL($customCategory[1]);
966
                                }
967
                                break;
968 View Code Duplication
                            case 'customsubcategory':
969
                                // Custom subCategory label
970
                                $customSubcategory = explode('=', $keyValPair[1], 2);
971
                                if (trim($customSubcategory[0])) {
972
                                    $subCategoryKey = strtolower($customSubcategory[0]);
973
                                    $this->subCategories[$subCategoryKey][0] = $this->getLanguageService()->sL($customSubcategory[1]);
974
                                }
975
                                break;
976
                        }
977
                    }
978
                }
979
            }
980
            if (isset($editableComments[$const])) {
981
                $editableComments[$const]['name'] = $const;
982
                $editableComments[$const]['value'] = trim($value);
983
                if (isset($default[$const])) {
984
                    $editableComments[$const]['default_value'] = trim($default[$const]);
985
                }
986
            }
987
        }
988
        return $editableComments;
989
    }
990
991
    /**
992
     * @param array $editConstArray
993
     */
994
    public function ext_categorizeEditableConstants($editConstArray)
995
    {
996
        // Runs through the available constants and fills the $this->categories array with pointers and priority-info
997
        foreach ($editConstArray as $constName => $constData) {
998
            if (!$constData['type']) {
999
                $constData['type'] = 'string';
1000
            }
1001
            $cats = explode(',', $constData['cat']);
1002
            // if = only one category, while allows for many. We have agreed on only one category is the most basic way...
1003
            foreach ($cats as $theCat) {
1004
                $theCat = trim($theCat);
1005
                if ($theCat) {
1006
                    $this->categories[$theCat][$constName] = $constData['subcat'];
1007
                }
1008
            }
1009
        }
1010
    }
1011
1012
    /**
1013
     * @return array
1014
     */
1015
    public function ext_getCategoryLabelArray()
1016
    {
1017
        // Returns array used for labels in the menu.
1018
        $retArr = [];
1019
        foreach ($this->categories as $k => $v) {
1020
            if (!empty($v)) {
1021
                $retArr[$k] = strtoupper($k) . ' (' . count($v) . ')';
1022
            }
1023
        }
1024
        return $retArr;
1025
    }
1026
1027
    /**
1028
     * @param string $type
1029
     * @return array
1030
     */
1031
    public function ext_getTypeData($type)
1032
    {
1033
        $retArr = [];
1034
        $type = trim($type);
1035
        if (!$type) {
1036
            $retArr['type'] = 'string';
1037
        } else {
1038
            $m = strcspn($type, ' [');
1039
            $retArr['type'] = strtolower(substr($type, 0, $m));
0 ignored issues
show
Bug introduced by
It seems like substr($type, 0, $m) can also be of type false; however, parameter $str of strtolower() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1039
            $retArr['type'] = strtolower(/** @scrutinizer ignore-type */ substr($type, 0, $m));
Loading history...
1040
            $types = ['int' => 1, 'options' => 1, 'file' => 1, 'boolean' => 1, 'offset' => 1, 'user' => 1];
1041
            if (isset($types[$retArr['type']])) {
1042
                $p = trim(substr($type, $m));
0 ignored issues
show
Bug introduced by
It seems like substr($type, $m) can also be of type false; however, parameter $str of trim() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1042
                $p = trim(/** @scrutinizer ignore-type */ substr($type, $m));
Loading history...
1043
                $reg = [];
1044
                preg_match('/\\[(.*)\\]/', $p, $reg);
1045
                $p = trim($reg[1]);
1046
                if ($p) {
1047
                    $retArr['paramstr'] = $p;
1048
                    switch ($retArr['type']) {
1049
                        case 'int':
1050
                            if ($retArr['paramstr'][0] === '-') {
1051
                                $retArr['params'] = GeneralUtility::intExplode('-', substr($retArr['paramstr'], 1));
0 ignored issues
show
Bug introduced by
It seems like substr($retArr['paramstr'], 1) can also be of type false; however, parameter $string of TYPO3\CMS\Core\Utility\G...alUtility::intExplode() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1051
                                $retArr['params'] = GeneralUtility::intExplode('-', /** @scrutinizer ignore-type */ substr($retArr['paramstr'], 1));
Loading history...
1052
                                $retArr['params'][0] = (int)('-' . $retArr['params'][0]);
1053
                            } else {
1054
                                $retArr['params'] = GeneralUtility::intExplode('-', $retArr['paramstr']);
1055
                            }
1056
                            $retArr['min'] = $retArr['params'][0];
1057
                            $retArr['max'] = $retArr['params'][1];
1058
                            $retArr['paramstr'] = $retArr['params'][0] . ' - ' . $retArr['params'][1];
1059
                            break;
1060
                        case 'options':
1061
                            $retArr['params'] = explode(',', $retArr['paramstr']);
1062
                            break;
1063
                    }
1064
                }
1065
            }
1066
        }
1067
        return $retArr;
1068
    }
1069
1070
    /**
1071
     * @param array $params
1072
     * @return array
1073
     */
1074
    public function ext_fNandV($params)
1075
    {
1076
        $fN = 'data[' . $params['name'] . ']';
1077
        $idName = str_replace('.', '-', $params['name']);
1078
        $fV = $params['value'];
1079
        // Values entered from the constantsedit cannot be constants!	230502; removed \{ and set {
1080
        if (preg_match('/^{[\\$][a-zA-Z0-9\\.]*}$/', trim($fV), $reg)) {
1081
            $fV = '';
1082
        }
1083
        $fV = htmlspecialchars($fV);
1084
        return [$fN, $fV, $params, $idName];
1085
    }
1086
1087
    /**
1088
     * This functions returns the HTML-code that creates the editor-layout of the module.
1089
     *
1090
     * @param array $theConstants
1091
     * @param string $category
1092
     * @return string
1093
     */
1094
    public function ext_printFields($theConstants, $category)
1095
    {
1096
        reset($theConstants);
1097
        $output = '';
1098
        $subcat = '';
1099
        if (is_array($this->categories[$category])) {
1100
            if (!$this->doNotSortCategoriesBeforeMakingForm) {
1101
                asort($this->categories[$category]);
1102
            }
1103
            /** @var IconFactory $iconFactory */
1104
            $iconFactory = GeneralUtility::makeInstance(IconFactory::class);
1105
            foreach ($this->categories[$category] as $name => $type) {
1106
                $params = $theConstants[$name];
1107
                if (is_array($params)) {
1108
                    if ($subcat != $params['subcat_name']) {
1109
                        $subcat = $params['subcat_name'];
1110
                        $subcat_name = $params['subcat_name'] ? $this->subCategories[$params['subcat_name']][0] : 'Others';
1111
                        $output .= '<h3>' . $subcat_name . '</h3>';
1112
                    }
1113
                    $label = $this->getLanguageService()->sL($params['label']);
1114
                    $label_parts = explode(':', $label, 2);
1115
                    if (count($label_parts) === 2) {
1116
                        $head = trim($label_parts[0]);
1117
                        $body = trim($label_parts[1]);
1118
                    } else {
1119
                        $head = trim($label_parts[0]);
1120
                        $body = '';
1121
                    }
1122
                    $typeDat = $this->ext_getTypeData($params['type']);
1123
                    $p_field = '';
1124
                    $raname = substr(md5($params['name']), 0, 10);
1125
                    $aname = '\'' . $raname . '\'';
0 ignored issues
show
Bug introduced by
Are you sure $raname of type false|string can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1125
                    $aname = '\'' . /** @scrutinizer ignore-type */ $raname . '\'';
Loading history...
1126
                    list($fN, $fV, $params, $idName) = $this->ext_fNandV($params);
1127
                    $idName = htmlspecialchars($idName);
1128
                    $hint = '';
1129
                    switch ($typeDat['type']) {
1130
                        case 'int':
1131
                        case 'int+':
1132
                            $additionalAttributes = '';
1133
                            if ($typeDat['paramstr']) {
1134
                                $hint = ' Range: ' . $typeDat['paramstr'];
1135
                            } elseif ($typeDat['type'] === 'int+') {
1136
                                $hint = ' Range: 0 - ';
1137
                                $typeDat['min'] = 0;
1138
                            } else {
1139
                                $hint = ' (Integer)';
1140
                            }
1141
1142
                            if (isset($typeDat['min'])) {
1143
                                $additionalAttributes .= ' min="' . (int)$typeDat['min'] . '" ';
1144
                            }
1145
                            if (isset($typeDat['max'])) {
1146
                                $additionalAttributes .= ' max="' . (int)$typeDat['max'] . '" ';
1147
                            }
1148
1149
                            $p_field =
1150
                                '<input class="form-control" id="' . $idName . '" type="number"'
1151
                                . ' name="' . $fN . '" value="' . $fV . '"' . ' onChange="uFormUrl(' . $aname . ')"' . $additionalAttributes . ' />';
1152
                            break;
1153
                        case 'color':
1154
                            $p_field = '
1155
                                <input class="form-control formengine-colorpickerelement t3js-color-picker" type="text" id="input-' . $idName . '" rel="' . $idName .
1156
                                '" name="' . $fN . '" value="' . $fV . '" onChange="uFormUrl(' . $aname . ')" />';
1157
1158
                            if (empty($this->inlineJavaScript[$typeDat['type']])) {
1159
                                $this->inlineJavaScript[$typeDat['type']] = 'require([\'TYPO3/CMS/Backend/ColorPicker\'], function(ColorPicker){ColorPicker.initialize()});';
1160
                            }
1161
                            break;
1162
                        case 'wrap':
1163
                            $wArr = explode('|', $fV);
1164
                            $p_field = '<div class="input-group">
1165
                                            <input class="form-control form-control-adapt" type="text" id="' . $idName . '" name="' . $fN . '" value="' . $wArr[0] . '" onChange="uFormUrl(' . $aname . ')" />
1166
                                            <span class="input-group-addon input-group-icon">|</span>
1167
                                            <input class="form-control form-control-adapt" type="text" name="W' . $fN . '" value="' . $wArr[1] . '" onChange="uFormUrl(' . $aname . ')" />
1168
                                         </div>';
1169
                            break;
1170
                        case 'offset':
1171
                            $wArr = explode(',', $fV);
1172
                            $labels = GeneralUtility::trimExplode(',', $typeDat['paramstr']);
1173
                            $p_field = '<span class="input-group-addon input-group-icon">' . ($labels[0] ?: 'x') . '</span><input type="text" class="form-control form-control-adapt" name="' . $fN . '" value="' . $wArr[0] . '" onChange="uFormUrl(' . $aname . ')" />';
1174
                            $p_field .= '<span class="input-group-addon input-group-icon">' . ($labels[1] ?: 'y') . '</span><input type="text" name="W' . $fN . '" value="' . $wArr[1] . '" class="form-control form-control-adapt" onChange="uFormUrl(' . $aname . ')" />';
1175
                            $labelsCount = count($labels);
1176
                            for ($aa = 2; $aa < $labelsCount; $aa++) {
1177
                                if ($labels[$aa]) {
1178
                                    $p_field .= '<span class="input-group-addon input-group-icon">' . $labels[$aa] . '</span><input type="text" name="W' . $aa . $fN . '" value="' . $wArr[$aa] . '" class="form-control form-control-adapt" onChange="uFormUrl(' . $aname . ')" />';
1179
                                } else {
1180
                                    $p_field .= '<input type="hidden" name="W' . $aa . $fN . '" value="' . $wArr[$aa] . '" />';
1181
                                }
1182
                            }
1183
                            $p_field = '<div class="input-group">' . $p_field . '</div>';
1184
                            break;
1185
                        case 'options':
1186
                            if (is_array($typeDat['params'])) {
1187
                                $p_field = '';
1188
                                foreach ($typeDat['params'] as $val) {
1189
                                    $vParts = explode('=', $val, 2);
1190
                                    $label = $vParts[0];
1191
                                    $val = isset($vParts[1]) ? $vParts[1] : $vParts[0];
1192
                                    // option tag:
1193
                                    $sel = '';
1194
                                    if ($val === $params['value']) {
1195
                                        $sel = ' selected';
1196
                                    }
1197
                                    $p_field .= '<option value="' . htmlspecialchars($val) . '"' . $sel . '>' . $this->getLanguageService()->sL($label) . '</option>';
1198
                                }
1199
                                $p_field = '<select class="form-control" id="' . $idName . '" name="' . $fN . '" onChange="uFormUrl(' . $aname . ')">' . $p_field . '</select>';
1200
                            }
1201
                            break;
1202
                        case 'boolean':
1203
                            $sel = $fV ? 'checked' : '';
1204
                            $p_field =
1205
                                '<input type="hidden" name="' . $fN . '" value="0" />'
1206
                                . '<label class="btn btn-default btn-checkbox">'
1207
                                . '<input id="' . $idName . '" type="checkbox" name="' . $fN . '" value="' . ($typeDat['paramstr'] ? $typeDat['paramstr'] : 1) . '" ' . $sel . ' onClick="uFormUrl(' . $aname . ')" />'
1208
                                . '<span class="t3-icon fa"></span>'
1209
                                . '</label>';
1210
                            break;
1211
                        case 'comment':
1212
                            $sel = $fV ? 'checked' : '';
1213
                            $p_field =
1214
                                '<input type="hidden" name="' . $fN . '" value="#" />'
1215
                                . '<label class="btn btn-default btn-checkbox">'
1216
                                . '<input id="' . $idName . '" type="checkbox" name="' . $fN . '" value="" ' . $sel . ' onClick="uFormUrl(' . $aname . ')" />'
1217
                                . '<span class="t3-icon fa"></span>'
1218
                                . '</label>';
1219
                            break;
1220
                        case 'file':
1221
                            // extensionlist
1222
                            $extList = $typeDat['paramstr'];
1223
                            if ($extList === 'IMAGE_EXT') {
1224
                                $extList = $GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'];
1225
                            }
1226
                            $p_field = '<option value="">(' . $extList . ')</option>';
1227
                            if (trim($params['value'])) {
1228
                                $val = $params['value'];
1229
                                $p_field .= '<option value=""></option>';
1230
                                $p_field .= '<option value="' . htmlspecialchars($val) . '" selected>' . $val . '</option>';
1231
                            }
1232
                            $p_field = '<select class="form-select" id="' . $idName . '" name="' . $fN . '" onChange="uFormUrl(' . $aname . ')">' . $p_field . '</select>';
1233
                            break;
1234
                        case 'user':
1235
                            $userFunction = $typeDat['paramstr'];
1236
                            $userFunctionParams = ['fieldName' => $fN, 'fieldValue' => $fV];
1237
                            $p_field = GeneralUtility::callUserFunction($userFunction, $userFunctionParams, $this);
1238
                            break;
1239
                        default:
1240
                            $p_field = '<input class="form-control" id="' . $idName . '" type="text" name="' . $fN . '" value="' . $fV . '"'
1241
                                . ' onChange="uFormUrl(' . $aname . ')" />';
1242
                    }
1243
                    // Define default names and IDs
1244
                    $userTyposcriptID = 'userTS-' . $idName;
1245
                    $defaultTyposcriptID = 'defaultTS-' . $idName;
1246
                    $checkboxName = 'check[' . $params['name'] . ']';
1247
                    $checkboxID = 'check-' . $idName;
1248
                    $userTyposcriptStyle = '';
1249
                    $deleteIconHTML = '';
1250
                    $constantCheckbox = '';
1251
                    $constantDefaultRow = '';
1252
                    if (!$this->ext_dontCheckIssetValues) {
1253
                        // Set the default styling options
1254
                        if (isset($this->objReg[$params['name']])) {
1255
                            $checkboxValue = 'checked';
1256
                            $defaultTyposcriptStyle = 'style="display:none;"';
1257
                        } else {
1258
                            $checkboxValue = '';
1259
                            $userTyposcriptStyle = 'style="display:none;"';
1260
                            $defaultTyposcriptStyle = '';
1261
                        }
1262
                        $deleteTitle = htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.deleteTitle'));
1263
                        $deleteIcon = $iconFactory->getIcon('actions-edit-undo', Icon::SIZE_SMALL)->render();
1264
                        $deleteIconHTML =
1265
                            '<button type="button" class="btn btn-default t3js-toggle" data-toggle="undo" rel="' . $idName . '">'
1266
                                . '<span title="' . $deleteTitle . '" alt="' . $deleteTitle . '">'
1267
                                    . $deleteIcon
1268
                                . '</span>'
1269
                            . '</button>';
1270
                        $editTitle = htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.editTitle'));
1271
                        $editIcon = $iconFactory->getIcon('actions-open', Icon::SIZE_SMALL)->render();
1272
                        $editIconHTML =
1273
                            '<button type="button" class="btn btn-default t3js-toggle" data-toggle="edit"  rel="' . $idName . '">'
1274
                                . '<span title="' . $editTitle . '" alt="' . $editTitle . '">'
1275
                                    . $editIcon
1276
                                . '</span>'
1277
                            . '</button>';
1278
                        $constantCheckbox = '<input type="hidden" name="' . $checkboxName . '" id="' . $checkboxID . '" value="' . $checkboxValue . '"/>';
1279
                        // If there's no default value for the field, use a static label.
1280
                        if (!$params['default_value']) {
1281
                            $params['default_value'] = '[Empty]';
1282
                        }
1283
                        $constantDefaultRow =
1284
                            '<div class="input-group defaultTS" id="' . $defaultTyposcriptID . '" ' . $defaultTyposcriptStyle . '>'
1285
                                . '<span class="input-group-btn">' . $editIconHTML . '</span>'
1286
                                . '<input class="form-control" type="text" placeholder="' . htmlspecialchars($params['default_value']) . '" readonly>'
1287
                            . '</div>';
1288
                    }
1289
                    $constantEditRow =
1290
                        '<div class="input-group userTS" id="' . $userTyposcriptID . '" ' . $userTyposcriptStyle . '>'
1291
                            . '<span class="input-group-btn">' . $deleteIconHTML . '</span>'
1292
                            . $p_field
1293
                        . '</div>';
1294
                    $constantLabel = '<label class="t3js-formengine-label"><span>' . htmlspecialchars($head) . '</span></label>';
1295
                    $constantName = '<span class="help-block">[' . $params['name'] . ']</span>';
1296
                    $constantDescription = $body ? '<p class="help-block">' . htmlspecialchars($body) . '</p>' : '';
1297
                    $constantData = '';
1298
                    if ($hint !== '') {
1299
                        $constantData .= '<span class="help-block">' . $hint . '</span>';
1300
                    }
1301
                    $constantData .=
1302
                        $constantCheckbox
1303
                        . $constantEditRow
1304
                        . $constantDefaultRow;
1305
1306
                    $output .=
1307
                        '<fieldset class="form-section">'
1308
                            . '<a name="' . $raname . '"></a>'
1309
                            . '<div class="form-group">'
1310
                                . $constantLabel . $constantName . $constantDescription . $constantData
1311
                            . '</div>'
1312
                        . '</fieldset>';
1313
                } else {
1314
                    debug('Error. Constant did not exist. Should not happen.');
1315
                }
1316
            }
1317
        }
1318
        return '<div class="tstemplate-constanteditor">' . $output . '</div>';
1319
    }
1320
1321
    /***************************
1322
     *
1323
     * Processing input values
1324
     *
1325
     ***************************/
1326
    /**
1327
     * @param string $constants
1328
     */
1329
    public function ext_regObjectPositions($constants)
1330
    {
1331
        // This runs through the lines of the constants-field of the active template and registers the constants-names
1332
        // and line positions in an array, $this->objReg
1333
        $this->raw = explode(LF, $constants);
1334
        $this->rawP = 0;
1335
        // Resetting the objReg if the divider is found!!
1336
        $this->objReg = [];
1337
        $this->ext_regObjects('');
1338
    }
1339
1340
    /**
1341
     * @param string $pre
1342
     */
1343
    public function ext_regObjects($pre)
1344
    {
1345
        // Works with regObjectPositions. "expands" the names of the TypoScript objects
1346
        while (isset($this->raw[$this->rawP])) {
1347
            $line = ltrim($this->raw[$this->rawP]);
1348
            $this->rawP++;
1349
            if ($line) {
1350
                if ($line[0] === '[') {
1351
                } elseif (strcspn($line, '}#/') != 0) {
1352
                    $varL = strcspn($line, ' {=<');
1353
                    $var = substr($line, 0, $varL);
1354
                    $line = ltrim(substr($line, $varL));
0 ignored issues
show
Bug introduced by
It seems like substr($line, $varL) can also be of type false; however, parameter $str of ltrim() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1354
                    $line = ltrim(/** @scrutinizer ignore-type */ substr($line, $varL));
Loading history...
1355
                    switch ($line[0]) {
1356
                        case '=':
1357
                            $this->objReg[$pre . $var] = $this->rawP - 1;
0 ignored issues
show
Bug introduced by
Are you sure $var of type false|string can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1357
                            $this->objReg[$pre . /** @scrutinizer ignore-type */ $var] = $this->rawP - 1;
Loading history...
1358
                            break;
1359
                        case '{':
1360
                            $this->ext_inBrace++;
1361
                            $this->ext_regObjects($pre . $var . '.');
1362
                            break;
1363
                    }
1364
                    $this->lastComment = '';
1365
                } elseif ($line[0] === '}') {
1366
                    $this->lastComment = '';
1367
                    $this->ext_inBrace--;
1368
                    if ($this->ext_inBrace < 0) {
1369
                        $this->ext_inBrace = 0;
1370
                    } else {
1371
                        break;
1372
                    }
1373
                }
1374
            }
1375
        }
1376
    }
1377
1378
    /**
1379
     * @param string $key
1380
     * @param string $var
1381
     */
1382
    public function ext_putValueInConf($key, $var)
1383
    {
1384
        // Puts the value $var to the TypoScript value $key in the current lines of the templates.
1385
        // If the $key is not found in the template constants field, a new line is inserted in the bottom.
1386
        $theValue = ' ' . trim($var);
1387
        if (isset($this->objReg[$key])) {
1388
            $lineNum = $this->objReg[$key];
1389
            $parts = explode('=', $this->raw[$lineNum], 2);
1390
            if (count($parts) === 2) {
1391
                $parts[1] = $theValue;
1392
            }
1393
            $this->raw[$lineNum] = implode($parts, '=');
0 ignored issues
show
Bug introduced by
$parts of type array<mixed,mixed|string>|array is incompatible with the type string expected by parameter $glue of implode(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1393
            $this->raw[$lineNum] = implode(/** @scrutinizer ignore-type */ $parts, '=');
Loading history...
Bug introduced by
'=' of type string is incompatible with the type array expected by parameter $pieces of implode(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1393
            $this->raw[$lineNum] = implode($parts, /** @scrutinizer ignore-type */ '=');
Loading history...
1394
        } else {
1395
            $this->raw[] = $key . ' =' . $theValue;
1396
        }
1397
        $this->changed = true;
1398
    }
1399
1400
    /**
1401
     * @param string $key
1402
     */
1403
    public function ext_removeValueInConf($key)
1404
    {
1405
        // Removes the value in the configuration
1406
        if (isset($this->objReg[$key])) {
1407
            $lineNum = $this->objReg[$key];
1408
            unset($this->raw[$lineNum]);
1409
        }
1410
        $this->changed = true;
1411
    }
1412
1413
    /**
1414
     * @param array $arr
1415
     * @param array $settings
1416
     * @return array
1417
     */
1418 View Code Duplication
    public function ext_depthKeys($arr, $settings)
1419
    {
1420
        $tsbrArray = [];
1421
        foreach ($arr as $theK => $theV) {
1422
            $theKeyParts = explode('.', $theK);
1423
            $depth = '';
1424
            $c = count($theKeyParts);
1425
            $a = 0;
1426
            foreach ($theKeyParts as $p) {
1427
                $a++;
1428
                $depth .= ($depth ? '.' : '') . $p;
1429
                $tsbrArray[$depth] = $c == $a ? $theV : 1;
1430
            }
1431
        }
1432
        // Modify settings
1433
        foreach ($tsbrArray as $theK => $theV) {
1434
            if ($theV) {
1435
                $settings[$theK] = 1;
1436
            } else {
1437
                unset($settings[$theK]);
1438
            }
1439
        }
1440
        return $settings;
1441
    }
1442
1443
    /**
1444
     * Process input
1445
     *
1446
     * @param array $http_post_vars
1447
     * @param array $http_post_files (not used anymore)
1448
     * @param array $theConstants
1449
     * @param array $tplRow Not used
1450
     */
1451
    public function ext_procesInput($http_post_vars, $http_post_files, $theConstants, $tplRow)
0 ignored issues
show
Unused Code introduced by
The parameter $tplRow is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

1451
    public function ext_procesInput($http_post_vars, $http_post_files, $theConstants, /** @scrutinizer ignore-unused */ $tplRow)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $http_post_files is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

1451
    public function ext_procesInput($http_post_vars, /** @scrutinizer ignore-unused */ $http_post_files, $theConstants, $tplRow)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1452
    {
1453
        $data = $http_post_vars['data'];
1454
        $check = $http_post_vars['check'];
1455
        $Wdata = $http_post_vars['Wdata'];
1456
        $W2data = $http_post_vars['W2data'];
1457
        $W3data = $http_post_vars['W3data'];
1458
        $W4data = $http_post_vars['W4data'];
1459
        $W5data = $http_post_vars['W5data'];
1460
        if (is_array($data)) {
1461
            foreach ($data as $key => $var) {
1462
                if (isset($theConstants[$key])) {
1463
                    // If checkbox is set, update the value
1464
                    if ($this->ext_dontCheckIssetValues || isset($check[$key])) {
1465
                        // Exploding with linebreak, just to make sure that no multiline input is given!
1466
                        list($var) = explode(LF, $var);
1467
                        $typeDat = $this->ext_getTypeData($theConstants[$key]['type']);
1468
                        switch ($typeDat['type']) {
1469
                            case 'int':
1470
                                if ($typeDat['paramstr']) {
1471
                                    $var = MathUtility::forceIntegerInRange($var, $typeDat['params'][0], $typeDat['params'][1]);
1472
                                } else {
1473
                                    $var = (int)$var;
1474
                                }
1475
                                break;
1476
                            case 'int+':
1477
                                $var = max(0, (int)$var);
1478
                                break;
1479
                            case 'color':
1480
                                $col = [];
1481
                                if ($var) {
1482
                                    $var = preg_replace('/[^A-Fa-f0-9]*/', '', $var);
1483
                                    $useFulHex = strlen($var) > 3;
1484
                                    $col[] = hexdec($var[0]);
1485
                                    $col[] = hexdec($var[1]);
1486
                                    $col[] = hexdec($var[2]);
1487
                                    if ($useFulHex) {
1488
                                        $col[] = hexdec($var[3]);
1489
                                        $col[] = hexdec($var[4]);
1490
                                        $col[] = hexdec($var[5]);
1491
                                    }
1492
                                    $var = substr(('0' . dechex($col[0])), -1) . substr(('0' . dechex($col[1])), -1) . substr(('0' . dechex($col[2])), -1);
0 ignored issues
show
Bug introduced by
Are you sure substr('0' . dechex($col[0]), -1) of type false|string can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1492
                                    $var = /** @scrutinizer ignore-type */ substr(('0' . dechex($col[0])), -1) . substr(('0' . dechex($col[1])), -1) . substr(('0' . dechex($col[2])), -1);
Loading history...
Bug introduced by
Are you sure substr('0' . dechex($col[2]), -1) of type false|string can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1492
                                    $var = substr(('0' . dechex($col[0])), -1) . substr(('0' . dechex($col[1])), -1) . /** @scrutinizer ignore-type */ substr(('0' . dechex($col[2])), -1);
Loading history...
Bug introduced by
It seems like $col[0] can also be of type double; however, parameter $number of dechex() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1492
                                    $var = substr(('0' . dechex(/** @scrutinizer ignore-type */ $col[0])), -1) . substr(('0' . dechex($col[1])), -1) . substr(('0' . dechex($col[2])), -1);
Loading history...
1493
                                    if ($useFulHex) {
1494
                                        $var .= substr(('0' . dechex($col[3])), -1) . substr(('0' . dechex($col[4])), -1) . substr(('0' . dechex($col[5])), -1);
0 ignored issues
show
Bug introduced by
Are you sure substr('0' . dechex($col[3]), -1) of type false|string can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1494
                                        $var .= /** @scrutinizer ignore-type */ substr(('0' . dechex($col[3])), -1) . substr(('0' . dechex($col[4])), -1) . substr(('0' . dechex($col[5])), -1);
Loading history...
Bug introduced by
Are you sure substr('0' . dechex($col[5]), -1) of type false|string can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1494
                                        $var .= substr(('0' . dechex($col[3])), -1) . substr(('0' . dechex($col[4])), -1) . /** @scrutinizer ignore-type */ substr(('0' . dechex($col[5])), -1);
Loading history...
1495
                                    }
1496
                                    $var = '#' . strtoupper($var);
1497
                                }
1498
                                break;
1499
                            case 'comment':
1500
                                if ($var) {
1501
                                    $var = '#';
1502
                                } else {
1503
                                    $var = '';
1504
                                }
1505
                                break;
1506
                            case 'wrap':
1507
                                if (isset($Wdata[$key])) {
1508
                                    $var .= '|' . $Wdata[$key];
1509
                                }
1510
                                break;
1511
                            case 'offset':
1512
                                if (isset($Wdata[$key])) {
1513
                                    $var = (int)$var . ',' . (int)$Wdata[$key];
1514
                                    if (isset($W2data[$key])) {
1515
                                        $var .= ',' . (int)$W2data[$key];
1516
                                        if (isset($W3data[$key])) {
1517
                                            $var .= ',' . (int)$W3data[$key];
1518
                                            if (isset($W4data[$key])) {
1519
                                                $var .= ',' . (int)$W4data[$key];
1520
                                                if (isset($W5data[$key])) {
1521
                                                    $var .= ',' . (int)$W5data[$key];
1522
                                                }
1523
                                            }
1524
                                        }
1525
                                    }
1526
                                }
1527
                                break;
1528
                            case 'boolean':
1529
                                if ($var) {
1530
                                    $var = $typeDat['paramstr'] ? $typeDat['paramstr'] : 1;
1531
                                }
1532
                                break;
1533
                        }
1534
                        if ($this->ext_printAll || (string)$theConstants[$key]['value'] !== (string)$var) {
1535
                            // Put value in, if changed.
1536
                            $this->ext_putValueInConf($key, $var);
1537
                        }
1538
                        // Remove the entry because it has been "used"
1539
                        unset($check[$key]);
1540
                    } else {
1541
                        $this->ext_removeValueInConf($key);
1542
                    }
1543
                }
1544
            }
1545
        }
1546
        // Remaining keys in $check indicates fields that are just clicked "on" to be edited.
1547
        // Therefore we get the default value and puts that in the template as a start...
1548
        if (!$this->ext_dontCheckIssetValues && is_array($check)) {
1549
            foreach ($check as $key => $var) {
1550
                if (isset($theConstants[$key])) {
1551
                    $dValue = $theConstants[$key]['default_value'];
1552
                    $this->ext_putValueInConf($key, $dValue);
1553
                }
1554
            }
1555
        }
1556
    }
1557
1558
    /**
1559
     * @param int $id
1560
     * @param string $perms_clause
1561
     * @return array
1562
     */
1563
    public function ext_prevPageWithTemplate($id, $perms_clause)
1564
    {
1565
        $rootLine = BackendUtility::BEgetRootLine($id, $perms_clause ? ' AND ' . $perms_clause : '');
1566
        foreach ($rootLine as $p) {
1567
            if ($this->ext_getFirstTemplate($p['uid'])) {
1568
                return $p;
1569
            }
1570
        }
1571
        return [];
1572
    }
1573
1574
    /**
1575
     * Is set by runThroughTemplates(), previously set via TemplateAnalyzerModuleFunctionController from the outside
1576
     *
1577
     * @return array
1578
     */
1579
    protected function getRootLine()
1580
    {
1581
        return is_array($this->absoluteRootLine) ? $this->absoluteRootLine : [];
1582
    }
1583
1584
    /**
1585
     * @return LanguageService
1586
     */
1587
    protected function getLanguageService()
1588
    {
1589
        return $GLOBALS['LANG'];
1590
    }
1591
1592
    /**
1593
     * @return DocumentTemplate
1594
     */
1595
    protected function getDocumentTemplate()
1596
    {
1597
        return $GLOBALS['TBE_TEMPLATE'];
1598
    }
1599
}
1600