From 22eb1dd9a335a3b64ce7a7c1472f80ed35e1b199 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Fri, 4 Sep 2026 18:29:11 +0200 Subject: [PATCH] [Php80] Skip empty string needle in StrContainsRector strpos()/strstr() with empty needle returned false on PHP < 8, while str_contains() with empty needle returns true, so the conversion changed behavior. Skip when the needle is an empty string literal. Claude-Session: https://claude.ai/code/session_01Hczn76uiK4bDwdHM4rTMui --- .../Fixture/skip_empty_needle_strpos.php.inc | 11 +++++++++++ .../Fixture/skip_empty_needle_strstr.php.inc | 11 +++++++++++ .../Rector/NotIdentical/StrContainsRector.php | 15 +++++++++++++++ 3 files changed, 37 insertions(+) create mode 100644 rules-tests/Php80/Rector/NotIdentical/StrContainsRector/Fixture/skip_empty_needle_strpos.php.inc create mode 100644 rules-tests/Php80/Rector/NotIdentical/StrContainsRector/Fixture/skip_empty_needle_strstr.php.inc diff --git a/rules-tests/Php80/Rector/NotIdentical/StrContainsRector/Fixture/skip_empty_needle_strpos.php.inc b/rules-tests/Php80/Rector/NotIdentical/StrContainsRector/Fixture/skip_empty_needle_strpos.php.inc new file mode 100644 index 00000000000..479799cdccd --- /dev/null +++ b/rules-tests/Php80/Rector/NotIdentical/StrContainsRector/Fixture/skip_empty_needle_strpos.php.inc @@ -0,0 +1,11 @@ +getArgs(); + if (isset($args[1]) && $this->isEmptyStringNeedle($args[1]->value)) { + return null; + } + if (isset($funcCall->getArgs()[2])) { $secondArg = $funcCall->getArgs()[2]; @@ -132,4 +138,13 @@ private function isIntegerZero(Expr $expr): bool return $expr->value === 0; } + + private function isEmptyStringNeedle(Expr $expr): bool + { + if (! $expr instanceof String_) { + return false; + } + + return $expr->value === ''; + } }