-
-
Notifications
You must be signed in to change notification settings - Fork 25
Add Request/Response Hooks & Events System #70
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
✅ Deploy Preview for fetch-php canceled.
|
Dependency Review✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.Scanned FilesNone |
- Create FetchEvent base class and event subclasses (RequestEvent, ResponseEvent, ErrorEvent, RetryEvent, TimeoutEvent, RedirectEvent) - Create EventDispatcher and EventDispatcherInterface - Create SupportsHooks trait for hook registration methods - Integrate event dispatching into ClientHandler request lifecycle - Add comprehensive unit tests for the event system Co-authored-by: Thavarshan <10804999+Thavarshan@users.noreply.github.com>
Co-authored-by: Thavarshan <10804999+Thavarshan@users.noreply.github.com>
…tant Co-authored-by: Thavarshan <10804999+Thavarshan@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR adds a comprehensive event-driven system for HTTP request/response lifecycle management, enabling observability, metrics collection, and custom logic injection through hooks and events.
Key changes:
- Introduces 7 event classes (
RequestEvent,ResponseEvent,ErrorEvent,RetryEvent,TimeoutEvent,RedirectEvent, plus baseFetchEvent) - Implements
EventDispatcherwith priority-based listener management and error isolation - Adds
SupportsHookstrait providing fluent API methods (onRequest(),onResponse(), etc.) with shorthand hook name support - Integrates event dispatching into existing request/response and retry flows
Reviewed changes
Copilot reviewed 18 out of 18 changed files in this pull request and generated 13 comments.
Show a summary per file
| File | Description |
|---|---|
src/Fetch/Events/FetchEvent.php |
Base abstract event class with common properties (request, correlationId, timestamp, context) |
src/Fetch/Events/RequestEvent.php |
Event dispatched before sending HTTP requests with options |
src/Fetch/Events/ResponseEvent.php |
Event dispatched after receiving responses with duration and latency |
src/Fetch/Events/ErrorEvent.php |
Event for error handling with retryability detection |
src/Fetch/Events/RetryEvent.php |
Event dispatched when retrying requests with attempt tracking |
src/Fetch/Events/TimeoutEvent.php |
Event for request timeouts with elapsed time tracking |
src/Fetch/Events/RedirectEvent.php |
Event for HTTP redirects with location and count tracking |
src/Fetch/Events/EventDispatcherInterface.php |
Interface defining event dispatcher contract |
src/Fetch/Events/EventDispatcher.php |
Priority-based dispatcher implementation with error isolation and listener caching |
src/Fetch/Concerns/SupportsHooks.php |
Trait providing fluent hook registration API with shorthand mappings |
src/Fetch/Interfaces/ClientHandler.php |
Extended interface with hook-related method signatures |
src/Fetch/Http/ClientHandler.php |
Added SupportsHooks trait usage |
src/Fetch/Concerns/PerformsHttpRequests.php |
Integrated RequestEvent and ResponseEvent dispatching into request flow |
src/Fetch/Concerns/ManagesRetries.php |
Added retryRequestWithEvents method with ErrorEvent and RetryEvent dispatching |
tests/Unit/Events/FetchEventsTest.php |
Comprehensive tests for all event classes (208 lines) |
tests/Unit/Events/EventDispatcherTest.php |
Tests for dispatcher functionality including priority ordering and error handling |
tests/Unit/SupportsHooksTest.php |
Tests for hooks trait including fluent API and shorthand name normalization |
tests/Unit/ManagesDebugAndProfilingTest.php |
Removed unused import |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| $correlationId = method_exists($handler, 'generateCorrelationId') | ||
| ? $handler->generateCorrelationId() | ||
| : bin2hex(random_bytes(16)); |
Copilot
AI
Nov 28, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] The correlation ID generation on lines 188-190 uses method_exists($handler, 'generateCorrelationId') check before calling, but generateCorrelationId() is defined in the SupportsHooks trait which is used by ClientHandler. This dynamic check is unnecessary since the trait is already in use and will always be available. Consider removing the method_exists check and directly calling $handler->generateCorrelationId(), or if this code needs to work with handlers that don't use the trait, document why the check is necessary.
| $correlationId = method_exists($handler, 'generateCorrelationId') | |
| ? $handler->generateCorrelationId() | |
| : bin2hex(random_bytes(16)); | |
| $correlationId = $handler->generateCorrelationId(); |
| $psrRequest = new GuzzleRequest($methodStr, $fullUri, $guzzleOptions['headers'] ?? []); | ||
| $handler->dispatchEvent(new RequestEvent( | ||
| $psrRequest, | ||
| $correlationId, | ||
| $startTime, | ||
| [], | ||
| $guzzleOptions | ||
| )); | ||
| } |
Copilot
AI
Nov 28, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] The PSR-7 Request object is created twice in the same method:
- Line 199 for dispatching the RequestEvent
- Line 381 (in the original code) and line 426 (in the retry logic) for retry handling
Creating the PSR request once at line 381 and reusing it at line 199 would be more efficient and ensure both the event and the retry logic use the exact same request object. Currently, the request object used in events might have different headers than the one used in retry logic if headers are modified between these points.
| protected static array $hookNameMappings = [ | ||
| 'before_send' => 'request.sending', | ||
| 'after_response' => 'response.received', | ||
| 'on_error' => 'error.occurred', | ||
| 'on_retry' => 'request.retrying', | ||
| 'on_timeout' => 'request.timeout', | ||
| 'on_redirect' => 'request.redirecting', | ||
| ]; |
Copilot
AI
Nov 28, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] The $hookNameMappings array is declared as static (line 26), which means it's shared across all instances using this trait. While this is likely intentional for memory efficiency since the mappings are constant, consider documenting this design decision or making it a const array instead if PHP version allows (PHP 8.2+). If it needs to remain mutable for extensibility, document that subclasses can modify the static mappings, but be aware this would affect all instances globally.
| */ | ||
| public function isLastAttempt(): bool | ||
| { | ||
| return $this->attempt >= $this->maxAttempts; |
Copilot
AI
Nov 28, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The isLastAttempt() method uses >= comparison (line 85), which may produce incorrect results depending on how $attempt and $maxAttempts are counted. According to the PHPDoc (line 20-21), $attempt is "1-based" and $maxAttempts is "the maximum number of attempts allowed". If:
$maxAttempts = 3(meaning 3 total attempts allowed)$attempt = 3(the 3rd attempt)
ThenisLastAttempt()returnstrue✓
However, if the retry event is only dispatched BEFORE retrying (not on the last attempt), then $attempt would never equal $maxAttempts because the last attempt isn't a "retry". The naming and logic need clarification:
- Is
$maxAttemptsthe number of retries or total attempts? - Is a retry event dispatched before the final attempt or only for actual retries?
This needs to be consistent with the usage in ManagesRetries::retryRequestWithEvents where it's called with $attempt + 1 and $attempts on line 346-350.
| return $this->attempt >= $this->maxAttempts; | |
| return $this->attempt === $this->maxAttempts; |
| * @param ResponseInterface $response The HTTP response received | ||
| * @param string $correlationId Unique identifier for correlating related events | ||
| * @param float $timestamp Unix timestamp with microseconds when the event occurred | ||
| * @param float $duration Time in seconds the request took to complete | ||
| * @param array<string, mixed> $context Additional contextual data | ||
| */ | ||
| public function __construct( | ||
| RequestInterface $request, | ||
| protected ResponseInterface $response, | ||
| string $correlationId, | ||
| float $timestamp, |
Copilot
AI
Nov 28, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] The parameter order in the ResponseEvent constructor is inconsistent with other event classes. The $response parameter comes before $correlationId, while in ErrorEvent and RedirectEvent, the response-like parameters come after the basic parameters but before correlation ID. Consider reordering parameters to follow the pattern: $request, $correlationId, $timestamp, then additional specific parameters like $response and $duration, for better consistency across event classes.
| * @param ResponseInterface $response The HTTP response received | |
| * @param string $correlationId Unique identifier for correlating related events | |
| * @param float $timestamp Unix timestamp with microseconds when the event occurred | |
| * @param float $duration Time in seconds the request took to complete | |
| * @param array<string, mixed> $context Additional contextual data | |
| */ | |
| public function __construct( | |
| RequestInterface $request, | |
| protected ResponseInterface $response, | |
| string $correlationId, | |
| float $timestamp, | |
| * @param string $correlationId Unique identifier for correlating related events | |
| * @param float $timestamp Unix timestamp with microseconds when the event occurred | |
| * @param ResponseInterface $response The HTTP response received | |
| * @param float $duration Time in seconds the request took to complete | |
| * @param array<string, mixed> $context Additional contextual data | |
| */ | |
| public function __construct( | |
| RequestInterface $request, | |
| string $correlationId, | |
| float $timestamp, | |
| protected ResponseInterface $response, |
| /** | ||
| * Register multiple hooks at once. | ||
| * | ||
| * @param array<string, callable> $hooks Array of hook name => callback pairs |
Copilot
AI
Nov 28, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The PHPDoc for the hooks method states "Array of hook name => callback pairs" but doesn't document that shorthand hook names (like before_send, after_response) are supported alongside full event names (like request.sending, response.received). Consider documenting the supported shorthand names in the PHPDoc or referencing the $hookNameMappings in SupportsHooks trait.
| * @param array<string, callable> $hooks Array of hook name => callback pairs | |
| * @param array<string, callable> $hooks Array of hook name => callback pairs. Hook names may be either full event names (e.g., "request.sending", "response.received") or supported shorthand names (e.g., "before_send", "after_response"). See the implementation or the SupportsHooks trait for the list of supported shorthand names. |
| public function test_multiple_listeners_are_called() | ||
| { | ||
| $order = []; | ||
|
|
||
| $this->dispatcher->addListener('response.received', function () use (&$order) { | ||
| $order[] = 'first'; | ||
| }); | ||
|
|
||
| $this->dispatcher->addListener('response.received', function () use (&$order) { | ||
| $order[] = 'second'; | ||
| }); | ||
|
|
||
| $request = new Request('GET', 'https://example.com/api'); | ||
| $event = new RequestEvent($request, 'corr-123', microtime(true)); | ||
| // Set the event name by using a real RequestEvent (which has 'request.sending') | ||
| // We need to test with an event that matches the listener | ||
| $this->dispatcher->dispatch($event); | ||
|
|
||
| // Nothing was called because we registered for 'response.received' but dispatched 'request.sending' | ||
| $this->assertEmpty($order); | ||
|
|
||
| // Now let's test properly | ||
| $this->dispatcher->clearListeners(); | ||
|
|
||
| $this->dispatcher->addListener('request.sending', function () use (&$order) { | ||
| $order[] = 'first'; | ||
| }); | ||
|
|
||
| $this->dispatcher->addListener('request.sending', function () use (&$order) { | ||
| $order[] = 'second'; | ||
| }); | ||
|
|
||
| $this->dispatcher->dispatch($event); | ||
|
|
||
| $this->assertEquals(['first', 'second'], $order); | ||
| } |
Copilot
AI
Nov 28, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] The test test_multiple_listeners_are_called has an unusual structure with a deliberate mismatch test (lines 59-74) followed by clearing and retesting (lines 77-89). While this approach works, it's confusing because:
- It tests a negative case (event type mismatch) that's not clear from the test name
- It then clears and tests the actual intended behavior
Consider either:
- Splitting this into two separate tests:
test_listeners_not_called_for_different_eventandtest_multiple_listeners_called_in_order - Or removing the mismatch test and only testing the positive case with the correct event type from the start
This would make the test clearer and more focused.
| if ($eventName === null) { | ||
| // Check if any listeners are registered | ||
| $events = [ | ||
| 'request.sending', | ||
| 'response.received', | ||
| 'error.occurred', | ||
| 'request.retrying', | ||
| 'request.timeout', | ||
| 'request.redirecting', | ||
| ]; | ||
|
|
||
| foreach ($events as $event) { | ||
| if ($this->eventDispatcher->hasListeners($event)) { | ||
| return true; | ||
| } | ||
| } | ||
|
|
||
| return false; | ||
| } |
Copilot
AI
Nov 28, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The hasHooks method with $eventName = null (line 186) iterates through a hardcoded list of event names to check if any listeners exist. However, this doesn't account for custom events registered via the when() method. If a user registers a custom event like custom.event, hasHooks() will return false even though hooks are registered. Consider either:
- Checking if the eventDispatcher has ANY listeners at all (e.g., checking if the
$listenersarray is non-empty) - Documenting that
hasHooks()only checks for standard events, not custom ones - Making the event list dynamic or extensible
| for ($attempt = 0; $attempt <= $attempts; $attempt++) { | ||
| try { | ||
| // Execute the request | ||
| return $request(); | ||
| } catch (Throwable $e) { | ||
| // Collect exception for later | ||
| $exceptions[] = $e; | ||
|
|
||
| // Get response from exception if available | ||
| $response = null; | ||
| if ($e instanceof FetchRequestException && $e->getResponse()) { | ||
| $response = $e->getResponse(); | ||
| } elseif (method_exists($e, 'getResponse')) { | ||
| $response = $e->getResponse(); | ||
| } | ||
|
|
||
| // If this was the last attempt, dispatch error event and break | ||
| if ($attempt === $attempts) { | ||
| // Dispatch error event | ||
| if (method_exists($this, 'dispatchEvent')) { | ||
| $this->dispatchEvent(new ErrorEvent( | ||
| $psrRequest, | ||
| $e, | ||
| $correlationId, | ||
| microtime(true), | ||
| $attempt + 1, | ||
| $response | ||
| )); | ||
| } | ||
| break; | ||
| } | ||
|
|
||
| // Only retry on retryable errors | ||
| if (! $this->isRetryableError($e)) { | ||
| // Dispatch error event for non-retryable errors | ||
| if (method_exists($this, 'dispatchEvent')) { | ||
| $this->dispatchEvent(new ErrorEvent( | ||
| $psrRequest, | ||
| $e, | ||
| $correlationId, | ||
| microtime(true), | ||
| $attempt + 1, | ||
| $response | ||
| )); | ||
| } | ||
| throw $e; | ||
| } | ||
|
|
||
| // Log the retry for debugging purposes | ||
| if (method_exists($this, 'logRetry')) { | ||
| $this->logRetry($attempt + 1, $attempts, $e); | ||
| } | ||
|
|
||
| // Calculate delay with exponential backoff and jitter | ||
| $currentDelay = $this->calculateBackoffDelay($delay, $attempt); | ||
|
|
||
| // Dispatch retry event | ||
| if (method_exists($this, 'dispatchEvent')) { | ||
| $this->dispatchEvent(new RetryEvent( | ||
| $psrRequest, | ||
| $e, | ||
| $attempt + 1, | ||
| $attempts, | ||
| $currentDelay, | ||
| $correlationId, | ||
| microtime(true) | ||
| )); | ||
| } |
Copilot
AI
Nov 28, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the retryRequestWithEvents method, the attempt number passed to events uses $attempt + 1 to make it 1-based (lines 313, 329), but this is inconsistent because the loop variable $attempt already represents the actual attempt index (0 for first attempt). This means:
- First attempt:
$attempt = 0, events report attempt1✓ - Second attempt:
$attempt = 1, events report attempt2✓ - Last attempt:
$attempt = $attempts, events report attempt$attempts + 1✗
When $attempts = 3 (meaning max 3 retries, 4 total attempts), the final error event would report attempt 4 instead of 3. The loop condition $attempt <= $attempts combined with $attempt + 1 causes an off-by-one error in the reported attempt numbers.
| if ($lastException instanceof FetchRequestException && $lastException->getResponse()) { | ||
| $statusCode = $lastException->getResponse()->getStatusCode(); | ||
| throw new RuntimeException( | ||
| sprintf( | ||
| 'Request failed after %d attempts with status code %d: %s', | ||
| $attempts + 1, | ||
| $statusCode, | ||
| $lastException->getMessage() | ||
| ), | ||
| $statusCode, | ||
| $lastException | ||
| ); | ||
| } |
Copilot
AI
Nov 28, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The error message on line 368 uses $attempts + 1 in the message "Request failed after %d attempts", but $attempts represents the number of retries, not total attempts. This should be either:
- "Request failed after %d retries" using
$attempts - "Request failed after %d attempts" using
$attempts + 1
However, given that the loop already runs from 0 to $attempts (inclusive), this gives $attempts + 1 total executions. The message construction is misleading about whether it's counting retries or total attempts.
Pull Request
Description
What does this PR do?
Adds a comprehensive event-driven system with hooks for request/response lifecycle events, enabling observability, metrics collection, debugging, and custom logic injection.
Fixes #(issue_number)
Type of Change
Changes Made
src/Fetch/Events/):FetchEvent(base),RequestEvent,ResponseEvent,ErrorEvent,RetryEvent,TimeoutEvent,RedirectEventonRequest(),onResponse(),onError(),onRetry(),onTimeout(),onRedirect(),when(),hooks())PerformsHttpRequestsandManagesRetriesClientHandlerinterface extended with hook methodsTesting
How has this been tested?
Test Environment:
Documentation
Checklist
Additional Notes
Event names follow
category.actionpattern:request.sending,response.received,error.occurred,request.retrying,request.timeout,request.redirecting.Hook shorthand mappings:
before_send→request.sending,after_response→response.received,on_error→error.occurred, etc.Warning
Firewall rules blocked me from connecting to one or more addresses (expand for details)
I tried to connect to the following addresses, but was blocked by firewall rules:
https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/ad732c2e9299c9743f9c55ae53cc0e7642ab1155/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/SyEDBv /usr/bin/composer install --no-interaction --prefer-dist(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/0ca86845ce43291e8f5692c7356fccf3bcf02bf4/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/SyEDBv /usr/bin/composer install --no-interaction --prefer-dist(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/Thavarshan/matrix/zipball/17077b50c6ab2689847561752fae9940e49c10e8/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/SyEDBv /usr/bin/composer install --no-interaction --prefer-dist(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/clue/reactphp-ndjson/zipball/392dc165fce93b5bb5c637b67e59619223c931b0/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/SyEDBv /usr/bin/composer install --no-interaction --prefer-dist(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/composer/pcre/zipball/b2bed4734f0cc156ee1fe9c0da2550420d99a21e/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/SyEDBv /usr/bin/composer install --no-interaction --prefer-dist(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/composer/semver/zipball/198166618906cb2de69b95d7d47e5fa8aa1b2b95/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/SyEDBv /usr/bin/composer install --no-interaction --prefer-dist(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/composer/xdebug-handler/zipball/6c1925561632e83d60a44492e0b344cf48ab85ef/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/SyEDBv /usr/bin/composer install --no-interaction --prefer-dist(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/guzzle/guzzle/zipball/b51ac707cfa420b7bfd4e4d5e510ba8008e822b4/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/SyEDBv /usr/bin/composer install --no-interaction --prefer-dist(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/guzzle/promises/zipball/481557b130ef3790cf82b713667b43030dc9c957/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/SyEDBv /usr/bin/composer install --no-interaction --prefer-dist(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/guzzle/psr7/zipball/21dc724a0583619cd1652f673303492272778051/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/SyEDBv /usr/bin/composer install --no-interaction --prefer-dist(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/hamcrest/hamcrest-php/zipball/f8b1c0173b22fa6ec77a81fe63e5b01eba7e6487/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/SyEDBv /usr/bin/composer install --no-interaction --prefer-dist(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/igorw/evenement/zipball/0a16b0d71ab13284339abb99d9d2bd813640efbc/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/SyEDBv /usr/bin/composer install --no-interaction --prefer-dist(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/laravel/pint/zipball/69dcca060ecb15e4b564af63d1f642c81a241d6f/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/SyEDBv /usr/bin/composer install --no-interaction --prefer-dist(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/mockery/mockery/zipball/1f4efdd7d3beafe9807b08156dfcb176d18f1699/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/SyEDBv /usr/bin/composer install --no-interaction --prefer-dist(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/myclabs/DeepCopy/zipball/07d290f0c47959fd5eed98c95ee5602db07e0b6a/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/SyEDBv /usr/bin/composer install --no-interaction --prefer-dist(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/nikic/PHP-Parser/zipball/3a454ca033b9e06b63282ce19562e892747449bb/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/SyEDBv /usr/bin/composer install --no-interaction --prefer-dist(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/SyEDBv /usr/bin/composer install --no-interaction --prefer-dist(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/SyEDBv /usr/bin/composer install --no-interaction --prefer-dist(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/SyEDBv /usr/bin/composer install --no-interaction --prefer-dist(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/SyEDBv /usr/bin/composer install --no-interaction --prefer-dist(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/SyEDBv /usr/bin/composer install --no-interaction --prefer-dist(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/phpstan/phpstan/zipball/2770dcdf5078d0b0d53f94317e06affe88419aa8/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/SyEDBv /usr/bin/composer install --no-interaction --prefer-dist(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/F0ZQOl /usr/bin/composer install --prefer-source --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/SyEDBv /usr/bin/composer install --no-interaction --prefer-dist(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/reactphp/cache/zipball/d47c472b64aa5608225f47965a484b75c7817d5b/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/SyEDBv /usr/bin/composer install --no-interaction --prefer-dist(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/reactphp/child-process/zipball/1721e2b93d89b745664353b9cfc8f155ba8a6159/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/SyEDBv /usr/bin/composer install --no-interaction --prefer-dist(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/reactphp/dns/zipball/7562c05391f42701c1fccf189c8225fece1cd7c3/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/SyEDBv /usr/bin/composer install --no-interaction --prefer-dist(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/reactphp/event-loop/zipball/ba276bda6083df7e0050fd9b33f66ad7a4ac747a/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/SyEDBv /usr/bin/composer install --no-interaction --prefer-dist(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/reactphp/promise/zipball/23444f53a813a3296c1368bb104793ce8d88f04a/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/SyEDBv /usr/bin/composer install --no-interaction --prefer-dist(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/reactphp/socket/zipball/ef5b17b81f6f60504c539313f94f2d826c5faa08/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/SyEDBv /usr/bin/composer install --no-interaction --prefer-dist(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/reactphp/stream/zipball/1e5b0acb8fe55143b5b426817155190eb6f5b18d/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/SyEDBv /usr/bin/composer install --no-interaction --prefer-dist(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/15c5dd40dc4f38794d383bb95465193f5e0ae180/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/183a9b2632194febd219bb9246eee421dad8d45e/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/sebastianbergmann/code-unit/zipball/54391c61e4af8078e5b276ab082b6d3c54c9ad64/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/sebastianbergmann/comparator/zipball/85c77556683e6eee4323e4c5468641ca0237e2e8/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/sebastianbergmann/complexity/zipball/ee41d384ab1906c68852636b6de493846e13e5a0/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/sebastianbergmann/diff/zipball/b4ccd857127db5d41a5b676f24b51371d76d8544/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/SyEDBv /usr/bin/composer install --no-interaction --prefer-dist(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/sebastianbergmann/environment/zipball/a5c75038693ad2e8d4b6c15ba2403532647830c4/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/sebastianbergmann/exporter/zipball/70a298763b40b213ec087c51c739efcaa90bcd74/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/sebastianbergmann/global-state/zipball/3be331570a721f9a4b5917f4209773de17f747d7/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/d36ad0d782e5756913e42ad87cb2890f4ffe467a/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/f5b498e631a74204185071eb41f33f38d64608aa/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/6e1a43b411b2ad34146dee7524cb13a068bb35f9/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/4f7722aa9a7b76aa775e2d9d4e95d1ea16eeeef4/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/118cfaaa8bc5aef3287bf315b6060b1174754af6/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/c1ca3814734c07492b3d4c5f794f4b0995333da2/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/3e0404dc6b300e6bf56415467ebcb3fe4f33e964/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3b415def83fbcb41f991d9ebf16ae4ad8b7837b3/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c346885c95423eda3f65d85a194aaa24873cda82/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/SyEDBv /usr/bin/composer install --no-interaction --prefer-dist(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/f6458abbf32a6c8174f8f26261475dc133b3d9dc/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/sebastianbergmann/type/zipball/f77d2d4e78738c98d9a68d2596fe5e8fa380f449/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/sebastianbergmann/version/zipball/c687e3387b99f5b03b6caa64c74b63e2936ff874/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/staabm/side-effects-detector/zipball/d8334211a140ce329c13726d4a715adbddd0a163/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/symfony/console/zipball/0bc0f45254b99c58d45a8fbf9fb955d46cbd1bb8/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/SyEDBv /usr/bin/composer install --no-interaction --prefer-dist(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/SyEDBv /usr/bin/composer install --no-interaction --prefer-dist(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/59eb412e93815df44f05f342958efa9f46b1e586/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/SyEDBv /usr/bin/composer install --no-interaction --prefer-dist(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/symfony/event-dispatcher/zipball/9dddcddff1ef974ad87b3708e4b442dc38b2261d/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/SyEDBv /usr/bin/composer install --no-interaction --prefer-dist(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/symfony/filesystem/zipball/d551b38811096d0be9c4691d406991b47c0c630a/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/SyEDBv /usr/bin/composer install --no-interaction --prefer-dist(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/symfony/finder/zipball/340b9ed7320570f319028a2cbec46d40535e94bd/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/SyEDBv /usr/bin/composer install --no-interaction --prefer-dist(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/symfony/options-resolver/zipball/b38026df55197f9e39a44f3215788edf83187b80/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/SyEDBv /usr/bin/composer install --no-interaction --prefer-dist(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/SyEDBv /usr/bin/composer install --no-interaction --prefer-dist(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/380872130d3a5dd3ace2f4010d95125fde5d5c70/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/SyEDBv /usr/bin/composer install --no-interaction --prefer-dist(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/SyEDBv /usr/bin/composer install --no-interaction --prefer-dist(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/SyEDBv /usr/bin/composer install --no-interaction --prefer-dist(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/symfony/polyfill-php80/zipball/0cc9dd0f17f61d8131e7df6b84bd344899fe2608/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/SyEDBv /usr/bin/composer install --no-interaction --prefer-dist(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/symfony/polyfill-php81/zipball/4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/SyEDBv /usr/bin/composer install --no-interaction --prefer-dist(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/symfony/polyfill-php84/zipball/d8ced4d875142b6a7426000426b8abc631d6b191/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/SyEDBv /usr/bin/composer install --no-interaction --prefer-dist(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/symfony/process/zipball/7ca8dc2d0dcf4882658313aba8be5d9fd01026c8/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/SyEDBv /usr/bin/composer install --no-interaction --prefer-dist(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/symfony/service-contracts/zipball/45112560a3ba2d715666a509a0bc9521d10b6c43/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/pYhtcH /usr/bin/composer install(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/SyEDBv /usr/bin/composer install --no-interaction --prefer-dist(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)https://api.github.com/repos/symfony/stopwatch/zipball/8a24af0a2e8a872fb745047180649b8418303084/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/SyEDBv /usr/bin/composer install --no-interaction --prefer-dist(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/symfony/string/zipball/d50e862cb0a0e0886f73ca1f31b865efbb795003/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/SyEDBv /usr/bin/composer install --no-interaction --prefer-dist(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/symfony/var-dumper/zipball/41fd6c4ae28c38b294b42af6db61446594a0dece/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/SyEDBv /usr/bin/composer install --no-interaction --prefer-dist(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/theofidry/cpu-core-counter/zipball/db9508f7b1474469d9d3c53b86f817e344732678/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/SyEDBv /usr/bin/composer install --no-interaction --prefer-dist(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/theseer/tokenizer/zipball/b7489ce515e168639d17feec34b8847c326b0b3c/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)https://api.github.com/repos/tighten/duster/zipball/0260abaaecabd9655a0836e4038238e6585a8b45/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/SyEDBv /usr/bin/composer install --no-interaction --prefer-dist(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/vT5ZWk /usr/bin/composer install --no-interaction(http block)/usr/bin/php8.3 /usr/bin/php8.3 -n -c /tmp/YLs2p1 /usr/bin/composer remove --dev phpstan/phpstan --no-interaction(http block)If you need me to access, download, or install something from one of these locations, you can either:
Original prompt
This section details on the original issue you should resolve
<issue_title>Request/Response Hooks & Events System</issue_title>
<issue_description>## Summary
Add a comprehensive event-driven system with hooks for request/response lifecycle events, enabling fine-grained observability, monitoring, and custom logic injection.
Motivation
Modern HTTP clients need extensible event systems for:
Proposed API
Implementation Details
Event Classes