Skip to content
Open
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
84 changes: 84 additions & 0 deletions config/rector/sets/cakephp60.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,16 @@
use Cake\Upgrade\Rector\Cake6\RouteBuilderToCallbackFirstRector;
use Cake\Upgrade\Rector\Cake6\TranslationToGetOrCreateTranslationRector;
use Cake\Upgrade\Rector\Cake6\VoidMethod;
use PHPStan\Type\ArrayType;
use PHPStan\Type\BooleanType;
use PHPStan\Type\MixedType;
use PHPStan\Type\NullType;
use PHPStan\Type\ObjectType;
use PHPStan\Type\StringType;
use PHPStan\Type\UnionType;
use Rector\Arguments\NodeAnalyzer\ArgumentAddingScope;
use Rector\Arguments\Rector\ClassMethod\ArgumentAdderRector;
use Rector\Arguments\ValueObject\ArgumentAdder;
use Rector\Config\RectorConfig;
use Rector\Renaming\Rector\MethodCall\RenameMethodRector;
use Rector\Renaming\Rector\Name\RenameClassRector;
Expand Down Expand Up @@ -72,6 +81,81 @@
new MethodCallRename('Cake\Http\Cookie\Cookie', 'resolveSameSiteEnum', 'resolveSameSite'),
]);

// ===== Http package: CakePHP's own PSR-7 implementations replace laminas/diactoros =====
// @see https://github.com/cakephp/cakephp/pull/19691
$rectorConfig->ruleWithConfiguration(RenameClassRector::class, [
'Laminas\Diactoros\Uri' => 'Cake\Http\Uri',
'Laminas\Diactoros\Stream' => 'Cake\Http\Stream',
'Laminas\Diactoros\UploadedFile' => 'Cake\Http\UploadedFile',
'Laminas\Diactoros\Response\RedirectResponse' => 'Cake\Http\Response\RedirectResponse',
'Laminas\Diactoros\MessageTrait' => 'Cake\Http\MessageTrait',
]);

// PSR-17 factories, the HTTP client and messages now declare narrower return types.
// Overriding methods need compatible return types.
$rectorConfig->ruleWithConfiguration(AddReturnTypeDeclarationRector::class, [
new AddReturnTypeDeclaration('Cake\Http\RequestFactory', 'createRequest', new ObjectType('Cake\Http\Client\Request')),
new AddReturnTypeDeclaration('Cake\Http\ResponseFactory', 'createResponse', new ObjectType('Cake\Http\Response')),
new AddReturnTypeDeclaration('Cake\Http\ServerRequestFactory', 'createServerRequest', new ObjectType('Cake\Http\ServerRequest')),
new AddReturnTypeDeclaration('Cake\Http\StreamFactory', 'createStream', new ObjectType('Cake\Http\Stream')),
new AddReturnTypeDeclaration('Cake\Http\StreamFactory', 'createStreamFromFile', new ObjectType('Cake\Http\Stream')),
new AddReturnTypeDeclaration('Cake\Http\StreamFactory', 'createStreamFromResource', new ObjectType('Cake\Http\Stream')),
new AddReturnTypeDeclaration('Cake\Http\UploadedFileFactory', 'createUploadedFile', new ObjectType('Cake\Http\UploadedFile')),
new AddReturnTypeDeclaration('Cake\Http\UriFactory', 'createUri', new ObjectType('Cake\Http\Uri')),
new AddReturnTypeDeclaration('Cake\Http\Client', 'sendRequest', new ObjectType('Cake\Http\Client\Response')),
new AddReturnTypeDeclaration('Cake\Http\Client', 'createAuth', new ObjectType('Cake\Http\Client\Auth\AuthenticationInterface')),
]);

// MessageTrait / request methods of the CakePHP messages now return static instead of the PSR interfaces
$httpMessageStaticMethods = [
'Cake\Http\Response' => ['withProtocolVersion', 'withHeader', 'withAddedHeader', 'withoutHeader', 'withBody'],
'Cake\Http\Client\Response' => ['withProtocolVersion', 'withHeader', 'withAddedHeader', 'withoutHeader', 'withBody'],
'Cake\Http\Client\Request' => [
'withProtocolVersion', 'withHeader', 'withAddedHeader', 'withoutHeader', 'withBody',
'withRequestTarget', 'withMethod', 'withUri',
],
];
foreach ($httpMessageStaticMethods as $className => $methods) {
foreach ($methods as $method) {
$rectorConfig->ruleWithConfiguration(AddReturnTypeDeclarationRector::class, [
new AddReturnTypeDeclaration($className, $method, new SimpleStaticType($className)),
]);
}
}

// Client request data is now limited to array|string|null
$clientDataType = new UnionType([new ArrayType(new MixedType(), new MixedType()), new StringType(), new NullType()]);
$rectorConfig->ruleWithConfiguration(AddParamTypeDeclarationRector::class, [
new AddParamTypeDeclaration('Cake\Http\Client', 'createRequest', 2, $clientDataType),
new AddParamTypeDeclaration('Cake\Http\Client', 'doRequest', 2, $clientDataType),
// The stream adapter now also accepts live response streams
new AddParamTypeDeclaration(
'Cake\Http\Client\Adapter\Stream',
'createResponses',
1,
new UnionType([new StringType(), new ObjectType('Psr\Http\Message\StreamInterface')]),
),
new AddParamTypeDeclaration(
'Cake\Http\Client\Adapter\Stream',
'buildResponse',
1,
new UnionType([new StringType(), new ObjectType('Psr\Http\Message\StreamInterface')]),
),
]);

// ResponseEmitter::emit() got a new optional $bodyIsRange parameter, add it to overriding methods
$rectorConfig->ruleWithConfiguration(ArgumentAdderRector::class, [
new ArgumentAdder(
'Cake\Http\ResponseEmitter',
'emit',
1,
'bodyIsRange',
null,
new UnionType([new BooleanType(), new NullType()]),
ArgumentAddingScope::SCOPE_CLASS_METHOD,
),
]);

// ===== Remove underscores from property names =====

$map = [
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php
declare(strict_types=1);

namespace App\Http;

use Cake\Http\Client;
use Cake\Http\Client\Request;

class AppClient extends Client
{
protected function createRequest(string $method, string $url, mixed $data, array $options): Request
{
return parent::createRequest($method, $url, $data, $options);
}

protected function createAuth(array $auth): object
{
return parent::createAuth($auth);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php
declare(strict_types=1);

namespace App\Http;

use Cake\Http\ResponseEmitter;
use Psr\Http\Message\ResponseInterface;

class AppEmitter extends ResponseEmitter
{
public function emit(ResponseInterface $response): void
{
parent::emit($response);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php
declare(strict_types=1);

namespace App\Http;

use Cake\Http\RequestFactory;
use Cake\Http\ResponseFactory;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;

class AppRequestFactory extends RequestFactory
{
public function createRequest(string $method, $uri): RequestInterface
{
return parent::createRequest($method, $uri);
}
}

class AppResponseFactory extends ResponseFactory
{
public function createResponse(int $code = 200, string $reasonPhrase = ''): ResponseInterface
{
return parent::createResponse($code, $reasonPhrase);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php
declare(strict_types=1);

namespace App\Http;

use Cake\Http\Response;
use Psr\Http\Message\MessageInterface;

class AppResponse extends Response
{
public function withHeader(string $name, $value): MessageInterface
{
return parent::withHeader($name, $value);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php
declare(strict_types=1);

namespace App\Http;

use Cake\Http\Client\Adapter\Stream;
use Cake\Http\Client\Response;

class AppStreamAdapter extends Stream
{
public function createResponses(array $headers, string $content): array
{
return parent::createResponses($headers, $content);
}

protected function buildResponse(array $headers, string $body): Response
{
return parent::buildResponse($headers, $body);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php
declare(strict_types=1);

namespace App\Http;

use Laminas\Diactoros\MessageTrait;
use Laminas\Diactoros\Response\RedirectResponse;
use Laminas\Diactoros\Stream;
use Laminas\Diactoros\UploadedFile;
use Laminas\Diactoros\Uri;

class DiactorosUsage
{
use MessageTrait;

public function build(): array
{
$uri = new Uri('https://example.com');
$stream = new Stream('php://memory', 'wb+');
$file = new UploadedFile($stream, 0, UPLOAD_ERR_OK, 'file.txt', 'text/plain');
$redirect = new RedirectResponse($uri);

return [$uri, $stream, $file, $redirect];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php
declare(strict_types=1);

namespace App\Http;

use Cake\Http\Client;
use Cake\Http\Client\Request;

class AppClient extends Client
{
protected function createRequest(string $method, string $url, array|string|null $data, array $options): Request
{
return parent::createRequest($method, $url, $data, $options);
}

protected function createAuth(array $auth): \Cake\Http\Client\Auth\AuthenticationInterface
{
return parent::createAuth($auth);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php
declare(strict_types=1);

namespace App\Http;

use Cake\Http\ResponseEmitter;
use Psr\Http\Message\ResponseInterface;

class AppEmitter extends ResponseEmitter
{
public function emit(ResponseInterface $response, ?bool $bodyIsRange = null): void
{
parent::emit($response);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php
declare(strict_types=1);

namespace App\Http;

use Cake\Http\RequestFactory;
use Cake\Http\ResponseFactory;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;

class AppRequestFactory extends RequestFactory
{
public function createRequest(string $method, $uri): \Cake\Http\Client\Request
{
return parent::createRequest($method, $uri);
}
}

class AppResponseFactory extends ResponseFactory
{
public function createResponse(int $code = 200, string $reasonPhrase = ''): \Cake\Http\Response
{
return parent::createResponse($code, $reasonPhrase);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php
declare(strict_types=1);

namespace App\Http;

use Cake\Http\Response;
use Psr\Http\Message\MessageInterface;

class AppResponse extends Response
{
public function withHeader(string $name, $value): static
{
return parent::withHeader($name, $value);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php
declare(strict_types=1);

namespace App\Http;

use Cake\Http\Client\Adapter\Stream;
use Cake\Http\Client\Response;

class AppStreamAdapter extends Stream
{
public function createResponses(array $headers, string|\Psr\Http\Message\StreamInterface $content): array
{
return parent::createResponses($headers, $content);
}

protected function buildResponse(array $headers, string|\Psr\Http\Message\StreamInterface $body): Response
{
return parent::buildResponse($headers, $body);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php
declare(strict_types=1);

namespace App\Http;

use Laminas\Diactoros\MessageTrait;
use Laminas\Diactoros\Response\RedirectResponse;
use Laminas\Diactoros\Stream;
use Laminas\Diactoros\UploadedFile;
use Laminas\Diactoros\Uri;

class DiactorosUsage
{
use \Cake\Http\MessageTrait;

public function build(): array
{
$uri = new \Cake\Http\Uri('https://example.com');
$stream = new \Cake\Http\Stream('php://memory', 'wb+');
$file = new \Cake\Http\UploadedFile($stream, 0, UPLOAD_ERR_OK, 'file.txt', 'text/plain');
$redirect = new \Cake\Http\Response\RedirectResponse($uri);

return [$uri, $stream, $file, $redirect];
}
}
Loading