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
66 changes: 33 additions & 33 deletions src/adapter/ServerRequestAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@
use function strtoupper;

/**
* Adapter for PSR-7 ServerRequest to Yii2 Request component.
* Adapter for PSR-7 ServerRequestInterface to Yii2 Request component.
*
* Provides a bridge between PSR-7 ServerRequestInterface and Yii2 Request component, enabling seamless integration
* of PSR-7 compatible HTTP stacks with Yii2 applications.
* Provides a bridge between PSR-7 {@see ServerRequestInterface} and Yii2 {@see Request} component, enabling seamless
* integration of PSR-7 compatible HTTP stacks with Yii2 Application.
*
* This adapter exposes methods to access request data such as body parameters, cookies, headers, HTTP method, query
* parameters, uploaded files, and URL information in a format compatible with Yii2 expectations.
Expand All @@ -32,14 +32,14 @@
* All returned data is immutable and designed for safe, read-only access.
*
* Key features.
* - Cookie extraction with optional Yii2-style validation.
* - Cookie extraction with optional Yii2 style validation.
* - Fluent, exception-safe API for request inspection.
* - HTTP method override support via body and headers.
* - Immutable, type-safe access to request data and metadata.
* - PSR-7 to Yii2 Request component for seamless interoperability.
* - Worker mode compatibility for modern PHP runtimes.
*
* @see ServerRequestInterface for PSR-7 request contract.
* @see ServerRequestInterface for PSR-7 ServerRequestInterface contract.
*
* @copyright Copyright (C) 2025 Terabytesoftw.
* @license https://opensource.org/license/bsd-3-clause BSD 3-Clause License.
Expand All @@ -51,20 +51,20 @@ final class ServerRequestAdapter
*
* @param ServerRequestInterface $psrRequest PSR-7 ServerRequestInterface instance to adapt.
*/
public function __construct(public ServerRequestInterface $psrRequest) {}
public function __construct(public readonly ServerRequestInterface $psrRequest) {}

/**
* Retrieves the request body parameters, excluding the HTTP method override parameter if present.
*
* Returns the parsed body parameters from the PSR-7 request, removing the specified method override parameter (such
* as '_method') if it exists.
* Returns the parsed body parameters from the PSR-7 ServerRequestInterface, removing the specified method override
* parameter (such as '_method') if it exists.
*
* This ensures that the method override value does not appear in the Yii2 Controller action parameters, maintaining
* compatibility with Yii2 Request component logic.
*
* - If the parsed body is not an array or the method parameter is not present, the original parsed body is
* returned.
* - If the parsed body is null, an empty array is returned for consistency.
* - If the parsed body is `null`, an empty array is returned for consistency.
*
* @param string $methodParam Name of the HTTP method override parameter to exclude (for example, '_method').
*
Expand Down Expand Up @@ -108,7 +108,7 @@ public function getBodyParams(string $methodParam): array|object
*
* @throws InvalidConfigException if the configuration is invalid or incomplete.
*
* @return array Array of {@see Cookie} objects extracted from the PSR-7 request.
* @return array Array of {@see Cookie} objects extracted from the PSR-7 ServerRequestInterface.
*
* @phpstan-return array<Cookie>
*
Expand All @@ -125,12 +125,12 @@ public function getCookies(bool $enableValidation, string $validationKey = ''):
}

/**
* Retrieves all HTTP headers from the PSR-7 request as a Yii2 {@see HeaderCollection} instance.
* Retrieves all HTTP headers from the PSR-7 ServerRequestInterface as a Yii2 {@see HeaderCollection} instance.
*
* Iterates over each header in the PSR-7 ServerRequest and adds it to a new {@see HeaderCollection} instance,
* concatenating multiple values with a comma and space, as expected by Yii2.
* Iterates over each header in the PSR-7 ServerRequestInterface and adds it to a new {@see HeaderCollection}
* instance, concatenating multiple values with a comma and space, as expected by Yii2.
*
* @return HeaderCollection Collection of HTTP headers from the PSR-7 request.
* @return HeaderCollection Collection of HTTP headers from the PSR-7 ServerRequestInterface.
*
* Usage example:
* ```php
Expand All @@ -156,7 +156,7 @@ public function getHeaders(): HeaderCollection
* 'X-Http-Method-Override' header.
*
* - If a valid override is found and is not one of 'GET', 'HEAD', or 'OPTIONS', it is returned in uppercase.
* - Otherwise, the original method from the PSR-7 request is returned.
* - Otherwise, the original method from the PSR-7 ServerRequestInterface is returned.
*
* This method enables support for HTTP method spoofing in environments where certain HTTP verbs are not natively
* supported by clients or proxies, ensuring compatibility with RESTful routing and Yii2 Controller actions.
Expand Down Expand Up @@ -200,7 +200,7 @@ public function getMethod(string $methodParam = '_method'): string
}

/**
* Retrieves the parsed body parameters from the PSR-7 request.
* Retrieves the parsed body parameters from the PSR-7 ServerRequestInterface.
*
* @return array|object|null Parsed body parameters as `array`, `object`, or `null` if not present.
*
Expand All @@ -217,7 +217,7 @@ public function getParsedBody(): array|object|null
}

/**
* Retrieves query parameters from the PSR-7 request.
* Retrieves query parameters from the PSR-7 ServerRequestInterface.
*
* Returns the query parameters as an associative array, providing direct access to all values present in the
* request URI.
Expand All @@ -237,7 +237,7 @@ public function getQueryParams(): array
}

/**
* Retrieves the raw query string from the PSR-7 request URI.
* Retrieves the raw query string from the PSR-7 ServerRequestInterface URI.
*
* @return string Raw query string from the request URI, or an empty string if not present.
*
Expand All @@ -252,7 +252,7 @@ public function getQueryString(): string
}

/**
* Retrieves the raw body content from the PSR-7 request stream.
* Retrieves the raw body content from the PSR-7 ServerRequestInterface stream.
*
* Returns the entire contents of the underlying stream as a string, rewinding first if the stream is seekable.
*
Expand All @@ -261,7 +261,7 @@ public function getQueryString(): string
*
* The stream is rewound before reading (if seekable) to ensure the full content is returned from the beginning.
*
* @return string Raw body content from the PSR-7 request stream.
* @return string Raw body content from the PSR-7 ServerRequestInterface stream.
*
* Usage example:
* ```php
Expand All @@ -282,7 +282,7 @@ public function getRawBody(): string
/**
* Retrieves the script URL from server parameters, supporting both SAPI and worker environments.
*
* Returns the value of 'SCRIPT_NAME' from server parameters for traditional SAPI-based PSR-7 applications.
* Returns the value of 'SCRIPT_NAME' from server parameters for traditional SAPI-based PSR-7 Application.
*
* For worker-based environments (such as RoadRunner, FrankenPHP), returns an empty string to prevent URL
* duplication, as routing is handled internally and no script file exists.
Expand All @@ -303,25 +303,25 @@ public function getScriptUrl(bool $workerMode): string
{
$serverParams = $this->psrRequest->getServerParams();

// for traditional 'PSR-7' apps where 'SCRIPT_NAME' is available
// for traditional PSR-7 apps where 'SCRIPT_NAME' is available
if ($workerMode === false && isset($serverParams['SCRIPT_NAME']) && is_string($serverParams['SCRIPT_NAME'])) {
return $serverParams['SCRIPT_NAME'];
}

// for 'PSR-7' workers (RoadRunner, FrankenPHP, etc.) where no script file exists
// for PSR-7 workers (RoadRunner, FrankenPHP, etc.) where no script file exists
// return empty to prevent URL duplication as routing is handled internally
return '';
}

/**
* Retrieves uploaded files from the PSR-7 request.
* Retrieves uploaded files from the PSR-7 ServerRequestInterface.
*
* Returns the uploaded files as provided by the underlying PSR-7 ServerRequest instance.
* Returns the uploaded files as provided by the underlying PSR-7 ServerRequestInterface instance.
*
* This method exposes the raw uploaded files array, enabling direct access to all files sent with the request
* in a format compatible with PSR-7 expectations.
*
* @return array Uploaded files from the PSR-7 request.
* @return array Uploaded files from the PSR-7 ServerRequestInterface.
*
* @phpstan-return array<mixed, mixed>
*
Expand Down Expand Up @@ -365,16 +365,16 @@ public function getUrl(): string
}

/**
* Extracts cookies from the PSR-7 request without validation.
* Extracts cookies from the PSR-7 ServerRequestInterface without validation.
*
* Iterates over the cookie parameters provided by the PSR-7 ServerRequest and creates a {@see Cookie} instance for
* Iterates over the cookie parameters provided by the PSR-7 ServerRequestInterface and creates a {@see Cookie} instance for
* each non-empty value.
*
* This method returns all cookies as-is, without applying Yii2 style validation or decoding.
*
* It is intended for use in cases where cookie integrity is not enforced by a validation key.
*
* @return array Array of {@see Cookie} objects extracted from the PSR-7 request.
* @return array Array of {@see Cookie} objects extracted from the PSR-7 ServerRequestInterface.
*
* @phpstan-return array<Cookie>
*/
Expand All @@ -399,15 +399,15 @@ private function getSimpleCookies(): array
}

/**
* Extracts and validates cookies from the PSR-7 request using Yii2 style validation.
* Extracts and validates cookies from the PSR-7 ServerRequestInterface using Yii2 style validation.
*
* Iterates over the cookie parameters provided by the PSR-7 ServerRequest and validates each value using the
* Iterates over the cookie parameters provided by the PSR-7 ServerRequestInterface and validates each value using the
* specified validation key.
*
* Only cookies that pass validation and decoding are included in the result.
*
* This ensures that only cookies with integrity verified by Yii2's security component are returned, supporting
* secure cookie extraction for Yii2 applications.
* This ensures that only cookies with integrity verified by Yii2 Security component are returned, supporting
* secure cookie extraction for Yii2 Application.
*
* @param string $validationKey Validation key used for Yii2 Cookie validation.
*
Expand Down
18 changes: 10 additions & 8 deletions src/emitter/SapiEmitter.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use yii\base\InvalidArgumentException;
use yii2\extensions\psrbridge\exception\{HeadersAlreadySentException, Message, OutputAlreadySentException};

use function array_map;
use function implode;
use function ob_get_length;
use function ob_get_level;
Expand All @@ -18,11 +19,12 @@
use function ucwords;

/**
* SAPI (Server API) Response Emitter.
* SAPI (Server API) ResponseInterface Emitter.
*
* This class is responsible for emitting PSR-7 Response objects to the output buffer using PHP's Server API. It handles
* the emission of headers, status line, and response body while supporting features like content range and buffered
* output.
* This class is responsible for emitting PSR-7 ResponseInterface objects to the output buffer using PHP's Server API.
*
* It handles the emission of headers, status line, and response body while supporting features like content range and
* buffered output.
*
* According to 'HTTP/1.1' specifications, certain status codes MUST NOT include a message body:
* - '1xx' (Informational): '100' Continue, '101' Switching Protocols, '102' Processing, '103' Early Hints.
Expand Down Expand Up @@ -64,7 +66,7 @@ public function __construct(private readonly int|null $bufferLength = null)
* ('100' - '103', '204', '205', '304') MUSTN'T include a message body. For these status codes, the body will not
* be emitted even if present in the response object. {@see HttpNoBodyStatus} for the complete list.
*
* @param ResponseInterface $response PSR-7 response instance.
* @param ResponseInterface $response PSR-7 ResponseInterface instance.
* @param bool $body Whether to emit the response with body (default: `true`).
*
* @throws HeadersAlreadySentException if HTTP headers have already been sent to the client.
Expand Down Expand Up @@ -97,7 +99,7 @@ public function emit(ResponseInterface $response, bool $body = true): void
* Handles the emission of the response body, supporting both buffered and unbuffered output, also supports content
* range responses for partial content delivery.
*
* @param ResponseInterface $response PSR-7 response instance.
* @param ResponseInterface $response PSR-7 ResponseInterface instance.
*/
private function emitBody(ResponseInterface $response): void
{
Expand Down Expand Up @@ -165,7 +167,7 @@ private function emitBodyRange(StreamInterface $body, int $first, int $last): vo
* Iterates through the response headers and emits each one. Special handling is provided for the 'Set-Cookie'
* header to ensure multiple cookies are handled correctly.
*
* @param ResponseInterface $response PSR-7 response instance.
* @param ResponseInterface $response PSR-7 ResponseInterface instance.
*/
private function emitHeaders(ResponseInterface $response): void
{
Expand All @@ -187,7 +189,7 @@ private function emitHeaders(ResponseInterface $response): void
*
* Emits the HTTP protocol version, status code, and reason phrase.
*
* @param ResponseInterface $response PSR-7 response instance.
* @param ResponseInterface $response PSR-7 ResponseInterface instance.
*/
private function emitStatusLine(ResponseInterface $response): void
{
Expand Down
Loading