diff --git a/composer.json b/composer.json index 04dc93ffc..1b1726fe8 100644 --- a/composer.json +++ b/composer.json @@ -25,6 +25,7 @@ ], "require": { "php": ">=7.2.5", + "symfony/polyfill-php80": "^1.22", "symfony/polyfill-mbstring": "^1.3", "symfony/polyfill-ctype": "^1.8" }, diff --git a/src/Error/Error.php b/src/Error/Error.php index a68be65f2..d2d1f97a9 100644 --- a/src/Error/Error.php +++ b/src/Error/Error.php @@ -130,13 +130,13 @@ class Error extends \Exception } $dot = false; - if ('.' === substr($this->message, -1)) { + if (str_ends_with($this->message, '.')) { $this->message = substr($this->message, 0, -1); $dot = true; } $questionMark = false; - if ('?' === substr($this->message, -1)) { + if (str_ends_with($this->message, '?')) { $this->message = substr($this->message, 0, -1); $questionMark = true; } @@ -172,7 +172,7 @@ class Error extends \Exception foreach ($backtrace as $trace) { if (isset($trace['object']) && $trace['object'] instanceof Template) { $currentClass = \get_class($trace['object']); - $isEmbedContainer = null === $templateClass ? false : 0 === strpos($templateClass, $currentClass); + $isEmbedContainer = null === $templateClass ? false : str_starts_with($templateClass, $currentClass); if (null === $this->name || ($this->name == $trace['object']->getTemplateName() && !$isEmbedContainer)) { $template = $trace['object']; $templateClass = \get_class($trace['object']); diff --git a/src/Error/SyntaxError.php b/src/Error/SyntaxError.php index 726b3309e..77c437c68 100644 --- a/src/Error/SyntaxError.php +++ b/src/Error/SyntaxError.php @@ -30,7 +30,7 @@ class SyntaxError extends Error $alternatives = []; foreach ($items as $item) { $lev = levenshtein($name, $item); - if ($lev <= \strlen($name) / 3 || false !== strpos($item, $name)) { + if ($lev <= \strlen($name) / 3 || str_contains($item, $name)) { $alternatives[$item] = $lev; } } diff --git a/src/Extension/CoreExtension.php b/src/Extension/CoreExtension.php index 6c16ee2b7..430102f86 100644 --- a/src/Extension/CoreExtension.php +++ b/src/Extension/CoreExtension.php @@ -926,7 +926,7 @@ function twig_in_filter($value, $compare) if (\is_string($compare)) { if (\is_string($value) || \is_int($value) || \is_float($value)) { - return '' === $value || false !== strpos($compare, (string) $value); + return '' === $value || str_contains($compare, (string) $value); } return false; @@ -1570,13 +1570,13 @@ function twig_get_attribute(Environment $env, Source $source, $object, $item, ar $classCache[$method] = $method; $classCache[$lcName = $lcMethods[$i]] = $method; - if ('g' === $lcName[0] && 0 === strpos($lcName, 'get')) { + if ('g' === $lcName[0] && str_starts_with($lcName, 'get')) { $name = substr($method, 3); $lcName = substr($lcName, 3); - } elseif ('i' === $lcName[0] && 0 === strpos($lcName, 'is')) { + } elseif ('i' === $lcName[0] && str_starts_with($lcName, 'is')) { $name = substr($method, 2); $lcName = substr($lcName, 2); - } elseif ('h' === $lcName[0] && 0 === strpos($lcName, 'has')) { + } elseif ('h' === $lcName[0] && str_starts_with($lcName, 'has')) { $name = substr($method, 3); $lcName = substr($lcName, 3); if (\in_array('is'.$lcName, $lcMethods)) { diff --git a/src/FileExtensionEscapingStrategy.php b/src/FileExtensionEscapingStrategy.php index 65198bbb6..812071bf9 100644 --- a/src/FileExtensionEscapingStrategy.php +++ b/src/FileExtensionEscapingStrategy.php @@ -37,7 +37,7 @@ class FileExtensionEscapingStrategy return 'html'; // return html for directories } - if ('.twig' === substr($name, -5)) { + if (str_ends_with($name, '.twig')) { $name = substr($name, 0, -5); } diff --git a/src/Lexer.php b/src/Lexer.php index 5a6258c2c..b23080f58 100644 --- a/src/Lexer.php +++ b/src/Lexer.php @@ -345,13 +345,13 @@ class Lexer $this->moveCursor($match[0]); } // punctuation - elseif (false !== strpos(self::PUNCTUATION, $this->code[$this->cursor])) { + elseif (str_contains(self::PUNCTUATION, $this->code[$this->cursor])) { // opening bracket - if (false !== strpos('([{', $this->code[$this->cursor])) { + if (str_contains('([{', $this->code[$this->cursor])) { $this->brackets[] = [$this->code[$this->cursor], $this->lineno]; } // closing bracket - elseif (false !== strpos(')]}', $this->code[$this->cursor])) { + elseif (str_contains(')]}', $this->code[$this->cursor])) { if (empty($this->brackets)) { throw new SyntaxError(sprintf('Unexpected "%s".', $this->code[$this->cursor]), $this->lineno, $this->source); } diff --git a/src/Loader/FilesystemLoader.php b/src/Loader/FilesystemLoader.php index 62267a11c..35a3299a4 100644 --- a/src/Loader/FilesystemLoader.php +++ b/src/Loader/FilesystemLoader.php @@ -250,7 +250,7 @@ class FilesystemLoader implements LoaderInterface private function validateName(string $name): void { - if (false !== strpos($name, "\0")) { + if (str_contains($name, "\0")) { throw new LoaderError('A template name cannot contain NUL bytes.'); } diff --git a/src/Node/Expression/CallExpression.php b/src/Node/Expression/CallExpression.php index 11a6b1abc..3a2d7a4fc 100644 --- a/src/Node/Expression/CallExpression.php +++ b/src/Node/Expression/CallExpression.php @@ -24,7 +24,7 @@ abstract class CallExpression extends AbstractExpression { $callable = $this->getAttribute('callable'); - if (\is_string($callable) && false === strpos($callable, '::')) { + if (\is_string($callable) && !str_contains($callable, '::')) { $compiler->raw($callable); } else { [$r, $callable] = $this->reflectCallable($callable); @@ -297,13 +297,13 @@ abstract class CallExpression extends AbstractExpression } $r = new \ReflectionFunction($closure); - if (false !== strpos($r->name, '{closure}')) { + if (str_contains($r->name, '{closure}')) { return $this->reflector = [$r, $callable, 'Closure']; } if ($object = $r->getClosureThis()) { $callable = [$object, $r->name]; - $callableName = (\function_exists('get_debug_type') ? get_debug_type($object) : \get_class($object)).'::'.$r->name; + $callableName = get_debug_type($object).'::'.$r->name; } elseif (\PHP_VERSION_ID >= 80111 && $class = $r->getClosureCalledClass()) { $callableName = $class->name.'::'.$r->name; } elseif (\PHP_VERSION_ID < 80111 && $class = $r->getClosureScopeClass()) { diff --git a/src/Parser.php b/src/Parser.php index 5590086f1..4016a5f39 100644 --- a/src/Parser.php +++ b/src/Parser.php @@ -305,7 +305,7 @@ class Parser ($node instanceof TextNode && !ctype_space($node->getAttribute('data'))) || (!$node instanceof TextNode && !$node instanceof BlockReferenceNode && $node instanceof NodeOutputInterface) ) { - if (false !== strpos((string) $node, \chr(0xEF).\chr(0xBB).\chr(0xBF))) { + if (str_contains((string) $node, \chr(0xEF).\chr(0xBB).\chr(0xBF))) { $t = substr($node->getAttribute('data'), 3); if ('' === $t || ctype_space($t)) { // bypass empty nodes starting with a BOM diff --git a/src/Profiler/Profile.php b/src/Profiler/Profile.php index 252ca9b0c..7979a23c6 100644 --- a/src/Profiler/Profile.php +++ b/src/Profiler/Profile.php @@ -32,7 +32,7 @@ final class Profile implements \IteratorAggregate, \Serializable { $this->template = $template; $this->type = $type; - $this->name = 0 === strpos($name, '__internal_') ? 'INTERNAL' : $name; + $this->name = str_starts_with($name, '__internal_') ? 'INTERNAL' : $name; $this->enter(); } diff --git a/src/Test/IntegrationTestCase.php b/src/Test/IntegrationTestCase.php index 0aa5c3a56..e97ad4170 100644 --- a/src/Test/IntegrationTestCase.php +++ b/src/Test/IntegrationTestCase.php @@ -102,7 +102,7 @@ abstract class IntegrationTestCase extends TestCase continue; } - if ($legacyTests xor false !== strpos($file->getRealpath(), '.legacy.test')) { + if ($legacyTests xor str_contains($file->getRealpath(), '.legacy.test')) { continue; }