[Laravel 5.8] Add CallOnAppArrayAccessToStandaloneAssignRector, PropertyDeferToDeferrableProviderToRector, MakeTaggedPassedToParameterIterableTypeRector (#4637)

* [Laravel 5.8] Add remember method

* [Laravel] Add PropertyDeferToDeferrableProviderToRector

* [Laravel] Add CallOnAppArrayAccessToStandaloneAssignRector

* [Laravel] Add MakeTaggedPassedToParameterIterableTypeRector

* [CI] changelog weekly only

* [ci-review] Rector Rectify

Co-authored-by: rector-bot <tomas@getrector.org>
This commit is contained in:
Tomas Votruba 2020-11-18 01:22:40 +00:00 committed by GitHub
parent 943eb55d65
commit 870a0f3822
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 1076 additions and 44 deletions

View File

@ -21,11 +21,6 @@ jobs:
run: "composer docs"
branch: 'automated-regenerated-nodes-rectors-documentation'
-
name: "Re-Generate CHANGELOG.md"
run: "composer changelog"
branch: 'automated-regenerated-changelog'
-
name: "Re-Propagate Monorepo Dependencies"
run: "composer propagate --ansi"

View File

@ -0,0 +1,51 @@
name: Weekly Pull Requests
on:
schedule:
# https://crontab.guru/once-a-week
- cron: "0 0 * * 0"
jobs:
weekly_pull_requests:
strategy:
fail-fast: false
matrix:
actions:
-
name: "Re-Generate CHANGELOG.md"
run: "composer changelog"
branch: 'automated-regenerated-changelog'
name: ${{ matrix.actions.name }}
runs-on: ubuntu-latest
steps:
-
uses: actions/checkout@v2
with:
token: ${{ secrets.ACCESS_TOKEN }}
# see https://github.com/shivammathur/setup-php
-
uses: shivammathur/setup-php@v2
with:
php-version: 7.4
coverage: none
tools: composer:v2
- run: composer install --no-progress --ansi
-
run: ${{ matrix.actions.run }}
# see https://github.com/peter-evans/create-pull-request
-
name: Create pull-request
uses: peter-evans/create-pull-request@v3
with:
token: ${{ secrets.GITHUB_TOKEN }}
commit-message: "[automated] ${{ matrix.actions.name }}"
base: 'master'
branch: ${{ matrix.actions.branch }}
title: '[automated] ${{ matrix.actions.name }}'
delete-branch: true

View File

@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
use Rector\Laravel\Rector\Assign\CallOnAppArrayAccessToStandaloneAssignRector;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $containerConfigurator): void {
$services = $containerConfigurator->services();
$services->set(CallOnAppArrayAccessToStandaloneAssignRector::class);
};

View File

@ -3,6 +3,8 @@
declare(strict_types=1);
use PHPStan\Type\BooleanType;
use Rector\Laravel\Rector\Class_\PropertyDeferToDeferrableProviderToRector;
use Rector\Laravel\Rector\New_\MakeTaggedPassedToParameterIterableTypeRector;
use Rector\Laravel\Rector\StaticCall\MinutesToSecondsInCacheRector;
use Rector\Renaming\Rector\PropertyFetch\RenamePropertyRector;
use Rector\Renaming\ValueObject\RenameProperty;
@ -16,26 +18,22 @@ use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigura
# see: https://laravel.com/docs/5.8/upgrade
return static function (ContainerConfigurator $containerConfigurator): void {
$containerConfigurator->import(__DIR__ . '/laravel-array-str-functions-to-static-call.php');
$services = $containerConfigurator->services();
$services->set(MinutesToSecondsInCacheRector::class);
$services->set(AddReturnTypeDeclarationRector::class)
->call('configure', [[
AddReturnTypeDeclarationRector::METHOD_RETURN_TYPES => inline_value_objects([
new AddReturnTypeDeclaration('Illuminate\Contracts\Cache\Repository', 'put', new BooleanType()),
new AddReturnTypeDeclaration('Illuminate\Contracts\Cache\Repository', 'forever', new BooleanType()),
new AddReturnTypeDeclaration('Illuminate\Contracts\Cache\Store', 'put', new BooleanType()),
new AddReturnTypeDeclaration('Illuminate\Contracts\Cache\Store', 'putMany', new BooleanType()),
new AddReturnTypeDeclaration('Illuminate\Contracts\Cache\Store', 'forever', new BooleanType()), ]
),
]]);
$services->set(RenamePropertyRector::class)
->call('configure', [[
RenamePropertyRector::RENAMED_PROPERTIES => inline_value_objects([
new RenameProperty('Illuminate\Routing\UrlGenerator', 'cachedSchema', 'cachedScheme'),
]),
]]);
$services->set(AddReturnTypeDeclarationRector::class)->call('configure', [[
AddReturnTypeDeclarationRector::METHOD_RETURN_TYPES => inline_value_objects([
new AddReturnTypeDeclaration('Illuminate\Contracts\Cache\Repository', 'put', new BooleanType()),
new AddReturnTypeDeclaration('Illuminate\Contracts\Cache\Repository', 'forever', new BooleanType()),
new AddReturnTypeDeclaration('Illuminate\Contracts\Cache\Store', 'put', new BooleanType()),
new AddReturnTypeDeclaration('Illuminate\Contracts\Cache\Store', 'putMany', new BooleanType()),
new AddReturnTypeDeclaration('Illuminate\Contracts\Cache\Store', 'forever', new BooleanType()),
]),
]]);
$services->set(RenamePropertyRector::class)->call('configure', [[
RenamePropertyRector::RENAMED_PROPERTIES => inline_value_objects([
new RenameProperty('Illuminate\Routing\UrlGenerator', 'cachedSchema', 'cachedScheme'),
]),
]]);
$services->set(PropertyDeferToDeferrableProviderToRector::class);
$services->set(MakeTaggedPassedToParameterIterableTypeRector::class);
};

View File

@ -8,12 +8,14 @@ use Nette\Utils\Arrays;
use Nette\Utils\Strings;
use PhpParser\Node;
use PhpParser\Node\Expr\Array_;
use PhpParser\Node\Expr\ClassConstFetch;
use PhpParser\Node\Expr\FuncCall;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\PropertyFetch;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassConst;
use PhpParser\Node\Stmt\ClassLike;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Function_;
@ -489,6 +491,11 @@ final class NodeRepository
return $this->findClassMethod($className, $methodName);
}
public function findClassConstByClassConstFetch(ClassConstFetch $classConstFetch): ?ClassConst
{
return $this->parsedNodeCollector->findClassConstByClassConstFetch($classConstFetch);
}
private function addMethod(ClassMethod $classMethod): void
{
$className = $classMethod->getAttribute(AttributeKey::CLASS_NAME);

View File

@ -220,7 +220,7 @@ final class ParsedNodeCollector
return $newsByClass;
}
public function findClassConstantByClassConstFetch(ClassConstFetch $classConstFetch): ?ClassConst
public function findClassConstByClassConstFetch(ClassConstFetch $classConstFetch): ?ClassConst
{
$className = $this->nodeNameResolver->getName($classConstFetch->class);
if ($className === null) {

View File

@ -114,7 +114,7 @@ CODE_SAMPLE
// B. is the value constant reference?
$argumentValue = $node->args[0]->value;
if ($argumentValue instanceof ClassConstFetch) {
$classConst = $this->parsedNodeCollector->findClassConstantByClassConstFetch($argumentValue);
$classConst = $this->nodeRepository->findClassConstByClassConstFetch($argumentValue);
if ($classConst === null) {
return null;
}

View File

@ -0,0 +1,58 @@
<?php
declare(strict_types=1);
namespace Rector\Laravel\NodeFactory;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\Assign;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Stmt\Expression;
use PHPStan\PhpDocParser\Ast\PhpDoc\VarTagValueNode;
use Rector\AttributeAwarePhpDoc\Ast\Type\AttributeAwareFullyQualifiedIdentifierTypeNode;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
use Rector\Laravel\ValueObject\ServiceNameTypeAndVariableName;
final class AppAssignFactory
{
/**
* @var PhpDocInfoFactory
*/
private $phpDocInfoFactory;
public function __construct(PhpDocInfoFactory $phpDocInfoFactory)
{
$this->phpDocInfoFactory = $phpDocInfoFactory;
}
public function createAssignExpression(
ServiceNameTypeAndVariableName $serviceNameTypeAndVariableName,
Expr $expr
): Expression {
$variable = new Variable($serviceNameTypeAndVariableName->getVariableName());
$assign = new Assign($variable, $expr);
$expression = new Expression($assign);
$this->decorateWithVarAnnotation($expression, $serviceNameTypeAndVariableName);
return $expression;
}
private function decorateWithVarAnnotation(
Expression $expression,
ServiceNameTypeAndVariableName $serviceNameTypeAndVariableName
): void {
$phpDocInfo = $this->phpDocInfoFactory->createEmpty($expression);
$attributeAwareFullyQualifiedIdentifierTypeNode = new AttributeAwareFullyQualifiedIdentifierTypeNode(
$serviceNameTypeAndVariableName->getType()
);
$varTagValueNode = new VarTagValueNode(
$attributeAwareFullyQualifiedIdentifierTypeNode,
'$' . $serviceNameTypeAndVariableName->getVariableName(),
''
);
$phpDocInfo->addTagValueNode($varTagValueNode);
$phpDocInfo->makeSingleLined();
}
}

View File

@ -0,0 +1,130 @@
<?php
declare(strict_types=1);
namespace Rector\Laravel\Rector\Assign;
use PhpParser\Node;
use PhpParser\Node\Expr\ArrayDimFetch;
use PhpParser\Node\Expr\Assign;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\Variable;
use Rector\Core\Rector\AbstractRector;
use Rector\Laravel\NodeFactory\AppAssignFactory;
use Rector\Laravel\ValueObject\ServiceNameTypeAndVariableName;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
/**
* @see \Rector\Laravel\Tests\Rector\Assign\CallOnAppArrayAccessToStandaloneAssignRector\CallOnAppArrayAccessToStandaloneAssignRectorTest
*/
final class CallOnAppArrayAccessToStandaloneAssignRector extends AbstractRector
{
/**
* @var ServiceNameTypeAndVariableName[]
*/
private $serviceNameTypeAndVariableNames = [];
/**
* @var AppAssignFactory
*/
private $appAssignFactory;
public function __construct(AppAssignFactory $appAssignFactory)
{
$this->serviceNameTypeAndVariableNames[] = new ServiceNameTypeAndVariableName(
'validator',
'Illuminate\Validation\Factory',
'validationFactory'
);
$this->appAssignFactory = $appAssignFactory;
}
/**
* @return string[]
*/
public function getNodeTypes(): array
{
return [Assign::class];
}
/**
* @param Assign $node
*/
public function refactor(Node $node): ?Node
{
if (! $node->expr instanceof MethodCall) {
return null;
}
$methodCall = $node->expr;
if (! $this->isObjectType($methodCall->var, 'Illuminate\Contracts\Foundation\Application')) {
return null;
}
if (! $methodCall->var instanceof ArrayDimFetch) {
return null;
}
$arrayDimFetchDim = $methodCall->var->dim;
if ($arrayDimFetchDim === null) {
return null;
}
foreach ($this->serviceNameTypeAndVariableNames as $serviceNameTypeAndVariableName) {
if (! $this->isValue($arrayDimFetchDim, $serviceNameTypeAndVariableName->getServiceName())) {
continue;
}
$assignExpression = $this->appAssignFactory->createAssignExpression(
$serviceNameTypeAndVariableName,
$methodCall->var
);
$this->addNodeBeforeNode($assignExpression, $node);
$methodCall->var = new Variable($serviceNameTypeAndVariableName->getVariableName());
return $node;
}
return null;
}
public function getRuleDefinition(): RuleDefinition
{
return new RuleDefinition(
'Replace magical call on $this->app["something"] to standalone type assign variable',
[new CodeSample(<<<'CODE_SAMPLE'
class SomeClass
{
/**
* @var \Illuminate\Contracts\Foundation\Application
*/
private $app;
public function run()
{
$validator = $this->app['validator']->make('...');
}
}
CODE_SAMPLE
, <<<'CODE_SAMPLE'
class SomeClass
{
/**
* @var \Illuminate\Contracts\Foundation\Application
*/
private $app;
public function run()
{
/** @var \Illuminate\Validation\Factory $validationFactory */
$validationFactory = $this->app['validator'];
$validator = $validationFactory->make('...');
}
}
CODE_SAMPLE
)]);
}
}

View File

@ -0,0 +1,101 @@
<?php
declare(strict_types=1);
namespace Rector\Laravel\Rector\Class_;
use PhpParser\Node;
use PhpParser\Node\Name\FullyQualified;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\Property;
use Rector\Core\Rector\AbstractRector;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
/**
* @see https://laravel.com/docs/5.8/upgrade#deferred-service-providers
*
* @see \Rector\Laravel\Tests\Rector\Class_\PropertyDeferToDeferrableProviderToRector\PropertyDeferToDeferrableProviderToRectorTest
*/
final class PropertyDeferToDeferrableProviderToRector extends AbstractRector
{
public function getRuleDefinition(): RuleDefinition
{
return new RuleDefinition(
'Change deprecated $defer = true; to Illuminate\Contracts\Support\DeferrableProvider interface',
[
new CodeSample(
<<<'CODE_SAMPLE'
use Illuminate\Support\ServiceProvider;
final class SomeServiceProvider extends ServiceProvider
{
/**
* @var bool
*/
protected $defer = true;
}
CODE_SAMPLE
,
<<<'CODE_SAMPLE'
use Illuminate\Support\ServiceProvider;
use Illuminate\Contracts\Support\DeferrableProvider;
final class SomeServiceProvider extends ServiceProvider implements DeferrableProvider
{
}
CODE_SAMPLE
),
]);
}
/**
* @return string[]
*/
public function getNodeTypes(): array
{
return [Class_::class];
}
/**
* @param Class_ $node
*/
public function refactor(Node $node): ?Node
{
if (! $this->isObjectType($node, 'Illuminate\Support\ServiceProvider')) {
return null;
}
$deferProperty = $this->matchDeferWithFalseProperty($node);
if ($deferProperty === null) {
return null;
}
$this->removeNode($deferProperty);
$node->implements[] = new FullyQualified('Illuminate\Contracts\Support\DeferrableProvider');
return $node;
}
private function matchDeferWithFalseProperty(Class_ $class): ?Property
{
foreach ($class->getProperties() as $property) {
if (! $this->isName($property, 'defer')) {
continue;
}
$onlyProperty = $property->props[0];
if ($onlyProperty->default === null) {
return null;
}
if ($this->isTrue($onlyProperty->default)) {
return $property;
}
}
return null;
}
}

View File

@ -0,0 +1,128 @@
<?php
declare(strict_types=1);
namespace Rector\Laravel\Rector\New_;
use PhpParser\Node;
use PhpParser\Node\Arg;
use PhpParser\Node\Expr\New_;
use PhpParser\Node\Stmt\Class_;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\ValueObject\MethodName;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
/**
* @see https://laravel.com/docs/5.8/upgrade#container-generators
*
* @see \Rector\Laravel\Tests\Rector\New_\MakeTaggedPassedToParameterIterableTypeRector\MakeTaggedPassedToParameterIterableTypeRectorTest
*/
final class MakeTaggedPassedToParameterIterableTypeRector extends AbstractRector
{
public function getRuleDefinition(): RuleDefinition
{
return new RuleDefinition('Change param type to iterable, if passed one', [
new CodeSample(
<<<'CODE_SAMPLE'
class AnotherClass
{
/**
* @var \Illuminate\Contracts\Foundation\Application
*/
private $app;
public function create()
{
$tagged = $this->app->tagged('some_tagged');
return new SomeClass($tagged);
}
}
class SomeClass
{
public function __construct(array $items)
{
}
}
CODE_SAMPLE
,
<<<'CODE_SAMPLE'
class AnotherClass
{
/**
* @var \Illuminate\Contracts\Foundation\Application
*/
private $app;
public function create()
{
$tagged = $this->app->tagged('some_tagged');
return new SomeClass($tagged);
}
}
class SomeClass
{
public function __construct(iterable $items)
{
}
}
CODE_SAMPLE
),
]);
}
/**
* @return string[]
*/
public function getNodeTypes(): array
{
return [New_::class];
}
/**
* @param New_ $node
*/
public function refactor(Node $node): ?Node
{
$className = $this->getName($node->class);
if ($className === null) {
return null;
}
$class = $this->nodeRepository->findClass($className);
if ($class === null) {
return null;
}
foreach ($node->args as $arg) {
$this->refactorClassWithArgType($class, $arg);
}
return null;
}
private function refactorClassWithArgType(Class_ $class, Arg $arg): void
{
$argValueType = $this->getStaticType($arg->value);
$constructClassMethod = $class->getMethod(MethodName::CONSTRUCT);
$argumentPosition = (int) $arg->getAttribute(AttributeKey::ARGUMENT_POSITION);
if ($constructClassMethod === null) {
return;
}
$param = $constructClassMethod->params[$argumentPosition] ?? null;
if ($param === null) {
return;
}
$argTypeNode = $this->staticTypeMapper->mapPHPStanTypeToPhpParserNode($argValueType);
$param->type = $argTypeNode;
}
}

View File

@ -8,34 +8,67 @@ use PhpParser\Node;
use PhpParser\Node\Arg;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\BinaryOp\Mul;
use PhpParser\Node\Expr\ClassConstFetch;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Scalar\LNumber;
use PHPStan\Type\Constant\ConstantIntegerType;
use Rector\Core\Rector\AbstractRector;
use Rector\Laravel\ValueObject\TypeToTimeMethodAndPosition;
use Rector\NodeCollector\NodeCollector\ParsedNodeCollector;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
/**
* @see https://github.com/laravel/framework/pull/27276
* @see https://laravel.com/docs/5.8/upgrade#cache-ttl-in-seconds
*
* @see \Rector\Laravel\Tests\Rector\StaticCall\MinutesToSecondsInCacheRector\MinutesToSecondsInCacheRectorTest
*/
final class MinutesToSecondsInCacheRector extends AbstractRector
{
/**
* @var string
*/
private const ATTRIBUTE_KEY_ALREADY_MULTIPLIED = 'already_multiplied';
/**
* @var string
*/
private const PUT = 'put';
/**
* @var string
*/
private const ADD = 'add';
/**
* @var string
*/
private const REMEMBER = 'remember';
/**
* @var TypeToTimeMethodAndPosition[]
*/
private $typeToTimeMethodsAndPositions = [];
public function __construct()
public function __construct(ParsedNodeCollector $parsedNodeCollector)
{
$this->parsedNodeCollector = $parsedNodeCollector;
$this->typeToTimeMethodsAndPositions = [
new TypeToTimeMethodAndPosition('Illuminate\Support\Facades\Cache', 'put', 2),
new TypeToTimeMethodAndPosition('Illuminate\Support\Facades\Cache', 'add', 2),
new TypeToTimeMethodAndPosition('Illuminate\Contracts\Cache\Store', 'put', 2),
new TypeToTimeMethodAndPosition('Illuminate\Support\Facades\Cache', self::PUT, 2),
new TypeToTimeMethodAndPosition('Illuminate\Contracts\Cache\Repository', self::PUT, 2),
new TypeToTimeMethodAndPosition('Illuminate\Contracts\Cache\Store', self::PUT, 2),
new TypeToTimeMethodAndPosition('Illuminate\Contracts\Cache\Repository', self::ADD, 2),
new TypeToTimeMethodAndPosition('Illuminate\Contracts\Cache\Store', self::ADD, 2),
new TypeToTimeMethodAndPosition('Illuminate\Support\Facades\Cache', self::ADD, 2),
new TypeToTimeMethodAndPosition('Illuminate\Contracts\Cache\Repository', self::REMEMBER, 2),
new TypeToTimeMethodAndPosition('Illuminate\Support\Facades\Cache', self::REMEMBER, 2),
new TypeToTimeMethodAndPosition('Illuminate\Contracts\Cache\Store', self::REMEMBER, 2),
new TypeToTimeMethodAndPosition('Illuminate\Contracts\Cache\Store', 'putMany', 1),
new TypeToTimeMethodAndPosition('Illuminate\Cache\DynamoDbStore', 'add', 2),
];
}
@ -95,27 +128,59 @@ CODE_SAMPLE
continue;
}
return $this->processArgumentPosition($node, $typeToTimeMethodAndPosition->getPosition());
$argValue = $node->args[$typeToTimeMethodAndPosition->getPosition()]->value;
return $this->processArgumentOnPosition($node, $argValue, $typeToTimeMethodAndPosition->getPosition());
}
return $node;
}
/**
* @param StaticCall|MethodCall $expr
* @return StaticCall|MethodCall
* @param StaticCall|MethodCall $node
* @return StaticCall|MethodCall|null
*/
private function processArgumentPosition(Expr $expr, int $argumentPosition): Expr
private function processArgumentOnPosition(Node $node, Expr $argExpr, int $argumentPosition): ?Expr
{
$oldValue = $expr->args[$argumentPosition]->value;
if (! $oldValue instanceof LNumber && ! $this->getStaticType($oldValue) instanceof ConstantIntegerType) {
return $expr;
if ($argExpr instanceof ClassConstFetch) {
$this->refactorClassConstFetch($argExpr);
return null;
}
$mul = new Mul($oldValue, new LNumber(60));
if (! $this->isNumberType($argExpr)) {
return null;
}
$expr->args[$argumentPosition] = new Arg($mul);
$mul = $this->mulByNumber($argExpr, 60);
$node->args[$argumentPosition] = new Arg($mul);
return $expr;
return $node;
}
private function refactorClassConstFetch(ClassConstFetch $classConstFetch): void
{
$classConst = $this->nodeRepository->findClassConstByClassConstFetch($classConstFetch);
if ($classConst === null) {
return;
}
$onlyConst = $classConst->consts[0];
$alreadyMultiplied = (bool) $onlyConst->getAttribute(self::ATTRIBUTE_KEY_ALREADY_MULTIPLIED);
if ($alreadyMultiplied) {
return;
}
$onlyConst->value = $this->mulByNumber($onlyConst->value, 60);
$onlyConst->setAttribute(self::ATTRIBUTE_KEY_ALREADY_MULTIPLIED, true);
}
private function mulByNumber(Expr $argExpr, int $value): Expr
{
if ($this->isValue($argExpr, 1)) {
return new LNumber($value);
}
return new Mul($argExpr, new LNumber($value));
}
}

View File

@ -0,0 +1,45 @@
<?php
declare(strict_types=1);
namespace Rector\Laravel\ValueObject;
final class ServiceNameTypeAndVariableName
{
/**
* @var string
*/
private $serviceName;
/**
* @var string
*/
private $type;
/**
* @var string
*/
private $variableName;
public function __construct(string $serviceName, string $type, string $variableName)
{
$this->serviceName = $serviceName;
$this->type = $type;
$this->variableName = $variableName;
}
public function getServiceName(): string
{
return $this->serviceName;
}
public function getType(): string
{
return $this->type;
}
public function getVariableName(): string
{
return $this->variableName;
}
}

View File

@ -0,0 +1,31 @@
<?php
declare(strict_types=1);
namespace Rector\Laravel\Tests\Rector\Assign\CallOnAppArrayAccessToStandaloneAssignRector;
use Iterator;
use Rector\Laravel\Rector\Assign\CallOnAppArrayAccessToStandaloneAssignRector;
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
use Symplify\SmartFileSystem\SmartFileInfo;
final class CallOnAppArrayAccessToStandaloneAssignRectorTest extends AbstractRectorTestCase
{
/**
* @dataProvider provideData()
*/
public function test(SmartFileInfo $fileInfo): void
{
$this->doTestFileInfo($fileInfo);
}
public function provideData(): Iterator
{
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
}
protected function getRectorClass(): string
{
return CallOnAppArrayAccessToStandaloneAssignRector::class;
}
}

View File

@ -0,0 +1,43 @@
<?php
declare(strict_types=1);
namespace Rector\Laravel\Tests\Rector\Assign\CallOnAppArrayAccessToStandaloneAssignRector\Fixture;
class SomeClass
{
/**
* @var \Illuminate\Contracts\Foundation\Application
*/
protected $app;
public function run()
{
$validator = $this->app['validator']->make('...');
}
}
?>
-----
<?php
declare(strict_types=1);
namespace Rector\Laravel\Tests\Rector\Assign\CallOnAppArrayAccessToStandaloneAssignRector\Fixture;
class SomeClass
{
/**
* @var \Illuminate\Contracts\Foundation\Application
*/
protected $app;
public function run()
{
/** @var \Illuminate\Validation\Factory $validationFactory */
$validationFactory = $this->app['validator'];
$validator = $validationFactory->make('...');
}
}
?>

View File

@ -0,0 +1,27 @@
<?php
namespace Rector\Laravel\Tests\Rector\Class_\PropertyDeferToDeferrableProviderToRector\Fixture;
use Illuminate\Support\ServiceProvider;
final class SomeServiceProvider extends ServiceProvider
{
/**
* @var bool
*/
protected $defer = true;
}
?>
-----
<?php
namespace Rector\Laravel\Tests\Rector\Class_\PropertyDeferToDeferrableProviderToRector\Fixture;
use Illuminate\Support\ServiceProvider;
final class SomeServiceProvider extends ServiceProvider implements \Illuminate\Contracts\Support\DeferrableProvider
{
}
?>

View File

@ -0,0 +1,13 @@
<?php
namespace Rector\Laravel\Tests\Rector\Class_\PropertyDeferToDeferrableProviderToRector\Fixture;
use Illuminate\Support\ServiceProvider;
final class SkipFalseDefer extends ServiceProvider
{
/**
* @var bool
*/
protected $defer = false;
}

View File

@ -0,0 +1,31 @@
<?php
declare(strict_types=1);
namespace Rector\Laravel\Tests\Rector\Class_\PropertyDeferToDeferrableProviderToRector;
use Iterator;
use Rector\Laravel\Rector\Class_\PropertyDeferToDeferrableProviderToRector;
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
use Symplify\SmartFileSystem\SmartFileInfo;
final class PropertyDeferToDeferrableProviderToRectorTest extends AbstractRectorTestCase
{
/**
* @dataProvider provideData()
*/
public function test(SmartFileInfo $fileInfo): void
{
$this->doTestFileInfo($fileInfo);
}
public function provideData(): Iterator
{
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
}
protected function getRectorClass(): string
{
return PropertyDeferToDeferrableProviderToRector::class;
}
}

View File

@ -0,0 +1,53 @@
<?php
namespace Rector\Laravel\Tests\Rector\New_\MakeTaggedPassedToParameterIterableTypeRector\Fixture;
class AnotherClass
{
/**
* @var \Illuminate\Contracts\Foundation\Application
*/
private $app;
public function create()
{
$tagged = $this->app->tagged('some_tagged');
return new SomeClass($tagged);
}
}
class SomeClass
{
public function __construct(array $items)
{
}
}
?>
-----
<?php
namespace Rector\Laravel\Tests\Rector\New_\MakeTaggedPassedToParameterIterableTypeRector\Fixture;
class AnotherClass
{
/**
* @var \Illuminate\Contracts\Foundation\Application
*/
private $app;
public function create()
{
$tagged = $this->app->tagged('some_tagged');
return new SomeClass($tagged);
}
}
class SomeClass
{
public function __construct(iterable $items)
{
}
}
?>

View File

@ -0,0 +1,31 @@
<?php
declare(strict_types=1);
namespace Rector\Laravel\Tests\Rector\New_\MakeTaggedPassedToParameterIterableTypeRector;
use Iterator;
use Rector\Laravel\Rector\New_\MakeTaggedPassedToParameterIterableTypeRector;
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
use Symplify\SmartFileSystem\SmartFileInfo;
final class MakeTaggedPassedToParameterIterableTypeRectorTest extends AbstractRectorTestCase
{
/**
* @dataProvider provideData()
*/
public function test(SmartFileInfo $fileInfo): void
{
$this->doTestFileInfo($fileInfo);
}
public function provideData(): Iterator
{
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
}
protected function getRectorClass(): string
{
return MakeTaggedPassedToParameterIterableTypeRector::class;
}
}

View File

@ -0,0 +1,27 @@
<?php
namespace Rector\Laravel\Tests\Rector\StaticCall\MinutesToSecondsInCacheRector\Fixture;
class CacheStaticCall
{
public function run()
{
\Illuminate\Support\Facades\Cache::remember('key', 'value', 60);
}
}
?>
-----
<?php
namespace Rector\Laravel\Tests\Rector\StaticCall\MinutesToSecondsInCacheRector\Fixture;
class CacheStaticCall
{
public function run()
{
\Illuminate\Support\Facades\Cache::remember('key', 'value', 60 * 60);
}
}
?>

View File

@ -0,0 +1,41 @@
<?php
namespace Rector\Laravel\Tests\Rector\StaticCall\MinutesToSecondsInCacheRector\Fixture;
use Illuminate\Contracts\Cache\Repository;
final class ConstReference
{
/**
* @var int
*/
private const TIME = 60;
public function run(Repository $repository)
{
$repository->remember('key', 'value', self::TIME);
}
}
?>
-----
<?php
namespace Rector\Laravel\Tests\Rector\StaticCall\MinutesToSecondsInCacheRector\Fixture;
use Illuminate\Contracts\Cache\Repository;
final class ConstReference
{
/**
* @var int
*/
private const TIME = 60 * 60;
public function run(Repository $repository)
{
$repository->remember('key', 'value', self::TIME);
}
}
?>

View File

@ -0,0 +1,43 @@
<?php
namespace Rector\Laravel\Tests\Rector\StaticCall\MinutesToSecondsInCacheRector\Fixture;
use Illuminate\Contracts\Cache\Repository;
final class MultipleUsedConstReference
{
/**
* @var int
*/
private const TIME = 60;
public function run(Repository $repository)
{
$repository->remember('key', 'value', self::TIME);
$repository->remember('key', 'value', self::TIME);
}
}
?>
-----
<?php
namespace Rector\Laravel\Tests\Rector\StaticCall\MinutesToSecondsInCacheRector\Fixture;
use Illuminate\Contracts\Cache\Repository;
final class MultipleUsedConstReference
{
/**
* @var int
*/
private const TIME = 60 * 60;
public function run(Repository $repository)
{
$repository->remember('key', 'value', self::TIME);
$repository->remember('key', 'value', self::TIME);
}
}
?>

View File

@ -0,0 +1,27 @@
<?php
namespace Rector\Laravel\Tests\Rector\StaticCall\MinutesToSecondsInCacheRector\Fixture;
class OnlyOne
{
public function run()
{
\Illuminate\Support\Facades\Cache::put('key', 'value', 1);
}
}
?>
-----
<?php
namespace Rector\Laravel\Tests\Rector\StaticCall\MinutesToSecondsInCacheRector\Fixture;
class OnlyOne
{
public function run()
{
\Illuminate\Support\Facades\Cache::put('key', 'value', 60);
}
}
?>

View File

@ -0,0 +1,31 @@
<?php
namespace Rector\Laravel\Tests\Rector\StaticCall\MinutesToSecondsInCacheRector\Fixture;
use Illuminate\Contracts\Cache\Repository;
final class RememberCache
{
public function run(Repository $repository)
{
$repository->remember('key', 'value', 60);
}
}
?>
-----
<?php
namespace Rector\Laravel\Tests\Rector\StaticCall\MinutesToSecondsInCacheRector\Fixture;
use Illuminate\Contracts\Cache\Repository;
final class RememberCache
{
public function run(Repository $repository)
{
$repository->remember('key', 'value', 60 * 60);
}
}
?>

View File

@ -204,7 +204,7 @@ final class RegexPatternArgumentManipulator
*/
private function resolveClassConstFetchValue(ClassConstFetch $classConstFetch): array
{
$classConstNode = $this->parsedNodeCollector->findClassConstantByClassConstFetch($classConstFetch);
$classConstNode = $this->parsedNodeCollector->findClassConstByClassConstFetch($classConstFetch);
if ($classConstNode === null) {
return [];
}

View File

@ -0,0 +1,17 @@
<?php
declare(strict_types=1);
namespace Illuminate\Contracts\Foundation;
if (class_exists('Illuminate\Contracts\Foundation\Application')) {
return;
}
final class Application
{
public function tagged(string $tagName): iterable
{
return [];
}
}

View File

@ -0,0 +1,13 @@
<?php
declare(strict_types=1);
namespace Illuminate\Contracts\Support;
if (interface_exists('Illuminate\Contracts\Support\DeferrableProvider')) {
return;
}
interface DeferrableProvider
{
}

View File

@ -0,0 +1,14 @@
<?php
declare(strict_types=1);
namespace Illuminate\Support;
if (class_exists('Illuminate\Support\ServiceProvider')) {
return;
}
abstract class ServiceProvider
{
}