On Fri, Feb 22, 2019, at 11:46 AM, Beau Simensen wrote:
> On Wednesday, January 30, 2019 at 12:05:11 PM UTC-6, Cees-Jan Kiewiet wrote:
> > As of today, with a unanimous vote from the working group, we formally begin the REVIEW phase of the proposed PSR-14 (Event Dispatcher) specification. The proposed specification is in the fig-standards repository at the following locations:
> > - Specification: https://github.com/php-fig/fig-standards/blob/master/proposed/event-dispatcher.md
> > - Metadocument: https://github.com/php-fig/fig-standards/blob/master/proposed/event-dispatcher-meta.md
> > During the Review phase, acceptable changes to the specification include wording, typographical fixes, and clarifications. If you feel major changes are necessary or have, please bring your arguments/questions to the list under this thread. If any major changes are considered, we will return to the Draft phase.
> > The Review period will end no sooner than 27 Jan 2019 at 11:59pm. At that time, if the working group can demonstrate two viable trial implementations, and no need for major changes, I will call for an Acceptance Vote.
> I've read the spec, meta document, taken a look at two reference
> implementations, and explored the util package. If the working group is
> happy with the spec as-is, I have little to add or ask questions about
> at this point with one minor exception.
> This wording seems a bit unclear: "Listener Providers MUST treat parent
> types identically to the Event's own type when determining listener
> applicability." It seems like there should be an easier way to say this
> that is more direct?
> At the same time, the bit just below the example reads: "A Listener
> Provider MUST treat listener() as an applicable listener for $b, as it
> is type compatible, unless some other criteria prevents it from doing
> Listener Providers MUST treat parent types identically, unless some
> other criteria prevents it from doing so? Is that the correct way to
> read this?
Yeah, that bit is a little tricky to state succinctly. Let me explain it long-form and maybe someone has a better, tighter way to word it.
Providers get huge latitude to determine what listeners they return and in what order. The Dispatcher just trusts whatever it gets back. That makes Providers the key "customization" point. (In practice most Dispatchers will be largely the same, but Providers can vary enormously.)
The most common case, and the one that we should encourage as a default, is "if a listener is type-compatible with the event, then it applies." So a listener whose first parameter is "LoginHappened $event" should apply to any event that is an instance of LoginHappened. But then what do you do with an instance of AdminLoginHappened, which extends LoginHappened?
The intent of the spec is to say that since AdminLoginHappened is a subclass of LoginHappened, then all listeners that apply to LoginHappened will also apply to AdminLoginHappened. That offers several advantages:
1) You can special-case an event very easily without losing access to a large set of existing listeners.
2) You can "tag" events with interfaces to create event groups. Laravel has that functionality currently using a junior-regex style naming of events. This offers the same capability but built on native language functionality.
However, we don't want some implementations to pay attention to the inheritance tree and others to just look at the specific class of the event; that would mean Emitters (which in PSR-14 speak is the calling library) can't rely on AdminLoginHappened also triggering LoginHappened listeners, and they'll start firing both just to be safe, and that's just a mess. So the spec requires that they both apply.
HOWEVER! A Provider is also totally able to use criteria beyond the type if it wants to. It can also be configured such that certain listeners only apply if the current user is an administrator, if the current user is anonymous, if the current environment is/is not production, and so forth. For example, it's entirely possible that a particular listener for LoginHappened is configured to only apply in development, not production. In that case, if an AdminLoginHappened event fires in production then that listener should NOT be returned, but because it's in the wrong environment, not because it's type doesn't match. Other listeners for either LoginHappened or AdminLoginHappend would still apply.
I hope that clears up the intent there. If someone can suggest a better way to state that in the spec that isn't 6 paragraphs long, I'm happy to update the text.