mirror of
https://github.com/rectorphp/rector.git
synced 2024-06-08 20:22:24 +00:00
[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:
parent
943eb55d65
commit
870a0f3822
5
.github/workflows/daily_pull_requests.yaml
vendored
5
.github/workflows/daily_pull_requests.yaml
vendored
|
@ -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"
|
||||
|
|
51
.github/workflows/weekly_pull_requests.yaml
vendored
Normal file
51
.github/workflows/weekly_pull_requests.yaml
vendored
Normal 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
|
12
config/set/laravel-code-quality.php
Normal file
12
config/set/laravel-code-quality.php
Normal 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);
|
||||
};
|
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
58
rules/laravel/src/NodeFactory/AppAssignFactory.php
Normal file
58
rules/laravel/src/NodeFactory/AppAssignFactory.php
Normal 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();
|
||||
}
|
||||
}
|
|
@ -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
|
||||
)]);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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('...');
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -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
|
||||
{
|
||||
}
|
||||
|
||||
?>
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -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 [];
|
||||
}
|
||||
|
|
17
stubs/Illuminate/Contracts/Foundation/Application.php
Normal file
17
stubs/Illuminate/Contracts/Foundation/Application.php
Normal 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 [];
|
||||
}
|
||||
}
|
13
stubs/Illuminate/Contracts/Support/DeferrableProvider.php
Normal file
13
stubs/Illuminate/Contracts/Support/DeferrableProvider.php
Normal file
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Illuminate\Contracts\Support;
|
||||
|
||||
if (interface_exists('Illuminate\Contracts\Support\DeferrableProvider')) {
|
||||
return;
|
||||
}
|
||||
|
||||
interface DeferrableProvider
|
||||
{
|
||||
}
|
14
stubs/Illuminate/Support/ServiceProvider.php
Normal file
14
stubs/Illuminate/Support/ServiceProvider.php
Normal file
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Illuminate\Support;
|
||||
|
||||
if (class_exists('Illuminate\Support\ServiceProvider')) {
|
||||
return;
|
||||
}
|
||||
|
||||
abstract class ServiceProvider
|
||||
{
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user