Jump to content
Esther E.

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



  • Management
4 minutes ago, DawPi said:

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?

Correct, there is less opportunity to overload/hook into/touch Invision Community 5. If you can give me some examples of why you'd want to overload those methods, we can help guide you to newer tools or understand why there is a need and consider adjustments to the dev toolkit.

1 hour ago, Kirill Gromov said:

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.

Monkey patching (code hooks) were convenient but the cost was very high in that we couldn't significantly alter our code without destroying most existing modifications causing WSOD, ISE500 or other errors on client communities. As PHP 8 becomes more strict about typing, return types, etc - a simple function signature change could break modifications.

Clearly, allowing almost every single class and method to be overloaded is not something that we could continue doing.

We also want to be a little more protective of some of our UI and flows. We want to build a toolkit that lets you build amazing add-ons and extra functionality but it will mean there is less scope for smaller apps that change some of our existing functionality.

The good thing about these blogs is that we get to have a conversation and learn from each other.

Link to comment
Share on other sites

Matt, could you clarify exactly what you mean with “less”. As far as we can see, there won’t be ways to use hooks anymore. Is that right? I don’t see the Hooks tab in dev center.

What you’re calling listeners that is fired in specific events can’t be called hooks at all, so I guess that’s the reason for such confusion. At least to me. 

Once and for all, will we be able to hook in class?

Thank you.

Link to comment
Share on other sites

  • Management
Just now, Adriano Faria said:

Once and for all, will we be able to hook in class?

No, code hooks are no longer in Invision Community 5.

We have the listeners, UIExtension, menus and more limited theme-hooks as the primary toolkit.

Link to comment
Share on other sites

Hypothetical question - let's say I've created a hook on \IPS\Helpers\Form\Text and added in something to be used as the $customValidationCode callback.

Will that be possible using the new tools you are currently planning to provide in v5?

Note: I'm aware that I can probably do something JS to do this in a different way - but I'm just looking for a Yes/No answer on the above question, as it will help me make an immediate decision on something.

 

Edited by Nathan Explosion
Link to comment
Share on other sites

Just now, Nathan Explosion said:

Hypothetical question - let's say I've created a hook on \IPS\Helpers\Form\Text and added in somethin to be used as the $customValidationCode callback.

Will that be possible using the new tools you are currently providing?

Note: I'm aware that I can probably do something JS to do this in a different way - but I'm just looking for a Yes/No answer on the above question, as it will help me make an immediate decision on something.

That's the kind of thing we don't really want people doing. 😉 Hooking into a core class like the Text field, where it's referenced literally everywhere, can have unintended consequences. So no, that wouldn't be possible.

Link to comment
Share on other sites

Just now, Nathan Explosion said:

Thank you - that's several project dead in the water then.

Perhaps when you have the full picture of all the available tools, you might come up with other ways. Very hard for me to say definitively if I don't know what you're trying to do.

Link to comment
Share on other sites

10 minutes ago, SeNioR- said:

So half or more of the plugins/apps will be removed from the marketplace 🥲

They will be there for a couple of years for those who won’t jump in V5 right away.

File edits will be back with resources being sold in dev’s board. And for those who use marketplace and can’t use FTP, will get limited resources.

But there’s no doubt it will be the end of this marketplace and I truly believe that’s what IPS is after for a while now.

Just now, SeNioR- said:

Controversial topic, I like it. 🫢 Adriano, good luck with the update over 300 resources 😁

I haven’t decided yet if I will keep developing for IPS, as I told somewhere else… and I must confess the answer its getting clear at every blog entry. 

Anyway, if I remain, certainly will reduce from 300 to 50 maximum, due to… framework limitations. 😂

Link to comment
Share on other sites

 

4 minutes ago, Esther E. said:

Hooking into a core class like the Text field, where it's referenced literally everywhere, can have unintended consequences

Maybe. Someone say yes, other no. I have plenty private custom mods (hooks) and I can take responsible and all consequences. Now it won't be possible.

12 minutes ago, SeNioR- said:

So half or more of the plugins/apps will be removed from the marketplace

~ 85-90% I think.

29 minutes ago, Matt said:

If you can give me some examples of why you'd want to overload those methods, we can help guide you to newer tools or understand why there is a need and consider adjustments to the dev toolkit.

I prefer to wait for more dev blog entries before I'll be more critical, but I feel close to certainty that more than 80% of my projects will not be possible on v5.

 

Quote

Today’s blog entry is going to focus on one of our powerful new tools, Listeners.

Nope, disagree. Hooks are powerfull.

Link to comment
Share on other sites

2 minutes ago, Esther E. said:

you might come up with other ways.

I already have, if I decide to continue developing them - as I mentioned.

2 minutes ago, Esther E. said:

Very hard for me to say definitively if I don't know what you're trying to do.

I'm adding a callback to the $customValidationCode for a text field, to validate it - as I mentioned.

Unfortunately,  based on the information provided thus far, a few projects I'm working on are now dead in the water. When more information is made available, maybe they'll be resuscitated but I can't proceed with them (at this time) in all good conscience without the bigger picture.

Link to comment
Share on other sites

1 minute ago, SeNioR- said:

Controversial topic, I like it. 🫢 Adriano, good luck with the update over 300 resources 😁

No issues there. He won't be able to upgrade 2/3 of them. Lots of time saved! 😂

 

Seriously, I have several apps and plugins extending classes in the /system folder. That means they're all dead for v5. So far, I don't like the direction v5 is taking at all. No matter what awesome tools you may have in place, being unable to overload (almost) all classes like before is a huge issue.

 

Well, that's it for me for now. I won't say anything further until there is more info about those "awesome tools" you mentioned. But I don't have much hope for them.

Link to comment
Share on other sites

4 minutes ago, teraßyte said:

No issues there. He won't be able to upgrade 2/3 of them. Lots of time saved! 😂

😃 right. My primitive but still free plugins will also go to the sand. Good thing I only have a few. We'll see what the next entries bring, maybe it won't be so tragic 🥲🫢

Link to comment
Share on other sites

12 minutes ago, teraßyte said:

Well, that's it for me for now. I won't say anything further until there is more info about those "awesome tools" you mentioned. But I don't have much hope for them.

Me too. Anything we say won't have any effect. As you said yesterday, I hoped we would be heard before it started.

Hoping the UIExtension will be a game-changer. 👍

Link to comment
Share on other sites

5 minutes ago, Esther E. said:

We literally changed code this morning because of your feedback on adding a listener to base classes. 🤔

True, thanks for this... but as you all already said, we can't say much now as we haven't the big picture yet. So waiting...

Link to comment
Share on other sites

I'm just curious, @Daniel F as far I remember you wrote that your SEO app will be ported into v5. But how? I can count all hooks used by this app and there are ~ 15 file hooks. Many of them are hooked into "not allowed by v5" areas. So how? 🙂

Link to comment
Share on other sites

  • Management
10 minutes ago, DawPi said:

I'm just curious, @Daniel F as far I remember you wrote that your SEO app will be ported into v5. But how? I can count all hooks used by this app and there are ~ 15 file hooks. Many of them are hooked into "not allowed by v5" areas. So how? 🙂

He will stare at me without blinking until I add in new tools. He can be quite scary.

Link to comment
Share on other sites

  • Management
33 minutes ago, teraßyte said:

No matter what awesome tools you may have in place, being unable to overload (almost) all classes like before is a huge issue.

But it can’t continue. In the past, we’ve changed the signature params in getItemsWithPermissions() and had to patch the release as tickets pile up as apps which overload that just break.

Internally we have a rule not to touch function params of commonly hooked methods. It means we can’t make changes to our PHP code without breaking loads of client sites. This means we can’t clean up and modernise our own code.

Just now, Charles said:

Sure. Basically, when we think Daniel, we think llamas.

Pretty sure it’s alpacas.

Link to comment
Share on other sites



×
×
  • Create New...