Completed
Pull Request — 3.x (#6145)
by Wojciech
06:07
created

StringExtension::twigTruncateFilter()   B

Complexity

Conditions 8
Paths 8

Size

Total Lines 29

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 29
rs 8.2114
c 0
b 0
f 0
cc 8
nc 8
nop 5
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Sonata Project package.
7
 *
8
 * (c) Thomas Rabaix <[email protected]>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Sonata\AdminBundle\Twig\Extension;
15
16
use Symfony\Component\String\UnicodeString as SymfonyUnicodeString;
17
use Twig\Environment;
18
use Twig\Extension\AbstractExtension;
19
use Twig\Extensions\TextExtension;
20
use Twig\TwigFilter;
21
22
/**
23
 * NEXT_MAJOR: Remove this class.
24
 *
25
 * Decorates `Twig\Extra\String\StringExtension` in order to provide the `$cut`
26
 * argument for `Symfony\Component\String\UnicodeString::truncate()`.
27
 * This class must be removed when the component ships this feature.
28
 *
29
 * @internal
30
 *
31
 * @see https://github.com/symfony/symfony/pull/35649
32
 * @deprecated since sonata-project/admin-bundle 3.69, to be removed in 4.0.
33
 *
34
 * @author Javier Spagnoletti <[email protected]>
35
 */
36
final class StringExtension extends AbstractExtension
37
{
38
    /**
39
     * @var AbstractExtension
40
     */
41
    private $legacyExtension;
42
43
    /**
44
     * @var bool
45
     */
46
    private $legacy;
47
48
    public function __construct(?AbstractExtension $legacyExtension = null)
49
    {
50
        if (!$legacyExtension instanceof TextExtension && !$legacyExtension instanceof DeprecatedTextExtension) {
51
            throw new \TypeError(sprintf(
0 ignored issues
show
Unused Code introduced by
The call to TypeError::__construct() has too many arguments starting with sprintf('Argument 1 pass...edTextExtension::class).

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
52
                'Argument 1 passed to %s::__construct() must be instance of %s or %s',
53
                self::class,
54
                TextExtension::class,
55
                DeprecatedTextExtension::class
56
            ));
57
        }
58
59
        $this->legacyExtension = $legacyExtension;
60
    }
61
62
    /**
63
     * @return TwigFilter[]
64
     */
65
    public function getFilters(): array
66
    {
67
        return [
68
            new TwigFilter('sonata_truncate', [$this, 'deprecatedTruncate'], ['needs_environment' => true]),
69
        ];
70
    }
71
72
    /**
73
     * @return SymfonyUnicodeString|string
74
     */
75
    public function deprecatedTruncate(Environment $env, ?string $text, int $length = 30, bool $preserve = false, string $ellipsis = '...')
76
    {
77
        @trigger_error(
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
78
            'The "sonata_truncate" twig filter is deprecated'
79
            .' since sonata-project/admin-bundle 3.69 and will be removed in 4.0. Use "u.truncate" instead.',
80
            E_USER_DEPRECATED
81
        );
82
83
        if ($this->legacyExtension instanceof TextExtension) {
84
            return twig_truncate_filter($env, $text, $length, $preserve, $ellipsis);
0 ignored issues
show
Compatibility introduced by
$env of type object<Twig\Environment> is not a sub-type of object<Twig_Environment>. It seems like you assume a child class of the class Twig\Environment to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
85
        } elseif ($this->legacyExtension instanceof DeprecatedTextExtension) {
86
            return $this->legacyExtension->twigTruncateFilter($env, $text, $length, $preserve, $ellipsis);
87
        }
88
89
        return $this->legacyTruncteWithUnicodeString($text, $length, $preserve, $ellipsis);
90
    }
91
92
    public function legacyTruncteWithUnicodeString(?string $text, int $length = 30, bool $preserve = false, string $ellipsis = '...'): SymfonyUnicodeString
93
    {
94
        return (new SymfonyUnicodeString($text ?? ''))->truncate($length, $ellipsis, $preserve);
95
    }
96
97
    private function twigTruncateFilter(Environment $env, ?string $value, int $length = 30, bool $preserve = false, $separator = '...')
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
98
    {
99
        if (\function_exists('mb_get_info')) {
100
            if (mb_strlen($value, $env->getCharset()) > $length) {
101
                if ($preserve) {
102
                    // If breakpoint is on the last word, return the value without separator.
103
                    if (false === ($breakpoint = mb_strpos($value, ' ', $length, $env->getCharset()))) {
104
                        return $value;
105
                    }
106
107
                    $length = $breakpoint;
108
                }
109
110
                return rtrim(mb_substr($value, 0, $length, $env->getCharset())).$separator;
111
            }
112
        } else {
113
            if (\strlen($value) > $length) {
114
                if ($preserve) {
115
                    if (false !== ($breakpoint = strpos($value, ' ', $length))) {
116
                        $length = $breakpoint;
117
                    }
118
                }
119
120
                return rtrim(substr($value, 0, $length)).$separator;
121
            }
122
        }
123
124
        return $value;
125
    }
126
}
127