Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions config/rector/sets/cakephp53.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
use Cake\Upgrade\Rector\Rector\MethodCall\EntityIsEmptyRector;
use Cake\Upgrade\Rector\Rector\MethodCall\EntityPatchRector;
use Cake\Upgrade\Rector\Rector\MethodCall\NewExprToFuncRector;
use Cake\Upgrade\Rector\Rector\MethodCall\QueryParamAccessRector;
use Rector\Config\RectorConfig;
use Rector\Renaming\Rector\MethodCall\RenameMethodRector;
use Rector\Renaming\Rector\Name\RenameClassRector;
Expand All @@ -24,4 +25,5 @@
]);
$rectorConfig->rule(EntityIsEmptyRector::class);
$rectorConfig->rule(EntityPatchRector::class);
$rectorConfig->rule(QueryParamAccessRector::class);
};
94 changes: 94 additions & 0 deletions src/Rector/Rector/MethodCall/QueryParamAccessRector.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<?php
declare(strict_types=1);

namespace Cake\Upgrade\Rector\Rector\MethodCall;

use PhpParser\Node;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Identifier;
use PHPStan\Type\ObjectType;
use Rector\PhpParser\Node\Value\ValueResolver;
use Rector\Rector\AbstractRector;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;

/**
* Transforms $request->getParam('?') to $request->getQueryParams()
*
* In CakePHP 6.0, the getParam('?') shortcut for accessing query parameters
* is removed. Instead, use getQueryParams() directly.
*
* @see https://book.cakephp.org/6/en/appendices/6-0-migration-guide.html
*/
final class QueryParamAccessRector extends AbstractRector
{
public function __construct(
private ValueResolver $valueResolver,
) {
}

public function getRuleDefinition(): RuleDefinition
{
return new RuleDefinition(
'Change $request->getParam(\'?\') to $request->getQueryParams()',
[
new CodeSample(
<<<'CODE_SAMPLE'
$queryParams = $request->getParam('?');
CODE_SAMPLE
,
<<<'CODE_SAMPLE'
$queryParams = $request->getQueryParams();
CODE_SAMPLE,
),
],
);
}

public function getNodeTypes(): array
{
return [MethodCall::class];
}

public function refactor(Node $node): ?Node
{
if (!$node instanceof MethodCall) {
return null;
}

// Must be ->getParam() call
if (!$node->name instanceof Identifier || $node->name->toString() !== 'getParam') {
return null;
}

// Must have at least one argument
if (count($node->args) < 1) {
return null;
}

// First argument must be the string '?'
$firstArg = $node->args[0]->value;
if (!$this->valueResolver->isValue($firstArg, '?')) {
return null;
}

// Check if this is called on a Request object
$callerType = $this->getType($node->var);
if (!$callerType instanceof ObjectType) {
return null;
}

if (
!$callerType->isInstanceOf('Cake\Http\ServerRequest')->yes() &&
!$callerType->isInstanceOf('Psr\Http\Message\ServerRequestInterface')->yes()
) {
return null;
}

// Transform to getQueryParams() with no arguments
$node->name = new Identifier('getQueryParams');
$node->args = [];

return $node;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?php

namespace Cake\Upgrade\Test\TestCase\Rector\MethodCall\QueryParamAccessRector\Fixture;

use Cake\Http\ServerRequest;

class MyController
{
public function index()
{
$request = new ServerRequest();

// Should transform: getParam('?')
$queryParams = $request->getParam('?');

// Should also work with method chaining
$params = $this->getRequest()->getParam('?');

return $queryParams;
}

protected function getRequest(): ServerRequest
{
return new ServerRequest();
}
}

?>
-----
<?php

namespace Cake\Upgrade\Test\TestCase\Rector\MethodCall\QueryParamAccessRector\Fixture;

use Cake\Http\ServerRequest;

class MyController
{
public function index()
{
$request = new ServerRequest();

// Should transform: getParam('?')
$queryParams = $request->getQueryParams();

// Should also work with method chaining
$params = $this->getRequest()->getQueryParams();

return $queryParams;
}

protected function getRequest(): ServerRequest
{
return new ServerRequest();
}
}

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

namespace Cake\Upgrade\Test\TestCase\Rector\MethodCall\QueryParamAccessRector\Fixture;

use Cake\Http\ServerRequest;

class MyController
{
public function index()
{
$request = new ServerRequest();

// Should NOT transform: getParam with different argument
$id = $request->getParam('id');
$action = $request->getParam('action');
$paging = $request->getParam('paging');

// Should NOT transform: non-Request object
$someObject->getParam('?');

return compact('id', 'action', 'paging');
}
}

?>
-----
<?php

namespace Cake\Upgrade\Test\TestCase\Rector\MethodCall\QueryParamAccessRector\Fixture;

use Cake\Http\ServerRequest;

class MyController
{
public function index()
{
$request = new ServerRequest();

// Should NOT transform: getParam with different argument
$id = $request->getParam('id');
$action = $request->getParam('action');
$paging = $request->getParam('paging');

// Should NOT transform: non-Request object
$someObject->getParam('?');

return compact('id', 'action', 'paging');
}
}

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php
declare(strict_types=1);

namespace Cake\Upgrade\Test\TestCase\Rector\MethodCall\QueryParamAccessRector;

use Iterator;
use Rector\Testing\PHPUnit\AbstractRectorTestCase;

final class QueryParamAccessRectorTest 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,9 @@
<?php
declare(strict_types=1);

use Cake\Upgrade\Rector\Rector\MethodCall\QueryParamAccessRector;
use Rector\Config\RectorConfig;

return static function (RectorConfig $rectorConfig): void {
$rectorConfig->rule(QueryParamAccessRector::class);
};
Loading