mirror of
https://github.com/rectorphp/rector.git
synced 2025-04-24 17:36:02 +02:00
Merge pull request #1283 from rectorphp/nette-utils-code-quality-match
[Nette] Add PregFunctionToNetteUtilsStringsRector
This commit is contained in:
commit
0543a5a2ab
@ -41,9 +41,10 @@ Rector **instantly upgrades and instantly refactors PHP code of your application
|
||||
- Rename classes, methods, properties, namespaces, constants... anything :)
|
||||
- Add, replace or remove arguments
|
||||
- Add [parameter or return type declarations](https://www.tomasvotruba.cz/blog/2019/01/03/how-to-complete-type-declarations-without-docblocks-with-rector/) without docblocks - just with static analysis
|
||||
- Change visibility of constant, property or method
|
||||
- Upgrade from PHP 5.3 to PHP 7.4
|
||||
- [Migrate from one PHP framework to another](https://www.tomasvotruba.cz/blog/2019/02/21/how-we-migrated-from-nette-to-symfony-in-3-weeks-part-1/)
|
||||
- [Complete PHP 7.4 property type declarations](https://www.tomasvotruba.cz/blog/2018/11/15/how-to-get-php-74-typed-properties-to-your-code-in-few-seconds/)
|
||||
- [Turn Laravel static to Dependency Injection](https://www.tomasvotruba.cz/blog/2019/03/04/how-to-turn-laravel-from-static-to-dependency-injection-in-one-day/)
|
||||
- And much more...
|
||||
|
||||
...**look at overview of [all available Rectors](/docs/AllRectorsOverview.md)** with before/after diffs and configuration examples. You can use them to build your own sets.
|
||||
@ -323,3 +324,9 @@ Using `rector.yaml`:
|
||||
```bash
|
||||
docker run -v $(pwd):/project rector/rector:latest process /project/app --config /project/rector.yaml --autoload-file /project/vendor/autoload.php --dry-run
|
||||
```
|
||||
|
||||
### Community Packages
|
||||
|
||||
Do you use Rector to upgrade your code? Share it here:
|
||||
|
||||
- [mxr576/drupal8-rector](https://github.com/mxr576/drupal8-rector) by @mxr576
|
||||
|
@ -15,3 +15,4 @@ services:
|
||||
Rector\Nette\Rector\FuncCall\SubstrStrlenFunctionToNetteUtilsStringsRector: ~
|
||||
Rector\Nette\Rector\Identical\StartsWithFunctionToNetteUtilsStringsRector: ~
|
||||
Rector\Nette\Rector\Identical\EndsWithFunctionToNetteUtilsStringsRector: ~
|
||||
Rector\Nette\Rector\FuncCall\PregFunctionToNetteUtilsStringsRector: ~
|
||||
|
@ -1,4 +1,4 @@
|
||||
# All 258 Rectors Overview
|
||||
# All 263 Rectors Overview
|
||||
|
||||
- [Projects](#projects)
|
||||
- [General](#general)
|
||||
@ -16,6 +16,7 @@
|
||||
- [Jms](#jms)
|
||||
- [Laravel](#laravel)
|
||||
- [MysqlToMysqli](#mysqltomysqli)
|
||||
- [Nette](#nette)
|
||||
- [NetteTesterToPHPUnit](#nettetestertophpunit)
|
||||
- [NetteToSymfony](#nettetosymfony)
|
||||
- [PHPStan](#phpstan)
|
||||
@ -427,7 +428,7 @@ Make if conditions more explicit
|
||||
public function run($items)
|
||||
{
|
||||
- if (!count($items)) {
|
||||
+ if (count($items) < 0) {
|
||||
+ if (count($items) !== 0) {
|
||||
return 'no items';
|
||||
}
|
||||
}
|
||||
@ -1429,6 +1430,113 @@ Replace mysql_pconnect() with mysqli_connect() with host p: prefix
|
||||
|
||||
<br>
|
||||
|
||||
## Nette
|
||||
|
||||
### `SubstrStrlenFunctionToNetteUtilsStringsRector`
|
||||
|
||||
- class: `Rector\Nette\Rector\FuncCall\SubstrStrlenFunctionToNetteUtilsStringsRector`
|
||||
|
||||
Use Nette\Utils\Strings over bare string-functions
|
||||
|
||||
```diff
|
||||
class SomeClass
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
- return substr($value, 0, 3);
|
||||
+ return \Nette\Utils\Strings::substring($value, 0, 3);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### `PregFunctionToNetteUtilsStringsRector`
|
||||
|
||||
- class: `Rector\Nette\Rector\FuncCall\PregFunctionToNetteUtilsStringsRector`
|
||||
|
||||
Use Nette\Utils\Strings over bare preg_* functions
|
||||
|
||||
```diff
|
||||
class SomeClass
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
$content = 'Hi my name is Tom';
|
||||
- preg_match('#Hi#', $content);
|
||||
+ \Nette\Utils\Strings::match($content, '#Hi#');
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### `StrposToStringsContainsRector`
|
||||
|
||||
- class: `Rector\Nette\Rector\NotIdentical\StrposToStringsContainsRector`
|
||||
|
||||
Use Nette\Utils\Strings over bare string-functions
|
||||
|
||||
```diff
|
||||
class SomeClass
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
$name = 'Hi, my name is Tom';
|
||||
- return strpos($name, 'Hi') !== false;
|
||||
+ return \Nette\Utils\Strings::contains($name, 'Hi');
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### `EndsWithFunctionToNetteUtilsStringsRector`
|
||||
|
||||
- class: `Rector\Nette\Rector\Identical\EndsWithFunctionToNetteUtilsStringsRector`
|
||||
|
||||
Use Nette\Utils\Strings over bare string-functions
|
||||
|
||||
```diff
|
||||
class SomeClass
|
||||
{
|
||||
public function end($needle)
|
||||
{
|
||||
$content = 'Hi, my name is Tom';
|
||||
|
||||
- $yes = substr($content, -strlen($needle)) === $needle;
|
||||
- $no = $needle !== substr($content, -strlen($needle));
|
||||
+ $yes = \Nette\Utils\Strings::endsWith($content, $needle);
|
||||
+ $no = !\Nette\Utils\Strings::endsWith($content, $needle);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### `StartsWithFunctionToNetteUtilsStringsRector`
|
||||
|
||||
- class: `Rector\Nette\Rector\Identical\StartsWithFunctionToNetteUtilsStringsRector`
|
||||
|
||||
Use Nette\Utils\Strings over bare string-functions
|
||||
|
||||
```diff
|
||||
class SomeClass
|
||||
{
|
||||
public function start($needle)
|
||||
{
|
||||
$content = 'Hi, my name is Tom';
|
||||
|
||||
- $yes = substr($content, 0, strlen($needle)) === $needle;
|
||||
- $no = $needle !== substr($content, 0, strlen($needle));
|
||||
+ $yes = \Nette\Utils\Strings::startwith($content, $needle);
|
||||
+ $no = !\Nette\Utils\Strings::startwith($content, $needle);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
## NetteTesterToPHPUnit
|
||||
|
||||
### `NetteAssertToPHPUnitAssertRector`
|
||||
@ -2606,7 +2714,7 @@ Changes rand, srand and getrandmax by new md_* alternatives.
|
||||
|
||||
- class: `Rector\Php\Rector\FuncCall\PregReplaceEModifierRector`
|
||||
|
||||
The /e modifier is no longer supported, use preg_replace_callback instead
|
||||
The /e modifier is no longer supported, use preg_replace_callback instead
|
||||
|
||||
```diff
|
||||
class SomeClass
|
||||
@ -3159,7 +3267,7 @@ each() function is deprecated, use foreach() instead.
|
||||
|
||||
- class: `Rector\Php\Rector\Each\ListEachRector`
|
||||
|
||||
each() function is deprecated, use foreach() instead.
|
||||
each() function is deprecated, use key() and current() instead
|
||||
|
||||
```diff
|
||||
-list($key, $callback) = each($callbacks);
|
||||
|
@ -910,7 +910,7 @@ if (true) {
|
||||
|
||||
```php
|
||||
?>
|
||||
<strong>feel</strong><?php
|
||||
<strong>feel</strong><?php
|
||||
```
|
||||
<br>
|
||||
|
||||
|
@ -0,0 +1,135 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\Nette\Rector\FuncCall;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\FuncCall;
|
||||
use Rector\NodeTypeResolver\Node\Attribute;
|
||||
use Rector\Rector\AbstractRector;
|
||||
use Rector\RectorDefinition\CodeSample;
|
||||
use Rector\RectorDefinition\RectorDefinition;
|
||||
|
||||
/**
|
||||
* @see https://www.tomasvotruba.cz/blog/2019/02/07/what-i-learned-by-using-thecodingmachine-safe/#is-there-a-better-way
|
||||
*/
|
||||
final class PregFunctionToNetteUtilsStringsRector extends AbstractRector
|
||||
{
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
private $functionNameToMethodName = [
|
||||
'preg_match' => 'match',
|
||||
'preg_match_all' => 'matchAll',
|
||||
'preg_split' => 'split',
|
||||
'preg_replace' => 'replace',
|
||||
'preg_replace_callback' => 'replace',
|
||||
];
|
||||
|
||||
public function getDefinition(): RectorDefinition
|
||||
{
|
||||
return new RectorDefinition('Use Nette\Utils\Strings over bare preg_* functions', [
|
||||
new CodeSample(
|
||||
<<<'CODE_SAMPLE'
|
||||
class SomeClass
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
$content = 'Hi my name is Tom';
|
||||
preg_match('#Hi#', $content);
|
||||
}
|
||||
}
|
||||
CODE_SAMPLE
|
||||
,
|
||||
<<<'CODE_SAMPLE'
|
||||
class SomeClass
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
$content = 'Hi my name is Tom';
|
||||
\Nette\Utils\Strings::match($content, '#Hi#');
|
||||
}
|
||||
}
|
||||
CODE_SAMPLE
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getNodeTypes(): array
|
||||
{
|
||||
return [FuncCall::class];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param FuncCall $node
|
||||
*/
|
||||
public function refactor(Node $node): ?Node
|
||||
{
|
||||
if (! $this->isNames($node, array_keys($this->functionNameToMethodName))) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$methodName = $this->functionNameToMethodName[$this->getName($node)];
|
||||
$matchStaticCall = $this->createMatchStaticCall($node, $methodName);
|
||||
|
||||
// skip assigns, might be used with differnt return value
|
||||
if ($node->getAttribute(Attribute::PARENT_NODE) instanceof Node\Expr\Assign) {
|
||||
if ($methodName === 'matchAll') {
|
||||
// use count
|
||||
return new FuncCall(new Node\Name('count'), [new Node\Arg($matchStaticCall)]);
|
||||
}
|
||||
|
||||
if ($methodName === 'split') {
|
||||
return $this->processSplit($node, $matchStaticCall);
|
||||
}
|
||||
|
||||
if ($methodName === 'replace') {
|
||||
return $matchStaticCall;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// assign
|
||||
if (isset($node->args[2])) {
|
||||
return new Node\Expr\Assign($node->args[2]->value, $matchStaticCall);
|
||||
}
|
||||
|
||||
return $matchStaticCall;
|
||||
}
|
||||
|
||||
private function createMatchStaticCall(FuncCall $funcCall, string $methodName): Node\Expr\StaticCall
|
||||
{
|
||||
$args = [];
|
||||
|
||||
if ($methodName === 'replace') {
|
||||
$args[] = $funcCall->args[2];
|
||||
$args[] = $funcCall->args[0];
|
||||
$args[] = $funcCall->args[1];
|
||||
} else {
|
||||
$args[] = $funcCall->args[1];
|
||||
$args[] = $funcCall->args[0];
|
||||
}
|
||||
|
||||
return $this->createStaticCall('Nette\Utils\Strings', $methodName, $args);
|
||||
}
|
||||
|
||||
private function processSplit(FuncCall $funcCall, Node\Expr\StaticCall $matchStaticCall): Node
|
||||
{
|
||||
if (isset($funcCall->args[2])) {
|
||||
if ($this->isValue($funcCall->args[2]->value, -1)) {
|
||||
if (isset($funcCall->args[3])) {
|
||||
$matchStaticCall->args[] = $funcCall->args[3];
|
||||
}
|
||||
|
||||
return $matchStaticCall;
|
||||
}
|
||||
|
||||
return $funcCall;
|
||||
}
|
||||
|
||||
return $matchStaticCall;
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\Nette\Tests\Rector\FuncCall\PregFunctionToNetteUtilsStringsRector\Fixture;
|
||||
|
||||
class SomeClass
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
$content = 'Hi my name is Tom';
|
||||
|
||||
$isIt = preg_match('#Hi#', $content);
|
||||
|
||||
if (preg_match('#Hi#', $content)) {
|
||||
// matched!
|
||||
}
|
||||
|
||||
preg_match('#Hi#', $content, $matches);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Nette\Tests\Rector\FuncCall\PregFunctionToNetteUtilsStringsRector\Fixture;
|
||||
|
||||
class SomeClass
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
$content = 'Hi my name is Tom';
|
||||
|
||||
$isIt = preg_match('#Hi#', $content);
|
||||
|
||||
if (\Nette\Utils\Strings::match($content, '#Hi#')) {
|
||||
// matched!
|
||||
}
|
||||
|
||||
$matches = \Nette\Utils\Strings::match($content, '#Hi#');
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\Nette\Tests\Rector\FuncCall\PregFunctionToNetteUtilsStringsRector\Fixture;
|
||||
|
||||
class PregMatchAll
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
$content = 'Hi my name is Tom, Hi';
|
||||
|
||||
$countOfMatches = preg_match_all('#Hi#', $content);
|
||||
|
||||
if (preg_match_all('#Hi#', $content)) {
|
||||
// matched!
|
||||
}
|
||||
|
||||
preg_match_all('#Hi#', $content, $matches);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Nette\Tests\Rector\FuncCall\PregFunctionToNetteUtilsStringsRector\Fixture;
|
||||
|
||||
class PregMatchAll
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
$content = 'Hi my name is Tom, Hi';
|
||||
|
||||
$countOfMatches = count(\Nette\Utils\Strings::matchAll($content, '#Hi#'));
|
||||
|
||||
if (\Nette\Utils\Strings::matchAll($content, '#Hi#')) {
|
||||
// matched!
|
||||
}
|
||||
|
||||
$matches = \Nette\Utils\Strings::matchAll($content, '#Hi#');
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\Nette\Tests\Rector\FuncCall\PregFunctionToNetteUtilsStringsRector\Fixture;
|
||||
|
||||
class PregReplace
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
$content = 'Hi my name is Tom';
|
||||
|
||||
$newContent = preg_replace('#Hi#', 'Hello', $content);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Nette\Tests\Rector\FuncCall\PregFunctionToNetteUtilsStringsRector\Fixture;
|
||||
|
||||
class PregReplace
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
$content = 'Hi my name is Tom';
|
||||
|
||||
$newContent = \Nette\Utils\Strings::replace($content, '#Hi#', 'Hello');
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\Nette\Tests\Rector\FuncCall\PregFunctionToNetteUtilsStringsRector\Fixture;
|
||||
|
||||
class PregReplaceCallback
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
$content = 'Hi my name is Tom';
|
||||
|
||||
$newContent = preg_replace_callback('#Hi#', function ($value) {
|
||||
return 'Hello';
|
||||
}, $content);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Nette\Tests\Rector\FuncCall\PregFunctionToNetteUtilsStringsRector\Fixture;
|
||||
|
||||
class PregReplaceCallback
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
$content = 'Hi my name is Tom';
|
||||
|
||||
$newContent = \Nette\Utils\Strings::replace($content, '#Hi#', function ($value) {
|
||||
return 'Hello';
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\Nette\Tests\Rector\FuncCall\PregFunctionToNetteUtilsStringsRector\Fixture;
|
||||
|
||||
class PregSplit
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
$content = 'Hi my name is Tom';
|
||||
|
||||
$splitted = preg_split('#Hi#', $content);
|
||||
$splitted = preg_split('#Hi#', $content, -1);
|
||||
$splitted = preg_split('#Hi#', $content, -1, PREG_SPLIT_NO_EMPTY);
|
||||
|
||||
$splitted = preg_split('#Hi#', $content, 2);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Nette\Tests\Rector\FuncCall\PregFunctionToNetteUtilsStringsRector\Fixture;
|
||||
|
||||
class PregSplit
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
$content = 'Hi my name is Tom';
|
||||
|
||||
$splitted = \Nette\Utils\Strings::split($content, '#Hi#');
|
||||
$splitted = \Nette\Utils\Strings::split($content, '#Hi#');
|
||||
$splitted = \Nette\Utils\Strings::split($content, '#Hi#', PREG_SPLIT_NO_EMPTY);
|
||||
|
||||
$splitted = preg_split('#Hi#', $content, 2);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
@ -0,0 +1,25 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\Nette\Tests\Rector\FuncCall\PregFunctionToNetteUtilsStringsRector;
|
||||
|
||||
use Rector\Nette\Rector\FuncCall\PregFunctionToNetteUtilsStringsRector;
|
||||
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
|
||||
|
||||
final class PregFunctionToNetteUtilsStringsRectorTest extends AbstractRectorTestCase
|
||||
{
|
||||
public function test(): void
|
||||
{
|
||||
$this->doTestFiles([
|
||||
__DIR__ . '/Fixture/preg_match.php.inc',
|
||||
__DIR__ . '/Fixture/preg_match_all.php.inc',
|
||||
__DIR__ . '/Fixture/preg_split.php.inc',
|
||||
__DIR__ . '/Fixture/preg_replace.php.inc',
|
||||
__DIR__ . '/Fixture/preg_replace_callback.php.inc',
|
||||
]);
|
||||
}
|
||||
|
||||
protected function getRectorClass(): string
|
||||
{
|
||||
return PregFunctionToNetteUtilsStringsRector::class;
|
||||
}
|
||||
}
|
@ -9,10 +9,7 @@ final class ActionSuffixRemoverRectorTest extends AbstractRectorTestCase
|
||||
{
|
||||
public function test(): void
|
||||
{
|
||||
$this->doTestFiles([
|
||||
// __DIR__ . '/Fixture/fixture.php.inc',
|
||||
__DIR__ . '/Fixture/fixture2.php.inc',
|
||||
]);
|
||||
$this->doTestFiles([__DIR__ . '/Fixture/fixture.php.inc', __DIR__ . '/Fixture/fixture2.php.inc']);
|
||||
}
|
||||
|
||||
public function getRectorClass(): string
|
||||
|
Loading…
x
Reference in New Issue
Block a user