Skip to content

Commit

Permalink
Add AnonymousMigrationsRector (#17)
Browse files Browse the repository at this point in the history
* Add AnonymousMigrationsRector

* Add reference link

* Re-trigger github action

* Re-Generate Rules Documentation
  • Loading branch information
zingimmick committed Oct 1, 2021
1 parent 1dae5c8 commit 4b0cf31
Show file tree
Hide file tree
Showing 7 changed files with 384 additions and 29 deletions.
236 changes: 207 additions & 29 deletions docs/rector_rules_overview.md
@@ -1,4 +1,44 @@
# 11 Rules Overview
# 19 Rules Overview

## AddArgumentDefaultValueRector

Adds default value for arguments in defined methods.

:wrench: **configure it!**

- class: [`Rector\Laravel\Rector\ClassMethod\AddArgumentDefaultValueRector`](../src/Rector/ClassMethod/AddArgumentDefaultValueRector.php)

```php
use Rector\Laravel\Rector\ClassMethod\AddArgumentDefaultValueRector;
use Rector\Laravel\ValueObject\AddArgumentDefaultValue;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Symplify\SymfonyPhpConfig\ValueObjectInliner;

return static function (ContainerConfigurator $containerConfigurator): void {
$services = $containerConfigurator->services();

$services->set(AddArgumentDefaultValueRector::class)
->call('configure', [[
AddArgumentDefaultValueRector::ADDED_ARGUMENTS => ValueObjectInliner::inline([
new AddArgumentDefaultValue('SomeClass', 'someMethod', 0, false),
]),
]]);
};
```


```diff
class SomeClass
{
- public function someMethod($value)
+ public function someMethod($value = false)
{
}
}
```

<br>

## AddGuardToLoginEventRector

Expand Down Expand Up @@ -70,6 +110,45 @@ Add `parent::boot();` call to `boot()` class method in child of `Illuminate\Data

<br>

## AddParentRegisterToEventServiceProviderRector

Add `parent::register();` call to `register()` class method in child of `Illuminate\Foundation\Support\Providers\EventServiceProvider`

- class: [`Rector\Laravel\Rector\ClassMethod\AddParentRegisterToEventServiceProviderRector`](../src/Rector/ClassMethod/AddParentRegisterToEventServiceProviderRector.php)

```diff
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;

class EventServiceProvider extends ServiceProvider
{
public function register()
{
+ parent::register();
}
}
```

<br>

## AnonymousMigrationsRector

Convert migrations to anonymous classes.

- class: [`Rector\Laravel\Rector\Class_\AnonymousMigrationsRector`](../src/Rector/Class_/AnonymousMigrationsRector.php)

```diff
use Illuminate\Database\Migrations\Migration;

-class CreateUsersTable extends Migration
+return new class extends Migration
{
// ...
-}
+};
```

<br>

## CallOnAppArrayAccessToStandaloneAssignRector

Replace magical call on `$this->app["something"]` to standalone type assign variable
Expand Down Expand Up @@ -119,51 +198,77 @@ Add `parent::boot();` call to `boot()` class method in child of `Illuminate\Data

<br>

## HelperFuncCallToFacadeClassRector
## FactoryApplyingStatesRector

Change `app()` func calls to facade calls
Call the state methods directly instead of specify the name of state.

- class: [`Rector\Laravel\Rector\FuncCall\HelperFuncCallToFacadeClassRector`](../src/Rector/FuncCall/HelperFuncCallToFacadeClassRector.php)
- class: [`Rector\Laravel\Rector\MethodCall\FactoryApplyingStatesRector`](../src/Rector/MethodCall/FactoryApplyingStatesRector.php)

```diff
class SomeClass
{
public function run()
{
- return app('translator')->trans('value');
+ return \Illuminate\Support\Facades\App::get('translator')->trans('value');
}
}
-$factory->state('delinquent');
-$factory->states('premium', 'delinquent');
+$factory->delinquent();
+$factory->premium()->delinquent();
```

<br>

## MakeTaggedPassedToParameterIterableTypeRector
## FactoryDefinitionRector

Change param type to iterable, if passed one
Upgrade legacy factories to support classes.

- class: [`Rector\Laravel\Rector\New_\MakeTaggedPassedToParameterIterableTypeRector`](../src/Rector/New_/MakeTaggedPassedToParameterIterableTypeRector.php)
- class: [`Rector\Laravel\Rector\Namespace_\FactoryDefinitionRector`](../src/Rector/Namespace_/FactoryDefinitionRector.php)

```diff
class AnotherClass
{
/**
* @var \Illuminate\Contracts\Foundation\Application
*/
private $app;
use Faker\Generator as Faker;

-$factory->define(App\User::class, function (Faker $faker) {
- return [
- 'name' => $faker->name,
- 'email' => $faker->unique()->safeEmail,
- ];
-});
+class UserFactory extends \Illuminate\Database\Eloquent\Factories\Factory
+{
+ protected $model = App\User::class;
+ public function definition()
+ {
+ return [
+ 'name' => $this->faker->name,
+ 'email' => $this->faker->unique()->safeEmail,
+ ];
+ }
+}
```

public function create()
{
$tagged = $this->app->tagged('some_tagged');
return new SomeClass($tagged);
}
}
<br>

## FactoryFuncCallToStaticCallRector

Use the static factory method instead of global factory function.

- class: [`Rector\Laravel\Rector\FuncCall\FactoryFuncCallToStaticCallRector`](../src/Rector/FuncCall/FactoryFuncCallToStaticCallRector.php)

```diff
-factory(User::class);
+User::factory();
```

<br>

## HelperFuncCallToFacadeClassRector

Change `app()` func calls to facade calls

- class: [`Rector\Laravel\Rector\FuncCall\HelperFuncCallToFacadeClassRector`](../src/Rector/FuncCall/HelperFuncCallToFacadeClassRector.php)

```diff
class SomeClass
{
- public function __construct(array $items)
+ public function __construct(iterable $items)
public function run()
{
- return app('translator')->trans('value');
+ return \Illuminate\Support\Facades\App::get('translator')->trans('value');
}
}
```
Expand Down Expand Up @@ -230,6 +335,26 @@ Change "redirect" call with 301 to "permanentRedirect"

<br>

## RemoveAllOnDispatchingMethodsWithJobChainingRector

Remove `allOnQueue()` and `allOnConnection()` methods used with job chaining, use the `onQueue()` and `onConnection()` methods instead.

- class: [`Rector\Laravel\Rector\MethodCall\RemoveAllOnDispatchingMethodsWithJobChainingRector`](../src/Rector/MethodCall/RemoveAllOnDispatchingMethodsWithJobChainingRector.php)

```diff
Job::withChain([
new ChainJob(),
])
- ->dispatch()
- ->allOnConnection('redis')
- ->allOnQueue('podcasts');
+ ->onQueue('podcasts')
+ ->onConnection('redis')
+ ->dispatch();
```

<br>

## RequestStaticValidateToInjectRector

Change static `validate()` method to `$request->validate()`
Expand All @@ -251,3 +376,56 @@ Change static `validate()` method to `$request->validate()`
```

<br>

## RouteActionCallableRector

Use PHP callable syntax instead of string syntax for controller route declarations.

:wrench: **configure it!**

- class: [`Rector\Laravel\Rector\StaticCall\RouteActionCallableRector`](../src/Rector/StaticCall/RouteActionCallableRector.php)

```php
use Rector\Laravel\Rector\StaticCall\RouteActionCallableRector;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;

return static function (ContainerConfigurator $containerConfigurator): void {
$services = $containerConfigurator->services();

$services->set(RouteActionCallableRector::class)
->call('configure', [[
RouteActionCallableRector::NAMESPACE => 'App\Http\Controllers',
]]);
};
```


```diff
-Route::get('/users', 'UserController@index');
+Route::get('/users', [\App\Http\Controllers\UserController::class, 'index']);
```

<br>

## UnifyModelDatesWithCastsRector

Unify Model `$dates` property with `$casts`

- class: [`Rector\Laravel\Rector\Class_\UnifyModelDatesWithCastsRector`](../src/Rector/Class_/UnifyModelDatesWithCastsRector.php)

```diff
use Illuminate\Database\Eloquent\Model;

class Person extends Model
{
protected $casts = [
- 'age' => 'integer',
+ 'age' => 'integer', 'birthday' => 'datetime',
];
-
- protected $dates = ['birthday'];
}
```

<br>
85 changes: 85 additions & 0 deletions src/Rector/Class_/AnonymousMigrationsRector.php
@@ -0,0 +1,85 @@
<?php

declare(strict_types=1);

namespace Rector\Laravel\Rector\Class_;

use PhpParser\Node;
use PhpParser\Node\Expr\New_;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\Return_;
use PHPStan\Type\ObjectType;
use Rector\Core\NodeAnalyzer\ClassAnalyzer;
use Rector\Core\Rector\AbstractRector;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;

/**
* @see https://github.com/laravel/framework/pull/36906
* @see https://github.com/laravel/framework/pull/37352
*
* @see \Rector\Laravel\Tests\Rector\Class_\AnonymousMigrationsRector\AnonymousMigrationsRectorTest
*/
final class AnonymousMigrationsRector extends AbstractRector
{
public function __construct(
private ClassAnalyzer $classAnalyzer
) {
}

public function getRuleDefinition(): RuleDefinition
{
return new RuleDefinition('Convert migrations to anonymous classes.', [
new CodeSample(
<<<'CODE_SAMPLE'
use Illuminate\Database\Migrations\Migration;
class CreateUsersTable extends Migration
{
// ...
}
CODE_SAMPLE

,
<<<'CODE_SAMPLE'
use Illuminate\Database\Migrations\Migration;
return new class extends Migration
{
// ...
};
CODE_SAMPLE
),
]);
}

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

/**
* @param Class_ $node
*/
public function refactor(Node $node): ?Node
{
if (! $this->isObjectType($node, new ObjectType('Illuminate\Database\Migrations\Migration'))) {
return null;
}

if ($this->classAnalyzer->isAnonymousClass($node)) {
return null;
}

return new Return_(new New_(new Class_(null, [
'flags' => $node->flags,
'extends' => $node->extends,
'implements' => $node->implements,
'stmts' => $node->stmts,
'attrGroups' => $node->attrGroups,
])));
}
}
11 changes: 11 additions & 0 deletions stubs/Illuminate/Database/Migrations/Migration.php
@@ -0,0 +1,11 @@
<?php

namespace Illuminate\Database\Migrations;

if (class_exists('Illuminate\Database\Migrations\Migration')) {
return;
}

class Migration
{
}

0 comments on commit 4b0cf31

Please sign in to comment.