Skip to content

Commit

Permalink
Migrate Laravel 10 Database Expressions (#98)
Browse files Browse the repository at this point in the history
* Add rule to convert DB expression casts to method call

* Add rule to convert DB expression __toString() calls to method call

* Generate docs

* Add rule to migrate DB expressions to the Laravel 10 set
  • Loading branch information
GeniJaho authored Apr 26, 2023
1 parent 870ca1f commit 731050b
Show file tree
Hide file tree
Showing 12 changed files with 316 additions and 0 deletions.
6 changes: 6 additions & 0 deletions config/sets/laravel100.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
use Rector\Renaming\Rector\PropertyFetch\RenamePropertyRector;
use Rector\Renaming\ValueObject\MethodCallRename;
use Rector\Renaming\ValueObject\RenameProperty;
use RectorLaravel\Rector\Cast\DatabaseExpressionCastsToMethodCallRector;
use RectorLaravel\Rector\Class_\UnifyModelDatesWithCastsRector;
use RectorLaravel\Rector\MethodCall\DatabaseExpressionToStringToMethodCallRector;

# see https://laravel.com/docs/10.x/upgrade
return static function (RectorConfig $rectorConfig): void {
Expand All @@ -17,6 +19,10 @@
// https://github.com/laravel/framework/pull/32856/files
$rectorConfig->rule(UnifyModelDatesWithCastsRector::class);

// https://github.com/laravel/framework/pull/44784/files
$rectorConfig->rule(DatabaseExpressionCastsToMethodCallRector::class);
$rectorConfig->rule(DatabaseExpressionToStringToMethodCallRector::class);

$rectorConfig
->ruleWithConfiguration(RenamePropertyRector::class, [
# https://github.com/laravel/laravel/commit/edcbe6de7c3f17070bf0ccaa2e2b785158ae5ceb
Expand Down
30 changes: 30 additions & 0 deletions docs/rector_rules_overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,36 @@ Add `parent::boot();` call to `boot()` class method in child of `Illuminate\Data

<br>

## DatabaseExpressionCastsToMethodCallRector

Convert DB Expression string casts to `getValue()` method calls.

- class: [`RectorLaravel\Rector\Cast\DatabaseExpressionCastsToMethodCallRector`](../src/Rector/Cast/DatabaseExpressionCastsToMethodCallRector.php)

```diff
use Illuminate\Support\Facades\DB;

-$string = (string) DB::raw('select 1');
+$string = DB::raw('select 1')->getValue(DB::connection()->getQueryGrammar());
```

<br>

## DatabaseExpressionToStringToMethodCallRector

Convert DB Expression `__toString()` calls to `getValue()` method calls.

- class: [`RectorLaravel\Rector\MethodCall\DatabaseExpressionToStringToMethodCallRector`](../src/Rector/MethodCall/DatabaseExpressionToStringToMethodCallRector.php)

```diff
use Illuminate\Support\Facades\DB;

-$string = DB::raw('select 1')->__toString();
+$string = DB::raw('select 1')->getValue(DB::connection()->getQueryGrammar());
```

<br>

## FactoryApplyingStatesRector

Call the state methods directly instead of specify the name of state.
Expand Down
70 changes: 70 additions & 0 deletions src/Rector/Cast/DatabaseExpressionCastsToMethodCallRector.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?php

declare(strict_types=1);

namespace RectorLaravel\Rector\Cast;

use PhpParser\Node;
use PhpParser\Node\Expr\Cast\String_;
use PhpParser\Node\Expr\StaticCall;
use Rector\Core\Rector\AbstractRector;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;

/**
* @see \RectorLaravel\Tests\Rector\Cast\DatabaseExpressionCastsToMethodCallRector\DatabaseExpressionCastsToMethodCallRectorTest
*/
final class DatabaseExpressionCastsToMethodCallRector extends AbstractRector
{
public function getRuleDefinition(): RuleDefinition
{
return new RuleDefinition('Convert DB Expression string casts to getValue() method calls.', [
new CodeSample(
<<<'CODE_SAMPLE'
use Illuminate\Support\Facades\DB;
$string = (string) DB::raw('select 1');
CODE_SAMPLE
,
<<<'CODE_SAMPLE'
use Illuminate\Support\Facades\DB;
$string = DB::raw('select 1')->getValue(DB::connection()->getQueryGrammar());
CODE_SAMPLE
),
]);
}

/**
* @return array<class-string<Node>>
*/
public function getNodeTypes(): array
{
return [String_::class];
}

/**
* @param String_ $node
*/
public function refactor(Node $node): ?Node
{
if (! $node->expr instanceof StaticCall) {
return null;
}

if (! $this->isName($node->expr->class, 'Illuminate\Support\Facades\DB')) {
return null;
}

if (! $this->isName($node->expr->name, 'raw')) {
return null;
}

return $this->nodeFactory->createMethodCall($node->expr, 'getValue', [
$this->nodeFactory->createMethodCall(
$this->nodeFactory->createStaticCall('Illuminate\Support\Facades\DB', 'connection'),
'getQueryGrammar'
),
]);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<?php

declare(strict_types=1);

namespace RectorLaravel\Rector\MethodCall;

use PhpParser\Node;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\StaticCall;
use Rector\Core\Rector\AbstractRector;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;

/**
* @see \RectorLaravel\Tests\Rector\MethodCall\DatabaseExpressionToStringToMethodCallRector\DatabaseExpressionToStringToMethodCallRectorTest
*/
final class DatabaseExpressionToStringToMethodCallRector extends AbstractRector
{
public function getRuleDefinition(): RuleDefinition
{
return new RuleDefinition('Convert DB Expression __toString() calls to getValue() method calls.', [
new CodeSample(
<<<'CODE_SAMPLE'
use Illuminate\Support\Facades\DB;
$string = DB::raw('select 1')->__toString();
CODE_SAMPLE
,
<<<'CODE_SAMPLE'
use Illuminate\Support\Facades\DB;
$string = DB::raw('select 1')->getValue(DB::connection()->getQueryGrammar());
CODE_SAMPLE
),
]);
}

/**
* @return array<class-string<Node>>
*/
public function getNodeTypes(): array
{
return [MethodCall::class];
}

/**
* @param MethodCall $node
*/
public function refactor(Node $node): ?Node
{
if (! $this->isName($node->name, '__toString')) {
return null;
}

if (! $node->var instanceof StaticCall) {
return null;
}

if (! $this->isName($node->var->class, 'Illuminate\Support\Facades\DB')) {
return null;
}

if (! $this->isName($node->var->name, 'raw')) {
return null;
}

return $this->nodeFactory->createMethodCall($node->var, 'getValue', [
$this->nodeFactory->createMethodCall(
$this->nodeFactory->createStaticCall('Illuminate\Support\Facades\DB', 'connection'),
'getQueryGrammar'
),
]);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

declare(strict_types=1);

namespace RectorLaravel\Tests\Rector\Cast\DatabaseExpressionCastsToMethodCallRector;

use Iterator;
use PHPUnit\Framework\Attributes\DataProvider;
use Rector\Testing\PHPUnit\AbstractRectorTestCase;

final class DatabaseExpressionCastsToMethodCallRectorTest extends AbstractRectorTestCase
{
#[DataProvider('provideData')]
public function test(string $filePath): void
{
$this->doTestFile($filePath);
}

public static function provideData(): Iterator
{
return self::yieldFilesFromDirectory(__DIR__ . '/Fixture');
}

public function provideConfigFilePath(): string
{
return __DIR__ . '/config/configured_rule.php';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace RectorLaravel\Tests\Rector\Cast\DatabaseExpressionCastsToMethodCall\Fixture;

use Illuminate\Support\Facades\DB;

$string = (string) DB::raw('select 1');

?>
-----
<?php

namespace RectorLaravel\Tests\Rector\Cast\DatabaseExpressionCastsToMethodCall\Fixture;

use Illuminate\Support\Facades\DB;

$string = DB::raw('select 1')->getValue(\Illuminate\Support\Facades\DB::connection()->getQueryGrammar());

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

namespace RectorLaravel\Tests\Rector\Cast\DatabaseExpressionCastsToMethodCall\Fixture;

use Illuminate\Support\Facades\DB;

DB::table('users')->where('name', DB::raw('select 1'))->get();

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

use Rector\Config\RectorConfig;
use RectorLaravel\Rector\Cast\DatabaseExpressionCastsToMethodCallRector;

return static function (RectorConfig $rectorConfig): void {
$rectorConfig->import(__DIR__ . '/../../../../../config/config.php');

$rectorConfig->rule(DatabaseExpressionCastsToMethodCallRector::class);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

declare(strict_types=1);

namespace RectorLaravel\Tests\Rector\MethodCall\DatabaseExpressionToStringToMethodCallRector;

use Iterator;
use PHPUnit\Framework\Attributes\DataProvider;
use Rector\Testing\PHPUnit\AbstractRectorTestCase;

final class DatabaseExpressionToStringToMethodCallRectorTest extends AbstractRectorTestCase
{
#[DataProvider('provideData')]
public function test(string $filePath): void
{
$this->doTestFile($filePath);
}

public static function provideData(): Iterator
{
return self::yieldFilesFromDirectory(__DIR__ . '/Fixture');
}

public function provideConfigFilePath(): string
{
return __DIR__ . '/config/configured_rule.php';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace RectorLaravel\Tests\Rector\Cast\DatabaseExpressionCastsToMethodCall\Fixture;

use Illuminate\Support\Facades\DB;

$string = DB::raw('select 1')->__toString();

?>
-----
<?php

namespace RectorLaravel\Tests\Rector\Cast\DatabaseExpressionCastsToMethodCall\Fixture;

use Illuminate\Support\Facades\DB;

$string = DB::raw('select 1')->getValue(\Illuminate\Support\Facades\DB::connection()->getQueryGrammar());

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

namespace RectorLaravel\Tests\Rector\Cast\DatabaseExpressionCastsToMethodCall\Fixture;

use Illuminate\Support\Facades\DB;

DB::table('users')->where('name', DB::raw('select 1'))->get();

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

use Rector\Config\RectorConfig;
use RectorLaravel\Rector\MethodCall\DatabaseExpressionToStringToMethodCallRector;

return static function (RectorConfig $rectorConfig): void {
$rectorConfig->import(__DIR__ . '/../../../../../config/config.php');

$rectorConfig->rule(DatabaseExpressionToStringToMethodCallRector::class);
};

0 comments on commit 731050b

Please sign in to comment.