Passed
Push — master ( 5f2715...9adfbc )
by MusikAnimal
06:16
created

AppExtension::titleWithNs()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
cc 2
eloc 3
nc 2
nop 3
dl 0
loc 6
ccs 0
cts 4
cp 0
crap 6
rs 10
c 0
b 0
f 0
1
<?php
2
declare(strict_types = 1);
3
4
/**
5
 * This file contains only the AppExtension class.
6
 */
7
8
namespace AppBundle\Twig;
9
10
use AppBundle\Helper\I18nHelper;
11
use AppBundle\Model\Edit;
12
use AppBundle\Model\Project;
13
use AppBundle\Model\User;
14
use AppBundle\Repository\ProjectRepository;
15
use DateTime;
16
use Doctrine\DBAL\Connection;
17
use Symfony\Component\DependencyInjection\ContainerInterface;
18
use Symfony\Component\HttpFoundation\RequestStack;
19
use Symfony\Component\HttpFoundation\Session\SessionInterface;
20
use Twig_Extension;
21
22
/**
23
 * Twig functions and filters for XTools.
24
 */
25
class AppExtension extends Twig_Extension
26
{
27
    /** @var ContainerInterface The application's container interface. */
28
    protected $container;
29
30
    /** @var RequestStack The request stack. */
31
    protected $requestStack;
32
33
    /** @var SessionInterface User's current session. */
34
    protected $session;
35
36
    /** @var I18nHelper For i18n and l10n. */
37
    protected $i18n;
38
39
    /** @var float Duration of the current HTTP request in seconds. */
40
    protected $requestTime;
41
42
    /**
43
     * Constructor, with the I18nHelper through dependency injection.
44
     * @param ContainerInterface $container
45
     * @param RequestStack $requestStack
46
     * @param SessionInterface $session
47
     * @param I18nHelper $i18n
48
     */
49 27
    public function __construct(
50
        ContainerInterface $container,
51
        RequestStack $requestStack,
52
        SessionInterface $session,
53
        I18nHelper $i18n
54
    ) {
55 27
        $this->container = $container;
56 27
        $this->requestStack = $requestStack;
57 27
        $this->session = $session;
58 27
        $this->i18n = $i18n;
59 27
    }
60
61
    /*********************************** FUNCTIONS ***********************************/
62
63
    /**
64
     * Get all functions that this class provides.
65
     * @return \Twig_SimpleFunction[]
66
     */
67 11
    public function getFunctions(): array
68
    {
69 11
        $options = ['is_safe' => ['html']];
70
        return [
71 11
            new \Twig_SimpleFunction('request_time', [$this, 'requestTime'], $options),
72 11
            new \Twig_SimpleFunction('memory_usage', [$this, 'requestMemory'], $options),
73 11
            new \Twig_SimpleFunction('msgIfExists', [$this, 'msgIfExists'], $options),
74 11
            new \Twig_SimpleFunction('msgExists', [$this, 'msgExists'], $options),
75 11
            new \Twig_SimpleFunction('msg', [$this, 'msg'], $options),
76 11
            new \Twig_SimpleFunction('lang', [$this, 'getLang'], $options),
77 11
            new \Twig_SimpleFunction('langName', [$this, 'getLangName'], $options),
78 11
            new \Twig_SimpleFunction('fallbackLangs', [$this, 'getFallbackLangs', $options]),
79 11
            new \Twig_SimpleFunction('allLangs', [$this, 'getAllLangs']),
80 11
            new \Twig_SimpleFunction('isRTL', [$this, 'isRTL']),
81 11
            new \Twig_SimpleFunction('shortHash', [$this, 'gitShortHash']),
82 11
            new \Twig_SimpleFunction('hash', [$this, 'gitHash']),
83 11
            new \Twig_SimpleFunction('releaseDate', [$this, 'gitDate']),
84 11
            new \Twig_SimpleFunction('enabled', [$this, 'tabEnabled']),
85 11
            new \Twig_SimpleFunction('tools', [$this, 'tools']),
86 11
            new \Twig_SimpleFunction('color', [$this, 'getColorList']),
87 11
            new \Twig_SimpleFunction('chartColor', [$this, 'chartColor']),
88 11
            new \Twig_SimpleFunction('isSingleWiki', [$this, 'isSingleWiki']),
89 11
            new \Twig_SimpleFunction('getReplagThreshold', [$this, 'getReplagThreshold']),
90 11
            new \Twig_SimpleFunction('isWMFLabs', [$this, 'isWMFLabs']),
91 11
            new \Twig_SimpleFunction('replag', [$this, 'replag']),
92 11
            new \Twig_SimpleFunction('quote', [$this, 'quote']),
93 11
            new \Twig_SimpleFunction('bugReportURL', [$this, 'bugReportURL']),
94 11
            new \Twig_SimpleFunction('logged_in_user', [$this, 'loggedInUser']),
95 11
            new \Twig_SimpleFunction('isUserAnon', [$this, 'isUserAnon']),
96 11
            new \Twig_SimpleFunction('nsName', [$this, 'nsName']),
97 11
            new \Twig_SimpleFunction('titleWithNs', [$this, 'titleWithNs']),
98 11
            new \Twig_SimpleFunction('formatDuration', [$this, 'formatDuration']),
99 11
            new \Twig_SimpleFunction('numberFormat', [$this, 'numberFormat']),
100 11
            new \Twig_SimpleFunction('buildQuery', [$this, 'buildQuery']),
101
        ];
102
    }
103
104
    /**
105
     * Get the duration of the current HTTP request in seconds.
106
     * @return float
107
     * Untestable since there is no request stack in the tests.
108
     * @codeCoverageIgnore
109
     */
110
    public function requestTime(): float
111
    {
112
        if (!isset($this->requestTime)) {
113
            $this->requestTime = microtime(true) - $this->getRequest()->server->get('REQUEST_TIME_FLOAT');
114
        }
115
116
        return $this->requestTime;
117
    }
118
119
    /**
120
     * Get the formatted real memory usage.
121
     * @return float
122
     */
123 12
    public function requestMemory(): float
124
    {
125 12
        $mem = memory_get_usage(false);
126 12
        $div = pow(1024, 2);
127 12
        return $mem / $div;
128
    }
129
130
    /**
131
     * Get an i18n message.
132
     * @param string $message
133
     * @param string[] $vars
134
     * @return string|null
135
     */
136 11
    public function msg(string $message = '', array $vars = []): ?string
137
    {
138 11
        return $this->i18n->msg($message, $vars);
139
    }
140
141
    /**
142
     * See if a given i18n message exists.
143
     * @param string $message The message.
144
     * @param string[] $vars
145
     * @return bool
146
     */
147
    public function msgExists(?string $message, array $vars = []): bool
148
    {
149
        return $this->i18n->msgExists($message, $vars);
150
    }
151
152
    /**
153
     * Get an i18n message if it exists, otherwise just get the message key.
154
     * @param string $message
155
     * @param string[] $vars
156
     * @return string
157
     */
158
    public function msgIfExists(?string $message, array $vars = []): string
159
    {
160
        return $this->i18n->msgIfExists($message, $vars);
161
    }
162
163
    /**
164
     * Get the current language code.
165
     * @return string
166
     */
167 12
    public function getLang(): string
168
    {
169 12
        return $this->i18n->getLang();
170
    }
171
172
    /**
173
     * Get the current language name (defaults to 'English').
174
     * @return string
175
     */
176 12
    public function getLangName(): string
177
    {
178 12
        return $this->i18n->getLangName();
179
    }
180
181
    /**
182
     * Get the fallback languages for the current language, so we know what to load with jQuery.i18n.
183
     * @return string[]
184
     */
185 11
    public function getFallbackLangs(): array
186
    {
187 11
        return $this->i18n->getFallbacks();
188
    }
189
190
    /**
191
     * Get all available languages in the i18n directory
192
     * @return string[] Associative array of langKey => langName
193
     */
194 12
    public function getAllLangs(): array
195
    {
196 12
        return $this->i18n->getAllLangs();
197
    }
198
199
    /**
200
     * Whether the current language is right-to-left.
201
     * @param string|null $lang Optionally provide a specific lanuage code.
202
     * @return bool
203
     */
204 12
    public function isRTL(?string $lang = null): bool
205
    {
206 12
        return $this->i18n->isRTL($lang);
207
    }
208
209
    /**
210
     * Get the short hash of the currently checked-out Git commit.
211
     * @return string
212
     */
213 11
    public function gitShortHash(): string
214
    {
215 11
        return exec('git rev-parse --short HEAD');
216
    }
217
218
    /**
219
     * Get the full hash of the currently checkout-out Git commit.
220
     * @return string
221
     */
222 12
    public function gitHash(): string
223
    {
224 12
        return exec('git rev-parse HEAD');
225
    }
226
227
    /**
228
     * Get the date of the HEAD commit.
229
     * @return string
230
     */
231 2
    public function gitDate(): string
232
    {
233 2
        $date = new DateTime(exec('git show -s --format=%ci'));
234 2
        return $this->dateFormat($date, 'yyyy-MM-dd');
235
    }
236
237
    /**
238
     * Check whether a given tool is enabled.
239
     * @param string $tool The short name of the tool.
240
     * @return bool
241
     */
242 11
    public function tabEnabled(string $tool = 'index'): bool
243
    {
244 11
        $param = false;
245 11
        if ($this->container->hasParameter("enable.$tool")) {
246 11
            $param = boolval($this->container->getParameter("enable.$tool"));
247
        }
248 11
        return $param;
249
    }
250
251
    /**
252
     * Get a list of the short names of all tools.
253
     * @return string[]
254
     */
255 11
    public function tools(): array
256
    {
257 11
        $retVal = [];
258 11
        if ($this->container->hasParameter('tools')) {
259 11
            $retVal = $this->container->getParameter('tools');
260
        }
261 11
        return $retVal;
262
    }
263
264
    /**
265
     * Get a list of namespace colours (one or all).
266
     * @param int|false $num The NS ID to get. False to get the full list.
267
     * @return string|string[] Color or all all colors indexed by namespace ID.
268
     */
269
    public static function getColorList($num = false)
270
    {
271
        $colors = [
272
            0 => '#FF5555',
273
            1 => '#55FF55',
274
            2 => '#FFEE22',
275
            3 => '#FF55FF',
276
            4 => '#5555FF',
277
            5 => '#55FFFF',
278
            6 => '#C00000',
279
            7 => '#0000C0',
280
            8 => '#008800',
281
            9 => '#00C0C0',
282
            10 => '#FFAFAF',
283
            11 => '#808080',
284
            12 => '#00C000',
285
            13 => '#404040',
286
            14 => '#C0C000',
287
            15 => '#C000C0',
288
            90 => '#991100',
289
            91 => '#99FF00',
290
            92 => '#000000',
291
            93 => '#777777',
292
            100 => '#75A3D1',
293
            101 => '#A679D2',
294
            102 => '#660000',
295
            103 => '#000066',
296
            104 => '#FAFFAF',
297
            105 => '#408345',
298
            106 => '#5c8d20',
299
            107 => '#e1711d',
300
            108 => '#94ef2b',
301
            109 => '#756a4a',
302
            110 => '#6f1dab',
303
            111 => '#301e30',
304
            112 => '#5c9d96',
305
            113 => '#a8cd8c',
306
            114 => '#f2b3f1',
307
            115 => '#9b5828',
308
            116 => '#002288',
309
            117 => '#0000CC',
310
            118 => '#99FFFF',
311
            119 => '#99BBFF',
312
            120 => '#FF99FF',
313
            121 => '#CCFFFF',
314
            122 => '#CCFF00',
315
            123 => '#CCFFCC',
316
            200 => '#33FF00',
317
            201 => '#669900',
318
            202 => '#666666',
319
            203 => '#999999',
320
            204 => '#FFFFCC',
321
            205 => '#FF00CC',
322
            206 => '#FFFF00',
323
            207 => '#FFCC00',
324
            208 => '#FF0000',
325
            209 => '#FF6600',
326
            250 => '#6633CC',
327
            251 => '#6611AA',
328
            252 => '#66FF99',
329
            253 => '#66FF66',
330
            446 => '#06DCFB',
331
            447 => '#892EE4',
332
            460 => '#99FF66',
333
            461 => '#99CC66',
334
            470 => '#CCCC33',
335
            471 => '#CCFF33',
336
            480 => '#6699FF',
337
            481 => '#66FFFF',
338
            484 => '#07C8D6',
339
            485 => '#2AF1FF',
340
            486 => '#79CB21',
341
            487 => '#80D822',
342
            490 => '#995500',
343
            491 => '#998800',
344
            710 => '#FFCECE',
345
            711 => '#FFC8F2',
346
            828 => '#F7DE00',
347
            829 => '#BABA21',
348
            866 => '#FFFFFF',
349
            867 => '#FFCCFF',
350
            1198 => '#FF34B3',
351
            1199 => '#8B1C62',
352
            2300 => '#A900B8',
353
            2301 => '#C93ED6',
354
            2302 => '#8A09C1',
355
            2303 => '#974AB8',
356
            2600 => '#000000',
357
        ];
358
359
        if (false === $num) {
360
            return $colors;
361
        } elseif (isset($colors[$num])) {
362
            return $colors[$num];
363
        } else {
364
            // Default to grey.
365
            return '#CCC';
366
        }
367
    }
368
369
    /**
370
     * Get color-blind friendly colors for use in charts
371
     * @param int $num Index of color
372
     * @return string RGBA color (so you can more easily adjust the opacity)
373
     */
374
    public function chartColor(int $num): string
375
    {
376
        $colors = [
377
            'rgba(171, 212, 235, 1)',
378
            'rgba(178, 223, 138, 1)',
379
            'rgba(251, 154, 153, 1)',
380
            'rgba(253, 191, 111, 1)',
381
            'rgba(202, 178, 214, 1)',
382
            'rgba(207, 182, 128, 1)',
383
            'rgba(141, 211, 199, 1)',
384
            'rgba(252, 205, 229, 1)',
385
            'rgba(255, 247, 161, 1)',
386
            'rgba(217, 217, 217, 1)',
387
        ];
388
389
        return $colors[$num % count($colors)];
390
    }
391
392
    /**
393
     * Whether XTools is running in single-project mode.
394
     * @return bool
395
     */
396 8
    public function isSingleWiki(): bool
397
    {
398 8
        $param = true;
399 8
        if ($this->container->hasParameter('app.single_wiki')) {
400 8
            $param = boolval($this->container->getParameter('app.single_wiki'));
401
        }
402 8
        return $param;
403
    }
404
405
    /**
406
     * Get the database replication-lag threshold.
407
     * @return int
408
     */
409
    public function getReplagThreshold(): int
410
    {
411
        $param = 30;
412
        if ($this->container->hasParameter('app.replag_threshold')) {
413
            $param = $this->container->getParameter('app.replag_threshold');
414
        }
415
        return $param;
416
    }
417
418
    /**
419
     * Whether XTools is running in WMF Labs mode.
420
     * @return bool
421
     */
422 11
    public function isWMFLabs(): bool
423
    {
424 11
        $param = false;
425 11
        if ($this->container->hasParameter('app.is_labs')) {
426 11
            $param = boolval($this->container->getParameter('app.is_labs'));
427
        }
428 11
        return $param;
429
    }
430
431
    /**
432
     * The current replication lag.
433
     * @return int
434
     * @codeCoverageIgnore
435
     */
436
    public function replag(): int
437
    {
438
        $retVal = 0;
439
440
        if ($this->isWMFLabs()) {
441
            $project = $this->getRequest()->get('project');
442
443
            if (!isset($project)) {
444
                $project = 'enwiki';
445
            }
446
447
            $dbName = ProjectRepository::getProject($project, $this->container)
448
                ->getDatabaseName();
449
450
            $sql = "SELECT lag FROM `heartbeat_p`.`heartbeat` h
451
                    RIGHT JOIN `meta_p`.`wiki` w ON concat(h.shard, \".labsdb\")=w.slice
452
                    WHERE dbname LIKE :project LIMIT 1";
453
454
            /** @var Connection $conn */
455
            $conn = $this->container->get('doctrine')->getManager('replicas')->getConnection();
456
457
            // Prepare the query and execute
458
            $resultQuery = $conn->prepare($sql);
459
            $resultQuery->bindParam('project', $dbName);
460
            $resultQuery->execute();
461
462
            if (0 == $resultQuery->errorCode()) {
463
                $results = $resultQuery->fetchAll();
464
465
                if (isset($results[0]['lag'])) {
466
                    $retVal = $results[0]['lag'];
467
                }
468
            }
469
        }
470
471
        return (int)$retVal;
472
    }
473
474
    /**
475
     * Get a random quote for the footer
476
     * @return string
477
     */
478 11
    public function quote(): string
479
    {
480
        // Don't show if Quote is turned off, but always show for Labs
481
        // (so quote is in footer but not in nav).
482 11
        $isLabs = $this->container->getParameter('app.is_labs');
483 11
        if (!$isLabs && !$this->container->getParameter('enable.Quote')) {
484 11
            return '';
485
        }
486
        $quotes = $this->container->getParameter('quotes');
487
        $id = array_rand($quotes);
488
        return $quotes[$id];
489
    }
490
491
    /**
492
     * Get the currently logged in user's details.
493
     * @return string[]|null
494
     */
495 11
    public function loggedInUser(): ?array
496
    {
497 11
        return $this->container->get('session')->get('logged_in_user');
498
    }
499
500
    /*********************************** FILTERS ***********************************/
501
502
    /**
503
     * Get all filters for this extension.
504
     * @return \Twig_SimpleFilter[]
505
     */
506 11
    public function getFilters(): array
507
    {
508
        return [
509 11
            new \Twig_SimpleFilter('capitalize_first', [$this, 'capitalizeFirst']),
510 11
            new \Twig_SimpleFilter('percent_format', [$this, 'percentFormat']),
511 11
            new \Twig_SimpleFilter('diff_format', [$this, 'diffFormat'], ['is_safe' => ['html']]),
512 11
            new \Twig_SimpleFilter('num_format', [$this, 'numberFormat']),
513 11
            new \Twig_SimpleFilter('date_format', [$this, 'dateFormat']),
514 11
            new \Twig_SimpleFilter('wikify', [$this, 'wikify']),
515
        ];
516
    }
517
518
    /**
519
     * Format a number based on language settings.
520
     * @param int|float $number
521
     * @param int $decimals Number of decimals to format to.
522
     * @return string
523
     */
524 14
    public function numberFormat($number, $decimals = 0): string
525
    {
526 14
        return $this->i18n->numberFormat($number, $decimals);
527
    }
528
529
    /**
530
     * Localize the given date based on language settings.
531
     * @param string|DateTime $datetime
532
     * @param string $pattern Format according to this ICU date format.
533
     * @see http://userguide.icu-project.org/formatparse/datetime
534
     * @return string
535
     */
536 3
    public function dateFormat($datetime, $pattern = 'yyyy-MM-dd HH:mm'): string
537
    {
538 3
        return $this->i18n->dateFormat($datetime, $pattern);
539
    }
540
541
    /**
542
     * Convert raw wikitext to HTML-formatted string.
543
     * @param string $str
544
     * @param Project $project
545
     * @return string
546
     */
547 1
    public function wikify(string $str, Project $project): string
548
    {
549 1
        return Edit::wikifyString($str, $project);
550
    }
551
552
    /**
553
     * Mysteriously missing Twig helper to capitalize only the first character.
554
     * E.g. used for table headings for translated messages
555
     * @param string $str The string
556
     * @return string The string, capitalized
557
     */
558 6
    public function capitalizeFirst(string $str): string
559
    {
560 6
        return ucfirst($str);
561
    }
562
563
    /**
564
     * Format a given number or fraction as a percentage.
565
     * @param int|float $numerator Numerator or single fraction if denominator is ommitted.
566
     * @param int $denominator Denominator.
567
     * @param integer $precision Number of decimal places to show.
568
     * @return string Formatted percentage.
569
     */
570 1
    public function percentFormat($numerator, ?int $denominator = null, int $precision = 1): string
571
    {
572 1
        return $this->i18n->percentFormat($numerator, $denominator, $precision);
573
    }
574
575
    /**
576
     * Helper to return whether the given user is an anonymous (logged out) user.
577
     * @param User|string $user User object or username as a string.
578
     * @return bool
579
     */
580 1
    public function isUserAnon($user): bool
581
    {
582 1
        if ($user instanceof User) {
583 1
            $username = $user->getUsername();
584
        } else {
585 1
            $username = $user;
586
        }
587
588 1
        return (bool)filter_var($username, FILTER_VALIDATE_IP);
589
    }
590
591
    /**
592
     * Helper to properly translate a namespace name.
593
     * @param int|string $namespace Namespace key as a string or ID.
594
     * @param string[] $namespaces List of available namespaces as retrieved from Project::getNamespaces().
595
     * @return string Namespace name
596
     */
597
    public function nsName($namespace, array $namespaces): string
598
    {
599
        if ('all' === $namespace) {
600
            return $this->i18n->msg('all');
601
        } elseif ('0' === $namespace || 0 === $namespace || 'Main' === $namespace) {
602
            return $this->i18n->msg('mainspace');
603
        } else {
604
            return $namespaces[$namespace] ?? $this->i18n->msg('unknown');
605
        }
606
    }
607
608
    /**
609
     * Given a page title and namespace, generate the full page title.
610
     * @param string $title
611
     * @param int $namespace
612
     * @param array $namespaces
613
     * @return string
614
     */
615
    public function titleWithNs(string $title, int $namespace, array $namespaces): string
616
    {
617
        if (0 === $namespace) {
618
            return $title;
619
        }
620
        return $this->nsName($namespace, $namespaces).':'.$title;
621
    }
622
623
    /**
624
     * Format a given number as a diff, colouring it green if it's positive, red if negative, gary if zero
625
     * @param int $size Diff size
626
     * @return string Markup with formatted number
627
     */
628 1
    public function diffFormat(int $size): string
629
    {
630 1
        if ($size < 0) {
631 1
            $class = 'diff-neg';
632 1
        } elseif ($size > 0) {
633 1
            $class = 'diff-pos';
634
        } else {
635 1
            $class = 'diff-zero';
636
        }
637
638 1
        $size = $this->numberFormat($size);
639
640 1
        return "<span class='$class'".
641 1
            ($this->i18n->isRTL() ? " dir='rtl'" : '').
642 1
            ">$size</span>";
643
    }
644
645
    /**
646
     * Format a time duration as humanized string.
647
     * @param int $seconds Number of seconds.
648
     * @param bool $translate Used for unit testing. Set to false to return
649
     *   the value and i18n key, instead of the actual translation.
650
     * @return string|mixed[] Examples: '30 seconds', '2 minutes', '15 hours', '500 days',
651
     *   or [30, 'num-seconds'] (etc.) if $translate is false.
652
     */
653 1
    public function formatDuration(int $seconds, bool $translate = true)
654
    {
655 1
        [$val, $key] = $this->getDurationMessageKey($seconds);
656
657 1
        if ($translate) {
658
            return $this->numberFormat($val).' '.$this->i18n->msg("num-$key", [$val]);
659
        } else {
660 1
            return [$this->numberFormat($val), "num-$key"];
661
        }
662
    }
663
664
    /**
665
     * Given a time duration in seconds, generate a i18n message key and value.
666
     * @param int $seconds Number of seconds.
667
     * @return array<integer|string> [int - message value, string - message key]
668
     */
669 1
    private function getDurationMessageKey(int $seconds)
670
    {
671
        /** @var int $val Value to show in message */
672 1
        $val = $seconds;
673
674
        /** @var string $key Unit of time, used in the key for the i18n message */
675 1
        $key = 'seconds';
676
677 1
        if ($seconds >= 86400) {
678
            // Over a day
679 1
            $val = (int) floor($seconds / 86400);
680 1
            $key = 'days';
681 1
        } elseif ($seconds >= 3600) {
682
            // Over an hour, less than a day
683 1
            $val = (int) floor($seconds / 3600);
684 1
            $key = 'hours';
685 1
        } elseif ($seconds >= 60) {
686
            // Over a minute, less than an hour
687 1
            $val = (int) floor($seconds / 60);
688 1
            $key = 'minutes';
689
        }
690
691 1
        return [$val, $key];
692
    }
693
694
    /**
695
     * Build URL query string from given params.
696
     * @param string[] $params
697
     * @return string
698
     */
699 1
    public function buildQuery(array $params): string
700
    {
701 1
        return is_array($params) ? http_build_query($params) : '';
0 ignored issues
show
introduced by
The condition is_array($params) is always true.
Loading history...
702
    }
703
704
    /**
705
     * Shorthand to get the current request from the request stack.
706
     * @return \Symfony\Component\HttpFoundation\Request
707
     * There is no request stack in the tests.
708
     * @codeCoverageIgnore
709
     */
710
    private function getRequest(): \Symfony\Component\HttpFoundation\Request
711
    {
712
        return $this->container->get('request_stack')->getCurrentRequest();
713
    }
714
}
715