Fix addEventListener in core/components/*/bootstrap.php and allow anonymous functions #16769
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
What does it do?
This PR introduces runtime and closure-based event listeners with support for priority and optional names in
modX
.I tried to leave 100% backward compatibility - we get a similar addEventListener syntax and correct operation of plugins and events, while getting a powerful tool for managing listeners in packages.
Main technical changes:
Added two new internal maps:
runtimeEventMap
— stores runtime listeners added viaaddEventListener()
so they are not overwritten by_initEventMap()
.closureEventMap
— stores closure-based listeners withpriority
,name
, andcallback
.Added new method:
This allows developers to register closure-based listeners with configurable execution order and optional unique names.
Updated
invokeEvent()
:eventMap
) as before.runtimeEventMap
).closureEventMap
), sorted by priority (lower = earlier).Added universal removal method:
Behavior:
$event
is provided → remove listeners for that event.$event
is null and$name
provided → remove all listeners with that name across all events.$event
is null and$priority
provided → remove all listeners with that priority across all events.Improved the
removeEventListener
method:Clearing of
runtimeEventMap
andclosureEventMap
has been added to the oldremoveAllEventListener
method.Added
removeAllRuntimeEventListeners
method which clears new event mapsruntimeEventMap
andclosureEventMap
.Why is it needed?
Currently,
addEventListener()
writes into$eventMap
, which is later reset by_initEventMap()
when loading from DB. As a result, listeners registered inbootstrap.php
or other runtime code are lost.With this PR:
priority
.name
, which simplifies package development and testing.This feature makes it possible to extend MODX in a more lightweight and programmatic way.
How to test
Use regular modx project
Go to project
core
directory and changemodX.php
file from my repoDownload and install (or create your own) package with
bootstrap.php
file, for example pdoTools.Register a closure listener in
core/components/yourextra/bootstrap.php
:Open any frontend page.
View page source.
Expected: the HTML ends with a comment like:
<!-- TEST CLOSURE: 2025-09-17 20:45:00 -->
Verify priority order:
Refresh the page.
Expected order:
Swap priorities and confirm that order changes accordingly.
Test replace by name:
Refresh the page.
Only the second comment was expected:
Test removal by event:
Test removal by name (global):
appendComment
should be removed across all events.Test removal by priority:
Test error handling:
Refresh the page.
Expected: page renders normally, but error log contains:
Related issue(s)/PR(s)
Closes #16768