diff --git a/.ht.router.php b/.ht.router.php
index 2c8a6f6ac35821ab3c09c17bfdbf31f3c7613b9e..b5884ef4a9d0fce4ea29e06c4e8e057af68bb230 100644
--- a/.ht.router.php
+++ b/.ht.router.php
@@ -39,7 +39,7 @@
 // Work around the PHP bug.
 $path = $url['path'];
 $script = 'index.php';
-if (strpos($path, '.php') !== FALSE) {
+if (str_contains($path, '.php')) {
   // Work backwards through the path to check if a script exists. Otherwise
   // fallback to index.php.
   do {
diff --git a/composer/Generator/ComponentGenerator.php b/composer/Generator/ComponentGenerator.php
index c82468cbe7b091d23f9e3f0ab614e99bd351ee5f..f2ec80751192ccae40556f038fa098858217ed3c 100644
--- a/composer/Generator/ComponentGenerator.php
+++ b/composer/Generator/ComponentGenerator.php
@@ -162,7 +162,7 @@ protected function getPackage(IOInterface $io, string $original_json): array {
       }
       // The package wasn't in the lock file, which means we need to tell the
       // user. But there are some packages we want to exclude from this list.
-      elseif ($package_name !== 'php' && (strpos($package_name, 'drupal/core-') === FALSE)) {
+      elseif ($package_name !== 'php' && !str_contains($package_name, 'drupal/core-')) {
         $not_in_core[$package_name] = $package_name;
       }
 
@@ -174,7 +174,7 @@ protected function getPackage(IOInterface $io, string $original_json): array {
 
       // Reconcile dependencies on other Drupal components, so we can set the
       // constraint to our current version.
-      if (strpos($package_name, 'drupal/core-') !== FALSE) {
+      if (str_contains($package_name, 'drupal/core-')) {
         if ($stability === 'stable') {
           // Set the constraint to ^maj.min.
           $package_data['require'][$package_name] = SemanticVersion::majorMinorConstraint(\Drupal::VERSION);
diff --git a/composer/Plugin/Scaffold/Operations/AppendOp.php b/composer/Plugin/Scaffold/Operations/AppendOp.php
index b9d0c0b9c61331952a13b095d7cfd42cf515051a..cd3ed05bdb3651648575ab2ff969fd6add54e0d0 100644
--- a/composer/Plugin/Scaffold/Operations/AppendOp.php
+++ b/composer/Plugin/Scaffold/Operations/AppendOp.php
@@ -201,7 +201,7 @@ protected function existingFileHasData($contents, $data_path) {
     }
     $data = file_get_contents($data_path->fullPath());
 
-    return strpos($contents, $data) !== FALSE;
+    return str_contains($contents, $data);
   }
 
 }
diff --git a/core/assets/scaffold/files/ht.router.php b/core/assets/scaffold/files/ht.router.php
index 2c8a6f6ac35821ab3c09c17bfdbf31f3c7613b9e..b5884ef4a9d0fce4ea29e06c4e8e057af68bb230 100644
--- a/core/assets/scaffold/files/ht.router.php
+++ b/core/assets/scaffold/files/ht.router.php
@@ -39,7 +39,7 @@
 // Work around the PHP bug.
 $path = $url['path'];
 $script = 'index.php';
-if (strpos($path, '.php') !== FALSE) {
+if (str_contains($path, '.php')) {
   // Work backwards through the path to check if a script exists. Otherwise
   // fallback to index.php.
   do {
diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc
index e3136e755eb827af1b510c73e5e7b86b69187511..e477a4685d2bd31d7700f62f26f1ca5cf870b648 100644
--- a/core/includes/install.core.inc
+++ b/core/includes/install.core.inc
@@ -318,7 +318,7 @@ function install_begin_request($class_loader, &$install_state) {
   // running tests. However, for security reasons, it is imperative that no
   // installation be permitted using such a prefix.
   $user_agent = $request->cookies->get('SIMPLETEST_USER_AGENT') ?: $request->server->get('HTTP_USER_AGENT');
-  if ($install_state['interactive'] && strpos($user_agent, 'simpletest') !== FALSE && !drupal_valid_test_ua()) {
+  if ($install_state['interactive'] && str_contains($user_agent, 'simpletest') && !drupal_valid_test_ua()) {
     header($request->server->get('SERVER_PROTOCOL') . ' 403 Forbidden');
     exit;
   }
diff --git a/core/lib/Drupal/Component/Annotation/Doctrine/DocParser.php b/core/lib/Drupal/Component/Annotation/Doctrine/DocParser.php
index ccc44feca843f1fcc5a6d3a1fcf12897539ab629..4070674cfb21e4eaa7b6c7535b2bfb6f99c5f8f2 100644
--- a/core/lib/Drupal/Component/Annotation/Doctrine/DocParser.php
+++ b/core/lib/Drupal/Component/Annotation/Doctrine/DocParser.php
@@ -485,7 +485,7 @@ private function collectAnnotationMetadata($name)
             'attribute_types'  => array(),
             'targets_literal'  => null,
             'targets'          => Target::TARGET_ALL,
-            'is_annotation'    => false !== strpos($docComment, '@Annotation'),
+            'is_annotation'    => str_contains($docComment, '@Annotation'),
         );
 
         // verify that the class is really meant to be an annotation
@@ -519,16 +519,16 @@ private function collectAnnotationMetadata($name)
 
                     $attribute = new Attribute();
 
-                    $attribute->required = (false !== strpos($propertyComment, '@Required'));
+                    $attribute->required = str_contains($propertyComment, '@Required');
                     $attribute->name     = $property->name;
-                    $attribute->type     = (false !== strpos($propertyComment, '@var') && preg_match('/@var\s+([^\s]+)/',$propertyComment, $matches))
+                    $attribute->type     = (str_contains($propertyComment, '@var') && preg_match('/@var\s+([^\s]+)/',$propertyComment, $matches))
                         ? $matches[1]
                         : 'mixed';
 
                     $this->collectAttributeTypeMetadata($metadata, $attribute);
 
                     // checks if the property has @Enum
-                    if (false !== strpos($propertyComment, '@Enum')) {
+                    if (str_contains($propertyComment, '@Enum')) {
                         $context = 'property ' . $class->name . "::\$" . $property->name;
 
                         self::$metadataParser->setTarget(Target::TARGET_PROPERTY);
@@ -896,7 +896,7 @@ private function Constant()
     {
         $identifier = $this->Identifier();
 
-        if ( ! defined($identifier) && false !== strpos($identifier, '::') && '\\' !== $identifier[0]) {
+        if ( ! defined($identifier) && str_contains($identifier, '::') && '\\' !== $identifier[0]) {
             [$className, $const] = explode('::', $identifier);
 
             $alias = (false === $pos = strpos($className, '\\')) ? $className : substr($className, 0, $pos);
diff --git a/core/lib/Drupal/Component/DependencyInjection/Container.php b/core/lib/Drupal/Component/DependencyInjection/Container.php
index ed3dc38e9f4dc3b6d94e8802f7fb074651686869..4c8fa97158619532af7e3fb7737d40ea62d2fa43 100644
--- a/core/lib/Drupal/Component/DependencyInjection/Container.php
+++ b/core/lib/Drupal/Component/DependencyInjection/Container.php
@@ -497,7 +497,7 @@ protected function getAlternatives($search_key, array $keys) {
     $alternatives = [];
     foreach ($keys as $key) {
       $lev = levenshtein($search_key, $key);
-      if ($lev <= strlen($search_key) / 3 || strpos($key, $search_key) !== FALSE) {
+      if ($lev <= strlen($search_key) / 3 || str_contains($key, $search_key)) {
         $alternatives[] = $key;
       }
     }
diff --git a/core/lib/Drupal/Component/DependencyInjection/Dumper/OptimizedPhpArrayDumper.php b/core/lib/Drupal/Component/DependencyInjection/Dumper/OptimizedPhpArrayDumper.php
index a390a3710776d15e9bc61d6ab39ff93c9f8ac23d..c5ce59b448fc690a8eb860ef366d1443844b579c 100644
--- a/core/lib/Drupal/Component/DependencyInjection/Dumper/OptimizedPhpArrayDumper.php
+++ b/core/lib/Drupal/Component/DependencyInjection/Dumper/OptimizedPhpArrayDumper.php
@@ -407,7 +407,7 @@ protected function dumpValue($value) {
     elseif ($value instanceof Parameter) {
       return $this->getParameterCall((string) $value);
     }
-    elseif (is_string($value) && FALSE !== strpos($value, '%')) {
+    elseif (is_string($value) && str_contains($value, '%')) {
       if (preg_match('/^%([^%]+)%$/', $value, $matches)) {
         return $this->getParameterCall($matches[1]);
       }
diff --git a/core/lib/Drupal/Component/Gettext/PoItem.php b/core/lib/Drupal/Component/Gettext/PoItem.php
index 3ef8a2acea81d254c5092204ee345086d71ff11d..b8930da851a1baed69828b1f860a17ede8c2e55b 100644
--- a/core/lib/Drupal/Component/Gettext/PoItem.php
+++ b/core/lib/Drupal/Component/Gettext/PoItem.php
@@ -202,8 +202,7 @@ public function setFromArray(array $values = []) {
     if (isset($values['comment'])) {
       $this->setComment($values['comment']);
     }
-    if (isset($this->source) &&
-        strpos($this->source, self::DELIMITER) !== FALSE) {
+    if (isset($this->source) && str_contains($this->source, self::DELIMITER)) {
       $this->setSource(explode(self::DELIMITER, $this->source));
       $this->setTranslation(explode(self::DELIMITER, $this->translation ?? ''));
       $this->setPlural(count($this->source) > 1);
diff --git a/core/lib/Drupal/Component/Gettext/PoStreamReader.php b/core/lib/Drupal/Component/Gettext/PoStreamReader.php
index e14ed213ab82cfb945c7b9dbf8f8d780dafcf46a..aed4bd9907d974e4de7d229f261e5494d3e32833 100644
--- a/core/lib/Drupal/Component/Gettext/PoStreamReader.php
+++ b/core/lib/Drupal/Component/Gettext/PoStreamReader.php
@@ -401,7 +401,7 @@ private function readLine() {
         }
 
         // Ensure the plurality is terminated.
-        if (strpos($line, ']') === FALSE) {
+        if (!str_contains($line, ']')) {
           $this->errors[] = new FormattableMarkup('The translation stream %uri contains an error: invalid format for "msgstr[]" on line %line.', $log_vars);
           return FALSE;
         }
diff --git a/core/lib/Drupal/Component/Transliteration/PhpTransliteration.php b/core/lib/Drupal/Component/Transliteration/PhpTransliteration.php
index 7aab75001b71bbd6cdc52655d13852f2019212a0..aa6cd91470b8403f14e43a60f7661f1d1fd740c2 100644
--- a/core/lib/Drupal/Component/Transliteration/PhpTransliteration.php
+++ b/core/lib/Drupal/Component/Transliteration/PhpTransliteration.php
@@ -132,7 +132,7 @@ public function transliterate($string, $langcode = 'en', $unknown_character = '?
     // Replace question marks with a unique hash if necessary. This because
     // mb_convert_encoding() replaces all invalid characters with a question
     // mark.
-    if ($unknown_character != '?' && strpos($string, '?') !== FALSE) {
+    if ($unknown_character != '?' && str_contains($string, '?')) {
       $hash = hash('sha256', $string);
       $string = str_replace('?', $hash, $string);
     }
diff --git a/core/lib/Drupal/Component/Utility/Tags.php b/core/lib/Drupal/Component/Utility/Tags.php
index ac0ce60817abd30cba05f833f3cc99fd0f2d7573..1d82e72f5bfda571fb36515bfff7a7911aa77c4f 100644
--- a/core/lib/Drupal/Component/Utility/Tags.php
+++ b/core/lib/Drupal/Component/Utility/Tags.php
@@ -49,7 +49,7 @@ public static function explode($tags) {
    *   The encoded string.
    */
   public static function encode($tag) {
-    if (strpos($tag, ',') !== FALSE || strpos($tag, '"') !== FALSE) {
+    if (str_contains($tag, ',') || str_contains($tag, '"')) {
       return '"' . str_replace('"', '""', $tag) . '"';
     }
     return $tag;
diff --git a/core/lib/Drupal/Component/Utility/UrlHelper.php b/core/lib/Drupal/Component/Utility/UrlHelper.php
index e2e8f6dfc5698c786ae0983b9a3e2a0b84207967..c78a27450ee5eb1e96f47ec631f03a8b9e2b7aed 100644
--- a/core/lib/Drupal/Component/Utility/UrlHelper.php
+++ b/core/lib/Drupal/Component/Utility/UrlHelper.php
@@ -189,7 +189,7 @@ public static function parse($url) {
     $query_delimiter_position = strpos($url, '?');
     if ($scheme_delimiter_position !== FALSE && ($query_delimiter_position === FALSE || $scheme_delimiter_position < $query_delimiter_position)) {
       // Split off the fragment, if any.
-      if (strpos($url, '#') !== FALSE) {
+      if (str_contains($url, '#')) {
         [$url, $options['fragment']] = explode('#', $url, 2);
       }
 
diff --git a/core/lib/Drupal/Component/Utility/Variable.php b/core/lib/Drupal/Component/Utility/Variable.php
index b4cfe04eff38f1a5fbc82f8db335f3eb01dcd9f3..338746e591ea34a6e4dcad72660a5e321851dda8 100644
--- a/core/lib/Drupal/Component/Utility/Variable.php
+++ b/core/lib/Drupal/Component/Utility/Variable.php
@@ -66,7 +66,7 @@ public static function export($var, $prefix = '') {
       $output = $var ? 'TRUE' : 'FALSE';
     }
     elseif (is_string($var)) {
-      if (strpos($var, "\n") !== FALSE || strpos($var, "'") !== FALSE) {
+      if (str_contains($var, "\n") || str_contains($var, "'")) {
         // If the string contains a line break or a single quote, use the
         // double quote export mode. Encode backslash, dollar symbols, and
         // double quotes and transform some common control characters.
diff --git a/core/lib/Drupal/Core/Action/Plugin/Action/EmailAction.php b/core/lib/Drupal/Core/Action/Plugin/Action/EmailAction.php
index 2a675fb990380dc739c1b7cbebbede92185d1ee8..78af30dccf9fcb6d1192877a4d53b27c3996b349 100644
--- a/core/lib/Drupal/Core/Action/Plugin/Action/EmailAction.php
+++ b/core/lib/Drupal/Core/Action/Plugin/Action/EmailAction.php
@@ -190,7 +190,7 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta
    * {@inheritdoc}
    */
   public function validateConfigurationForm(array &$form, FormStateInterface $form_state) {
-    if (!$this->emailValidator->isValid($form_state->getValue('recipient')) && strpos($form_state->getValue('recipient'), ':mail') === FALSE) {
+    if (!$this->emailValidator->isValid($form_state->getValue('recipient')) && !str_contains($form_state->getValue('recipient'), ':mail')) {
       // We want the literal %author placeholder to be emphasized in the error message.
       $form_state->setErrorByName('recipient', $this->t('Enter a valid email address or use a token email address such as %author.', ['%author' => '[node:author:mail]']));
     }
diff --git a/core/lib/Drupal/Core/Asset/AssetResolver.php b/core/lib/Drupal/Core/Asset/AssetResolver.php
index 35d6608256c036da1187f1eb3db17935c87c092b..42b51c39d8889c3e6a3acf8788a5762858160112 100644
--- a/core/lib/Drupal/Core/Asset/AssetResolver.php
+++ b/core/lib/Drupal/Core/Asset/AssetResolver.php
@@ -142,7 +142,7 @@ public function getCssAssets(AttachedAssetsInterface $assets, $optimize, Languag
           $options['license'] = $definition['license'];
 
           // Files with a query string cannot be preprocessed.
-          if ($options['type'] === 'file' && $options['preprocess'] && strpos($options['data'], '?') !== FALSE) {
+          if ($options['type'] === 'file' && $options['preprocess'] && str_contains($options['data'], '?')) {
             $options['preprocess'] = FALSE;
           }
 
diff --git a/core/lib/Drupal/Core/Asset/CssCollectionRenderer.php b/core/lib/Drupal/Core/Asset/CssCollectionRenderer.php
index 41634af7ef87519c3c4b34e62329ae3fc455ff31..940ace05bb0ed442fecedd9385d55a8203368af8 100644
--- a/core/lib/Drupal/Core/Asset/CssCollectionRenderer.php
+++ b/core/lib/Drupal/Core/Asset/CssCollectionRenderer.php
@@ -69,7 +69,7 @@ public function render(array $css_assets) {
           // Only add the cache-busting query string if this isn't an aggregate
           // file.
           if (!isset($css_asset['preprocessed'])) {
-            $query_string_separator = (strpos($css_asset['data'], '?') !== FALSE) ? '&' : '?';
+            $query_string_separator = str_contains($css_asset['data'], '?') ? '&' : '?';
             $element['#attributes']['href'] .= $query_string_separator . $query_string;
           }
           break;
diff --git a/core/lib/Drupal/Core/Asset/JsCollectionRenderer.php b/core/lib/Drupal/Core/Asset/JsCollectionRenderer.php
index 04afedf0904fed50f343a7e3ef8e090607824b32..7c71e4f6dd974b5ad03b44a13c8836b9bec30fee 100644
--- a/core/lib/Drupal/Core/Asset/JsCollectionRenderer.php
+++ b/core/lib/Drupal/Core/Asset/JsCollectionRenderer.php
@@ -82,7 +82,7 @@ public function render(array $js_assets) {
 
         case 'file':
           $query_string = $js_asset['version'] == -1 ? $default_query_string : 'v=' . $js_asset['version'];
-          $query_string_separator = (strpos($js_asset['data'], '?') !== FALSE) ? '&' : '?';
+          $query_string_separator = str_contains($js_asset['data'], '?') ? '&' : '?';
           $element['#attributes']['src'] = $this->fileUrlGenerator->generateString($js_asset['data']);
           // Only add the cache-busting query string if this isn't an aggregate
           // file.
diff --git a/core/lib/Drupal/Core/Cache/Context/CacheContextsManager.php b/core/lib/Drupal/Core/Cache/Context/CacheContextsManager.php
index 5df8a51c6ea8c05dc8e43841685ad7f6b6827b66..1c0a127cb56311691cc1d69dfcaacc329db91ec0 100644
--- a/core/lib/Drupal/Core/Cache/Context/CacheContextsManager.php
+++ b/core/lib/Drupal/Core/Cache/Context/CacheContextsManager.php
@@ -168,7 +168,7 @@ public function optimizeTokens(array $context_tokens) {
       // Extract the parameter if available.
       $parameter = NULL;
       $context_id = $context_token;
-      if (strpos($context_token, ':') !== FALSE) {
+      if (str_contains($context_token, ':')) {
         [$context_id, $parameter] = explode(':', $context_token);
       }
 
@@ -176,7 +176,7 @@ public function optimizeTokens(array $context_tokens) {
       // - a period means they don't have a parent
       // - a colon means they're not a specific value of a cache context
       // hence no optimizations are possible.
-      if (strpos($context_token, '.') === FALSE && strpos($context_token, ':') === FALSE) {
+      if (!str_contains($context_token, '.') && !str_contains($context_token, ':')) {
         $optimized_content_tokens[] = $context_token;
       }
       // Check cacheability. If the context defines a max-age of 0, then it
@@ -199,7 +199,7 @@ public function optimizeTokens(array $context_tokens) {
             $ancestor_found = TRUE;
           }
 
-        } while (!$ancestor_found && strpos($ancestor, '.') !== FALSE);
+        } while (!$ancestor_found && str_contains($ancestor, '.'));
         if (!$ancestor_found) {
           $optimized_content_tokens[] = $context_token;
         }
@@ -240,7 +240,7 @@ public static function parseTokens(array $context_tokens) {
     foreach ($context_tokens as $context) {
       $context_id = $context;
       $parameter = NULL;
-      if (strpos($context, ':') !== FALSE) {
+      if (str_contains($context, ':')) {
         [$context_id, $parameter] = explode(':', $context, 2);
       }
       $contexts_with_parameters[] = [$context_id, $parameter];
diff --git a/core/lib/Drupal/Core/Cache/Context/CacheContextsPass.php b/core/lib/Drupal/Core/Cache/Context/CacheContextsPass.php
index 579fc2a886416854bf89e628762ece39e1c6beae..3f233beca5a8f3bb2c55090e49eb0c6135da9e84 100644
--- a/core/lib/Drupal/Core/Cache/Context/CacheContextsPass.php
+++ b/core/lib/Drupal/Core/Cache/Context/CacheContextsPass.php
@@ -28,7 +28,7 @@ public function process(ContainerBuilder $container) {
     sort($cache_contexts);
     foreach ($cache_contexts as $id) {
       // Validate the hierarchy of non-root-level cache contexts.
-      if (strpos($id, '.') !== FALSE) {
+      if (str_contains($id, '.')) {
         $parent = substr($id, 0, strrpos($id, '.'));
         if (!in_array($parent, $cache_contexts)) {
           throw new \InvalidArgumentException(sprintf('The service "%s" has an invalid service ID: the period indicates the hierarchy of cache contexts, therefore "%s" is considered the parent cache context, but no cache context service with that name was found.', $id, $parent));
diff --git a/core/lib/Drupal/Core/Command/InstallCommand.php b/core/lib/Drupal/Core/Command/InstallCommand.php
index 92ca6a255a4c3cde498d969224781feca60aab76..ef4ec3c1080a2b017c9887d4aa3f635389596c06 100644
--- a/core/lib/Drupal/Core/Command/InstallCommand.php
+++ b/core/lib/Drupal/Core/Command/InstallCommand.php
@@ -291,7 +291,7 @@ protected function validateProfile($install_profile, SymfonyStyle $io) {
       $alternatives = [];
       foreach (array_keys($profiles) as $profile_name) {
         $lev = levenshtein($install_profile, $profile_name);
-        if ($lev <= strlen($profile_name) / 4 || FALSE !== strpos($profile_name, $install_profile)) {
+        if ($lev <= strlen($profile_name) / 4 || str_contains($profile_name, $install_profile)) {
           $alternatives[] = $profile_name;
         }
       }
diff --git a/core/lib/Drupal/Core/Config/ConfigBase.php b/core/lib/Drupal/Core/Config/ConfigBase.php
index 0bf960e93e4d92011494dcec0e830b3f48f92462..e4d298511599eeabfab91f6c8c71dccf964f7708 100644
--- a/core/lib/Drupal/Core/Config/ConfigBase.php
+++ b/core/lib/Drupal/Core/Config/ConfigBase.php
@@ -93,7 +93,7 @@ public function setName($name) {
    */
   public static function validateName($name) {
     // The name must be namespaced by owner.
-    if (strpos($name, '.') === FALSE) {
+    if (!str_contains($name, '.')) {
       throw new ConfigNameException("Missing namespace in Config object name $name.");
     }
     // The name must be shorter than Config::MAX_NAME_LENGTH characters.
@@ -207,7 +207,7 @@ public function set($key, $value) {
    */
   protected function validateKeys(array $data) {
     foreach ($data as $key => $value) {
-      if (strpos($key, '.') !== FALSE) {
+      if (str_contains($key, '.')) {
         throw new ConfigValueException("$key key contains a dot which is not supported.");
       }
       if (is_array($value)) {
diff --git a/core/lib/Drupal/Core/Config/Entity/Query/Condition.php b/core/lib/Drupal/Core/Config/Entity/Query/Condition.php
index a1a03409ccd2f44e21f095de3ea4032efb4dfb60..9597de2ddf9bbda6ba07d191fe365d6ced932210 100644
--- a/core/lib/Drupal/Core/Config/Entity/Query/Condition.php
+++ b/core/lib/Drupal/Core/Config/Entity/Query/Condition.php
@@ -203,7 +203,7 @@ protected function match(array $condition, $value) {
           return strpos($value, $condition['value']) === 0;
 
         case 'CONTAINS':
-          return strpos($value, $condition['value']) !== FALSE;
+          return str_contains($value, $condition['value']);
 
         case 'ENDS_WITH':
           return substr($value, -strlen($condition['value'])) === (string) $condition['value'];
diff --git a/core/lib/Drupal/Core/Config/Entity/Query/Query.php b/core/lib/Drupal/Core/Config/Entity/Query/Query.php
index 9adcd181bb59f83986f7e8da8e4cfcd3fe4d3a3e..109efb8382af18b36e7f3ca3ec430cfbd77e41fc 100644
--- a/core/lib/Drupal/Core/Config/Entity/Query/Query.php
+++ b/core/lib/Drupal/Core/Config/Entity/Query/Query.php
@@ -207,7 +207,7 @@ protected function loadRecords() {
         case 'CONTAINS':
           $filter = static function ($name) use ($value, $prefix_length) {
             $id = substr($name, $prefix_length);
-            return strpos($id, $value) !== FALSE;
+            return str_contains($id, $value);
           };
           break;
 
diff --git a/core/lib/Drupal/Core/Controller/ControllerResolver.php b/core/lib/Drupal/Core/Controller/ControllerResolver.php
index a4e4ebaf74f02d92da51fa696a5b477d16810a2d..a7f60b1436464608f0d40ed2fb427b60d9521655 100644
--- a/core/lib/Drupal/Core/Controller/ControllerResolver.php
+++ b/core/lib/Drupal/Core/Controller/ControllerResolver.php
@@ -58,7 +58,7 @@ public function getControllerFromDefinition($controller, $path = '') {
       return $controller;
     }
 
-    if (strpos($controller, ':') === FALSE) {
+    if (!str_contains($controller, ':')) {
       if (function_exists($controller)) {
         return $controller;
       }
@@ -106,7 +106,7 @@ protected function createController($controller) {
       [$class_or_service, $method] = explode(':', $controller, 2);
     }
     // Controller in the class::method notation.
-    elseif (strpos($controller, '::') !== FALSE) {
+    elseif (str_contains($controller, '::')) {
       [$class_or_service, $method] = explode('::', $controller, 2);
     }
     else {
diff --git a/core/lib/Drupal/Core/Database/Connection.php b/core/lib/Drupal/Core/Database/Connection.php
index 75966d7fcbc8e1a8212d94c0245e7913daa8e8fb..2bb3c057b4f2e878fdb34d1b3316db86211a4858 100644
--- a/core/lib/Drupal/Core/Database/Connection.php
+++ b/core/lib/Drupal/Core/Database/Connection.php
@@ -566,7 +566,7 @@ protected function preprocessStatement(string $query, array $options): string {
       $trim_chars .= ';';
     }
     $query = rtrim($query, $trim_chars);
-    if (strpos($query, ';') !== FALSE && empty($options['allow_delimiter_in_query'])) {
+    if (str_contains($query, ';') && empty($options['allow_delimiter_in_query'])) {
       throw new \InvalidArgumentException('; is not supported in SQL strings. Use only one statement at a time.');
     }
 
diff --git a/core/lib/Drupal/Core/Database/Query/Select.php b/core/lib/Drupal/Core/Database/Query/Select.php
index c4fd8535f4504d10abb8c9da935d5e779891eec9..157696d1c28fd322b5893b10e9eef37b7f77095a 100644
--- a/core/lib/Drupal/Core/Database/Query/Select.php
+++ b/core/lib/Drupal/Core/Database/Query/Select.php
@@ -856,7 +856,7 @@ public function __toString() {
       else {
         $table_string = $this->connection->escapeTable($table['table']);
         // Do not attempt prefixing cross database / schema queries.
-        if (strpos($table_string, '.') === FALSE) {
+        if (!str_contains($table_string, '.')) {
           $table_string = '{' . $table_string . '}';
         }
       }
diff --git a/core/lib/Drupal/Core/DependencyInjection/YamlFileLoader.php b/core/lib/Drupal/Core/DependencyInjection/YamlFileLoader.php
index 879966fda0293451fc6250559dfa9c18dcc8d28e..36cd99d586db4a189dd2b30f3731bfb61d727610 100644
--- a/core/lib/Drupal/Core/DependencyInjection/YamlFileLoader.php
+++ b/core/lib/Drupal/Core/DependencyInjection/YamlFileLoader.php
@@ -288,7 +288,7 @@ private function parseDefinition(string $id, $service, string $file, array $defa
 
         if (isset($service['factory'])) {
             if (is_string($service['factory'])) {
-                if (strpos($service['factory'], ':') !== false && strpos($service['factory'], '::') === false) {
+                if (str_contains($service['factory'], ':') && !str_contains($service['factory'], '::')) {
                     $parts = explode(':', $service['factory']);
                     $definition->setFactory(array($this->resolveServices('@'.$parts[0]), $parts[1]));
                 } else {
diff --git a/core/lib/Drupal/Core/Entity/Enhancer/EntityRouteEnhancer.php b/core/lib/Drupal/Core/Entity/Enhancer/EntityRouteEnhancer.php
index e895273d8893f97023bf9bbc4e1e7002d3eae71d..1e9dc258c6620742e98a16fc90c346d3da044e68 100644
--- a/core/lib/Drupal/Core/Entity/Enhancer/EntityRouteEnhancer.php
+++ b/core/lib/Drupal/Core/Entity/Enhancer/EntityRouteEnhancer.php
@@ -103,7 +103,7 @@ protected function enhanceEntityList(array $defaults, Request $request) {
    */
   protected function enhanceEntityView(array $defaults, Request $request) {
     $defaults['_controller'] = '\Drupal\Core\Entity\Controller\EntityViewController::view';
-    if (strpos($defaults['_entity_view'], '.') !== FALSE) {
+    if (str_contains($defaults['_entity_view'], '.')) {
       // The _entity_view entry is of the form entity_type.view_mode.
       [$entity_type, $view_mode] = explode('.', $defaults['_entity_view']);
       $defaults['view_mode'] = $view_mode;
diff --git a/core/lib/Drupal/Core/Entity/EntityCreateAccessCheck.php b/core/lib/Drupal/Core/Entity/EntityCreateAccessCheck.php
index 25566ba4bf648279c6ce128ea2de0ef9884d9487..592bbc5c796249a1665d2017f420ff5b1af4195c 100644
--- a/core/lib/Drupal/Core/Entity/EntityCreateAccessCheck.php
+++ b/core/lib/Drupal/Core/Entity/EntityCreateAccessCheck.php
@@ -56,12 +56,12 @@ public function access(Route $route, RouteMatchInterface $route_match, AccountIn
     // The bundle argument can contain request argument placeholders like
     // {name}, loop over the raw variables and attempt to replace them in the
     // bundle name. If a placeholder does not exist, it won't get replaced.
-    if ($bundle && strpos($bundle, '{') !== FALSE) {
+    if ($bundle && str_contains($bundle, '{')) {
       foreach ($route_match->getRawParameters()->all() as $name => $value) {
         $bundle = str_replace('{' . $name . '}', $value, $bundle);
       }
       // If we were unable to replace all placeholders, deny access.
-      if (strpos($bundle, '{') !== FALSE) {
+      if (str_contains($bundle, '{')) {
         return AccessResult::neutral(sprintf("Could not find '%s' request argument, therefore cannot check create access.", $bundle));
       }
     }
diff --git a/core/lib/Drupal/Core/Entity/EntityReferenceSelection/SelectionPluginManager.php b/core/lib/Drupal/Core/Entity/EntityReferenceSelection/SelectionPluginManager.php
index cf9bb7e49de8963dd4ff9b114cb67e02fc25adfe..0b90f826332ace6030ac00cc34b22f1fda809ec5 100644
--- a/core/lib/Drupal/Core/Entity/EntityReferenceSelection/SelectionPluginManager.php
+++ b/core/lib/Drupal/Core/Entity/EntityReferenceSelection/SelectionPluginManager.php
@@ -42,7 +42,7 @@ public function getInstance(array $options) {
     ];
 
     // A specific selection plugin ID was already specified.
-    if (strpos($options['handler'], ':') !== FALSE) {
+    if (str_contains($options['handler'], ':')) {
       $plugin_id = $options['handler'];
     }
     // Only a selection group name was specified.
diff --git a/core/lib/Drupal/Core/Entity/EntityResolverManager.php b/core/lib/Drupal/Core/Entity/EntityResolverManager.php
index 55f87ea2b70cae176803c43552e1137f56479449..0430a74f8b7342b08456378c6e37fe4810e407b0 100644
--- a/core/lib/Drupal/Core/Entity/EntityResolverManager.php
+++ b/core/lib/Drupal/Core/Entity/EntityResolverManager.php
@@ -86,7 +86,7 @@ protected function getControllerClass(array $defaults) {
       return NULL;
     }
 
-    if (strpos($controller, ':') === FALSE) {
+    if (!str_contains($controller, ':')) {
       if (method_exists($controller, '__invoke')) {
         return [$controller, '__invoke'];
       }
@@ -105,7 +105,7 @@ protected function getControllerClass(array $defaults) {
       [$class_or_service, $method] = explode(':', $controller, 2);
       return [$this->classResolver->getInstanceFromDefinition($class_or_service), $method];
     }
-    elseif (strpos($controller, '::') !== FALSE) {
+    elseif (str_contains($controller, '::')) {
       // Controller in the class::method notation.
       return explode('::', $controller, 2);
     }
@@ -182,7 +182,7 @@ protected function setParametersFromEntityInformation(Route $route) {
     // Do not add parameter information if the route does not declare a
     // parameter in the first place. This is the case for add forms, for
     // example.
-    if (isset($entity_type) && isset($this->getEntityTypes()[$entity_type]) && (strpos($route->getPath(), '{' . $entity_type . '}') !== FALSE)) {
+    if (isset($entity_type) && isset($this->getEntityTypes()[$entity_type]) && str_contains($route->getPath(), '{' . $entity_type . '}')) {
       $parameter_definitions = $route->getOption('parameters') ?: [];
 
       // First try to figure out whether there is already a parameter upcasting
diff --git a/core/lib/Drupal/Core/Entity/Plugin/EntityReferenceSelection/PhpSelection.php b/core/lib/Drupal/Core/Entity/Plugin/EntityReferenceSelection/PhpSelection.php
index 0309f76bbfd82f592c710091dc8ae26dec3bd386..f9a749eb47dddfcfd9871df4f0f1347a01dc7d8c 100644
--- a/core/lib/Drupal/Core/Entity/Plugin/EntityReferenceSelection/PhpSelection.php
+++ b/core/lib/Drupal/Core/Entity/Plugin/EntityReferenceSelection/PhpSelection.php
@@ -119,7 +119,7 @@ protected function matchLabel($match, $match_operator, $label) {
         return strpos($label, $match) === 0;
 
       case 'CONTAINS':
-        return strpos($label, $match) !== FALSE;
+        return str_contains($label, $match);
 
       case 'ENDS_WITH':
         return mb_substr($label, -mb_strlen($match)) === (string) $match;
diff --git a/core/lib/Drupal/Core/Entity/Query/Sql/Tables.php b/core/lib/Drupal/Core/Entity/Query/Sql/Tables.php
index 91b43bef9396f0f02992f2aa54255ee09ac4e93e..5e5dfb815c82dc887ffbbb4da2f29b63243143a4 100644
--- a/core/lib/Drupal/Core/Entity/Query/Sql/Tables.php
+++ b/core/lib/Drupal/Core/Entity/Query/Sql/Tables.php
@@ -284,7 +284,7 @@ public function addField($field, $type, $langcode) {
         $entity_type_id = NULL;
         // Relationship specifier can also contain the entity type ID, i.e.
         // entity:node, entity:user or entity:taxonomy.
-        if (strpos($relationship_specifier, ':') !== FALSE) {
+        if (str_contains($relationship_specifier, ':')) {
           [$relationship_specifier, $entity_type_id] = explode(':', $relationship_specifier, 2);
         }
         // Check for a valid relationship.
diff --git a/core/lib/Drupal/Core/Entity/Routing/DefaultHtmlRouteProvider.php b/core/lib/Drupal/Core/Entity/Routing/DefaultHtmlRouteProvider.php
index 4dbd1d1bfecde6094d04751645bbde79ac50bfa8..9bf08fde26577125078d88d96d97eaed98baf850 100644
--- a/core/lib/Drupal/Core/Entity/Routing/DefaultHtmlRouteProvider.php
+++ b/core/lib/Drupal/Core/Entity/Routing/DefaultHtmlRouteProvider.php
@@ -158,7 +158,7 @@ protected function getAddFormRoute(EntityTypeInterface $entity_type) {
       // @todo We have to check if a route contains a bundle in its path as
       //   test entities have inconsistent usage of "add-form" link templates.
       //   Fix it in https://www.drupal.org/node/2699959.
-      if (($bundle_key = $entity_type->getKey('bundle')) && strpos($route->getPath(), '{' . $expected_parameter . '}') !== FALSE) {
+      if (($bundle_key = $entity_type->getKey('bundle')) && str_contains($route->getPath(), '{' . $expected_parameter . '}')) {
         $route->setDefault('_title_callback', EntityController::class . '::addBundleTitle');
         // If the bundles are entities themselves, we can add parameter
         // information to the route options.
diff --git a/core/lib/Drupal/Core/EventSubscriber/AjaxResponseSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/AjaxResponseSubscriber.php
index 266dfc6a82385d6aba8da55f3f2e40c19801b2be..816546070b8e25c1fb93b9407d432fe659aeac87 100644
--- a/core/lib/Drupal/Core/EventSubscriber/AjaxResponseSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/AjaxResponseSubscriber.php
@@ -85,7 +85,7 @@ public function onResponse(ResponseEvent $event) {
       // @see Drupal.ajax.prototype.beforeSend()
       $accept = $event->getRequest()->headers->get('accept', '');
 
-      if (strpos($accept, 'text/html') !== FALSE) {
+      if (str_contains($accept, 'text/html')) {
         $response->headers->set('Content-Type', 'text/html; charset=utf-8');
 
         // Browser IFRAMEs expect HTML. Browser extensions, such as Linkification
diff --git a/core/lib/Drupal/Core/EventSubscriber/RedirectLeadingSlashesSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/RedirectLeadingSlashesSubscriber.php
index 75fd237f77a872f952df1718c82585d8a6ddaaa4..7c03ba267714b81a5e86dba89fbf584da782f903 100644
--- a/core/lib/Drupal/Core/EventSubscriber/RedirectLeadingSlashesSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/RedirectLeadingSlashesSubscriber.php
@@ -28,7 +28,7 @@ public function redirect(RequestEvent $event) {
     // submits back to the same URI this presents an open redirect
     // vulnerability. Also, Drupal 7 renders the same page for
     // http://www.example.org/foo and http://www.example.org////foo.
-    if (strpos($path, '//') !== FALSE) {
+    if (str_contains($path, '//')) {
       $path = preg_replace('/\/+/', '/', $path);
       $qs = $request->getQueryString();
       if ($qs) {
diff --git a/core/lib/Drupal/Core/Extension/Dependency.php b/core/lib/Drupal/Core/Extension/Dependency.php
index 42caa67df35dbf6448b32a9e9b0e041e16043225..0f305df890173b129cbe980bf27fcd85f4aa424f 100644
--- a/core/lib/Drupal/Core/Extension/Dependency.php
+++ b/core/lib/Drupal/Core/Extension/Dependency.php
@@ -123,7 +123,7 @@ public function isCompatible($version) {
    * @return static
    */
   public static function createFromString($dependency) {
-    if (strpos($dependency, ':') !== FALSE) {
+    if (str_contains($dependency, ':')) {
       [$project, $dependency] = explode(':', $dependency);
     }
     else {
diff --git a/core/lib/Drupal/Core/Form/FormHelper.php b/core/lib/Drupal/Core/Form/FormHelper.php
index 68066bac3e6fa9d163abceae893c17d363c95466..8ac7266a1649cf6aa9af338fc348d59d6f2bc8d2 100644
--- a/core/lib/Drupal/Core/Form/FormHelper.php
+++ b/core/lib/Drupal/Core/Form/FormHelper.php
@@ -60,7 +60,7 @@ protected static function processStatesArray(array &$conditions, $search, $repla
     $keys = array_keys($conditions);
     $update_keys = FALSE;
     foreach ($conditions as $id => $values) {
-      if (strpos($id, $search) !== FALSE) {
+      if (str_contains($id, $search)) {
         $update_keys = TRUE;
         $new_id = str_replace($search, $replace, $id);
         // Replace the key and keep the array in the same order.
diff --git a/core/lib/Drupal/Core/Logger/LogMessageParser.php b/core/lib/Drupal/Core/Logger/LogMessageParser.php
index 73c0917d37d8cd02aa76abf801e8b4fe87059aae..3d94f6b77b6ef952d10f8dd324cec5674233b710 100644
--- a/core/lib/Drupal/Core/Logger/LogMessageParser.php
+++ b/core/lib/Drupal/Core/Logger/LogMessageParser.php
@@ -25,7 +25,7 @@ public function parseMessagePlaceholders(&$message, array &$context) {
         // Keys are not prefixed with anything according to PSR3 specs.
         // If the message is "User {username} created" the variable key will be
         // just "username".
-        if (strpos($message, '@' . $key) !== FALSE) {
+        if (str_contains($message, '@' . $key)) {
           $key = '@' . $key;
         }
       }
diff --git a/core/lib/Drupal/Core/Mail/MailFormatHelper.php b/core/lib/Drupal/Core/Mail/MailFormatHelper.php
index 4198d443e6fc0363b878506dac33fa1ffa4c57e7..97cbbc0fe242a8f42ed3ee3aa77c04f50b55dac2 100644
--- a/core/lib/Drupal/Core/Mail/MailFormatHelper.php
+++ b/core/lib/Drupal/Core/Mail/MailFormatHelper.php
@@ -54,9 +54,9 @@ public static function wrapMail($text, $indent = '') {
     $text = str_replace("\r", '', $text);
     // See if soft-wrapping is allowed.
     $clean_indent = static::htmlToTextClean($indent);
-    $soft = strpos($clean_indent, ' ') === FALSE;
+    $soft = !str_contains($clean_indent, ' ');
     // Check if the string has line breaks.
-    if (strpos($text, "\n") !== FALSE) {
+    if (str_contains($text, "\n")) {
       // Remove trailing spaces to make existing breaks hard, but leave
       // signature marker untouched (RFC 3676, Section 4.3).
       $text = preg_replace('/(?(?<!^--) +\n|  +\n)/m', "\n", $text);
diff --git a/core/lib/Drupal/Core/ParamConverter/EntityConverter.php b/core/lib/Drupal/Core/ParamConverter/EntityConverter.php
index c3820baaca01c8a2a92b308d39f2b8dd4c0d9af4..aa2b00d647647df5528a443f8050486f79c4a3e3 100644
--- a/core/lib/Drupal/Core/ParamConverter/EntityConverter.php
+++ b/core/lib/Drupal/Core/ParamConverter/EntityConverter.php
@@ -169,7 +169,7 @@ public function convert($value, $definition, $name, array $defaults) {
   public function applies($definition, $name, Route $route) {
     if (!empty($definition['type']) && strpos($definition['type'], 'entity:') === 0) {
       $entity_type_id = substr($definition['type'], strlen('entity:'));
-      if (strpos($definition['type'], '{') !== FALSE) {
+      if (str_contains($definition['type'], '{')) {
         $entity_type_slug = substr($entity_type_id, 1, -1);
         return $name != $entity_type_slug && in_array($entity_type_slug, $route->compile()->getVariables(), TRUE);
       }
diff --git a/core/lib/Drupal/Core/ParamConverter/EntityRevisionParamConverter.php b/core/lib/Drupal/Core/ParamConverter/EntityRevisionParamConverter.php
index 4f4d94311f5ff75f2ea81201f9522ae5815f997b..f7aeaf36619537f3d0c52c2ff5cdb554c068886c 100644
--- a/core/lib/Drupal/Core/ParamConverter/EntityRevisionParamConverter.php
+++ b/core/lib/Drupal/Core/ParamConverter/EntityRevisionParamConverter.php
@@ -76,7 +76,7 @@ public function convert($value, $definition, $name, array $defaults) {
    * {@inheritdoc}
    */
   public function applies($definition, $name, Route $route) {
-    return isset($definition['type']) && strpos($definition['type'], 'entity_revision:') !== FALSE;
+    return isset($definition['type']) && str_contains($definition['type'], 'entity_revision:');
   }
 
 }
diff --git a/core/lib/Drupal/Core/Routing/Enhancer/EntityRevisionRouteEnhancer.php b/core/lib/Drupal/Core/Routing/Enhancer/EntityRevisionRouteEnhancer.php
index 18f0fb598fab50967140cbeb50fb12f708a5027a..71107c685d77d5f001db42def57109e277704324 100644
--- a/core/lib/Drupal/Core/Routing/Enhancer/EntityRevisionRouteEnhancer.php
+++ b/core/lib/Drupal/Core/Routing/Enhancer/EntityRevisionRouteEnhancer.php
@@ -44,7 +44,7 @@ public function enhance(array $defaults, Request $request) {
     $options = $route->getOptions();
     if (isset($options['parameters'])) {
       foreach ($options['parameters'] as $name => $details) {
-        if (!empty($details['type']) && strpos($details['type'], 'entity_revision:') !== FALSE) {
+        if (!empty($details['type']) && str_contains($details['type'], 'entity_revision:')) {
           $defaults['_entity_revision'] = $defaults[$name];
           break;
         }
diff --git a/core/lib/Drupal/Core/Routing/RequestHelper.php b/core/lib/Drupal/Core/Routing/RequestHelper.php
index 0a532abb19fa4f5fdd0acc6f6c4f54406cfad989..23063901a0b2b004ad6a986f8ffa498efbbd16a0 100644
--- a/core/lib/Drupal/Core/Routing/RequestHelper.php
+++ b/core/lib/Drupal/Core/Routing/RequestHelper.php
@@ -27,7 +27,7 @@ class RequestHelper {
    */
   public static function isCleanUrl(Request $request) {
     $base_url = $request->getBaseUrl();
-    return (empty($base_url) || strpos($base_url, $request->getScriptName()) === FALSE);
+    return (empty($base_url) || !str_contains($base_url, $request->getScriptName()));
   }
 
 }
diff --git a/core/lib/Drupal/Core/Routing/RouteCompiler.php b/core/lib/Drupal/Core/Routing/RouteCompiler.php
index 2d6d19d1b54a92c9a52ad7367c51b8439062bc90..5a09a384d858195fa221a1084870341e11651129 100644
--- a/core/lib/Drupal/Core/Routing/RouteCompiler.php
+++ b/core/lib/Drupal/Core/Routing/RouteCompiler.php
@@ -98,7 +98,7 @@ public static function getFit($path) {
     // patterns we need to check in the RouteProvider.
     $fit = 0;
     foreach ($parts as $k => $part) {
-      if (strpos($part, '{') === FALSE) {
+      if (!str_contains($part, '{')) {
         $fit |= 1 << ($slashes - $k);
       }
     }
diff --git a/core/lib/Drupal/Core/Routing/UrlGenerator.php b/core/lib/Drupal/Core/Routing/UrlGenerator.php
index 599f226f62adb6d2a232c5c3e6318d2617fa499e..99dfcc4a2e48e8477cf6247763caf2ba00aedf38 100644
--- a/core/lib/Drupal/Core/Routing/UrlGenerator.php
+++ b/core/lib/Drupal/Core/Routing/UrlGenerator.php
@@ -311,7 +311,7 @@ public function generateFromRoute($name, $parameters = [], $options = [], $colle
     $path = str_replace($this->decodedChars[0], $this->decodedChars[1], rawurlencode($path));
 
     // Drupal paths rarely include dots, so skip this processing if possible.
-    if (strpos($path, '/.') !== FALSE) {
+    if (str_contains($path, '/.')) {
       // the path segments "." and ".." are interpreted as relative reference when
       // resolving a URI; see http://tools.ietf.org/html/rfc3986#section-3.3
       // so we need to encode them as they are not used for this purpose here
diff --git a/core/lib/Drupal/Core/Security/DoTrustedCallbackTrait.php b/core/lib/Drupal/Core/Security/DoTrustedCallbackTrait.php
index 31900041ca443d0ad2f4920f7a8455ec740e3eed..3457cd60ff40f0457ca4cbbcef763e759513c2a9 100644
--- a/core/lib/Drupal/Core/Security/DoTrustedCallbackTrait.php
+++ b/core/lib/Drupal/Core/Security/DoTrustedCallbackTrait.php
@@ -55,7 +55,7 @@ public function doTrustedCallback(callable $callback, array $args, $message, $er
     if (is_array($callback)) {
       [$object_or_classname, $method_name] = $callback;
     }
-    elseif (is_string($callback) && strpos($callback, '::') !== FALSE) {
+    elseif (is_string($callback) && str_contains($callback, '::')) {
       [$object_or_classname, $method_name] = explode('::', $callback, 2);
     }
 
diff --git a/core/lib/Drupal/Core/Test/AssertMailTrait.php b/core/lib/Drupal/Core/Test/AssertMailTrait.php
index e0b36180b4ce84637798562fa646ff217a9ca96d..44e4a5d09a27eafa9e6ad7533057e3edb2949e42 100644
--- a/core/lib/Drupal/Core/Test/AssertMailTrait.php
+++ b/core/lib/Drupal/Core/Test/AssertMailTrait.php
@@ -89,7 +89,7 @@ protected function assertMailString($field_name, $string, $email_depth, $message
       // done. Any run of whitespace becomes a single space.
       $normalized_mail = preg_replace('/\s+/', ' ', $mail[$field_name]);
       $normalized_string = preg_replace('/\s+/', ' ', $string);
-      $string_found = (FALSE !== strpos($normalized_mail, $normalized_string));
+      $string_found = str_contains($normalized_mail, $normalized_string);
       if ($string_found) {
         break;
       }
diff --git a/core/lib/Drupal/Core/Test/TestDiscovery.php b/core/lib/Drupal/Core/Test/TestDiscovery.php
index a0fa2ceaba3a0cc3c187794cfad474e966879e83..9e394a4342e8fe0f27e2e1efa30870277ef95449 100644
--- a/core/lib/Drupal/Core/Test/TestDiscovery.php
+++ b/core/lib/Drupal/Core/Test/TestDiscovery.php
@@ -174,7 +174,7 @@ public function getTestClasses($extension = NULL, array $types = []) {
       }
       catch (MissingGroupException $e) {
         // If the class name ends in Test and is not a migrate table dump.
-        if (preg_match('/Test$/', $classname) && strpos($classname, 'migrate_drupal\Tests\Table') === FALSE) {
+        if (preg_match('/Test$/', $classname) && !str_contains($classname, 'migrate_drupal\Tests\Table')) {
           throw $e;
         }
         // If the class is @group annotation just skip it. Most likely it is an
diff --git a/core/lib/Drupal/Core/Utility/LinkGenerator.php b/core/lib/Drupal/Core/Utility/LinkGenerator.php
index e3f3fe418e116c2e1c8167752f10cb6c0decf6e4..c30b233b0610d8f5ceed5220658a5944e955a924 100644
--- a/core/lib/Drupal/Core/Utility/LinkGenerator.php
+++ b/core/lib/Drupal/Core/Utility/LinkGenerator.php
@@ -149,7 +149,7 @@ public function generate($text, Url $url) {
 
     // Remove all HTML and PHP tags from a tooltip, calling expensive strip_tags()
     // only when a quick strpos() gives suspicion tags are present.
-    if (isset($variables['options']['attributes']['title']) && strpos($variables['options']['attributes']['title'], '<') !== FALSE) {
+    if (isset($variables['options']['attributes']['title']) && str_contains($variables['options']['attributes']['title'], '<')) {
       $variables['options']['attributes']['title'] = strip_tags($variables['options']['attributes']['title']);
     }
 
diff --git a/core/lib/Drupal/Core/Utility/UnroutedUrlAssembler.php b/core/lib/Drupal/Core/Utility/UnroutedUrlAssembler.php
index 768103b0c39cfbe5d80fc677c9dbc50a6504eb24..b4746186bf346060b516474b6617dd77169f05c8 100644
--- a/core/lib/Drupal/Core/Utility/UnroutedUrlAssembler.php
+++ b/core/lib/Drupal/Core/Utility/UnroutedUrlAssembler.php
@@ -178,7 +178,7 @@ protected function addOptionDefaults(array &$options) {
     // is added, to allow simple string concatenation with other parts.
     if (!empty($base_path_with_script)) {
       $script_name = $request->getScriptName();
-      if (strpos($base_path_with_script, $script_name) !== FALSE) {
+      if (str_contains($base_path_with_script, $script_name)) {
         $current_script_path = ltrim(substr($script_name, strlen($current_base_path)), '/') . '/';
       }
     }
diff --git a/core/lib/Drupal/Core/Utility/link.api.php b/core/lib/Drupal/Core/Utility/link.api.php
index 6033068927a5b106ac0e2cc979a60c27b0ba5e60..8a44b1b886c22aca25ff96da0b768d9e424e4033 100644
--- a/core/lib/Drupal/Core/Utility/link.api.php
+++ b/core/lib/Drupal/Core/Utility/link.api.php
@@ -53,7 +53,7 @@
  */
 function hook_link_alter(&$variables) {
   // Add a warning to the end of route links to the admin section.
-  if (isset($variables['route_name']) && strpos($variables['route_name'], 'admin') !== FALSE) {
+  if (isset($variables['route_name']) && str_contains($variables['route_name'], 'admin')) {
     $variables['text'] = new TranslatableMarkup('@text (Warning!)', ['@text' => $variables['text']]);
   }
 }
diff --git a/core/modules/big_pipe/tests/modules/big_pipe_test/src/EventSubscriber/BigPipeTestSubscriber.php b/core/modules/big_pipe/tests/modules/big_pipe_test/src/EventSubscriber/BigPipeTestSubscriber.php
index c21d153acec651448e9e78a0a56aff1c45c7f574..73e23921f10e2d44be01a81d2543dd6604433d95 100644
--- a/core/modules/big_pipe/tests/modules/big_pipe_test/src/EventSubscriber/BigPipeTestSubscriber.php
+++ b/core/modules/big_pipe/tests/modules/big_pipe_test/src/EventSubscriber/BigPipeTestSubscriber.php
@@ -36,7 +36,7 @@ public function onRespondTriggerException(ResponseEvent $event) {
 
     $attachments = $response->getAttachments();
     if (!isset($attachments['big_pipe_placeholders']) && !isset($attachments['big_pipe_nojs_placeholders'])) {
-      if (strpos($response->getContent(), static::CONTENT_TRIGGER_EXCEPTION) !== FALSE) {
+      if (str_contains($response->getContent(), static::CONTENT_TRIGGER_EXCEPTION)) {
         throw new \Exception('Oh noes!');
       }
     }
diff --git a/core/modules/block/tests/modules/block_test/src/Form/TestForm.php b/core/modules/block/tests/modules/block_test/src/Form/TestForm.php
index 55b13f78258005703a87b08f7688bd88b39baff4..232a974e8b3f9ff5d171d50849405f6fa06668a2 100644
--- a/core/modules/block/tests/modules/block_test/src/Form/TestForm.php
+++ b/core/modules/block/tests/modules/block_test/src/Form/TestForm.php
@@ -40,7 +40,7 @@ public function buildForm(array $form, FormStateInterface $form_state) {
    * {@inheritdoc}
    */
   public function validateForm(array &$form, FormStateInterface $form_state) {
-    if (strpos($form_state->getValue('email'), '.com') === FALSE) {
+    if (!str_contains($form_state->getValue('email'), '.com')) {
       $form_state->setErrorByName('email', $this->t('This is not a .com email address.'));
     }
   }
diff --git a/core/modules/ckeditor5/ckeditor5.module b/core/modules/ckeditor5/ckeditor5.module
index 9a7d0aae39f0edf5e91d6a7a7e77d7ee79c56d99..af80c687fbc6640ca8f26e1af10b1718340b0417 100644
--- a/core/modules/ckeditor5/ckeditor5.module
+++ b/core/modules/ckeditor5/ckeditor5.module
@@ -212,7 +212,7 @@ function _add_ajax_listeners_to_plugin_inputs(array &$plugins_config_form): void
       }
 
       foreach ($plugins_config_form as $key => &$value) {
-        if (is_array($value) && strpos((string) $key, '#') === FALSE) {
+        if (is_array($value) && !str_contains((string) $key, '#')) {
           _add_ajax_listeners_to_plugin_inputs($value);
         }
       }
@@ -345,7 +345,7 @@ function _add_attachments_to_editor_update_response(array $form, AjaxResponse &$
         if ($key === "#attached") {
           $response->addAttachments(array_diff_key($value, ['placeholders' => '']));
         }
-        elseif (is_array($value) && strpos((string) $key, '#') === FALSE) {
+        elseif (is_array($value) && !str_contains((string) $key, '#')) {
           _add_attachments_to_editor_update_response($value, $response);
         }
       }
diff --git a/core/modules/ckeditor5/src/HTMLRestrictions.php b/core/modules/ckeditor5/src/HTMLRestrictions.php
index 238d412c17083c17011e7c02d07faeef8cbe7557..09485d93a2b8bc7d5f208fab6309355c11082d4b 100644
--- a/core/modules/ckeditor5/src/HTMLRestrictions.php
+++ b/core/modules/ckeditor5/src/HTMLRestrictions.php
@@ -1040,7 +1040,7 @@ private static function applyOperation(HTMLRestrictions $a, HTMLRestrictions $b,
   private static function isWildcardAttributeName(string $attribute_name): bool {
     // @see ::validateAllowedRestrictionsPhase3()
     assert($attribute_name !== '*');
-    return strpos($attribute_name, '*') !== FALSE;
+    return str_contains($attribute_name, '*');
   }
 
   /**
@@ -1315,7 +1315,7 @@ public function toGeneralHtmlSupportConfig(): array {
           // the attribute name contains a partial wildcard, more complex syntax
           // is needed.
           $to_allow['attributes'][] = [
-            'key' => strpos($name, '*') === FALSE ? $name : ['regexp' => ['pattern' => self::getRegExForWildCardAttributeName($name)]],
+            'key' => !str_contains($name, '*') ? $name : ['regexp' => ['pattern' => self::getRegExForWildCardAttributeName($name)]],
             'value' => $allowed_attribute_value,
           ];
         }
diff --git a/core/modules/ckeditor5/src/Plugin/Validation/Constraint/SourceEditingPreventSelfXssConstraintValidator.php b/core/modules/ckeditor5/src/Plugin/Validation/Constraint/SourceEditingPreventSelfXssConstraintValidator.php
index 2fd9632380dbd4cd21cdf6ed7c9c30fce06b807c..53bc51913956e32259dfa1603c953f214f150d54 100644
--- a/core/modules/ckeditor5/src/Plugin/Validation/Constraint/SourceEditingPreventSelfXssConstraintValidator.php
+++ b/core/modules/ckeditor5/src/Plugin/Validation/Constraint/SourceEditingPreventSelfXssConstraintValidator.php
@@ -101,7 +101,7 @@ public function validate($value, Constraint $constraint) {
    */
   private static function isWildcardAttributeName(string $attribute_name): bool {
     assert($attribute_name !== '*');
-    return strpos($attribute_name, '*') !== FALSE;
+    return str_contains($attribute_name, '*');
   }
 
   /**
diff --git a/core/modules/ckeditor5/src/SmartDefaultSettings.php b/core/modules/ckeditor5/src/SmartDefaultSettings.php
index 9da23d1aba1eca47e92c6d6a784a35a3633544a8..4a17e004f1a28ed20431d105b4bdc07f354b4d5e 100644
--- a/core/modules/ckeditor5/src/SmartDefaultSettings.php
+++ b/core/modules/ckeditor5/src/SmartDefaultSettings.php
@@ -571,7 +571,7 @@ private static function computeSurplusScore(HTMLRestrictions $surplus, HTMLRestr
 
       foreach ($attributes_config as $attribute_name => $attribute_config) {
         // 10^4 per surplus wildcard attribute.
-        if (strpos($attribute_name, '*') !== FALSE) {
+        if (str_contains($attribute_name, '*')) {
           $surplus_score += pow(10, 4);
         }
         // 10^3 per surplus attribute.
@@ -590,7 +590,7 @@ private static function computeSurplusScore(HTMLRestrictions $surplus, HTMLRestr
 
         foreach ($attribute_config as $allowed_attribute_value => $allowed_attribute_value_config) {
           // 10^1 per surplus wildcard attribute value.
-          if (strpos($allowed_attribute_value, '*') !== FALSE) {
+          if (str_contains($allowed_attribute_value, '*')) {
             $surplus_score += pow(10, 1);
           }
           // 10^0 per surplus attribute value.
diff --git a/core/modules/comment/src/Plugin/Action/UnpublishByKeywordComment.php b/core/modules/comment/src/Plugin/Action/UnpublishByKeywordComment.php
index b0eb8bb50bbb2a6235e2c98242ba4cd86fad0c14..054196509900f2433a4cfbda9604b42a558f4147 100644
--- a/core/modules/comment/src/Plugin/Action/UnpublishByKeywordComment.php
+++ b/core/modules/comment/src/Plugin/Action/UnpublishByKeywordComment.php
@@ -77,7 +77,7 @@ public function execute($comment = NULL) {
     $build = $this->viewBuilder->view($comment);
     $text = $this->renderer->renderPlain($build);
     foreach ($this->configuration['keywords'] as $keyword) {
-      if (strpos($text, $keyword) !== FALSE) {
+      if (str_contains($text, $keyword)) {
         $comment->setUnpublished();
         $comment->save();
         break;
diff --git a/core/modules/config_translation/src/FormElement/ListElement.php b/core/modules/config_translation/src/FormElement/ListElement.php
index 612b0f1bc32f1d24dfcf21e0f5b654007e5e2eb8..2c22cfa28065945d869fdeb25be6e56f2407822c 100644
--- a/core/modules/config_translation/src/FormElement/ListElement.php
+++ b/core/modules/config_translation/src/FormElement/ListElement.php
@@ -119,7 +119,7 @@ protected function getGroupTitle(DataDefinitionInterface $definition, array $gro
     }
     else {
       foreach (array_keys($group_build) as $title_key) {
-        if (isset($group_build[$title_key]['source']) && (strpos($title_key, 'title') !== FALSE || strpos($title_key, 'label') !== FALSE)) {
+        if (isset($group_build[$title_key]['source']) && (str_contains($title_key, 'title') || str_contains($title_key, 'label'))) {
           $title = $group_build[$title_key]['source']['#markup'];
           break;
         }
diff --git a/core/modules/content_moderation/tests/src/Functional/ModerationLocaleTest.php b/core/modules/content_moderation/tests/src/Functional/ModerationLocaleTest.php
index 0d60b435cae3f375437a1cb71bb6606bdb63eddf..c54fa1d4d7d94814742e9439ab2168bcd1d482da 100644
--- a/core/modules/content_moderation/tests/src/Functional/ModerationLocaleTest.php
+++ b/core/modules/content_moderation/tests/src/Functional/ModerationLocaleTest.php
@@ -462,7 +462,7 @@ public function testNewTranslationSourceValues() {
    *   A node object if a new one is being created, NULL otherwise.
    */
   protected function submitNodeForm($title, $moderation_state, $default_translation = FALSE, $langcode = 'en') {
-    $is_new = strpos($this->getSession()->getCurrentUrl(), '/node/add/') !== FALSE;
+    $is_new = str_contains($this->getSession()->getCurrentUrl(), '/node/add/');
     $edit = [
       'title[0][value]' => $title,
       'moderation_state[0][state]' => $moderation_state,
diff --git a/core/modules/editor/tests/src/Functional/EditorLoadingTest.php b/core/modules/editor/tests/src/Functional/EditorLoadingTest.php
index c8d062976760218faaa8737022dbc1569fa3176f..fc2d6aa773c9108c7027ab955f75b9fe64135de2 100644
--- a/core/modules/editor/tests/src/Functional/EditorLoadingTest.php
+++ b/core/modules/editor/tests/src/Functional/EditorLoadingTest.php
@@ -316,7 +316,7 @@ protected function getThingsToCheck($field_name, $type = 'textarea') {
       // Editor.module's JS settings present.
       isset($settings['editor']),
       // Editor.module's JS present.
-      strpos($this->getSession()->getPage()->getContent(), $this->getModulePath('editor') . '/js/editor.js') !== FALSE,
+      str_contains($this->getSession()->getPage()->getContent(), $this->getModulePath('editor') . '/js/editor.js'),
       // Body field.
       '//' . $type . '[@id="edit-' . $field_name . '-0-value"]',
     ];
diff --git a/core/modules/field_ui/src/Form/FieldStorageAddForm.php b/core/modules/field_ui/src/Form/FieldStorageAddForm.php
index 9e4f3ddd4f7967cef8d48bc8bcb1fc29721c0991..a250432bf4679ea588bddbf4cb2877492765ba88 100644
--- a/core/modules/field_ui/src/Form/FieldStorageAddForm.php
+++ b/core/modules/field_ui/src/Form/FieldStorageAddForm.php
@@ -337,7 +337,7 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
       $widget_settings = $formatter_settings = [];
 
       // Check if we're dealing with a preconfigured field.
-      if (strpos($field_storage_values['type'], 'field_ui:') !== FALSE) {
+      if (str_contains($field_storage_values['type'], 'field_ui:')) {
         [, $field_type, $option_key] = explode(':', $field_storage_values['type'], 3);
         $field_storage_values['type'] = $field_type;
 
diff --git a/core/modules/field_ui/src/Routing/RouteSubscriber.php b/core/modules/field_ui/src/Routing/RouteSubscriber.php
index 75e6b4b6916ba35a5c0370fc4c03c3ce53ab9b41..ec2677c8b47b34f8f97c3aa2e0c4a85cc991ca59 100644
--- a/core/modules/field_ui/src/Routing/RouteSubscriber.php
+++ b/core/modules/field_ui/src/Routing/RouteSubscriber.php
@@ -56,7 +56,7 @@ protected function alterRoutes(RouteCollection $collection) {
         ];
         // If the entity type has no bundles and it doesn't use {bundle} in its
         // admin path, use the entity type.
-        if (strpos($path, '{bundle}') === FALSE) {
+        if (!str_contains($path, '{bundle}')) {
           $defaults['bundle'] = !$entity_type->hasKey('bundle') ? $entity_type_id : '';
         }
 
diff --git a/core/modules/file/file.install b/core/modules/file/file.install
index e2e4ce61a7c7b2b9fd73c2c6bdd0cc6a64d8d60d..de86c7bca84b7b1ad5d2dc00ed81118afdfad9fb 100644
--- a/core/modules/file/file.install
+++ b/core/modules/file/file.install
@@ -82,7 +82,7 @@ function file_requirements($phase) {
     elseif (preg_match("/Apache/i", $server_software)) {
       $is_nginx = FALSE;
       $is_apache = TRUE;
-      $fastcgi = strpos($server_software, 'mod_fastcgi') !== FALSE || strpos($server_software, 'mod_fcgi') !== FALSE;
+      $fastcgi = str_contains($server_software, 'mod_fastcgi') || str_contains($server_software, 'mod_fcgi');
     }
     else {
       $is_nginx = FALSE;
diff --git a/core/modules/help_topics/tests/src/Functional/HelpTopicsSyntaxTest.php b/core/modules/help_topics/tests/src/Functional/HelpTopicsSyntaxTest.php
index db3b6ad5d3ba1b52cc1a6433e71fe99c92d9a65a..417859140fcef41d2a24765261cbad9a32bcbeaa 100644
--- a/core/modules/help_topics/tests/src/Functional/HelpTopicsSyntaxTest.php
+++ b/core/modules/help_topics/tests/src/Functional/HelpTopicsSyntaxTest.php
@@ -311,8 +311,7 @@ protected function listDirectories($type) {
       // You can tell test modules because they are in package 'Testing', but
       // test themes are only known by being found in test directories. So...
       // exclude things in test directories.
-      if ((strpos($path, '/tests') === FALSE) &&
-        (strpos($path, '/testing') === FALSE)) {
+      if (!str_contains($path, '/tests') && !str_contains($path, '/testing')) {
         $directories[$name] = $path . '/help_topics';
       }
     }
diff --git a/core/modules/image/src/Entity/ImageStyle.php b/core/modules/image/src/Entity/ImageStyle.php
index f7edba286b088452af0d545dd5ea7ca2f3e573cb..e7777f45f91fff548313a83e99b16503c43c0375 100644
--- a/core/modules/image/src/Entity/ImageStyle.php
+++ b/core/modules/image/src/Entity/ImageStyle.php
@@ -255,7 +255,7 @@ public function buildUrl($path, $clean_urls = NULL) {
     $file_url = $file_url_generator->generateAbsoluteString($uri);
     // Append the query string with the token, if necessary.
     if ($token_query) {
-      $file_url .= (strpos($file_url, '?') !== FALSE ? '&' : '?') . UrlHelper::buildQuery($token_query);
+      $file_url .= (str_contains($file_url, '?') ? '&' : '?') . UrlHelper::buildQuery($token_query);
     }
 
     return $file_url;
diff --git a/core/modules/image/src/PathProcessor/PathProcessorImageStyles.php b/core/modules/image/src/PathProcessor/PathProcessorImageStyles.php
index b154bd4df39882ca44816211f470386a51fd90c5..a33132c64fc03d5a06a0a8c87768dc6327d6f3fb 100644
--- a/core/modules/image/src/PathProcessor/PathProcessorImageStyles.php
+++ b/core/modules/image/src/PathProcessor/PathProcessorImageStyles.php
@@ -50,7 +50,7 @@ public function processInbound($path, Request $request) {
     }
     // Check if the string '/system/files/styles/' exists inside the path,
     // that means we have a case of private file's image style.
-    elseif (strpos($path, '/system/files/styles/') !== FALSE) {
+    elseif (str_contains($path, '/system/files/styles/')) {
       $path_prefix = '/system/files/styles/';
       $path = substr($path, strpos($path, $path_prefix), strlen($path));
     }
diff --git a/core/modules/image/tests/src/Functional/ImageStylesPathAndUrlTest.php b/core/modules/image/tests/src/Functional/ImageStylesPathAndUrlTest.php
index 6d89a920d85ad17ff119b174d1d885d0d78704ec..9926f8c9d2cd15fbab0f3d6cc8fde1f4e21e8c58 100644
--- a/core/modules/image/tests/src/Functional/ImageStylesPathAndUrlTest.php
+++ b/core/modules/image/tests/src/Functional/ImageStylesPathAndUrlTest.php
@@ -250,7 +250,7 @@ public function doImageStyleUrlAndPathTests($scheme, $clean_url = TRUE, $extra_s
       $this->assertSession()->statusCodeEquals(403);
       // Verify that images are not appended to the response.
       // Currently this test only uses PNG images.
-      if (strpos($generate_url, '.png') === FALSE) {
+      if (!str_contains($generate_url, '.png')) {
         $this->fail('Confirming that private image styles are not appended require PNG file.');
       }
       else {
diff --git a/core/modules/jsonapi/src/Context/FieldResolver.php b/core/modules/jsonapi/src/Context/FieldResolver.php
index e405c16c15dc7113aabff78aa3bf8b48af9afdc2..ff746b6e83bb218bb52ba90534997d48b6acc8ba 100644
--- a/core/modules/jsonapi/src/Context/FieldResolver.php
+++ b/core/modules/jsonapi/src/Context/FieldResolver.php
@@ -736,7 +736,7 @@ protected static function isCandidateDefinitionReferenceProperty($part, array $c
    *   The property name from a path part.
    */
   protected static function getPathPartPropertyName($part) {
-    return strpos($part, ':') !== FALSE ? explode(':', $part)[0] : $part;
+    return str_contains($part, ':') ? explode(':', $part)[0] : $part;
   }
 
   /**
diff --git a/core/modules/jsonapi/src/EventSubscriber/ResourceResponseValidator.php b/core/modules/jsonapi/src/EventSubscriber/ResourceResponseValidator.php
index 3f08f56a8a69dbc857c563ba65a28936bc9e81e5..9761f0a7f3782db39aa369f804ee67cf444bc572 100644
--- a/core/modules/jsonapi/src/EventSubscriber/ResourceResponseValidator.php
+++ b/core/modules/jsonapi/src/EventSubscriber/ResourceResponseValidator.php
@@ -101,7 +101,7 @@ public function setValidator(Validator $validator = NULL) {
    */
   public function onResponse(ResponseEvent $event) {
     $response = $event->getResponse();
-    if (strpos($response->headers->get('Content-Type', ''), 'application/vnd.api+json') === FALSE) {
+    if (!str_contains($response->headers->get('Content-Type', ''), 'application/vnd.api+json')) {
       return;
     }
 
diff --git a/core/modules/jsonapi/src/JsonApiResource/LinkCollection.php b/core/modules/jsonapi/src/JsonApiResource/LinkCollection.php
index 32ebe6248b44f06b2b175be1dc131b80282d14bc..6381dfce5c6aa22538a3a3117241ddaab176ccfa 100644
--- a/core/modules/jsonapi/src/JsonApiResource/LinkCollection.php
+++ b/core/modules/jsonapi/src/JsonApiResource/LinkCollection.php
@@ -195,7 +195,7 @@ public static function merge(LinkCollection $a, LinkCollection $b) {
    *   TRUE if the key is valid, FALSE otherwise.
    */
   protected static function validKey($key) {
-    return is_string($key) && !is_numeric($key) && strpos($key, ':') === FALSE;
+    return is_string($key) && !is_numeric($key) && !str_contains($key, ':');
   }
 
 }
diff --git a/core/modules/jsonapi/src/Normalizer/FieldItemNormalizer.php b/core/modules/jsonapi/src/Normalizer/FieldItemNormalizer.php
index aebb2bb8fbeeaa9e3ce1186ac79e6ad11d7869c2..296cb3dfbf9d85a95ca6fccd5d76f7f5ad3cfd1e 100644
--- a/core/modules/jsonapi/src/Normalizer/FieldItemNormalizer.php
+++ b/core/modules/jsonapi/src/Normalizer/FieldItemNormalizer.php
@@ -205,7 +205,7 @@ private static function getAlternatives(string $search_key, array $keys) : array
     $alternatives = [];
     foreach ($keys as $key) {
       $lev = levenshtein($search_key, $key);
-      if ($lev <= strlen($search_key) / 3 || strpos($key, $search_key) !== FALSE) {
+      if ($lev <= strlen($search_key) / 3 || str_contains($key, $search_key)) {
         $alternatives[] = $key;
       }
     }
diff --git a/core/modules/language/src/Form/NegotiationUrlForm.php b/core/modules/language/src/Form/NegotiationUrlForm.php
index 8f43315452e986f6409e9fe6f0aaf4c98a783ee2..f0f0a39f0bb887534be8ed8245868ffd2c379afe 100644
--- a/core/modules/language/src/Form/NegotiationUrlForm.php
+++ b/core/modules/language/src/Form/NegotiationUrlForm.php
@@ -156,7 +156,7 @@ public function validateForm(array &$form, FormStateInterface $form_state) {
           ]));
         }
       }
-      elseif (strpos($value, '/') !== FALSE) {
+      elseif (str_contains($value, '/')) {
         // Throw a form error if the string contains a slash,
         // which would not work.
         $form_state->setErrorByName("prefix][$langcode", $this->t('The prefix may not contain a slash.'));
diff --git a/core/modules/language/src/Plugin/LanguageNegotiation/LanguageNegotiationUrl.php b/core/modules/language/src/Plugin/LanguageNegotiation/LanguageNegotiationUrl.php
index 4eb48e4ea6a20688bdf94bff5528c451f4e62f21..133604df1b314ef54d054fbddaf81b2fe0e4b220 100644
--- a/core/modules/language/src/Plugin/LanguageNegotiation/LanguageNegotiationUrl.php
+++ b/core/modules/language/src/Plugin/LanguageNegotiation/LanguageNegotiationUrl.php
@@ -166,7 +166,7 @@ public function processOutbound($path, &$options = [], Request $request = NULL,
 
         // In case either the original base URL or the HTTP host contains a
         // port, retain it.
-        if (isset($normalized_base_url) && strpos($normalized_base_url, ':') !== FALSE) {
+        if (isset($normalized_base_url) && str_contains($normalized_base_url, ':')) {
           [, $port] = explode(':', $normalized_base_url);
           $options['base_url'] .= ':' . $port;
         }
diff --git a/core/modules/language/tests/src/Functional/LanguageNegotiationInfoTest.php b/core/modules/language/tests/src/Functional/LanguageNegotiationInfoTest.php
index d92af69c74612220a0610a709aa6585064acd105..1c3f55060709e7b869186552dd42b51e57a5f19f 100644
--- a/core/modules/language/tests/src/Functional/LanguageNegotiationInfoTest.php
+++ b/core/modules/language/tests/src/Functional/LanguageNegotiationInfoTest.php
@@ -138,7 +138,7 @@ public function testInfoAlterations() {
     $last = $this->container->get('state')->get('language_test.language_negotiation_last');
     foreach ($this->languageManager()->getDefinedLanguageTypes() as $type) {
       $langcode = $last[$type];
-      $value = $type == LanguageInterface::TYPE_CONTENT || strpos($type, 'test') !== FALSE ? 'it' : 'en';
+      $value = $type == LanguageInterface::TYPE_CONTENT || str_contains($type, 'test') ? 'it' : 'en';
       $this->assertEquals($langcode, $value, new FormattableMarkup('The negotiated language for %type is %language', ['%type' => $type, '%language' => $value]));
     }
 
diff --git a/core/modules/language/tests/src/Functional/LanguageUrlRewritingTest.php b/core/modules/language/tests/src/Functional/LanguageUrlRewritingTest.php
index 463b0d9b37bd81701cdb34db569b049250fcf923..5067447301a0b3e5bc214e74cc585a5b9e6dcaf3 100644
--- a/core/modules/language/tests/src/Functional/LanguageUrlRewritingTest.php
+++ b/core/modules/language/tests/src/Functional/LanguageUrlRewritingTest.php
@@ -137,7 +137,7 @@ public function testDomainNameNegotiationPort() {
 
     // In case index.php is part of the URLs, we need to adapt the asserted
     // URLs as well.
-    $index_php = strpos(Url::fromRoute('<front>', [], ['absolute' => TRUE])->toString(), 'index.php') !== FALSE;
+    $index_php = str_contains(Url::fromRoute('<front>', [], ['absolute' => TRUE])->toString(), 'index.php');
 
     $request = Request::createFromGlobals();
     $server = $request->server->all();
diff --git a/core/modules/layout_builder/src/Plugin/SectionStorage/DefaultsSectionStorage.php b/core/modules/layout_builder/src/Plugin/SectionStorage/DefaultsSectionStorage.php
index 4c5d6f103b82a43c0ccf86d80b49f7e0534d4fb9..0c57f191446ed9b2e2c7f9e7277fcd62410f1a65 100644
--- a/core/modules/layout_builder/src/Plugin/SectionStorage/DefaultsSectionStorage.php
+++ b/core/modules/layout_builder/src/Plugin/SectionStorage/DefaultsSectionStorage.php
@@ -162,7 +162,7 @@ public function buildRoutes(RouteCollection $collection) {
       $defaults['entity_type_id'] = $entity_type_id;
       // If the entity type has no bundles and it doesn't use {bundle} in its
       // admin path, use the entity type.
-      if (strpos($path, '{bundle}') === FALSE) {
+      if (!str_contains($path, '{bundle}')) {
         if (!$entity_type->hasKey('bundle')) {
           $defaults['bundle'] = $entity_type_id;
         }
@@ -265,7 +265,7 @@ private function extractEntityFromRoute($value, array $defaults) {
       $defaults['bundle'] = $defaults[$defaults['bundle_key']];
     }
 
-    if (is_string($value) && strpos($value, '.') !== FALSE) {
+    if (is_string($value) && str_contains($value, '.')) {
       [$entity_type_id, $bundle, $view_mode] = explode('.', $value, 3);
     }
     elseif (!empty($defaults['entity_type_id']) && !empty($defaults['bundle']) && !empty($defaults['view_mode_name'])) {
diff --git a/core/modules/layout_builder/src/Plugin/SectionStorage/OverridesSectionStorage.php b/core/modules/layout_builder/src/Plugin/SectionStorage/OverridesSectionStorage.php
index 219a3c6a0a8446e16537c0563b942215c2cb032d..7e17c88e7b3b86c44fac4832e72b487fa9a57852 100644
--- a/core/modules/layout_builder/src/Plugin/SectionStorage/OverridesSectionStorage.php
+++ b/core/modules/layout_builder/src/Plugin/SectionStorage/OverridesSectionStorage.php
@@ -194,7 +194,7 @@ public function deriveContextsFromRoute($value, $definition, $name, array $defau
    * @see \Drupal\Core\ParamConverter\ParamConverterInterface::convert()
    */
   private function extractEntityFromRoute($value, array $defaults) {
-    if (strpos($value, '.') !== FALSE) {
+    if (str_contains($value, '.')) {
       [$entity_type_id, $entity_id] = explode('.', $value, 2);
     }
     elseif (isset($defaults['entity_type_id']) && !empty($defaults[$defaults['entity_type_id']])) {
diff --git a/core/modules/layout_builder/tests/src/FunctionalJavascript/ContentPreviewToggleTest.php b/core/modules/layout_builder/tests/src/FunctionalJavascript/ContentPreviewToggleTest.php
index bd2357a3b8abbcf943613ebfb312cff81275fd4e..f836e478da2c8b97a3b6a5661cc0e5acb3e7fee3 100644
--- a/core/modules/layout_builder/tests/src/FunctionalJavascript/ContentPreviewToggleTest.php
+++ b/core/modules/layout_builder/tests/src/FunctionalJavascript/ContentPreviewToggleTest.php
@@ -153,7 +153,7 @@ protected function assertOrderInPage(array $items): void {
     // Filter will only return value if block contains expected text.
     $blocks_with_expected_text = array_filter($blocks, function ($block, $key) use ($items) {
       $block_text = $block->getText();
-      return strpos($block_text, $items[$key]) !== FALSE;
+      return str_contains($block_text, $items[$key]);
     }, ARRAY_FILTER_USE_BOTH);
 
     $this->assertSameSize($items, $blocks_with_expected_text);
diff --git a/core/modules/locale/src/LocaleLookup.php b/core/modules/locale/src/LocaleLookup.php
index ab1401b35e210443c841d170a049c7ecf0871cdd..d4f97281fe4601a87eb46887c5bef39742d908c6 100644
--- a/core/modules/locale/src/LocaleLookup.php
+++ b/core/modules/locale/src/LocaleLookup.php
@@ -178,7 +178,7 @@ protected function resolveCacheMiss($offset) {
       }
     }
 
-    if (is_string($value) && strpos($value, PoItem::DELIMITER) !== FALSE) {
+    if (is_string($value) && str_contains($value, PoItem::DELIMITER)) {
       // Community translations imported from localize.drupal.org as well as
       // migrated translations may contain @count[number].
       $value = preg_replace('!@count\[\d+\]!', '@count', $value);
diff --git a/core/modules/media/tests/modules/media_test_source/src/Plugin/Validation/Constraint/MediaTestConstraintValidator.php b/core/modules/media/tests/modules/media_test_source/src/Plugin/Validation/Constraint/MediaTestConstraintValidator.php
index 1c744430a5fb905d9c707fb3db18d9963ff93101..d54c71a02973da718b43c12843f8e7ea6982aeac 100644
--- a/core/modules/media/tests/modules/media_test_source/src/Plugin/Validation/Constraint/MediaTestConstraintValidator.php
+++ b/core/modules/media/tests/modules/media_test_source/src/Plugin/Validation/Constraint/MediaTestConstraintValidator.php
@@ -26,7 +26,7 @@ public function validate($value, Constraint $constraint) {
       return;
     }
 
-    if (strpos($string_to_test, 'love Drupal') === FALSE) {
+    if (!str_contains($string_to_test, 'love Drupal')) {
       $this->context->addViolation($constraint->message);
     }
   }
diff --git a/core/modules/media_library/tests/modules/media_library_test_widget/src/Plugin/Field/FieldWidget/MediaLibraryInceptionWidget.php b/core/modules/media_library/tests/modules/media_library_test_widget/src/Plugin/Field/FieldWidget/MediaLibraryInceptionWidget.php
index e5a030ecc0940f7d6ef3c987604679937f4f03f3..8fe42c0c294082e68be760ceca8678cc22ec58f1 100644
--- a/core/modules/media_library/tests/modules/media_library_test_widget/src/Plugin/Field/FieldWidget/MediaLibraryInceptionWidget.php
+++ b/core/modules/media_library/tests/modules/media_library_test_widget/src/Plugin/Field/FieldWidget/MediaLibraryInceptionWidget.php
@@ -44,7 +44,7 @@ public function elementValidate($element, FormStateInterface $form_state, $form)
     $field_name = $element['#field_name'];
     $entity = $form_state->getFormObject()->getEntity();
     $input = $form_state->getUserInput();
-    if (!empty($input['_triggering_element_name']) && strpos($input['_triggering_element_name'], 'media-library-update') !== FALSE) {
+    if (!empty($input['_triggering_element_name']) && str_contains($input['_triggering_element_name'], 'media-library-update')) {
       // This will validate a required field before an upload is completed.
       $display = EntityFormDisplay::collectRenderDisplay($entity, 'edit');
       $display->extractFormValues($entity, $form, $form_state);
diff --git a/core/modules/migrate_drupal/tests/src/Kernel/d6/EntityContentBaseTest.php b/core/modules/migrate_drupal/tests/src/Kernel/d6/EntityContentBaseTest.php
index 45fa0dc0bb322979df96e83689ce9cfa0d3d0367..c726babb2b7631b213ad9fb3d4c4f7081f2d7f73 100644
--- a/core/modules/migrate_drupal/tests/src/Kernel/d6/EntityContentBaseTest.php
+++ b/core/modules/migrate_drupal/tests/src/Kernel/d6/EntityContentBaseTest.php
@@ -115,7 +115,7 @@ public function testUntranslatable() {
     // Match the expected message. Can't use default argument types, because
     // we need to convert to string from TranslatableMarkup.
     $argument = Argument::that(function ($msg) {
-      return strpos((string) $msg, htmlentities('The "no_language_entity_test" entity type does not support translations.')) !== FALSE;
+      return str_contains((string) $msg, htmlentities('The "no_language_entity_test" entity type does not support translations.'));
     });
     $message->display($argument, Argument::any())
       ->shouldBeCalled();
diff --git a/core/modules/mysql/src/Driver/Database/mysql/Install/Tasks.php b/core/modules/mysql/src/Driver/Database/mysql/Install/Tasks.php
index a6ad642425d05218ec33c35ba1b5d2786043b2c0..3a41083d68474f0822ff33f91b50320054e26178 100644
--- a/core/modules/mysql/src/Driver/Database/mysql/Install/Tasks.php
+++ b/core/modules/mysql/src/Driver/Database/mysql/Install/Tasks.php
@@ -196,7 +196,7 @@ protected function checkEngineVersion() {
 
     // Ensure that the MySQL driver supports utf8mb4 encoding.
     $version = Database::getConnection()->clientVersion();
-    if (FALSE !== strpos($version, 'mysqlnd')) {
+    if (str_contains($version, 'mysqlnd')) {
       // The mysqlnd driver supports utf8mb4 starting at version 5.0.9.
       $version = preg_replace('/^\D+([\d.]+).*/', '$1', $version);
       if (version_compare($version, self::MYSQLND_MINIMUM_VERSION, '<')) {
diff --git a/core/modules/node/src/Plugin/Action/UnpublishByKeywordNode.php b/core/modules/node/src/Plugin/Action/UnpublishByKeywordNode.php
index 42f344d52ca2be05dde1fa6296a1028a576f6c50..dcca814629b7a8aea181447d47a15b557e7f7218 100644
--- a/core/modules/node/src/Plugin/Action/UnpublishByKeywordNode.php
+++ b/core/modules/node/src/Plugin/Action/UnpublishByKeywordNode.php
@@ -27,7 +27,7 @@ public function execute($node = NULL) {
       ->view(clone $node);
     $render = \Drupal::service('renderer')->render($elements);
     foreach ($this->configuration['keywords'] as $keyword) {
-      if (strpos($render, $keyword) !== FALSE || strpos($node->label(), $keyword) !== FALSE) {
+      if (str_contains($render, $keyword) || str_contains($node->label(), $keyword)) {
         $node->setUnpublished();
         $node->save();
         break;
diff --git a/core/modules/path_alias/src/PathProcessor/AliasPathProcessor.php b/core/modules/path_alias/src/PathProcessor/AliasPathProcessor.php
index 9959c9373fcc3503bfd753fdb3fb72c85ddd6af8..e9e572ca5c5b92a013b2671cb8e8e2b7d9403cfa 100644
--- a/core/modules/path_alias/src/PathProcessor/AliasPathProcessor.php
+++ b/core/modules/path_alias/src/PathProcessor/AliasPathProcessor.php
@@ -51,7 +51,7 @@ public function processOutbound($path, &$options = [], Request $request = NULL,
       // also, to protect against this problem in arbitrary path processors,
       // but it is duplicated here to protect any other URL generation code
       // that might call this method separately.
-      if (strpos($path, '//') === 0) {
+      if (str_starts_with($path, '//')) {
         $path = '/' . ltrim($path, '/');
       }
     }
diff --git a/core/modules/pgsql/src/Driver/Database/pgsql/Connection.php b/core/modules/pgsql/src/Driver/Database/pgsql/Connection.php
index a458b5d4e4e6f0ab97a1d5618eb7cfb5bce628dc..c5d53e29f139be378293c00f21410af3d6de825a 100644
--- a/core/modules/pgsql/src/Driver/Database/pgsql/Connection.php
+++ b/core/modules/pgsql/src/Driver/Database/pgsql/Connection.php
@@ -132,10 +132,10 @@ public static function open(array &$connection_options = []) {
     }
     catch (\PDOException $e) {
       if (static::getSQLState($e) == static::CONNECTION_FAILURE) {
-        if (strpos($e->getMessage(), 'password authentication failed for user') !== FALSE) {
+        if (str_contains($e->getMessage(), 'password authentication failed for user')) {
           throw new DatabaseAccessDeniedException($e->getMessage(), $e->getCode(), $e);
         }
-        elseif (strpos($e->getMessage(), 'database') !== FALSE && strpos($e->getMessage(), 'does not exist') !== FALSE) {
+        elseif (str_contains($e->getMessage(), 'database') && str_contains($e->getMessage(), 'does not exist')) {
           throw new DatabaseNotFoundException($e->getMessage(), $e->getCode(), $e);
         }
       }
diff --git a/core/modules/pgsql/src/Driver/Database/pgsql/Schema.php b/core/modules/pgsql/src/Driver/Database/pgsql/Schema.php
index 2336d103fa987cb0c5e4be443a1059bcbfa5a323..5c3052e56a3892507f2e0715e3eb319e18979537 100644
--- a/core/modules/pgsql/src/Driver/Database/pgsql/Schema.php
+++ b/core/modules/pgsql/src/Driver/Database/pgsql/Schema.php
@@ -121,7 +121,7 @@ public function queryTableInformation($table) {
     // Take into account that temporary tables are stored in a different schema.
     // \Drupal\Core\Database\Connection::generateTemporaryTableName() sets the
     // 'db_temporary_' prefix to all temporary tables.
-    if (strpos($key, '.') === FALSE && strpos($table, 'db_temporary_') === FALSE) {
+    if (!str_contains($key, '.') && !str_contains($table, 'db_temporary_')) {
       $key = 'public.' . $key;
     }
     else {
@@ -207,7 +207,7 @@ protected function getTempNamespaceName() {
    */
   protected function resetTableInformation($table) {
     $key = $this->connection->prefixTables('{' . $table . '}');
-    if (strpos($key, '.') === FALSE) {
+    if (!str_contains($key, '.')) {
       $key = 'public.' . $key;
     }
     unset($this->tableInformation[$key]);
@@ -564,7 +564,7 @@ public function renameTable($table, $new_name) {
       // exceed the 63 chars limit of PostgreSQL, we need to take care of that.
       // cSpell:disable-next-line
       // Example (drupal_Gk7Su_T1jcBHVuvSPeP22_I3Ni4GrVEgTYlIYnBJkro_idx).
-      if (strpos($index->indexname, 'drupal_') !== FALSE) {
+      if (str_contains($index->indexname, 'drupal_')) {
         preg_match('/^drupal_(.*)_' . preg_quote($index_type) . '/', $index->indexname, $matches);
         $index_name = $matches[1];
       }
diff --git a/core/modules/pgsql/src/Driver/Database/pgsql/Select.php b/core/modules/pgsql/src/Driver/Database/pgsql/Select.php
index dbd787027b81c9f35e02ab1609b11d2d13a83988..d04f06c440c91df8e21963cdea4953bd38c28a09 100644
--- a/core/modules/pgsql/src/Driver/Database/pgsql/Select.php
+++ b/core/modules/pgsql/src/Driver/Database/pgsql/Select.php
@@ -72,7 +72,7 @@ public function orderBy($field, $direction = 'ASC') {
     }
 
     // If there is a table alias specified, split it up.
-    if (strpos($field, '.') !== FALSE) {
+    if (str_contains($field, '.')) {
       [$table, $table_field] = explode('.', $field);
     }
     // Figure out if the field has already been added.
diff --git a/core/modules/search/search.module b/core/modules/search/search.module
index b9edc39de6012e3a9b3959aa6db1cc4b098a3080..92f4e78b7536c152c1c0bd09df6237ff45450cee 100644
--- a/core/modules/search/search.module
+++ b/core/modules/search/search.module
@@ -333,7 +333,7 @@ function _search_find_match_with_simplify($key, $text, $boundary, $langcode = NU
   $text_processor = \Drupal::service('search.text_processor');
   $simplified_key = trim($text_processor->analyze($key, $langcode));
   $simplified_text = trim($text_processor->analyze($text, $langcode));
-  if ($simplified_key == '' || $simplified_text == '' || strpos($simplified_text, $simplified_key) === FALSE) {
+  if ($simplified_key == '' || $simplified_text == '' || !str_contains($simplified_text, $simplified_key)) {
     // The simplified keyword and text do not match at all, or are empty.
     return NULL;
   }
@@ -358,7 +358,7 @@ function _search_find_match_with_simplify($key, $text, $boundary, $langcode = NU
     // Since the split was done with preg_split(), the positions are byte counts
     // not character counts, so use substr() not mb_substr() here.
     $trial_text = trim($text_processor->analyze(substr($text, $start_pos, $proposed_end_pos - $start_pos), $langcode));
-    if (strpos($trial_text, $simplified_key) !== FALSE) {
+    if (str_contains($trial_text, $simplified_key)) {
       // The proposed endpoint is fine, text still matches.
       $max_end_index = $proposed_end_index;
     }
@@ -385,7 +385,7 @@ function _search_find_match_with_simplify($key, $text, $boundary, $langcode = NU
     // Since the split was done with preg_split(), the positions are byte counts
     // not character counts, so use substr() not mb_substr() here.
     $trial_text = trim($text_processor->analyze(substr($text, $proposed_start_pos, $end_pos - $proposed_start_pos), $langcode));
-    if (strpos($trial_text, $simplified_key) !== FALSE) {
+    if (str_contains($trial_text, $simplified_key)) {
       // The proposed start point is fine, text still matches.
       $min_start_index = $proposed_start_index;
     }
diff --git a/core/modules/search/src/SearchQuery.php b/core/modules/search/src/SearchQuery.php
index ec858789238c70989b6e863e2cf7958d41584f9f..73817872e344b4cfede39c40192fb72717ad04c6 100644
--- a/core/modules/search/src/SearchQuery.php
+++ b/core/modules/search/src/SearchQuery.php
@@ -521,7 +521,7 @@ public function addScore($score, $arguments = [], $multiply = FALSE) {
     // search expression. So, use string replacement to change this to a
     // calculated query expression, counting the number of occurrences so
     // in the execute() method we can add arguments.
-    while (strpos($score, 'i.relevance') !== FALSE) {
+    while (str_contains($score, 'i.relevance')) {
       $pieces = explode('i.relevance', $score, 2);
       $score = implode('((ROUND(:normalization_' . $this->relevance_count . ', 4)) * i.score * t.count)', $pieces);
       $this->relevance_count++;
diff --git a/core/modules/system/src/Controller/LinksetController.php b/core/modules/system/src/Controller/LinksetController.php
index 35588c789a2ee890be78e4b579b968262f5c00ee..793040adb06356d377449fe2a1fbfd288cf1992c 100644
--- a/core/modules/system/src/Controller/LinksetController.php
+++ b/core/modules/system/src/Controller/LinksetController.php
@@ -231,7 +231,7 @@ private function processCustomLinkAttributes(array &$link, array $attributes = [
         continue;
       }
       // Skip the attribute key if it has an asterisk (*).
-      if (strpos($key, '*') !== FALSE) {
+      if (str_contains($key, '*')) {
         continue;
       }
       // Skip the value if it is an object.
diff --git a/core/modules/system/system.install b/core/modules/system/system.install
index 17aa30df73c6b18edd59d2a539fddcfde9fb828e..f7be7128f64d9b344585f8b94d272a1ac224b2f2 100644
--- a/core/modules/system/system.install
+++ b/core/modules/system/system.install
@@ -215,7 +215,7 @@ function system_requirements($phase) {
   ];
 
   // Tests clean URL support.
-  if ($phase == 'install' && $install_state['interactive'] && !$request_object->query->has('rewrite') && strpos($software, 'Apache') !== FALSE) {
+  if ($phase == 'install' && $install_state['interactive'] && !$request_object->query->has('rewrite') && str_contains($software, 'Apache')) {
     // If the Apache rewrite module is not enabled, Apache version must be >=
     // 2.2.16 because of the FallbackResource directive in the root .htaccess
     // file. Since the Apache version reported by the server is dependent on the
@@ -705,7 +705,7 @@ function system_requirements($phase) {
       $htaccess_file = $protected_dir->getPath() . '/.htaccess';
       // Check for the string which was added to the recommended .htaccess file
       // in the latest security update.
-      if (!file_exists($htaccess_file) || !($contents = @file_get_contents($htaccess_file)) || strpos($contents, 'Drupal_Security_Do_Not_Remove_See_SA_2013_003') === FALSE) {
+      if (!file_exists($htaccess_file) || !($contents = @file_get_contents($htaccess_file)) || !str_contains($contents, 'Drupal_Security_Do_Not_Remove_See_SA_2013_003')) {
         $url = 'https://www.drupal.org/SA-CORE-2013-003';
         $requirements[$htaccess_file] = [
           'title' => new TranslatableMarkup($protected_dir->getTitle()),
@@ -1360,7 +1360,7 @@ function system_requirements($phase) {
     $provider = $connection->getProvider();
     if ($provider !== 'core' && !\Drupal::moduleHandler()->moduleExists($provider)) {
       $autoload = $connection->getConnectionOptions()['autoload'] ?? '';
-      if (strpos($autoload, 'src/Driver/Database/') !== FALSE) {
+      if (str_contains($autoload, 'src/Driver/Database/')) {
         $post_update_registry = \Drupal::service('update.post_update_registry');
         $pending_updates = $post_update_registry->getPendingUpdateInformation();
         if (!in_array('enable_provider_database_driver', array_keys($pending_updates['system']['pending'] ?? []), TRUE)) {
diff --git a/core/modules/system/tests/modules/advisory_feed_test/src/AdvisoryTestClientMiddleware.php b/core/modules/system/tests/modules/advisory_feed_test/src/AdvisoryTestClientMiddleware.php
index c522047013c13cac5348d0b1546dd30a9fa7c93d..1988377e9922cff9e8e019f24e88b4cbbd99676a 100644
--- a/core/modules/system/tests/modules/advisory_feed_test/src/AdvisoryTestClientMiddleware.php
+++ b/core/modules/system/tests/modules/advisory_feed_test/src/AdvisoryTestClientMiddleware.php
@@ -18,7 +18,7 @@ public function __invoke() {
     return function ($handler) {
       return function (RequestInterface $request, array $options) use ($handler): PromiseInterface {
         $test_end_point = \Drupal::state()->get('advisories_test_endpoint');
-        if ($test_end_point && strpos($request->getUri(), '://updates.drupal.org/psa.json') !== FALSE) {
+        if ($test_end_point && str_contains($request->getUri(), '://updates.drupal.org/psa.json')) {
           // Only override $uri if it matches the advisories JSON feed to avoid
           // changing any other uses of the 'http_client' service during tests with
           // this module installed.
diff --git a/core/modules/system/tests/modules/form_test/src/Form/FormTestClickedButtonForm.php b/core/modules/system/tests/modules/form_test/src/Form/FormTestClickedButtonForm.php
index b54770804375f967a06e3ab736c369012e857ee3..6527e37db3e763a87d73beffb7fd72133672e7d7 100644
--- a/core/modules/system/tests/modules/form_test/src/Form/FormTestClickedButtonForm.php
+++ b/core/modules/system/tests/modules/form_test/src/Form/FormTestClickedButtonForm.php
@@ -43,13 +43,13 @@ public function buildForm(array $form, FormStateInterface $form_state, $first =
     foreach ($args as $arg) {
       $name = 'button' . ++$i;
       // 's', 'b', or 'i' in the argument define the button type wanted.
-      if (strpos($arg, 's') !== FALSE) {
+      if (str_contains($arg, 's')) {
         $type = 'submit';
       }
-      elseif (strpos($arg, 'b') !== FALSE) {
+      elseif (str_contains($arg, 'b')) {
         $type = 'button';
       }
-      elseif (strpos($arg, 'i') !== FALSE) {
+      elseif (str_contains($arg, 'i')) {
         $type = 'image_button';
       }
       else {
@@ -69,7 +69,7 @@ public function buildForm(array $form, FormStateInterface $form_state, $first =
         }
         // 'r' for restricted, so we can test that button click detection code
         // correctly takes #access security into account.
-        if (strpos($arg, 'r') !== FALSE) {
+        if (str_contains($arg, 'r')) {
           $form[$name]['#access'] = FALSE;
         }
       }
diff --git a/core/modules/system/tests/modules/form_test/src/Form/FormTestMachineNameValidationForm.php b/core/modules/system/tests/modules/form_test/src/Form/FormTestMachineNameValidationForm.php
index 22cbb7cf456fd471c09360b4cfbb907190700fe2..63350a65fc2aaaa41c9b89e43dcd5dcb54b12233 100644
--- a/core/modules/system/tests/modules/form_test/src/Form/FormTestMachineNameValidationForm.php
+++ b/core/modules/system/tests/modules/form_test/src/Form/FormTestMachineNameValidationForm.php
@@ -126,7 +126,7 @@ public function buildAjaxSnackConfigureForm(array $form, FormStateInterface $for
    * @return bool
    */
   public function load($machine_name) {
-    if (strpos($machine_name, 'duplicate') !== FALSE) {
+    if (str_contains($machine_name, 'duplicate')) {
       return TRUE;
     }
 
diff --git a/core/modules/system/tests/modules/jqueryui_library_assets_test/src/Controller/JqueryUiTestAssetsController.php b/core/modules/system/tests/modules/jqueryui_library_assets_test/src/Controller/JqueryUiTestAssetsController.php
index 2db6550c68d91be5ba0ec137bf3e4de4d143d8c4..f53c8b3671fd82b19482d30d91bf91121146f132 100644
--- a/core/modules/system/tests/modules/jqueryui_library_assets_test/src/Controller/JqueryUiTestAssetsController.php
+++ b/core/modules/system/tests/modules/jqueryui_library_assets_test/src/Controller/JqueryUiTestAssetsController.php
@@ -21,7 +21,7 @@ class JqueryUiTestAssetsController extends ControllerBase {
   public function build($library) {
     // If there are pipes in $library, they are separating multiple library
     // names.
-    if (strpos($library, '|') !== FALSE) {
+    if (str_contains($library, '|')) {
       $library = explode('|', $library);
       $library = array_map(function ($item) {
         return "core/$item";
diff --git a/core/modules/system/tests/src/Functional/Form/CheckboxTest.php b/core/modules/system/tests/src/Functional/Form/CheckboxTest.php
index c281123833a037205eb37e8facda4124f83a8f46..d5aebdb7f482872937c25395386a841cc01c5264 100644
--- a/core/modules/system/tests/src/Functional/Form/CheckboxTest.php
+++ b/core/modules/system/tests/src/Functional/Form/CheckboxTest.php
@@ -53,7 +53,7 @@ public function testFormCheckbox() {
         elseif ($return_value === '1foobar') {
           $checked = ($default_value === '1foobar');
         }
-        $checked_in_html = strpos($form, 'checked') !== FALSE;
+        $checked_in_html = str_contains($form, 'checked');
         $message = new FormattableMarkup('#default_value is %default_value #return_value is %return_value.', ['%default_value' => var_export($default_value, TRUE), '%return_value' => var_export($return_value, TRUE)]);
         $this->assertSame($checked, $checked_in_html, $message);
       }
diff --git a/core/modules/system/tests/src/Functional/Form/FormTest.php b/core/modules/system/tests/src/Functional/Form/FormTest.php
index d0027d859fa32f8a8adb77d05acaf3d9964c8d1f..3797cbb137769ea703fa23b8cd81df8e63d07854 100644
--- a/core/modules/system/tests/src/Functional/Form/FormTest.php
+++ b/core/modules/system/tests/src/Functional/Form/FormTest.php
@@ -145,7 +145,7 @@ public function testRequiredFields() {
               // Select elements are going to have validation errors with empty
               // input, since those are not allowed choices. Just make sure the
               // error is not "field is required".
-              $this->assertTrue((empty($errors[$element]) || strpos('field is required', (string) $errors[$element]) === FALSE), "Optional '$type' field '$element' is not treated as a required element");
+              $this->assertTrue((empty($errors[$element]) || !str_contains('field is required', (string) $errors[$element])), "Optional '$type' field '$element' is not treated as a required element");
             }
             else {
               // Make sure there is *no* form error for this element. We're
diff --git a/core/modules/system/tests/src/Functional/UpdateSystem/UpdatePathTestJavaScriptTest.php b/core/modules/system/tests/src/Functional/UpdateSystem/UpdatePathTestJavaScriptTest.php
index 209ca4801daa4257722f24a47ac3124f10fee5c3..657ce60be0ddb03d5c4f19e3dfcb2b786bd6e748 100644
--- a/core/modules/system/tests/src/Functional/UpdateSystem/UpdatePathTestJavaScriptTest.php
+++ b/core/modules/system/tests/src/Functional/UpdateSystem/UpdatePathTestJavaScriptTest.php
@@ -51,7 +51,7 @@ protected function doSelectionTest() {
       $src = preg_replace('#^' . $GLOBALS['base_path'] . '(.*)#i', $GLOBALS['base_url'] . '/' . '${1}', $script->getAttribute('src'));
       $file_content = file_get_contents($src);
 
-      if (strpos($file_content, 'window.drupalSettings =') !== FALSE) {
+      if (str_contains($file_content, 'window.drupalSettings =')) {
         $found = TRUE;
         break;
       }
diff --git a/core/modules/system/tests/themes/engines/nyan_cat/nyan_cat.engine b/core/modules/system/tests/themes/engines/nyan_cat/nyan_cat.engine
index bcc3f7ef83f79431abf55c9af9aa5ff4b3058593..9a5f5d5d51b1ce3d76e97eb1bd97c5c2deaf7d1b 100644
--- a/core/modules/system/tests/themes/engines/nyan_cat/nyan_cat.engine
+++ b/core/modules/system/tests/themes/engines/nyan_cat/nyan_cat.engine
@@ -36,7 +36,7 @@ function nyan_cat_extension() {
 function nyan_cat_render_template($template_file, $variables) {
   $output = str_replace('div', 'nyancat', file_get_contents(\Drupal::root() . '/' . $template_file));
   foreach ($variables as $key => $variable) {
-    if (strpos($output, '9' . $key) !== FALSE) {
+    if (str_contains($output, '9' . $key)) {
       $output = str_replace('9' . $key, Html::escape($variable), $output);
     }
   }
diff --git a/core/modules/text/src/Plugin/migrate/field/d6/TextField.php b/core/modules/text/src/Plugin/migrate/field/d6/TextField.php
index 59c5ab57ed24f0506b0f7a1bba9cf79ab5c79efa..b1e3ae7b4fa6f9beb082916223cd1bbff7c096e1 100644
--- a/core/modules/text/src/Plugin/migrate/field/d6/TextField.php
+++ b/core/modules/text/src/Plugin/migrate/field/d6/TextField.php
@@ -59,7 +59,7 @@ public function defineValueProcessPipeline(MigrationInterface $migration, $field
       ];
 
       $checked_value = explode("\n", $field_info['global_settings']['allowed_values'])[1];
-      if (strpos($checked_value, '|') !== FALSE) {
+      if (str_contains($checked_value, '|')) {
         $checked_value = substr($checked_value, 0, strpos($checked_value, '|'));
       }
       $process['value']['map'][$checked_value] = 1;
diff --git a/core/modules/tour/tests/src/Functional/TourTest.php b/core/modules/tour/tests/src/Functional/TourTest.php
index aaf2a781a28395061cfe4e33539f98204da7101b..11bfef4d54c11ff9a9d628a9c2d936eb4c0733dc 100644
--- a/core/modules/tour/tests/src/Functional/TourTest.php
+++ b/core/modules/tour/tests/src/Functional/TourTest.php
@@ -80,7 +80,7 @@ public function testTourFunctionality() {
     $href = Url::fromRoute('<front>', [], ['absolute' => TRUE])->toString();
     $elements = [];
     foreach ($tips as $tip) {
-      if ($tip['id'] == 'tour-test-1' && $tip['module'] == 'tour_test' && $tip['type'] == 'text' && strpos($tip['body'], $href) !== FALSE && strpos($tip['body'], 'Drupal') !== FALSE) {
+      if ($tip['id'] == 'tour-test-1' && $tip['module'] == 'tour_test' && $tip['type'] == 'text' && str_contains($tip['body'], $href) && str_contains($tip['body'], 'Drupal')) {
         $elements[] = $tip;
       }
     }
@@ -107,7 +107,7 @@ public function testTourFunctionality() {
     // Ensure that plugins work.
     $elements = [];
     foreach ($tips as $tip) {
-      if (strpos($tip['body'], 'http://local/image.png') !== FALSE) {
+      if (str_contains($tip['body'], 'http://local/image.png')) {
         $elements[] = $tip;
       }
     }
diff --git a/core/modules/update/src/Plugin/migrate/source/UpdateSettings.php b/core/modules/update/src/Plugin/migrate/source/UpdateSettings.php
index 69a9be8397595e38b96c57c156c21ed7e627ff9a..a492a2d538f6c1eb1d9c4eb2713c6a585d4936d3 100644
--- a/core/modules/update/src/Plugin/migrate/source/UpdateSettings.php
+++ b/core/modules/update/src/Plugin/migrate/source/UpdateSettings.php
@@ -25,7 +25,7 @@ class UpdateSettings extends Variable {
    */
   protected function values() {
     $values = parent::values();
-    if (empty($values['update_fetch_url']) || strpos($values['update_fetch_url'], 'http://updates.drupal.org/release-history') !== FALSE) {
+    if (empty($values['update_fetch_url']) || str_contains($values['update_fetch_url'], 'http://updates.drupal.org/release-history')) {
       $values['update_fetch_url'] = 'https://updates.drupal.org/release-history';
     }
     return $values;
diff --git a/core/modules/update/src/UpdateFetcher.php b/core/modules/update/src/UpdateFetcher.php
index 263f1745108637584ff060d6c3b899d6e59525a9..6d7c71cc04dcd71cf71fea8f25f7e664b00aa20e 100644
--- a/core/modules/update/src/UpdateFetcher.php
+++ b/core/modules/update/src/UpdateFetcher.php
@@ -98,7 +98,7 @@ protected function doRequest(string $url, array $options, bool $with_http_fallba
     }
     catch (TransferException $exception) {
       watchdog_exception('update', $exception);
-      if ($with_http_fallback && strpos($url, "http://") === FALSE) {
+      if ($with_http_fallback && !str_contains($url, "http://")) {
         $url = str_replace('https://', 'http://', $url);
         return $this->doRequest($url, $options, FALSE);
       }
@@ -116,9 +116,9 @@ public function buildFetchUrl(array $project, $site_key = '') {
 
     // Only append usage information if we have a site key and the project is
     // enabled. We do not want to record usage statistics for disabled projects.
-    if (!empty($site_key) && (strpos($project['project_type'], 'disabled') === FALSE)) {
+    if (!empty($site_key) && !str_contains($project['project_type'], 'disabled')) {
       // Append the site key.
-      $url .= (strpos($url, '?') !== FALSE) ? '&' : '?';
+      $url .= str_contains($url, '?') ? '&' : '?';
       $url .= 'site_key=';
       $url .= rawurlencode($site_key);
 
diff --git a/core/modules/user/src/Event/UserFloodEvent.php b/core/modules/user/src/Event/UserFloodEvent.php
index c62cb3da57a3bcdd664b1ca8c15a786da8b5b5a4..39c92e3a2f020f14df336bda959b40b8a036420b 100644
--- a/core/modules/user/src/Event/UserFloodEvent.php
+++ b/core/modules/user/src/Event/UserFloodEvent.php
@@ -73,7 +73,7 @@ public function __construct($name, $threshold, $window, $identifier) {
       $this->uid = $identifier;
       return;
     }
-    if (strpos($identifier, '-') !== FALSE) {
+    if (str_contains($identifier, '-')) {
       [$uid, $ip] = explode('-', $identifier);
       $this->uid = $uid;
       $this->ip = $ip;
diff --git a/core/modules/user/src/Plugin/Validation/Constraint/UserNameConstraintValidator.php b/core/modules/user/src/Plugin/Validation/Constraint/UserNameConstraintValidator.php
index 9c438969aab43fa0406d1f50cdd9f35b1abc40d4..b775d09fa7909bbcde988e41e12b8c8ddd1044bc 100644
--- a/core/modules/user/src/Plugin/Validation/Constraint/UserNameConstraintValidator.php
+++ b/core/modules/user/src/Plugin/Validation/Constraint/UserNameConstraintValidator.php
@@ -26,7 +26,7 @@ public function validate($items, Constraint $constraint) {
     if (substr($name, -1) == ' ') {
       $this->context->addViolation($constraint->spaceEndMessage);
     }
-    if (strpos($name, '  ') !== FALSE) {
+    if (str_contains($name, '  ')) {
       $this->context->addViolation($constraint->multipleSpacesMessage);
     }
     if (preg_match('/[^\x{80}-\x{F7} a-z0-9@+_.\'-]/i', $name)
diff --git a/core/modules/user/tests/src/Functional/UserCancelTest.php b/core/modules/user/tests/src/Functional/UserCancelTest.php
index 8f183bc0fe6cfd1965db288f9da8fb8cbd24f792..41db9a5fb34e3e229ddbd662e0838f74c9a0f8d7 100644
--- a/core/modules/user/tests/src/Functional/UserCancelTest.php
+++ b/core/modules/user/tests/src/Functional/UserCancelTest.php
@@ -626,7 +626,7 @@ public function testMassUserCancelByAdmin() {
     $this->submitForm([], 'Confirm');
     $status = TRUE;
     foreach ($users as $account) {
-      $status = $status && (strpos($this->getTextContent(), "Account {$account->getAccountName()} has been deleted.") !== FALSE);
+      $status = $status && (str_contains($this->getTextContent(), "Account {$account->getAccountName()} has been deleted."));
       $user_storage->resetCache([$account->id()]);
       $status = $status && !$user_storage->load($account->id());
     }
diff --git a/core/modules/views/src/Entity/Render/EntityTranslationRenderTrait.php b/core/modules/views/src/Entity/Render/EntityTranslationRenderTrait.php
index 178c1b1aa5fb6964656f4797afd6b1cb85642ff9..f858c07145d4d2b200145821c700a2b3123b544b 100644
--- a/core/modules/views/src/Entity/Render/EntityTranslationRenderTrait.php
+++ b/core/modules/views/src/Entity/Render/EntityTranslationRenderTrait.php
@@ -41,7 +41,7 @@ protected function getEntityTranslationRenderer() {
         $this->entityTranslationRenderer = new $class($view, $this->getLanguageManager(), $entity_type);
       }
       else {
-        if (strpos($rendering_language, '***LANGUAGE_') !== FALSE) {
+        if (str_contains($rendering_language, '***LANGUAGE_')) {
           $langcode = PluginBase::queryLanguageSubstitutions()[$rendering_language];
         }
         else {
diff --git a/core/modules/views/src/Plugin/views/PluginBase.php b/core/modules/views/src/Plugin/views/PluginBase.php
index bf925dd38390a6e61398d9826662a208854c3d2a..2a7fd90db557eaf29c6f399caa6ec1ff0f3787ca 100644
--- a/core/modules/views/src/Plugin/views/PluginBase.php
+++ b/core/modules/views/src/Plugin/views/PluginBase.php
@@ -368,7 +368,7 @@ protected function viewsTokenReplace($text, $tokens) {
       // Twig wants a token replacement array stripped of curly-brackets.
       // Some Views tokens come with curly-braces, others do not.
       // @todo: https://www.drupal.org/node/2544392
-      if (strpos($token, '{{') !== FALSE) {
+      if (str_contains($token, '{{')) {
         // Twig wants a token replacement array stripped of curly-brackets.
         $token = trim(str_replace(['{{', '}}'], '', $token));
       }
@@ -376,7 +376,7 @@ protected function viewsTokenReplace($text, $tokens) {
       // Check for arrays in Twig tokens. Internally these are passed as
       // dot-delimited strings, but need to be turned into associative arrays
       // for parsing.
-      if (strpos($token, '.') === FALSE) {
+      if (!str_contains($token, '.')) {
         // We need to validate tokens are valid Twig variables. Twig uses the
         // same variable naming rules as PHP.
         // @see http://php.net/manual/language.variables.basics.php
diff --git a/core/modules/views/src/Plugin/views/area/Entity.php b/core/modules/views/src/Plugin/views/area/Entity.php
index e514c4fb1c37a440401772488e3f54a290e4eba9..221fb44ab27c62b346aecf06b0109bb00c078334 100644
--- a/core/modules/views/src/Plugin/views/area/Entity.php
+++ b/core/modules/views/src/Plugin/views/area/Entity.php
@@ -131,7 +131,7 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) {
     // display the entity ID to the admin form user.
     // @todo Use a method to check for tokens in
     //   https://www.drupal.org/node/2396607.
-    if (strpos($this->options['target'], '{{') === FALSE) {
+    if (!str_contains($this->options['target'], '{{')) {
       // @todo If the entity does not exist, this will show the config target
       //   identifier. Decide if this is the correct behavior in
       //   https://www.drupal.org/node/2415391.
@@ -164,7 +164,7 @@ public function submitOptionsForm(&$form, FormStateInterface $form_state) {
     // @todo Use a method to check for tokens in
     //   https://www.drupal.org/node/2396607.
     $options = $form_state->getValue('options');
-    if (strpos($options['target'], '{{') === FALSE) {
+    if (!str_contains($options['target'], '{{')) {
       if ($entity = $this->entityTypeManager->getStorage($this->entityType)->load($options['target'])) {
         $options['target'] = $entity->getConfigTarget();
       }
@@ -179,7 +179,7 @@ public function render($empty = FALSE) {
     if (!$empty || !empty($this->options['empty'])) {
       // @todo Use a method to check for tokens in
       //   https://www.drupal.org/node/2396607.
-      if (strpos($this->options['target'], '{{') !== FALSE) {
+      if (str_contains($this->options['target'], '{{')) {
         // We cast as we need the integer/string value provided by the
         // ::tokenizeValue() call.
         $target_id = (string) $this->tokenizeValue($this->options['target']);
@@ -210,7 +210,7 @@ public function calculateDependencies() {
     // Ensure that we don't add dependencies for placeholders.
     // @todo Use a method to check for tokens in
     //   https://www.drupal.org/node/2396607.
-    if (strpos($this->options['target'], '{{') === FALSE) {
+    if (!str_contains($this->options['target'], '{{')) {
       if ($entity = $this->entityRepository->loadEntityByConfigTarget($this->entityType, $this->options['target'])) {
         $dependencies[$this->entityTypeManager->getDefinition($this->entityType)->getConfigDependencyKey()][] = $entity->getConfigDependencyName();
       }
diff --git a/core/modules/views/src/Plugin/views/area/Result.php b/core/modules/views/src/Plugin/views/area/Result.php
index efe78d07706875810eb0797f94fb14409b76fac5..6405a9bf4320b4c99cb4434ecd2abb46804e42a3 100644
--- a/core/modules/views/src/Plugin/views/area/Result.php
+++ b/core/modules/views/src/Plugin/views/area/Result.php
@@ -60,7 +60,7 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) {
    * {@inheritdoc}
    */
   public function query() {
-    if (strpos($this->options['content'], '@total') !== FALSE) {
+    if (str_contains($this->options['content'], '@total')) {
       $this->view->get_total_rows = TRUE;
     }
   }
diff --git a/core/modules/views/src/Plugin/views/area/Text.php b/core/modules/views/src/Plugin/views/area/Text.php
index c62d4646effb1bcc233f5ede6393368b80c9c4d6..d9751b0294dad3cf825d1055e1a1ada8b42bc98f 100644
--- a/core/modules/views/src/Plugin/views/area/Text.php
+++ b/core/modules/views/src/Plugin/views/area/Text.php
@@ -49,7 +49,7 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) {
   public function preQuery() {
     $content = $this->options['content']['value'];
     // Check for tokens that require a total row count.
-    if (strpos($content, '[view:page-count]') !== FALSE || strpos($content, '[view:total-rows]') !== FALSE) {
+    if (str_contains($content, '[view:page-count]') || str_contains($content, '[view:total-rows]')) {
       $this->view->get_total_rows = TRUE;
     }
   }
diff --git a/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php b/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php
index 97be99852f93b54e81efbd1af1f370d1309ba794..e1827a8104b0c83d970346c007de8e78f40427f6 100644
--- a/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php
+++ b/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php
@@ -1925,7 +1925,7 @@ public function validateOptionsForm(&$form, FormStateInterface $form_state) {
 
     // Validate plugin options. Every section with "_options" in it, belongs to
     // a plugin type, like "style_options".
-    if (strpos($section, '_options') !== FALSE) {
+    if (str_contains($section, '_options')) {
       $plugin_type = str_replace('_options', '', $section);
       // Load the plugin and let it handle the validation.
       if ($plugin = $this->getPlugin($plugin_type)) {
diff --git a/core/modules/views/src/Plugin/views/display/Page.php b/core/modules/views/src/Plugin/views/display/Page.php
index c378885b7a28a870c628a229144045417452f382..19f129148dbdd15e914c9fa93723b5704ec6e2b0 100644
--- a/core/modules/views/src/Plugin/views/display/Page.php
+++ b/core/modules/views/src/Plugin/views/display/Page.php
@@ -495,7 +495,7 @@ public function validateOptionsForm(&$form, FormStateInterface $form_state) {
     if ($form_state->get('section') == 'menu') {
       $path = $this->getOption('path');
       $menu_type = $form_state->getValue(['menu', 'type']);
-      if ($menu_type == 'normal' && strpos($path, '%') !== FALSE) {
+      if ($menu_type == 'normal' && str_contains($path, '%')) {
         $form_state->setError($form['menu']['type'], $this->t('Views cannot create normal menu links for paths with a % in them.'));
       }
 
diff --git a/core/modules/views/src/Plugin/views/field/FieldPluginBase.php b/core/modules/views/src/Plugin/views/field/FieldPluginBase.php
index e49be3139d7653ab49d284d9ec562723eb0bcb26..b13ef749dc8d92a02f558ae683f788247710f241 100644
--- a/core/modules/views/src/Plugin/views/field/FieldPluginBase.php
+++ b/core/modules/views/src/Plugin/views/field/FieldPluginBase.php
@@ -360,7 +360,7 @@ public function elementClasses($row_index = NULL) {
    * {@inheritdoc}
    */
   public function tokenizeValue($value, $row_index = NULL) {
-    if (strpos($value, '{{') !== FALSE) {
+    if (str_contains($value, '{{')) {
       $fake_item = [
         'alter_text' => TRUE,
         'text' => $value,
diff --git a/core/modules/views/src/Plugin/views/join/FieldOrLanguageJoin.php b/core/modules/views/src/Plugin/views/join/FieldOrLanguageJoin.php
index 44734d450e34992b8b0f63ee9795d2f5367a06a2..25dcc92bce3f0240b92b6b0b2a941d5a5755659a 100644
--- a/core/modules/views/src/Plugin/views/join/FieldOrLanguageJoin.php
+++ b/core/modules/views/src/Plugin/views/join/FieldOrLanguageJoin.php
@@ -80,7 +80,7 @@ protected function joinAddExtra(&$arguments, &$condition, $table, SelectInterfac
       // Remove and store the langcode OR bundle join condition extra.
       $language_bundle_conditions = [];
       foreach ($extras as $key => $extra) {
-        if (strpos($extra, '.langcode') !== FALSE || strpos($extra, '.bundle') !== FALSE) {
+        if (str_contains($extra, '.langcode') || str_contains($extra, '.bundle')) {
           $language_bundle_conditions[] = $extra;
           unset($extras[$key]);
         }
diff --git a/core/modules/views/src/Plugin/views/pager/SqlBase.php b/core/modules/views/src/Plugin/views/pager/SqlBase.php
index c3b1d99920df22cef802e82f5408e5b696f90b30..bf2a328ddd80fbebe134c74429673be6b54a44e9 100644
--- a/core/modules/views/src/Plugin/views/pager/SqlBase.php
+++ b/core/modules/views/src/Plugin/views/pager/SqlBase.php
@@ -227,7 +227,7 @@ public function validateOptionsForm(&$form, FormStateInterface $form_state) {
     // Only accept integer values.
     $error = FALSE;
     $exposed_options = $form_state->getValue(['pager_options', 'expose', 'items_per_page_options']);
-    if (strpos($exposed_options, '.') !== FALSE) {
+    if (str_contains($exposed_options, '.')) {
       $error = TRUE;
     }
     $options = explode(',', $exposed_options);
diff --git a/core/modules/views/src/Plugin/views/relationship/GroupwiseMax.php b/core/modules/views/src/Plugin/views/relationship/GroupwiseMax.php
index ab6becbdd68c41142aa3f9b802171736df12832d..be72d1da36935e5da2f54fb0c5f22881bcad0017 100644
--- a/core/modules/views/src/Plugin/views/relationship/GroupwiseMax.php
+++ b/core/modules/views/src/Plugin/views/relationship/GroupwiseMax.php
@@ -331,7 +331,7 @@ protected function alterSubqueryCondition(AlterableInterface $query, &$condition
   protected function conditionNamespace($string) {
     $parts = explode(' = ', $string);
     foreach ($parts as &$part) {
-      if (strpos($part, '.') !== FALSE) {
+      if (str_contains($part, '.')) {
         $part = '"' . str_replace('.', $this->subquery_namespace . '".', $part);
       }
     }
diff --git a/core/modules/views/src/Plugin/views/style/StylePluginBase.php b/core/modules/views/src/Plugin/views/style/StylePluginBase.php
index f9f77169af595620dbdeb1ac88ec022c1c193c09..6b839222659d7c06f5a7387279096ab67dd79e92 100644
--- a/core/modules/views/src/Plugin/views/style/StylePluginBase.php
+++ b/core/modules/views/src/Plugin/views/style/StylePluginBase.php
@@ -198,7 +198,7 @@ public function usesFields() {
   public function usesTokens() {
     if ($this->usesRowClass()) {
       $class = $this->options['row_class'];
-      if (strpos($class, '{{') !== FALSE) {
+      if (str_contains($class, '{{')) {
         return TRUE;
       }
     }
@@ -235,7 +235,7 @@ public function getRowClass($row_index) {
    * Take a value and apply token replacement logic to it.
    */
   public function tokenizeValue($value, $row_index) {
-    if (strpos($value, '{{') !== FALSE) {
+    if (str_contains($value, '{{')) {
       // Row tokens might be empty, for example for node row style.
       $tokens = $this->rowTokens[$row_index] ?? [];
       if (!empty($this->view->build_info['substitutions'])) {
diff --git a/core/modules/views/src/ViewExecutable.php b/core/modules/views/src/ViewExecutable.php
index defce1aa8c6a572857bf75163e24861010d46a90..2be19b8ad92e09d0a7c5b3dc6fd182bad601229a 100644
--- a/core/modules/views/src/ViewExecutable.php
+++ b/core/modules/views/src/ViewExecutable.php
@@ -1972,7 +1972,7 @@ public function getUrl($args = NULL, $display_id = NULL) {
     $path = $this->getPath();
 
     // Don't bother working if there's nothing to do:
-    if (empty($path) || (empty($args) && strpos($path, '%') === FALSE)) {
+    if (empty($path) || (empty($args) && !str_contains($path, '%'))) {
       return $display_handler->getUrlInfo();
     }
 
diff --git a/core/modules/views/tests/src/FunctionalJavascript/Plugin/views/Handler/FilterTest.php b/core/modules/views/tests/src/FunctionalJavascript/Plugin/views/Handler/FilterTest.php
index e669e14c4f501dbf91e2a36278b7f12e79200faf..08c1394b315f3f6de875440392791045bd2195bb 100644
--- a/core/modules/views/tests/src/FunctionalJavascript/Plugin/views/Handler/FilterTest.php
+++ b/core/modules/views/tests/src/FunctionalJavascript/Plugin/views/Handler/FilterTest.php
@@ -151,7 +151,7 @@ protected function waitForOnlyContentRows($timeout = 10000) {
 
       foreach ($handler_rows as $handler_row) {
         // Test that all the visible rows are of the 'content' type.
-        if (strpos($handler_row->getAttribute('class'), 'content') === FALSE) {
+        if (!str_contains($handler_row->getAttribute('class'), 'content')) {
           return FALSE;
         }
       }
diff --git a/core/modules/views/tests/src/Kernel/Entity/RowEntityRenderersTest.php b/core/modules/views/tests/src/Kernel/Entity/RowEntityRenderersTest.php
index 02a2b04e3d6e7d615fd60919fbc697f7a25a16f5..62f4f0e4911762914f95f2455d84d04ad3f1f614 100644
--- a/core/modules/views/tests/src/Kernel/Entity/RowEntityRenderersTest.php
+++ b/core/modules/views/tests/src/Kernel/Entity/RowEntityRenderersTest.php
@@ -384,7 +384,7 @@ protected function assertTranslations(string $display, string $renderer_id, arra
       if (!empty($view->result[$index])) {
         $build = $view->rowPlugin->render($view->result[$index]);
         $output = \Drupal::service('renderer')->renderRoot($build);
-        $result = strpos($output, $expected_output) !== FALSE;
+        $result = str_contains($output, $expected_output);
         if (!$result) {
           break;
         }
diff --git a/core/modules/views/tests/src/Kernel/Handler/FieldRenderedEntityTest.php b/core/modules/views/tests/src/Kernel/Handler/FieldRenderedEntityTest.php
index 1c598edcb29ea5812e4493aac8c8f3700ad36aac..a1971abfd0f3015d58bd2ed0410695f6f8d9e37f 100644
--- a/core/modules/views/tests/src/Kernel/Handler/FieldRenderedEntityTest.php
+++ b/core/modules/views/tests/src/Kernel/Handler/FieldRenderedEntityTest.php
@@ -129,7 +129,7 @@ public function testRenderedEntityWithoutField() {
     $renderer->renderPlain($build);
     for ($i = 1; $i <= 3; $i++) {
       $view_field = $view->style_plugin->getField($i - 1, 'rendered_entity');
-      $search_result = strpos($view_field, "Test $i") !== FALSE;
+      $search_result = str_contains($view_field, "Test $i");
       $this->assertFalse($search_result, "The text 'Test $i' not found in the view.");
     }
 
@@ -202,7 +202,7 @@ public function testRenderedEntityWithField() {
     $renderer->renderPlain($build);
     for ($i = 1; $i <= 3; $i++) {
       $view_field = $view->style_plugin->getField($i - 1, 'rendered_entity');
-      $search_result = strpos($view_field, "Test $i") !== FALSE;
+      $search_result = str_contains($view_field, "Test $i");
       $this->assertTrue($search_result, "The text 'Test $i' found in the view.");
     }
 
diff --git a/core/modules/views/tests/src/Kernel/ViewExecutableTest.php b/core/modules/views/tests/src/Kernel/ViewExecutableTest.php
index 5fa97a3928cfb23779143f4b3f295ca937a5bcfe..2a5e816ba1acad0c3a965491f70ea3fa81ff2398 100644
--- a/core/modules/views/tests/src/Kernel/ViewExecutableTest.php
+++ b/core/modules/views/tests/src/Kernel/ViewExecutableTest.php
@@ -446,7 +446,7 @@ public function testValidate() {
     $count = 0;
     foreach ($view->displayHandlers as $id => $display) {
       $match = function ($value) use ($display) {
-        return strpos($value, $display->display['display_title']) !== FALSE;
+        return str_contains($value, $display->display['display_title']);
       };
       $this->assertNotEmpty(array_filter($validate[$id], $match), new FormattableMarkup('Error message found for @id display', ['@id' => $id]));
       $count++;
diff --git a/core/modules/views_ui/src/ViewEditForm.php b/core/modules/views_ui/src/ViewEditForm.php
index c384ee2c6180f22165ea07e0c0642e093689f529..d10d3a3613e9e0681e409682a9f4d48b68a89085 100644
--- a/core/modules/views_ui/src/ViewEditForm.php
+++ b/core/modules/views_ui/src/ViewEditForm.php
@@ -450,7 +450,7 @@ public function getDisplayDetails($view, $display) {
         elseif ($view->status() && $view->getExecutable()->displayHandlers->get($display['id'])->hasPath()) {
           $path = $view->getExecutable()->displayHandlers->get($display['id'])->getPath();
 
-          if ($path && (strpos($path, '%') === FALSE)) {
+          if ($path && (!str_contains($path, '%'))) {
             // Wrap this in a try/catch as trying to generate links to some
             // routes may throw a NotAcceptableHttpException if they do not
             // respond to HTML, such as RESTExports.
diff --git a/core/modules/views_ui/src/ViewListBuilder.php b/core/modules/views_ui/src/ViewListBuilder.php
index 2f6302ac3049cd82ae29afcec69d9dc7b60ad413..b494fbc78c3d0a256556ac8df6cd3fe15bca154c 100644
--- a/core/modules/views_ui/src/ViewListBuilder.php
+++ b/core/modules/views_ui/src/ViewListBuilder.php
@@ -259,7 +259,7 @@ protected function getDisplaysList(EntityInterface $view) {
       if (!empty($definition['admin'])) {
         if ($display->hasPath()) {
           $path = $display->getPath();
-          if ($view->status() && strpos($path, '%') === FALSE) {
+          if ($view->status() && !str_contains($path, '%')) {
             // Wrap this in a try/catch as trying to generate links to some
             // routes may throw a NotAcceptableHttpException if they do not
             // respond to HTML, such as RESTExports.
diff --git a/core/modules/views_ui/tests/src/Functional/UITestBase.php b/core/modules/views_ui/tests/src/Functional/UITestBase.php
index 3f5cb0476b97db519ca129174d81108fd407d554..deb140595b8a7491fde1bfe0995b630f60fec166 100644
--- a/core/modules/views_ui/tests/src/Functional/UITestBase.php
+++ b/core/modules/views_ui/tests/src/Functional/UITestBase.php
@@ -77,7 +77,7 @@ protected function drupalGet($path, array $options = [], array $headers = []) {
     $url = $this->buildUrl($path, $options);
 
     // Ensure that each nojs page is accessible via ajax as well.
-    if (strpos($url, '/nojs/') !== FALSE) {
+    if (str_contains($url, '/nojs/')) {
       $url = preg_replace('|/nojs/|', '/ajax/', $url, 1);
       $result = $this->drupalGet($url, $options);
       $this->assertSession()->statusCodeEquals(200);
diff --git a/core/scripts/run-tests.sh b/core/scripts/run-tests.sh
index d8db1a2625dc9f9b244269d97a927c70b9279031..699fb9dad292a9e36a1b5dc938f5a45c7c2a4280 100755
--- a/core/scripts/run-tests.sh
+++ b/core/scripts/run-tests.sh
@@ -1131,7 +1131,7 @@ function simpletest_script_reporter_write_xml_results(TestRunResultsStorageInter
       // Create the XML element for this test case:
       $case = $dom_document->createElement('testcase');
       $case->setAttribute('classname', $test_class);
-      if (strpos($result->function, '->') !== FALSE) {
+      if (str_contains($result->function, '->')) {
         [$class, $name] = explode('->', $result->function, 2);
       }
       else {
@@ -1322,7 +1322,7 @@ function simpletest_script_print_alternatives($string, $array, $degree = 4) {
   $alternatives = [];
   foreach ($array as $item) {
     $lev = levenshtein($string, $item);
-    if ($lev <= strlen($item) / $degree || FALSE !== strpos($string, $item)) {
+    if ($lev <= strlen($item) / $degree || str_contains($string, $item)) {
       $alternatives[] = $item;
     }
   }
diff --git a/core/scripts/update-countries.sh b/core/scripts/update-countries.sh
index 37504df75185499281bb6364eb1f87abd4626fda..043eceae800d2c1ae7278391736ee055dbee54a0 100755
--- a/core/scripts/update-countries.sh
+++ b/core/scripts/update-countries.sh
@@ -102,7 +102,7 @@ function t($string) {
 foreach ($countries as $code => $name) {
   // For .po translation file's sake, use double-quotes instead of escaped
   // single-quotes.
-  $name = (strpos($name, '\'') !== FALSE ? '"' . $name . '"' : "'" . $name . "'");
+  $name = str_contains($name, '\'' ? '"' . $name . '"' : "'" . $name . "'");
   $out .= '      ' . var_export($code, TRUE) . ' => t(' . $name . '),' . "\n";
 }
 
diff --git a/core/tests/Drupal/BuildTests/Composer/Component/ComponentsTaggedReleaseTest.php b/core/tests/Drupal/BuildTests/Composer/Component/ComponentsTaggedReleaseTest.php
index 946a57d20ec70da753cc9e6ede1aa257d42d7fbc..8fd0fbbfad33e1a90a86acf678c8a022afe0216c 100644
--- a/core/tests/Drupal/BuildTests/Composer/Component/ComponentsTaggedReleaseTest.php
+++ b/core/tests/Drupal/BuildTests/Composer/Component/ComponentsTaggedReleaseTest.php
@@ -68,7 +68,7 @@ public function testReleaseTagging(string $tag, string $constraint): void {
       );
       // Required packages from drupal/core-* should have our constraint.
       foreach ($requires as $package => $req_constraint) {
-        if (strpos($package, 'drupal/core-') !== FALSE) {
+        if (str_contains($package, 'drupal/core-')) {
           $this->assertEquals($constraint, $req_constraint);
         }
       }
diff --git a/core/tests/Drupal/FunctionalTests/Bootstrap/UncaughtExceptionTest.php b/core/tests/Drupal/FunctionalTests/Bootstrap/UncaughtExceptionTest.php
index fbf557fb1b288c3db96f653eaa88c65634013dc0..c85cc3c6e1fe6bdb0e41cdb2f65dfd44a3bab5c2 100644
--- a/core/tests/Drupal/FunctionalTests/Bootstrap/UncaughtExceptionTest.php
+++ b/core/tests/Drupal/FunctionalTests/Bootstrap/UncaughtExceptionTest.php
@@ -271,7 +271,7 @@ protected function assertErrorLogged(string $error_message): void {
     // afterwards.
     $found = FALSE;
     foreach ($rows as $row_index => $row) {
-      if (strpos($content, $error_message) !== FALSE) {
+      if (str_contains($content, $error_message)) {
         $found = TRUE;
         unset($rows[$row_index]);
       }
diff --git a/core/tests/Drupal/FunctionalTests/Libraries/JqueryUiLibraryAssetsTest.php b/core/tests/Drupal/FunctionalTests/Libraries/JqueryUiLibraryAssetsTest.php
index f92fd3c5354ed10ab3bff8ae368737131848c4af..e276f4a6d09b7dd01a88ef41ab13e198b7364e54 100644
--- a/core/tests/Drupal/FunctionalTests/Libraries/JqueryUiLibraryAssetsTest.php
+++ b/core/tests/Drupal/FunctionalTests/Libraries/JqueryUiLibraryAssetsTest.php
@@ -70,7 +70,7 @@ protected function setUp(): void {
       foreach (['js', 'css'] as $type) {
         foreach ($library[$type] as $asset) {
           $file = $asset['data'];
-          if (strpos($file, 'jquery.ui') === FALSE) {
+          if (!str_contains($file, 'jquery.ui')) {
             continue;
           }
           $weight = $asset['weight'];
@@ -175,7 +175,7 @@ public function testSameAssetSameWeight() {
         foreach ($library[$type] as $asset) {
           $file = $asset['data'];
 
-          if (strpos($file, 'jquery.ui') !== FALSE) {
+          if (str_contains($file, 'jquery.ui')) {
             // If this is the first time a given file is checked, add the weight
             // value to an array.
             if (!isset($asset_weights[$file])) {
@@ -220,7 +220,7 @@ public function testLibraryAssetLoadingOrder($library) {
     $this->assertSession()->statusCodeEquals(200);
 
     // A pipe character in $libraries is delimiting multiple library names.
-    $libraries = strpos($library, '|') !== FALSE ? explode('|', $library) : [$library];
+    $libraries = str_contains($library, '|') ? explode('|', $library) : [$library];
     $files_to_check = [];
 
     // Populate an array with the filenames of every jQuery UI asset in the
@@ -230,7 +230,7 @@ public function testLibraryAssetLoadingOrder($library) {
       foreach (['css', 'js'] as $type) {
         $assets = $this->coreLibrariesWithJqueryUiAssets[$library_name][$type];
         foreach ($assets as $asset) {
-          if (strpos($asset['data'], 'jquery.ui') !== FALSE) {
+          if (str_contains($asset['data'], 'jquery.ui')) {
             $files_to_check[$asset['data']] = TRUE;
           }
         }
diff --git a/core/tests/Drupal/FunctionalTests/Update/UpdatePathTestBaseTest.php b/core/tests/Drupal/FunctionalTests/Update/UpdatePathTestBaseTest.php
index b72ac4949686cfded8821f01d81ea1f4ae33bc87..59485977c2580f6a53ed97fd8ea83c5203a39fc4 100644
--- a/core/tests/Drupal/FunctionalTests/Update/UpdatePathTestBaseTest.php
+++ b/core/tests/Drupal/FunctionalTests/Update/UpdatePathTestBaseTest.php
@@ -103,7 +103,7 @@ public function testUpdateHookN() {
     $select->fields('watchdog', ['message']);
 
     $container_cannot_be_saved_messages = array_filter(iterator_to_array($select->execute()), function ($row) {
-      return strpos($row->message, 'Container cannot be saved to cache.') !== FALSE;
+      return str_contains($row->message, 'Container cannot be saved to cache.');
     });
     $this->assertEquals([], $container_cannot_be_saved_messages);
 
diff --git a/core/tests/Drupal/KernelTests/AssertConfigTrait.php b/core/tests/Drupal/KernelTests/AssertConfigTrait.php
index 307bdcb170f833607dde959c6351d470b080d43d..4d15c9925ab2e19fb8019f35b023c4f1d0c553e7 100644
--- a/core/tests/Drupal/KernelTests/AssertConfigTrait.php
+++ b/core/tests/Drupal/KernelTests/AssertConfigTrait.php
@@ -56,7 +56,7 @@ protected function assertConfigDiff(Diff $result, $config_name, array $skipped_c
             $found = FALSE;
             if (!empty($skipped_config[$config_name])) {
               foreach ($skipped_config[$config_name] as $line) {
-                if (strpos($closing, $line) !== FALSE) {
+                if (str_contains($closing, $line)) {
                   $found = TRUE;
                   break;
                 }
diff --git a/core/tests/Drupal/KernelTests/Core/DependencyInjection/AutowireTest.php b/core/tests/Drupal/KernelTests/Core/DependencyInjection/AutowireTest.php
index 749fc582133a126acafca1a640607cf7d5aba2ce..ac8246c8ef86fdb0c4bdb90db943925c15d02bb8 100644
--- a/core/tests/Drupal/KernelTests/Core/DependencyInjection/AutowireTest.php
+++ b/core/tests/Drupal/KernelTests/Core/DependencyInjection/AutowireTest.php
@@ -70,7 +70,7 @@ public function testCoreServiceAliases(): void {
     $interfaces = [];
     foreach (get_declared_classes() as $class) {
       // Ignore proxy classes for autowiring purposes.
-      if (strpos($class, '\\ProxyClass\\') !== FALSE) {
+      if (str_contains($class, '\\ProxyClass\\')) {
         continue;
       }
 
diff --git a/core/tests/Drupal/KernelTests/Core/Theme/StableLibraryOverrideTestBase.php b/core/tests/Drupal/KernelTests/Core/Theme/StableLibraryOverrideTestBase.php
index a40dddb62b541a215d2e353281fbb0b6743d156a..6e80b20fbd52d03ece7219eaccfa1154c88fb50f 100644
--- a/core/tests/Drupal/KernelTests/Core/Theme/StableLibraryOverrideTestBase.php
+++ b/core/tests/Drupal/KernelTests/Core/Theme/StableLibraryOverrideTestBase.php
@@ -95,7 +95,7 @@ protected function removeVendorAssets(array $all_libraries) {
         }
         foreach (['css', 'js'] as $asset_type) {
           foreach ($library[$asset_type] as $index => $asset) {
-            if (strpos($asset['data'], 'core/assets/vendor') !== FALSE) {
+            if (str_contains($asset['data'], 'core/assets/vendor')) {
               unset($all_libraries[$extension][$library_name][$asset_type][$index]);
               // Re-key the array of assets. This is needed because
               // libraries-override doesn't always preserve the order.
diff --git a/core/tests/Drupal/KernelTests/KernelTestBase.php b/core/tests/Drupal/KernelTests/KernelTestBase.php
index 47fd9b5862843dc0e5dad8314989fb75fb31a932..da2b8fa1204d85d12a0d7c7dce0680380c0e07ff 100644
--- a/core/tests/Drupal/KernelTests/KernelTestBase.php
+++ b/core/tests/Drupal/KernelTests/KernelTestBase.php
@@ -350,7 +350,7 @@ private function bootKernel() {
     $driver = $connection_info['default']['driver'];
     $namespace = $connection_info['default']['namespace'] ?? '';
     $autoload = $connection_info['default']['autoload'] ?? '';
-    if (strpos($autoload, 'src/Driver/Database/') !== FALSE) {
+    if (str_contains($autoload, 'src/Driver/Database/')) {
       [$first, $second] = explode('\\', $namespace, 3);
       if ($first === 'Drupal' && strtolower($second) === $second) {
         // Add the module that provides the database driver to the list of
diff --git a/core/tests/Drupal/Tests/Component/Serialization/YamlTest.php b/core/tests/Drupal/Tests/Component/Serialization/YamlTest.php
index 1aa6b8ddae47c9101d34bda20d0dac1d7e667ef9..040dcc8e3b25db382c7524073be0e1518631abce 100644
--- a/core/tests/Drupal/Tests/Component/Serialization/YamlTest.php
+++ b/core/tests/Drupal/Tests/Component/Serialization/YamlTest.php
@@ -129,8 +129,8 @@ public function providerYamlFilesInCore() {
     foreach ($dirs as $dir) {
       $pathname = $dir->getPathname();
       // Exclude core/node_modules.
-      if ($dir->getExtension() == 'yml' && strpos($pathname, '/../../../../../node_modules') === FALSE) {
-        if (strpos($dir->getRealPath(), 'invalid_file') !== FALSE) {
+      if ($dir->getExtension() == 'yml' && !str_contains($pathname, '/../../../../../node_modules')) {
+        if (str_contains($dir->getRealPath(), 'invalid_file')) {
           // There are some intentionally invalid files provided for testing
           // library API behaviors, ignore them.
           continue;
diff --git a/core/tests/Drupal/Tests/Component/Utility/HtmlTest.php b/core/tests/Drupal/Tests/Component/Utility/HtmlTest.php
index e486961360017aef0ea22d84d6597702eadfa8a6..4dc8eea2137c4edb847a6f6e11570e21587abba7 100644
--- a/core/tests/Drupal/Tests/Component/Utility/HtmlTest.php
+++ b/core/tests/Drupal/Tests/Component/Utility/HtmlTest.php
@@ -165,7 +165,7 @@ public function testHtmlGetUniqueIdWithAjaxIds($expected, $source) {
 
     // Note, we truncate two hyphens at the end.
     // @see \Drupal\Component\Utility\Html::getId()
-    if (strpos($source, '--') !== FALSE) {
+    if (str_contains($source, '--')) {
       $random_suffix = substr($id, strlen($source) + 1);
     }
     else {
diff --git a/core/tests/Drupal/Tests/Composer/Plugin/Scaffold/Functional/ScaffoldUpgradeTest.php b/core/tests/Drupal/Tests/Composer/Plugin/Scaffold/Functional/ScaffoldUpgradeTest.php
index e5d781799e6824e6e3fb6f66705bebfe2800f585..35f74f1e2ce3d411b13cbf9fe3af5b94db6bd241 100644
--- a/core/tests/Drupal/Tests/Composer/Plugin/Scaffold/Functional/ScaffoldUpgradeTest.php
+++ b/core/tests/Drupal/Tests/Composer/Plugin/Scaffold/Functional/ScaffoldUpgradeTest.php
@@ -53,7 +53,7 @@ protected function setUp(): void {
    */
   public function testScaffoldUpgrade() {
     $composerVersionLine = exec('composer --version');
-    if (strpos($composerVersionLine, 'Composer version 2') !== FALSE) {
+    if (str_contains($composerVersionLine, 'Composer version 2')) {
       $this->markTestSkipped('We cannot run the scaffold upgrade test with Composer 2 until we have a stable version of drupal/core-composer-scaffold to start from that we can install with Composer 2.x.');
     }
     $this->fixturesDir = $this->fixtures->tmpDir($this->getName());
diff --git a/core/tests/Drupal/Tests/Core/Entity/EntityCreateAccessCheckTest.php b/core/tests/Drupal/Tests/Core/Entity/EntityCreateAccessCheckTest.php
index 4496499df88b47e9ce01b705f8d82281649a3cf7..d9069f9382b8614675a1e2785281f7b43ac5861b 100644
--- a/core/tests/Drupal/Tests/Core/Entity/EntityCreateAccessCheckTest.php
+++ b/core/tests/Drupal/Tests/Core/Entity/EntityCreateAccessCheckTest.php
@@ -82,7 +82,7 @@ public function testAccess($entity_bundle, $requirement, $access, $expected, $ex
 
     // Don't expect a call to the access control handler when we have a bundle
     // argument requirement but no bundle is provided.
-    if ($entity_bundle || strpos($requirement, '{') === FALSE) {
+    if ($entity_bundle || !str_contains($requirement, '{')) {
       $access_control_handler = $this->createMock('Drupal\Core\Entity\EntityAccessControlHandlerInterface');
       $access_control_handler->expects($this->once())
         ->method('createAccess')
diff --git a/core/tests/Drupal/Tests/Listeners/DrupalStandardsListenerTrait.php b/core/tests/Drupal/Tests/Listeners/DrupalStandardsListenerTrait.php
index a13af0e0b8fe91d5b6d49f7933f41caf4b3a0975..46e732ed22bc4727be4710500aba25ddcfe00ee4 100644
--- a/core/tests/Drupal/Tests/Listeners/DrupalStandardsListenerTrait.php
+++ b/core/tests/Drupal/Tests/Listeners/DrupalStandardsListenerTrait.php
@@ -94,13 +94,13 @@ private function checkValidCoversForTest(TestCase $test) {
           return;
         }
         // Ensure we don't have ().
-        if (strpos($covers, '()') !== FALSE) {
+        if (str_contains($covers, '()')) {
           $this->fail($test, "@covers invalid syntax: Do not use '()'");
         }
         // Glean the class and method from @covers.
         $class = $covers;
         $method = '';
-        if (strpos($covers, '::') !== FALSE) {
+        if (str_contains($covers, '::')) {
           [$class, $method] = explode('::', $covers);
         }
         // Check for the existence of the class if it's specified by @covers.
diff --git a/core/tests/Drupal/Tests/WebAssert.php b/core/tests/Drupal/Tests/WebAssert.php
index 427a0a0496497d12027d4b2970e81b0bd2859b9c..ee4408c90ae3aa33042161979a66e64115e8c3dc 100644
--- a/core/tests/Drupal/Tests/WebAssert.php
+++ b/core/tests/Drupal/Tests/WebAssert.php
@@ -705,7 +705,7 @@ public function pageContainsNoDuplicateId() {
    */
   public function addressEquals($page) {
     $expected = $this->cleanUrl($page, TRUE);
-    $actual = $this->cleanUrl($this->session->getCurrentUrl(), strpos($expected, '?') !== FALSE);
+    $actual = $this->cleanUrl($this->session->getCurrentUrl(), str_contains($expected, '?'));
 
     $this->assert($actual === $expected, sprintf('Current page is "%s", but "%s" expected.', $actual, $expected));
   }
@@ -715,7 +715,7 @@ public function addressEquals($page) {
    */
   public function addressNotEquals($page) {
     $expected = $this->cleanUrl($page, TRUE);
-    $actual = $this->cleanUrl($this->session->getCurrentUrl(), strpos($expected, '?') !== FALSE);
+    $actual = $this->cleanUrl($this->session->getCurrentUrl(), str_contains($expected, '?'));
 
     $this->assert($actual !== $expected, sprintf('Current page is "%s", but should not be.', $actual));
   }
diff --git a/core/tests/bootstrap.php b/core/tests/bootstrap.php
index ed4a164ccfd925bc78b7e8d6231f9a1117033647..34778e39cff91ef6284af18d61562fd0b4d467f0 100644
--- a/core/tests/bootstrap.php
+++ b/core/tests/bootstrap.php
@@ -23,7 +23,7 @@ function drupal_phpunit_find_extension_directories($scan_directory) {
   $extensions = [];
   $dirs = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($scan_directory, \RecursiveDirectoryIterator::FOLLOW_SYMLINKS));
   foreach ($dirs as $dir) {
-    if (strpos($dir->getPathname(), '.info.yml') !== FALSE) {
+    if (str_contains($dir->getPathname(), '.info.yml')) {
       // Cut off ".info.yml" from the filename for use as the extension name. We
       // use getRealPath() so that we can scan extensions represented by
       // directory aliases.
diff --git a/core/themes/claro/claro.theme b/core/themes/claro/claro.theme
index 889efcebfeb90af9934771728e50711d492e1ecc..a4be416f7de29f49b4e308bae8f2af939a7c5d0b 100644
--- a/core/themes/claro/claro.theme
+++ b/core/themes/claro/claro.theme
@@ -416,7 +416,7 @@ function claro_form_alter(array &$form, FormStateInterface $form_state, $form_id
     // Determine if the Views form includes a bulk operations form. If it does,
     // move it to the bottom and remove the second bulk operations submit.
     foreach (Element::children($form['header']) as $key) {
-      if (strpos($key, '_bulk_form') !== FALSE) {
+      if (str_contains($key, '_bulk_form')) {
         // Move the bulk actions form from the header to its own container.
         $form['bulk_actions_container'] = $form['header'][$key];
         unset($form['header'][$key]);
@@ -1616,7 +1616,7 @@ function claro_form_views_ui_config_item_form_alter(array &$form, FormStateInter
     // wrapper.
     if (isset($form['options']['operator']['#prefix'])) {
       foreach (['views-left-30', 'views-left-40'] as $left_class) {
-        if (strpos($form['options']['operator']['#prefix'], $left_class) !== FALSE) {
+        if (str_contains($form['options']['operator']['#prefix'], $left_class)) {
           $form['options']['operator']['#prefix'] = '<div class="views-config-group-region">' . str_replace($left_class, 'views-group-box--operator', $form['options']['operator']['#prefix']);
           $form['options']['value']['#suffix'] = $form['options']['value']['#suffix'] . '</div>';
         }
@@ -1627,14 +1627,14 @@ function claro_form_views_ui_config_item_form_alter(array &$form, FormStateInter
     // removed in order to style these forms consistently.
     // @see \Drupal\views\Plugin\views\filter\InOperator::valueForm
     $wrapper_div_to_remove = '<div id="edit-options-value-wrapper">';
-    if (isset($form['options']['value']['#prefix']) && strpos($form['options']['value']['#prefix'], $wrapper_div_to_remove) !== FALSE) {
+    if (isset($form['options']['value']['#prefix']) && str_contains($form['options']['value']['#prefix'], $wrapper_div_to_remove)) {
       $form['options']['value']['#prefix'] = str_replace($wrapper_div_to_remove, '', $form['options']['value']['#prefix']);
       $form['options']['value']['#suffix'] = preg_replace('/<\/div>/', '', $form['options']['value']['#suffix'], 1);
     }
 
     if (isset($form['options']['value']['#prefix'])) {
       foreach (['views-right-70', 'views-right-60'] as $right_class) {
-        if (strpos($form['options']['value']['#prefix'], $right_class) !== FALSE) {
+        if (str_contains($form['options']['value']['#prefix'], $right_class)) {
           $form['options']['value']['#prefix'] = str_replace($right_class, 'views-group-box--value', $form['options']['value']['#prefix']);
         }
       }
@@ -1643,7 +1643,7 @@ function claro_form_views_ui_config_item_form_alter(array &$form, FormStateInter
     // If the form includes a `value` field, the `.views-group-box--value` and
     // `.views-group-box` classes must be present in a wrapper div. Add them
     // here if it they are not yet present.
-    if (!isset($form['options']['value']['#prefix']) || strpos($form['options']['value']['#prefix'], 'views-group-box--value') === FALSE) {
+    if (!isset($form['options']['value']['#prefix']) || !str_contains($form['options']['value']['#prefix'], 'views-group-box--value')) {
       $prefix = $form['options']['value']['#prefix'] ?? '';
       $suffix = $form['options']['value']['#suffix'] ?? '';
       $form['options']['value']['#prefix'] = '<div class="views-group-box views-group-box--value">' . $prefix;
diff --git a/core/themes/engines/twig/twig.engine b/core/themes/engines/twig/twig.engine
index 4ab093c4c81af0569f30803d54e3e313495bc04b..cb32cbaa95cf5dadf10679d38590e23197dd6cd3 100644
--- a/core/themes/engines/twig/twig.engine
+++ b/core/themes/engines/twig/twig.engine
@@ -72,7 +72,7 @@ function twig_render_template($template_file, array $variables) {
     }
     // Add debug output for directly called suggestions like
     // '#theme' => 'comment__node__article'.
-    if (strpos($variables['theme_hook_original'], '__') !== FALSE) {
+    if (str_contains($variables['theme_hook_original'], '__')) {
       $derived_suggestions[] = $hook = $variables['theme_hook_original'];
       while ($pos = strrpos($hook, '__')) {
         $hook = substr($hook, 0, $pos);
@@ -90,7 +90,7 @@ function twig_render_template($template_file, array $variables) {
       $suggestions = $variables['theme_hook_suggestions'];
       // Only add the original theme hook if it wasn't a directly called
       // suggestion.
-      if (strpos($variables['theme_hook_original'], '__') === FALSE) {
+      if (!str_contains($variables['theme_hook_original'], '__')) {
         $suggestions[] = $variables['theme_hook_original'];
       }
       $invalid_suggestions = [];