Jump to content

IC5: Introduction to Listeners

I'm very excited to be posting my first blog entry for IPS, and thrilled that this is what I get to post.

When we started planning the new development tools for v5, we looked at existing resources - from the marketplace, from some contributors, and from our own managed clients - and asked, what is it that developers find themselves doing the most often? Matt’s previous blog entry gave a brief summary of some of those functions. Today’s blog entry is going to focus on one of our powerful new tools, Listeners.

One common reason for a code hook was to execute custom code when a specific action occurs. For example, when a topic is created, or when a new reply is posted. Listeners allow you to execute your code at key points in the workflow, without the worry of finding exactly the right hook location.

Here is an excerpt from the BlogComment listener in our Cloud application:

Could contain: Electronics, Screen, Computer Hardware, Hardware, Monitor, Computer, Pc, Page, TV, Business Card

 

Creating Listeners

Let’s start with the application’s Developer Center.

Could contain: Page, Text

We’ve added a new tab for Listeners. This tab lists all your existing listeners, as well as the class on which it is listening.

You’ll notice that each listener can only observe a single class. While this may seem slightly tedious, the idea here was that as a developer, you should be conscious of what class you are working with. It also eliminates the need to check what type of object is being passed preventing accidents and unintended consequences when missing class checks.

When you add a listener, there are several listener types available. We will discuss each one in detail.

Could contain: Page, Text, Computer, Electronics, Pc, White Board

 

Content Listener

This listener is fired on an Item or Comment (or Review) class. When adding a Content Listener, you must specify the class you are observing. When you hit Save, there is a validation check in place to ensure that the class exists, and that it is a valid class for the selected listener type.

Content Listeners have the following methods available. All methods are included in the default listener file that is generated.

  • onLoad
    Triggered when an object is loaded (in Content::constructFromData)

NOTE: Be careful! This event could be fired at unexpected times. If you’re executing code here, you may want to check the dispatcher instance to verify that your code is running where you expect.

  • onBeforeCreateOrEdit
    Fired when a form is submitted, before it is saved. This is the equivalent of Item::processBeforeCreate and Item::processBeforeEdit. This method includes a parameter to indicate whether this is a create or edit.
  • onCreateOrEdit
    Fired after a form is saved. This is the equivalent of Item::processAfterCreate and Item::processAfterEdit. This method includes a parameter to indicate whether this is a create or edit.
  • onDelete
    Fired after an object is deleted.
  • onStatusChange
    Fired when any moderation action occurs. For example, when an item is pinned/unpinned, locked/unlocked. The moderation action is passed as a parameter so that your code can take that into account.
  • onMerge
    Triggered AFTER an item is merged.
  • onItemView
    Triggered when an item is viewed and the view count is incremented.

 

Invoice Listener

An Invoice listener is fired only on the \IPS\nexus\Invoice class. This listener does not require you to specify a class to extend.

The Invoice listener includes a single method, onStatusChange. This is fired when the invoice is saved and the status changes (pending/paid/expired/canceled).

 

Member Listener

The Member listener will be familiar to many of you. We have taken the MemberSync extension and moved it in its entirety to a listener, as it was a better fit for this structure. All the previous methods that were available are still available here. We have also added the following new methods:

  • onJoinClub
    Fired when a member joins a club. If approval is required, this is fired after they are approved.
  • onLeaveClub
    Fired when a member leaves or is removed from a club.
  • onEventRsvp
    Fired when a member responds to an event. The response is included as a parameter to this method.

 

Commerce Package Listener

The Commerce Package listener is fired on any implementation of \IPS\nexus\Invoice\Item. You must specify the class that you are observing.

The methods are the same as those that are available in an item extension.

  • onCancel
  • onChange
  • onDelete
  • onExpireWarning
  • onExpire
  • onInvoiceCancel
  • onPaid
  • onPurchaseGenerated
  • onReactivate
  • onRenew
  • onTransfer
  • onUnpaid

 

Some Technical Notes

  • All listener files will be generated in a “listeners” directory within your application.
  • Your application’s data directory will include a listeners.json file that defines all your listeners. The json file is automatically generated when you add/remove a listener.
  • All listener methods are optional. The default class that is generated will include all available methods, but they do not have to be present in your file.
  • All listener methods are return type void.
  • If a listener method fails, an exception will be thrown when IN_DEV is enabled. In production, the exception will be logged with a reference to the listener class and the event on which the exception occurred.

 

Firing Events

Your code can fire any existing event using the Event::fire method.

Example:

Event::fire( 'onBeforeCreateOrEdit', $comment, array( $values ) );

The Event::fire method is called statically and accepts an event name, the object on which the event will be fired, and an array of additional parameters (varies according to the event that you are triggering).

This concludes our introduction to Listeners. We do intend to implement additional listener types and events based on your feedback and as the need arises.

Comments

Recommended Comments



Adriano Faria

Posted

Am I still allowed to hook in \IPS\Content\Item, for example?

“NOTE: You can only create a listener on an implemented Item/Comment/Review class. You cannot listen on \IPS\Content\Item”

There are resources that extends the global class, like this or this. These are suite resources, not single apps resources.

Thank you.

  • Management
Matt

Posted

24 minutes ago, Adriano Faria said:

Am I still allowed to hook in \IPS\Content\Item, for example?

“NOTE: You can only create a listener on an implemented Item/Comment/Review class. You cannot listen on \IPS\Content\Item”

There are resources that extends the global class, like this or this. These are suite resources, not single apps resources.

Thank you.

In this case, just create a listener for every applications Review class. This allows you to be intentional what you want to happen for each class and application. So you can still create this app in v5.

Adriano Faria

Posted (edited)

14 minutes ago, Matt said:

In this case, just create a listener for every applications Review class. This allows you to be intentional what you want to happen for each class and application. So you can still create this app in v5.

So the answer is no as there is no HOOKS tab anymore. So resources from now on will extend only official apps that I have in my license. If the user has another 3rd-party resource, it won’t work anymore because I don’t have all the marketplace resources out there to add listeners since it checks for the class. 

Great improvement. 

Edited by Adriano Faria
DawPi

Posted

Quote

onBeforeCreateOrEdit
Fired when a form is submitted, before it is saved. This is the equivalent of Item::processBeforeCreate and Item::processBeforeEdit. This method includes a parameter to indicate whether this is a create or edit.

One question - it's fine for "default" form item. What if I want to add new form helper or even modify existing into specific item type and then use these Listeners?

Esther E.

Posted

1 minute ago, DawPi said:

One question - it's fine for "default" form item. What if I want to add new form helper or even modify existing into specific item type and then use these Listeners?

Are you referring to adding fields to the form?

DawPi

Posted

Adding/modifyfing/removing etc. 😉

Esther E.

Posted

2 minutes ago, DawPi said:

Adding/modifyfing/removing etc. 😉

That will be dealt with in UIExtensions. We're wrapping some things up on those before the blog entry, but it's coming.

36 minutes ago, Adriano Faria said:

So the answer is no as there is no HOOKS tab anymore. So resources from now on will extend only official apps that I have in my license. If the user has another 3rd-party resource, it won’t work anymore because I don’t have all the marketplace resources out there to add listeners since it checks for the class. 

Great improvement. 

We will be removing the block on base classes and you'll be able to add listeners to \IPS\Content\Item (or Comment or Review).

Adriano Faria

Posted (edited)

20 minutes ago, Esther E. said:

We will be removing the block on base classes and you'll be able to add listeners to \IPS\Content\Item (or Comment or Review).

Thank you. 👏👍

Still, remove the ability to hook is a huge step back and will make marketplace even worse and smaller but I guess that’s the point after all. A massive number of resources are dead.

We’re basically back to IP.Board 2 (file edits will be required for custom jobs as we can’t hook) and IP.Board 3 (back to hook points era). 

Anyway, just my feedback. Not trying to annoy anyone; just my honest feedback.

Tks.

Edited by Adriano Faria
teraßyte

Posted (edited)

I was silent so far, hoping for some revolutionary idea, but I have to agree with Adriano: with these changes modding is dead.

 

Listeners are basically the old Library hooks from 3.x, and we can no longer overload any other methods (unlike before). I won't be able to update 85%+ of my modifications with this system.

 

@Matt As an example, I see no way to update these plugins for 5.x:

 

 

Unless I'm missing something, or you have more coming to still allow them.

Edited by teraßyte
Daniel F

Posted

Not sure about your first example, but the "Delete All System Logs Button" won't be a problem at all!

As Matt or Esther said, just wait for our further blog entries, especially about the new UIExtensions

teraßyte

Posted

1 minute ago, Daniel F said:

Not sure about your first example, but the "Delete All System Logs Button" won't be a problem at all!

As Matt or Esther said, just wait for our further blog entries, especially about the new UIExtensions

The second plugin is something that should be included by default really, but, leaving that aside, my main issue is the first one I linked. I have plenty of similar (custom) modifications. That's the biggest problem, and your reply doesn't help at all, unfortunately. 😔

Esther E.

Posted

1 minute ago, teraßyte said:

The second plugin is something that should be included by default really, but, leaving that aside, my main issue is the first one I linked. I have plenty of similar (custom) modifications. That's the biggest problem, and your reply doesn't help at all, unfortunately. 😔

Without looking at the source code of your modification, I am pretty sure it can still be done. Just from looking at the screenshots and the feature list.

teraßyte

Posted

4 minutes ago, Esther E. said:

Without looking at the source code of your modification, I am pretty sure it can still be done. Just from looking at the screenshots and the feature list.

To log the download, I have an hook on \IPS\File. I see no way to access it with Listeners?

Guess I can only wait and see what comes next for now... 🙄

  • Management
Matt

Posted

As mentioned in my first blog, there will be things you can’t do in 5 and this is deliberate. But there is still a lot you can do. 

Esther E.

Posted

10 minutes ago, teraßyte said:

To log the download, I have an hook on \IPS\File. I see no way to access it with Listeners?

Guess I can only wait and see what comes next for now... 🙄

Listeners is just one tool in the box. I would suggest waiting until you see the full structure before worrying about what you can and cannot do.

Dll

Posted (edited)

Maybe it would have been a plan to hold off announcing this 1 tool until you were ready to announce the rest, or at least some of them. 

Edited by Dll
Marc

Posted

16 minutes ago, Dll said:

Maybe it would have been a plan to hold off announcing this 1 tool until you were ready to announce the rest, or at least some of them. 

I'm sure there are others who have found in nice to get a glimpse 🙂 No matter which way we do this, releasing everything in a single blog would just be too much. And actually, we announced one yesterday, then release another today. These things are always a "damned if you do, damned if you don't" kind of thing. If we say nothing, some dont like it, if we say something, some wont like it.

There's more to come, as mentioned.

Ocean West

Posted

So essentially what you are describing is a transaction (more than just crud operations) along with Pub/Sub or a simple que type system

  • Management
Matt

Posted

1 hour ago, Dll said:

Maybe it would have been a plan to hold off announcing this 1 tool until you were ready to announce the rest, or at least some of them. 

I'm always keen to get information out as soon as we have it fixed on our end. There are pros and cons but the earlier the feedback, the more chance we have at addressing it and making sure we've not missed any angles. Give it a few months and the v5 codebase will be much stabler and we'll be more reluctant to make big changes.

Some of the tools we're still actively working on, and stuff like theme tools are only about 80% complete, so there may be some gaps between blogs but we'll post them as soon as we have them ready.

7 minutes ago, Ocean West said:

So essentially what you are describing is a transaction (more than just crud operations) along with Pub/Sub or a simple que type system

Not exactly, it's more like the JS event system, you can listen in on events and execute your code when those events are triggered.

Kirill Gromov

Posted

The hooking of methods seemed to me close to ideal in IPS4 (although it had big problems), I did not think that IPSs would abandon this coding trick in IC5, which helped to fill the market with excellent solutions. Disappointed. But I still hope the team will please us with good news. Pending.

Miss_B

Posted

Thank you for the well written and detailed blog @Esther E.. I am happy to see that Ipb 5 is coming along very nicely and I am looking forward to the next blogs. And congratulations on joining the Ips team 😊

 

DawPi

Posted

To be clear - inside system/ directory we would have access to Content and Member folders only? What if we want to adjust/modify Output/Sitemap/Helpers/Lang etc. classes and methods inside them?



×
×
  • Create New...