Skip to content

Commit 8f4f33c

Browse files
committed
[StrContainsRector] also replace multibyte functions fro strpos and strstr
1 parent 8e60090 commit 8f4f33c

10 files changed

+199
-9
lines changed

config/set/php85.php

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,5 @@
66
use Rector\Php85\Rector\ArrayDimFetch\ArrayFirstLastRector;
77

88
return static function (RectorConfig $rectorConfig): void {
9-
$rectorConfig->rules(
10-
[
11-
ArrayFirstLastRector::class,
12-
]
13-
);
9+
$rectorConfig->rules([ArrayFirstLastRector::class]);
1410
};
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
namespace Rector\Tests\Php80\Rector\NotIdentical\StrContainsRector\Fixture;
4+
5+
class MultibyteOffsetStrpos
6+
{
7+
public function run()
8+
{
9+
$isMatch = mb_strpos('happy 😊 euro €', 'a', 1) !== false;
10+
}
11+
}
12+
?>
13+
-----
14+
<?php
15+
16+
namespace Rector\Tests\Php80\Rector\NotIdentical\StrContainsRector\Fixture;
17+
18+
class MultibyteOffsetStrpos
19+
{
20+
public function run()
21+
{
22+
$isMatch = str_contains(mb_substr('happy 😊 euro €', 1), 'a');
23+
}
24+
}
25+
?>
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
namespace Rector\Tests\Php80\Rector\NotIdentical\StrContainsRector\Fixture;
4+
5+
class MultibyteStrposFunction
6+
{
7+
public function run()
8+
{
9+
$isMatch = mb_strpos('happy 😊 euro €', 'a') !== false;
10+
}
11+
}
12+
13+
?>
14+
-----
15+
<?php
16+
17+
namespace Rector\Tests\Php80\Rector\NotIdentical\StrContainsRector\Fixture;
18+
19+
class MultibyteStrposFunction
20+
{
21+
public function run()
22+
{
23+
$isMatch = str_contains('happy 😊 euro €', 'a');
24+
}
25+
}
26+
27+
?>
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
namespace Rector\Tests\Php80\Rector\NotIdentical\StrContainsRector\Fixture;
4+
5+
class MultibyteStrstrFunction
6+
{
7+
public function run()
8+
{
9+
$isMatch = mb_strstr('happy 😊 euro €', 'a') === false;
10+
}
11+
}
12+
13+
?>
14+
-----
15+
<?php
16+
17+
namespace Rector\Tests\Php80\Rector\NotIdentical\StrContainsRector\Fixture;
18+
19+
class MultibyteStrstrFunction
20+
{
21+
public function run()
22+
{
23+
$isMatch = !str_contains('happy 😊 euro €', 'a');
24+
}
25+
}
26+
27+
?>
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
namespace Rector\Tests\Php80\Rector\NotIdentical\StrContainsRector\Fixture;
4+
5+
class OffsetVariableMultibyteStrpos
6+
{
7+
public function run()
8+
{
9+
$offset = 1;
10+
$isMatch = mb_strpos('happy 😊 euro €', 'a', $offset) != false;
11+
}
12+
}
13+
?>
14+
-----
15+
<?php
16+
17+
namespace Rector\Tests\Php80\Rector\NotIdentical\StrContainsRector\Fixture;
18+
19+
class OffsetVariableMultibyteStrpos
20+
{
21+
public function run()
22+
{
23+
$offset = 1;
24+
$isMatch = str_contains(mb_substr('happy 😊 euro €', $offset), 'a');
25+
}
26+
}
27+
?>
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
namespace Rector\Tests\Php80\Rector\NotIdentical\StrContainsRector\Fixture;
4+
5+
class ReplaceMultibyteStrposWithEncodingNull
6+
{
7+
public function run()
8+
{
9+
$isMatch = mb_strpos('happy 😊 euro €', 'a', 0, null) !== false;
10+
}
11+
}
12+
13+
?>
14+
-----
15+
<?php
16+
17+
namespace Rector\Tests\Php80\Rector\NotIdentical\StrContainsRector\Fixture;
18+
19+
class ReplaceMultibyteStrposWithEncodingNull
20+
{
21+
public function run()
22+
{
23+
$isMatch = str_contains('happy 😊 euro €', 'a');
24+
}
25+
}
26+
27+
?>
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
namespace Rector\Tests\Php80\Rector\NotIdentical\StrContainsRector\Fixture;
4+
5+
class ReplaceMultibyteStrstrWithEncodingNull
6+
{
7+
public function run()
8+
{
9+
$isMatch = mb_strstr('happy 😊 euro €', 'a', false, null) !== false;
10+
}
11+
}
12+
13+
?>
14+
-----
15+
<?php
16+
17+
namespace Rector\Tests\Php80\Rector\NotIdentical\StrContainsRector\Fixture;
18+
19+
class ReplaceMultibyteStrstrWithEncodingNull
20+
{
21+
public function run()
22+
{
23+
$isMatch = str_contains('happy 😊 euro €', 'a');
24+
}
25+
}
26+
27+
?>
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
namespace Rector\Tests\Php80\Rector\NotIdentical\StrContainsRector\Fixture;
4+
5+
class SkipMultibyteStrposWithEncoding
6+
{
7+
public function run()
8+
{
9+
$isMatch = mb_strpos('happy 😊 euro €', 'a', 0, 'UTF-8') !== false;
10+
}
11+
}
12+
13+
?>
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
namespace Rector\Tests\Php80\Rector\NotIdentical\StrContainsRector\Fixture;
4+
5+
class SkipMultibyteStrstrWithEncoding
6+
{
7+
public function run()
8+
{
9+
$isMatch = mb_strstr('happy 😊 euro €', 'a', false, 'UTF-8') !== false;
10+
}
11+
}
12+
13+
?>

rules/Php80/Rector/NotIdentical/StrContainsRector.php

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ final class StrContainsRector extends AbstractRector implements MinPhpVersionInt
3232
/**
3333
* @var string[]
3434
*/
35-
private const OLD_STR_NAMES = ['strpos', 'strstr'];
35+
private const OLD_STR_NAMES = ['mb_strpos', 'mb_strstr', 'strpos', 'strstr'];
3636

3737
public function __construct(
3838
private readonly ValueResolver $valueResolver
@@ -47,7 +47,7 @@ public function provideMinPhpVersion(): int
4747
public function getRuleDefinition(): RuleDefinition
4848
{
4949
return new RuleDefinition(
50-
'Replace strpos() !== false and strstr() with str_contains()',
50+
'Replace strpos|mb_strpos() !== false and strstr()|mb_strstr() with str_contains()',
5151
[
5252
new CodeSample(
5353
<<<'CODE_SAMPLE'
@@ -97,12 +97,20 @@ public function refactor(Node $node): ?Node
9797
return null;
9898
}
9999

100+
if ($this->isNames($funcCall->name, ['mb_strpos', 'mb_strstr']) && isset($funcCall->getArgs()[3])) {
101+
if (! $this->valueResolver->isNull($funcCall->getArgs()[3]->value)) {
102+
return null;
103+
}
104+
105+
unset($funcCall->args[3]);
106+
}
107+
100108
if (isset($funcCall->getArgs()[2])) {
101109
$secondArg = $funcCall->getArgs()[2];
102110

103-
if ($this->isName($funcCall->name, 'strpos') && ! $this->isIntegerZero($secondArg->value)) {
111+
if ($this->isNames($funcCall->name, ['strpos', 'mb_strpos']) && ! $this->isIntegerZero($secondArg->value)) {
104112
$funcCall->args[0] = new Arg($this->nodeFactory->createFuncCall(
105-
'substr',
113+
$this->isName($funcCall->name, 'strpos') ? 'substr' : 'mb_substr',
106114
[$funcCall->args[0], $secondArg]
107115
));
108116
}

0 commit comments

Comments
 (0)