Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
874f7eb
Introduce `UploadedFile` class bridge implementation with tests.
terabytesoftw Aug 28, 2025
348810a
Apply fixes from StyleCI
terabytesoftw Aug 28, 2025
bee44e9
fix(http): Remove unnecessary PHPStan ignore comment from UploadedFil…
terabytesoftw Aug 28, 2025
dbd6bcd
refactor(http): Remove unused PSR-7 adapter reference in UploadedFile…
terabytesoftw Aug 28, 2025
196da6c
refactor(http): Remove UploadedFile reset method and update lifecycle…
terabytesoftw Aug 28, 2025
3ad793e
test(http): Add tests for UploadedFile handling in stateless applicat…
terabytesoftw Aug 28, 2025
d73bbab
Apply fixes from StyleCI
terabytesoftw Aug 28, 2025
38fc95c
feat(http): Add reset method to `UploadedFile` for clearing internal …
terabytesoftw Aug 28, 2025
015bea3
Merge branch 'feature-9' of github-principal:yii2-extensions/psr-brid…
terabytesoftw Aug 28, 2025
a916a1e
feat(http): Enhance UploadedFile handling for multiple file uploads a…
terabytesoftw Aug 28, 2025
08c8146
feat(http): Enhance reset method to clear PSR-7 adapter state and upl…
terabytesoftw Aug 28, 2025
a174e4c
feat(http): Update UploadedFile and Request classes to improve resour…
terabytesoftw Aug 28, 2025
fe97d0c
test(http): Add test for reset method to verify closure of detached r…
terabytesoftw Aug 28, 2025
d7e7f98
feat(http): Enhance `UploadedFile` conversion to handle upload errors…
terabytesoftw Aug 28, 2025
6f50895
test(http): Ensure UploadedFile `reset()` method is called in `setUp`…
terabytesoftw Aug 28, 2025
6c97da9
fix(http): Simplify resource closure logic in closeResources method.
terabytesoftw Aug 28, 2025
da822e2
fix(http): Ensure resources are closed before resetting UploadedFile …
terabytesoftw Aug 28, 2025
82326d7
Apply fixes from StyleCI
terabytesoftw Aug 28, 2025
f94a1d1
refactor(http): Remove unused `psr7FilesLoaded` flag and update relat…
terabytesoftw Aug 28, 2025
37f5837
test(http): Add test for UploadedFile handling `null` size to default…
terabytesoftw Aug 28, 2025
e737812
fix(http): Cast UploadedFile size to integer for consistency.
terabytesoftw Aug 28, 2025
4c57293
test(http): Add test for handling legacy file size as an array in Upl…
terabytesoftw Aug 29, 2025
2cac0c7
fix(http): Reset UploadedFile state in `StatelessApplication` to prev…
terabytesoftw Aug 29, 2025
ed5b095
test(http): Add tests for `UploadedFile` handling with complex model …
terabytesoftw Aug 29, 2025
c75094a
fix(http): Update `UploadedFileModel` and `ComplexUploadedFileModel` …
terabytesoftw Aug 29, 2025
344152c
test(http): Add tests for handling multiple files and error scenarios…
terabytesoftw Aug 29, 2025
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: 1 addition & 1 deletion src/adapter/ServerRequestAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ public function getServerParams(): array
*
* @return array Uploaded files from the PSR-7 ServerRequestInterface.
*
* @phpstan-return array<mixed, mixed>
* @phpstan-return array<array-key, mixed>
*
* Usage example:
* ```php
Expand Down
8 changes: 5 additions & 3 deletions src/http/Request.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
use Psr\Http\Message\{ServerRequestInterface, UploadedFileInterface};
use Yii;
use yii\base\InvalidConfigException;
use yii\web\{CookieCollection, HeaderCollection, NotFoundHttpException, UploadedFile};
use yii\web\{CookieCollection, HeaderCollection, NotFoundHttpException};
use yii2\extensions\psrbridge\adapter\ServerRequestAdapter;
use yii2\extensions\psrbridge\exception\Message;

Expand Down Expand Up @@ -777,8 +777,7 @@ public function resolve(): array
* This method injects a stateless application start time header (`statelessAppStartTime`) into the request for
* tracing and debugging purposes.
*
* Once set, all request operations will use the PSR-7 ServerRequestInterface via the adapter until {@see reset()}
* is called.
* Once set, all request operations will use the PSR-7 ServerRequestInterface via the adapter until is called.
*
* @param ServerRequestInterface $request PSR-7 ServerRequestInterface instance to bridge.
*
Expand All @@ -793,6 +792,8 @@ public function setPsr7Request(ServerRequestInterface $request): void
$this->adapter = new ServerRequestAdapter(
$request->withHeader('statelessAppStartTime', (string) microtime(true)),
);

UploadedFile::setPsr7Adapter($this->adapter);
}

/**
Expand Down Expand Up @@ -851,6 +852,7 @@ private function createUploadedFile(UploadedFileInterface $psrFile): UploadedFil
'size' => $psrFile->getSize(),
'tempName' => $psrFile->getStream()->getMetadata('uri') ?? '',
'type' => $psrFile->getClientMediaType() ?? '',
'tempResource' => $psrFile->getStream()->detach(),
],
);
}
Expand Down
11 changes: 6 additions & 5 deletions src/http/StatelessApplication.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
use Throwable;
use yii\base\{Event, InvalidConfigException};
use yii\di\{Container, NotInstantiableException};
use yii\web\{Application, UploadedFile};
use yii\web\Application;

use function array_merge;
use function array_reverse;
Expand Down Expand Up @@ -387,7 +387,7 @@
* Resets the StatelessApplication state and prepares the Yii2 environment for handling a PSR-7 request.
*
* Performs a full reinitialization of the application state, including event tracking, error handler cleanup,
* request adapter reset, session management, and PSR-7 request injection.
* request adapter reset, session management, uploaded file state reset, and PSR-7 request injection.
*
* This method ensures that the application is ready to process a new stateless request in worker or SAPI
* environments, maintaining strict type safety and compatibility with Yii2 core components.
Expand All @@ -402,6 +402,9 @@
{
$this->startEventTracking();

// reset UploadedFile static state to avoid cross-request contamination
UploadedFile::reset();

// parent constructor is called because StatelessApplication uses a custom initialization pattern
// @phpstan-ignore-next-line
parent::__construct($this->config);
Expand Down Expand Up @@ -441,7 +444,7 @@
/**
* Finalizes the application lifecycle and converts the Yii2 Response to a PSR-7 ResponseInterface.
*
* Cleans up registered events, resets uploaded files, flushes the logger.
* Cleans up registered events, and flushes the logger.
*
* This method ensures that all application resources are released and the response is converted to a PSR-7
* ResponseInterface for interoperability with PSR-7 compatible HTTP stacks.
Expand All @@ -457,10 +460,8 @@
{
$this->cleanupEvents();

UploadedFile::reset();

if ($this->flushLogger) {
$this->getLog()->getLogger()->flush(true);

Check warning on line 464 in src/http/StatelessApplication.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.3-ubuntu-latest

Escaped Mutant for Mutator "MethodCallRemoval": @@ @@ { $this->cleanupEvents(); if ($this->flushLogger) { - $this->getLog()->getLogger()->flush(true); + } return $response->getPsr7Response(); }

Check warning on line 464 in src/http/StatelessApplication.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.3-ubuntu-latest

Escaped Mutant for Mutator "TrueValue": @@ @@ { $this->cleanupEvents(); if ($this->flushLogger) { - $this->getLog()->getLogger()->flush(true); + $this->getLog()->getLogger()->flush(false); } return $response->getPsr7Response(); }

Check warning on line 464 in src/http/StatelessApplication.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.3-ubuntu-latest

Escaped Mutant for Mutator "MethodCallRemoval": @@ @@ { $this->cleanupEvents(); if ($this->flushLogger) { - $this->getLog()->getLogger()->flush(true); + } return $response->getPsr7Response(); }

Check warning on line 464 in src/http/StatelessApplication.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.3-ubuntu-latest

Escaped Mutant for Mutator "TrueValue": @@ @@ { $this->cleanupEvents(); if ($this->flushLogger) { - $this->getLog()->getLogger()->flush(true); + $this->getLog()->getLogger()->flush(false); } return $response->getPsr7Response(); }
}

return $response->getPsr7Response();
Expand All @@ -482,17 +483,17 @@
*/
private function cleanupEvents(): void
{
Event::off('*', '*', $this->eventHandler);

Check warning on line 486 in src/http/StatelessApplication.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.3-ubuntu-latest

Escaped Mutant for Mutator "MethodCallRemoval": @@ @@ */ private function cleanupEvents(): void { - Event::off('*', '*', $this->eventHandler); + foreach (array_reverse($this->registeredEvents) as $event) { if ($event->sender !== null && method_exists($event->sender, 'off')) { $event->sender->off($event->name);

Check warning on line 486 in src/http/StatelessApplication.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.3-ubuntu-latest

Escaped Mutant for Mutator "MethodCallRemoval": @@ @@ */ private function cleanupEvents(): void { - Event::off('*', '*', $this->eventHandler); + foreach (array_reverse($this->registeredEvents) as $event) { if ($event->sender !== null && method_exists($event->sender, 'off')) { $event->sender->off($event->name);

foreach (array_reverse($this->registeredEvents) as $event) {

Check warning on line 488 in src/http/StatelessApplication.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.3-ubuntu-latest

Escaped Mutant for Mutator "UnwrapArrayReverse": @@ @@ private function cleanupEvents(): void { Event::off('*', '*', $this->eventHandler); - foreach (array_reverse($this->registeredEvents) as $event) { + foreach ($this->registeredEvents as $event) { if ($event->sender !== null && method_exists($event->sender, 'off')) { $event->sender->off($event->name); }

Check warning on line 488 in src/http/StatelessApplication.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.3-ubuntu-latest

Escaped Mutant for Mutator "UnwrapArrayReverse": @@ @@ private function cleanupEvents(): void { Event::off('*', '*', $this->eventHandler); - foreach (array_reverse($this->registeredEvents) as $event) { + foreach ($this->registeredEvents as $event) { if ($event->sender !== null && method_exists($event->sender, 'off')) { $event->sender->off($event->name); }
if ($event->sender !== null && method_exists($event->sender, 'off')) {
$event->sender->off($event->name);

Check warning on line 490 in src/http/StatelessApplication.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.3-ubuntu-latest

Escaped Mutant for Mutator "MethodCallRemoval": @@ @@ Event::off('*', '*', $this->eventHandler); foreach (array_reverse($this->registeredEvents) as $event) { if ($event->sender !== null && method_exists($event->sender, 'off')) { - $event->sender->off($event->name); + } } $this->registeredEvents = [];

Check warning on line 490 in src/http/StatelessApplication.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.3-ubuntu-latest

Escaped Mutant for Mutator "MethodCallRemoval": @@ @@ Event::off('*', '*', $this->eventHandler); foreach (array_reverse($this->registeredEvents) as $event) { if ($event->sender !== null && method_exists($event->sender, 'off')) { - $event->sender->off($event->name); + } } $this->registeredEvents = [];
}
}

$this->registeredEvents = [];

Event::offAll();

Check warning on line 496 in src/http/StatelessApplication.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.3-ubuntu-latest

Escaped Mutant for Mutator "MethodCallRemoval": @@ @@ } } $this->registeredEvents = []; - Event::offAll(); + } /** * Handles application errors and returns a Yii2 Response instance.

Check warning on line 496 in src/http/StatelessApplication.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.3-ubuntu-latest

Escaped Mutant for Mutator "MethodCallRemoval": @@ @@ } } $this->registeredEvents = []; - Event::offAll(); + } /** * Handles application errors and returns a Yii2 Response instance.
}

/**
Expand All @@ -512,7 +513,7 @@
{
$response = $this->errorHandler->handleException($exception);

$this->trigger(self::EVENT_AFTER_REQUEST);

Check warning on line 516 in src/http/StatelessApplication.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.3-ubuntu-latest

Escaped Mutant for Mutator "MethodCallRemoval": @@ @@ private function handleError(Throwable $exception): Response { $response = $this->errorHandler->handleException($exception); - $this->trigger(self::EVENT_AFTER_REQUEST); + $this->state = self::STATE_END; return $response; }

Check warning on line 516 in src/http/StatelessApplication.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.3-ubuntu-latest

Escaped Mutant for Mutator "MethodCallRemoval": @@ @@ private function handleError(Throwable $exception): Response { $response = $this->errorHandler->handleException($exception); - $this->trigger(self::EVENT_AFTER_REQUEST); + $this->state = self::STATE_END; return $response; }

$this->state = self::STATE_END;

Expand Down Expand Up @@ -547,6 +548,6 @@
*/
private function startEventTracking(): void
{
Event::on('*', '*', $this->eventHandler);

Check warning on line 551 in src/http/StatelessApplication.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.3-ubuntu-latest

Escaped Mutant for Mutator "MethodCallRemoval": @@ @@ */ private function startEventTracking(): void { - Event::on('*', '*', $this->eventHandler); + } }

Check warning on line 551 in src/http/StatelessApplication.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.3-ubuntu-latest

Escaped Mutant for Mutator "MethodCallRemoval": @@ @@ */ private function startEventTracking(): void { - Event::on('*', '*', $this->eventHandler); + } }
}
}
Loading
Loading