Skip to content

Issue/536 event foundation and boot stage lifecycle events - #573

Merged
armanist merged 7 commits into
quantum-php:masterfrom
armanist:issue/536-event-lifecycle-foundation
Oct 8, 2026
Merged

armanist merged 7 commits into
quantum-php:masterfrom
armanist:issue/536-event-lifecycle-foundation

Conversation

@armanist

@armanist armanist commented Oct 8, 2026 •

Copy link
Copy Markdown
Collaborator

Closes #536

What changed

  • Replaced the Hook package with Quantum\Event: event()->listen() and event()->dispatch(). Event names need no registration, so hooks.php is no longer read; an empty name throws EventException. Listeners now persist after dispatch and run in registration order.
  • BootPipeline dispatches BEFORE/AFTER events that stages declare, with the AppContext as a named payload. The environment, config, error handler, HTTP and modules stages declare boot.<stage>.before|after. LoadHelpersStage and InitDebuggerStage declare none, and dispatch is skipped while event() is not loaded.
  • App helper files are the supported place to register early listeners; they load before config and before any boot event.
  • The debugbar Hooks tab now lists only events that have listeners. It previously listed every pre-registered hook name.

Why

Optional integrations such as debugbar need to hook into specific boot points without hardcoded stages in core. This is the foundation for #537, #538 and #539.

Breaking changes

hook(), HookManager and HookException are removed with no aliases; listeners are no longer one-shot; shared/config/hooks.php is obsolete. Documented in CHANGELOG.md.

Validation

  • Full vendor/bin/phpunit: 1568 tests, 3840 assertions, 4 skipped (optional Twig not installed)
  • composer cs:check and composer phpstan passed
  • Smoke test in quantum-php-project: web and API routes respond, the debugbar renders, and a temporary helper listener received all ten boot events in order
  • composer rector:check reports 22 files, none touched by this PR

Summary by CodeRabbit

  • New Features
    • Added events before and after key application startup stages, with startup context available to listeners.
    • Added an event system that supports named events, ordered listeners, and payloads.
  • Breaking Changes
    • Replaced hooks with events. Update integrations to use event listeners and dispatch; existing hook APIs and hook configuration are no longer supported.
    • Updated configuration setup and environment loading behavior, including configuration paths that resolve from the application base directory.

armanist and others added 6 commits October 8, 2026 18:32
Introduce Quantum\Event\EventManager and the event() helper as the
replacement for the Hook package. Event names need no pre-registration,
listeners persist across dispatches and run in registration order, and
the manager does not read config, so it is safe to use during boot.
The Hook package is removed in a follow-up commit.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Delete Quantum\Hook (HookManager, HookException, hook() helper) and its
tests, and read the debugger Hooks tab from event()->getRegistered().
Event replaces Hook with no aliases; no other caller existed.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Boot stages may declare BEFORE/AFTER constants naming an event.
BootPipeline dispatches them around each stage with the AppContext as a
named payload, and skips dispatch while the event() helper is not
loaded yet. Environment, config, error handler, HTTP and modules stages
declare boot.<stage>.before/after; the helpers and debugger stages
declare none.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…t names

Cover registering an event listener from an app helper during web boot:
it fires at boot.modules.before, registers before the app config is
loaded, and is not registered again on a second boot in the same
process (helpers load with require_once).

Align the Event and boot pipeline tests with repo conventions: name
methods test<Subject><Behavior>, move the pipeline event tests into
BootPipelineTest, and add EventExceptionTest to mirror EventException.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…ngelog

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Test that logDebugInfo() records registered event listeners in the
debugger Hooks cell, records nothing without listeners or when debug is
disabled, and reset the shared debugger store in tearDown() so the
static store does not leak between test classes.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Oct 8, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 36 seconds.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: f888c297-ded1-4945-bbb8-77fc30eb3b72
📥 Commits

Reviewing files that changed from the base of the PR and between 72c4ffb and 39adef2.

📒 Files selected for processing (8)
  • CHANGELOG.md
  • src/App/Helpers/dir.php
  • src/App/Traits/WebAppTrait.php
  • src/Debugger/Debugger.php
  • tests/Unit/App/Adapters/WebAppAdapterTest.php
  • tests/Unit/App/Helpers/DirHelperTest.php
  • tests/Unit/Debugger/DebuggerTest.php
  • tests/_root/shared/config/hooks.php

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 1a775644-11a0-4427-9fbd-a1cd666ebac3
📥 Commits

Reviewing files that changed from the base of the PR and between a5d3a99 and 72c4ffb.

📒 Files selected for processing (23)
  • CHANGELOG.md
  • src/App/BootPipeline.php
  • src/App/Stages/InitHttpStage.php
  • src/App/Stages/LoadAppConfigStage.php
  • src/App/Stages/LoadEnvironmentStage.php
  • src/App/Stages/LoadModulesStage.php
  • src/App/Stages/SetupErrorHandlerStage.php
  • src/App/Traits/WebAppTrait.php
  • src/Event/Enums/ExceptionMessages.php
  • src/Event/EventManager.php
  • src/Event/Exceptions/EventException.php
  • src/Event/Helpers/event.php
  • src/Hook/Exceptions/HookException.php
  • src/Hook/Helpers/hook.php
  • src/Hook/HookManager.php
  • tests/Unit/App/Adapters/WebAppAdapterTest.php
  • tests/Unit/App/BootPipelineTest.php
  • tests/Unit/Event/EventManagerTest.php
  • tests/Unit/Event/Exceptions/EventExceptionTest.php
  • tests/Unit/Event/Helpers/EventHelperTest.php
  • tests/Unit/Hook/Exceptions/HookExceptionTest.php
  • tests/Unit/Hook/Helpers/HookHelperTest.php
  • tests/Unit/Hook/HookManagerTest.php
💤 Files with no reviewable changes (6)
  • tests/Unit/Hook/Helpers/HookHelperTest.php
  • tests/Unit/Hook/Exceptions/HookExceptionTest.php
  • src/Hook/Helpers/hook.php
  • src/Hook/Exceptions/HookException.php
  • tests/Unit/Hook/HookManagerTest.php
  • src/Hook/HookManager.php

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

The Hook API is replaced by an Event API with persistent listeners and named payloads. Boot stages declare before and after event names, and BootPipeline dispatches them with the application context. Debug logging now records registered event handlers.

Changes

Events and boot lifecycle

Layer / File(s) Summary
Event API and Hook replacement
src/Event/*, src/Hook/*, tests/Unit/Event/*, tests/Unit/Hook/*, CHANGELOG.md
Adds EventManager and the event() helper. Listeners receive an array payload, remain registered after dispatch, and run in registration order. Empty event names raise EventException; dispatch without listeners invokes none. Removes the Hook manager, helper, and exception class, with no compatibility aliases described in the changelog.
Boot-stage lifecycle dispatch
src/App/BootPipeline.php, src/App/Stages/*, src/App/Traits/WebAppTrait.php, tests/Unit/App/*, CHANGELOG.md
Five boot stages declare before and after event names. BootPipeline dispatches declared events around stage processing when event() is available, passing the context under the context key. Debug logging records registered event handlers. Tests cover stage ordering, payloads, helper registration, and debug logging.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~25 minutes

Change: Feature

Sequence Diagram(s)

sequenceDiagram
  participant BootPipeline
  participant EventHelper as event()
  participant EventManager
  participant Stage
  participant Listener
  BootPipeline->>EventHelper: Dispatch BEFORE event with context
  EventHelper->>EventManager: Resolve manager
  EventManager->>Listener: Invoke listener with payload
  BootPipeline->>Stage: Process stage with context
  BootPipeline->>EventHelper: Dispatch AFTER event with context
  EventHelper->>EventManager: Resolve manager
  EventManager->>Listener: Invoke listener with payload
Loading

Merge Risk: ⚪ Minimal · up to 72c4f

No actionable merge-blocking issue is established; the change is mergeable after normal checks.

🚥 Pre-merge checks | ✅ 2 | ❌ 3

❌ Failed checks (3 warnings)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The implementation satisfies the new lifecycle behavior in #536. BootPipeline dispatches stage-declared BEFORE and AFTER events with a named context payload. The event manager supports bootstr… Keep the existing Hook-style API available while adding the new event API, including compatible hook(), on(), and fire() behavior or an equivalent compatibility layer. If the breaking replacement is intended, update #536 before treati…
Out of Scope Changes check ⚠️ Warning The whole-PR diff adds unrelated CHANGELOG entries for adapter-based language providers and removal of Quantum\\\\Loader, labeled #533 and #535. The linked issue #536 concerns the event manager and bo… Remove the #533 and #535 changelog entries from this PR, or move them to the pull requests that implement those changes.
Docstring Coverage ⚠️ Warning Docstring coverage is 12.90% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 62 functions across 16 files. (1 skipped:… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main changes: introducing the event foundation and adding boot-stage lifecycle events. It is concise, specific, and directly related to the changeset.
Full details: Linked Issues check

Explanation

The implementation satisfies the new lifecycle behavior in #536. BootPipeline dispatches stage-declared BEFORE and AFTER events with a named context payload. The event manager supports bootstrap-safe registration, arbitrary event names, persistent listeners, and registration order. Added tests cover these behaviors. However, #536 requires the current Hook-style mechanism to be strengthened rather than replaced. This PR deletes src/Hook/HookManager.php, hook(), HookException, and the old tests. It provides no compatibility aliases for the existing API.

Resolution

Keep the existing Hook-style API available while adding the new event API, including compatible hook(), on(), and fire() behavior or an equivalent compatibility layer. If the breaking replacement is intended, update #536 before treating this PR as compliant.

Full details: Out of Scope Changes check

Explanation

The whole-PR diff adds unrelated CHANGELOG entries for adapter-based language providers and removal of Quantum\\Loader, labeled #533 and #535. The linked issue #536 concerns the event manager and boot-stage lifecycle events. The PR description does not connect these entries to the event foundation.

Full details: Docstring Coverage

Explanation

Docstring coverage is 12.90% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 62 functions across 16 files. (1 skipped: 1 unsupported.)

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codecov-commenter

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Delete the unused hooks_dir() helper and its test, rename the debugger
tab constant Debugger::HOOKS to Debugger::EVENTS (tab value "events"),
and drop the obsolete tests/_root hooks.php config fixture. Record the
removal and rename in the changelog as part of the Hook to Event change.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@armanist
armanist merged commit 8738221 into quantum-php:master Oct 8, 2026
6 checks passed
@armanist
armanist deleted the issue/536-event-lifecycle-foundation branch October 8, 2026 17:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Enhance Hook package and boot pipeline to support bootstrap-time stage lifecycle events for optional integrations

3 participants