Drupal 8 introduced the concept of Events, alongside hooks, as a way for code components to communicate with one another.

There is currently no example code that demonstrates how to subscribe to an event, or how to dispatch an event. In addition to plugins, and hooks, which are both covered already, events are a common means for extending, and altering Drupal core. However, it seems like this would be a good thing for us to cover. Similar to how we've got plugins and hooks examples already.

I've been working on an example of this already for some new Drupalize.Me tutorials and will post a patch with my progress shortly.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

eojthebrave created an issue. See original summary.

eojthebrave’s picture

Here's my in progress work on this. Right now the example creates a new form at examples/events-example that when submitted dispatches a new event. The new event is documented following examples from core, and dispatched using the event dispatcher service. The module also provides an event subscriber for the new event that demonstrates how to subscribe to an event.

This definitely needs a copy review for the comments, and a code review. I've run it through phpcs so it should be good as far as standards go.

This still needs tests. Probably a set of functional tests that submit the form and verify that the appropriate message is displayed. This will confirm the example can be accessed, and that the event is dispatched, and that the subscriber responds. There are two subscribers, with different messages, both should be tested.

eojthebrave’s picture

Status: Active » Needs review
FileSize
0 bytes
2.38 KB

This new patch contains some tests to ensure things are working properly.

Status: Needs review » Needs work

The last submitted patch, 3: 2841453-3-events_example.patch, failed testing.

eojthebrave’s picture

Status: Needs work » Needs review
FileSize
22.46 KB

Guess it helps if the file isn't empty.

Amber Himes Matz’s picture

Copy edit review only. (Code not reviewed.)

  1. +++ b/events_example/src/Event/IncidentEvents.php
    @@ -0,0 +1,55 @@
    + * In this example we're defining one new event;
    

    Use colon (:) instead of a semi-colon.

  2. +++ b/events_example/src/Event/IncidentEvents.php
    @@ -0,0 +1,55 @@
    + * incident is reported. If you're application dispatches more than one event
    

    Change compound "you're" to possessive "your". "If your application..."

  3. +++ b/events_example/src/Event/IncidentEvents.php
    @@ -0,0 +1,55 @@
    + * constant for each. Group like related events together with a single class,
    

    Seems like there's an extra unnecessary word. My suggestion: "Group related events together..." (Omit the word "like".)

  4. +++ b/events_example/src/EventSubscriber/EventsExampleSubscriber.php
    @@ -0,0 +1,108 @@
    +    // unique task/concept rather than just creating a catch all class for all
    

    Hyphenate "catch-all".

  5. +++ b/events_example/src/EventSubscriber/EventsExampleSubscriber.php
    @@ -0,0 +1,108 @@
    +    // the code responsible for dispatching the event. This way if for example
    

    Add commas for phrasing: "This way, if, for example,"...

  6. +++ b/events_example/src/EventSubscriber/EventsExampleSubscriber.php
    @@ -0,0 +1,108 @@
    +    // here https://api.drupal.org/api/drupal/core%21core.api.php/group/events/8.2.x.
    

    Add colon after "here:" and possibly put URL on a new line for readability and line-length.

eojthebrave’s picture

Thanks @Amber Himes Matz. Here's an updated patch.

Amber Himes Matz’s picture

Title: Add events_example module to demonstrate subscribing too and dispatching events » Add events_example module to demonstrate subscribing to and dispatching events
Issue summary: View changes

Great! Also, just copy edited the issue title.

Example still needs a code review.

Mile23’s picture

Status: Needs review » Needs work

Thanks... Glad to see this example.

A few coding standards errors:

$ ../../vendor/bin/phpcs -ps events_example/
WW.E..


FILE: ...pj2/drupal/modules/examples/events_example/events_example.module
----------------------------------------------------------------------
FOUND 0 ERRORS AND 2 WARNINGS AFFECTING 2 LINES
----------------------------------------------------------------------
 27 | WARNING | Line exceeds 80 characters; contains 83 characters
    |         | (Drupal.Files.LineLength.TooLong)
 52 | WARNING | Line exceeds 80 characters; contains 82 characters
    |         | (Drupal.Files.LineLength.TooLong)
----------------------------------------------------------------------


FILE: ...pal/modules/examples/events_example/src/Event/IncidentEvents.php
----------------------------------------------------------------------
FOUND 0 ERRORS AND 2 WARNINGS AFFECTING 2 LINES
----------------------------------------------------------------------
  4 | WARNING | [x] Unused use statement
    |         |     (Drupal.Classes.UnusedUseStatement.UnusedUse)
 29 | WARNING | [ ] Line exceeds 80 characters; contains 83
    |         |     characters (Drupal.Files.LineLength.TooLong)
----------------------------------------------------------------------
PHPCBF CAN FIX THE 1 MARKED SNIFF VIOLATIONS AUTOMATICALLY
----------------------------------------------------------------------


FILE: ...s/events_example/src/EventSubscriber/EventsExampleSubscriber.php
----------------------------------------------------------------------
FOUND 1 ERROR AFFECTING 1 LINE
----------------------------------------------------------------------
 3 | ERROR | [x] Namespaced classes, interfaces and traits should not
   |       |     begin with a file doc comment
   |       |     (Drupal.Commenting.FileComment.NamespaceNoFileDoc)
----------------------------------------------------------------------
PHPCBF CAN FIX THE 1 MARKED SNIFF VIOLATIONS AUTOMATICALLY
----------------------------------------------------------------------

Some review-y stuff:

  1. +++ b/events_example/events_example.services.yml
    @@ -0,0 +1,16 @@
    +  events_example_subscriber:
    

    Let's add a kernel test that just grabs this service from the container, to verify that it's reachable.

  2. +++ b/events_example/src/Event/IncidentEvents.php
    @@ -0,0 +1,55 @@
    +namespace Drupal\events_example\Event;
    +use Drupal\Core\Config\ConfigCrudEvent;
    

    Add a line between these.

  3. +++ b/events_example/src/Event/IncidentEvents.php
    @@ -0,0 +1,55 @@
    +final class IncidentEvents {
    

    Explain in the class docblock why this class is final.

  4. +++ b/events_example/src/EventSubscriber/EventsExampleSubscriber.php
    @@ -0,0 +1,109 @@
    +// By convention, classes subscribing to an event live in the
    +// Drupal/{module_name}/EventSubscriber namespace.
    

    Move this to the class docblock.

  5. +++ b/events_example/src/EventSubscriber/EventsExampleSubscriber.php
    @@ -0,0 +1,109 @@
    +class EventsExampleSubscriber implements EventSubscriberInterface {
    +  use StringTranslationTrait;
    

    Add a blank line between these.

Mile23’s picture

Some editorial review:

  1. +++ b/events_example/events_example.module
    @@ -0,0 +1,70 @@
    + * communicate with each other. One system component or module dispatches the
    + * event at an appropriate time; many events are dispatched during every
    + * request. Other system components or modules can register as event
    + * subscribers; when an event is dispatched, a method is called on each
    + * registered subscriber, allowing each one to react.
    

    This is a dense paragraph... I'd say about half of it should be another paragraph explaining that modules can dispatch events but they don't need to, and can just subscribe to existing events.

  2. +++ b/events_example/events_example.module
    @@ -0,0 +1,70 @@
    + * This allows modules to alter and extend other systems without the need to
    + * modify the original code.
    

    Events don't actually allow modules to alter anything, or at least shouldn't. It's just a ping that something happened.

  3. +++ b/events_example/events_example.module
    @@ -0,0 +1,70 @@
    + * Subscribe to an event in order to react whenever that event occurs.
    + *
    + * This requires:
    

    Who's subscribing? Also condense these to one line.

  4. +++ b/events_example/events_example.module
    @@ -0,0 +1,70 @@
    + * Dispatch an event to allow other code to react to what your code is doing.
    + *
    + * This requires:
    

    Who's dispatching? Also condense these to one line.

  5. +++ b/events_example/events_example.module
    @@ -0,0 +1,70 @@
    + * https://drupalize.me/blog/201502/responding-events-drupal-8 Responding to
    

    Yay drupalize.me. :-)

  6. +++ b/events_example/src/Event/IncidentEvents.php
    @@ -0,0 +1,55 @@
    + * It is best practice define the unique names for events as constants on a
    + * static class. This provides a place for documentation of the events. As well
    ...
    +final class IncidentEvents {
    

    Docs say it should be static, but it's not.

  7. +++ b/events_example/src/Event/IncidentEvents.php
    @@ -0,0 +1,55 @@
    + * Additionally the docblock for each event should contain an "@Event" tag. This
    

    I think @Event isn't really 'additionally' important. :-) It should come first in describing how this works.

joshi.rohit100’s picture

+++ b/events_example/src/EventSubscriber/EventsExampleSubscriber.php
@@ -0,0 +1,108 @@
+      // If there are other subscribers that have not been called yet this will
+      // cause them to be skipped.

No fear when batman is here. No need to call the police :) first thought that came in mind while reviewing it.

yogeshmpawar’s picture

Assigned: Unassigned » yogeshmpawar
yogeshmpawar’s picture

Assigned: yogeshmpawar » Unassigned
eojthebrave’s picture

Status: Needs work » Needs review
FileSize
23.85 KB
7.59 KB

Here's an update that address all the comments from @Mile23's awesome review. Thanks. The only one I'm not 100% sure about is re-writing the previously dense intro paragraph. I tried to break it up into smaller, and more parseable bits. Let me know if this works for you.

Status: Needs review » Needs work

The last submitted patch, 14: 2841453-14-events_example.patch, failed testing.

eojthebrave’s picture

Trying again. The patch seems fine. This looks like the testbot didn't have a copy of the examples project maybe?

20:52:40 Git commit info:
20:52:40 	8f380cf (grafted, HEAD, origin/HEAD, origin/8.2.x, 8.2.x) Issue #2824827 by damiankloip, dawehner, Wim Leers, klausi: \Drupal\hal\Normalizer\ContentEntityNormalizer::denormalize() fails with fatal PHP error when bundles are missing from link relation types
20:52:40 Checkout complete.
20:52:40 Fetch of https://www.drupal.org/files/issues/2841453-14-events_example.patch to /var/lib/drupalci/workspace/jenkins-default-296882/ancillary/2841453-14-events_example.patch complete.
20:52:40 Patch Error
20:52:40 The target patch directory /var/lib/drupalci/workspace/jenkins-default-296882/source/modules/examples is invalid.
Mile23’s picture

Status: Needs work » Needs review

Testbot issues aside, +1 on the changes and the patch does in fact apply. Thanks.

Let's see if we can kick the testbot into behaving...

  • Mile23 committed 359383b on 8.x-1.x authored by eojthebrave
    Issue #2841453 by eojthebrave, Mile23, Amber Himes Matz: Add...
Mile23’s picture

Status: Needs review » Fixed

OK, the testbot is happier now. ::unhappy glances at the DA::

Committed, pushed. :-)

Thanks!

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.