Triggering Events / Hooks

Triggering Events / Hooks

by Paul Stanyer -
Number of replies: 13
Does anyone know if there are any plans for adding an event observing system or "hooks" type functionality to the moodle code to enable modules to react to events in the page? Perhaps this is already in place, but I simply haven't noticed it - I've mostly been using 1.8.x versions so could be in 1.9?

I sometimes find it very difficult to modify the behaviour of moodle code without having to resort to editing core files, which is less than ideal. Of course, if I do have to do this I make sure I only add a single line call to a function, but it would obviously be much better if I could just register for an "Event", or "Hook".

So for example, you wish to capture specific user and course related data, but only when the student enters a specific course. Ideally when course/view.php is browsed to, the code could fire and 'coursePageView' event. Our moodle module will have registered to recieve these events, and is then notified that it has occured, and can redirect to a page where the user can enter these details, and is then redirected back to the course page.

To make this effective there would obviously need to be a lot of events triggers added to a lot of files, but we could take the route of Montala, where events are suggested as and when needed by developers, and then incorporated into the code for the next release? See: http://rswiki.montala.net/index.php/Writing_plugins. Clearly, a much bigger user base for Moodle would complicate this process though.

After gibbering on for so long, I fully expect this feature to already have been requested and/or implemented, but I could find anything after searcing the moodle Tracker instance, so I thought I'd ask direct on here first.

Average of ratings: -
In reply to Paul Stanyer

Re: Triggering Events / Hooks

by Tim Hunt -
Picture of Core developers Picture of Documentation writers Picture of Particularly helpful Moodlers Picture of Peer reviewers Picture of Plugin developers
There are events triggered in Moodle in 1.9, but only for big significant actions. For example 'course created' or 'user enrolled in course'.

Firing events for minor things like course view would hurt performance a lot.

What exactly are you trying to do?
In reply to Tim Hunt

Re: Triggering Events / Hooks

by Paul Stanyer -
Hi Tim, thanks for your reply.

At the moment, nothing. This was just an observation after working with many systems that employ the Observer pattern or hooks approach to allow for flexible plug-in design, that it is something which Moodle could benefit from having. I was just intending to open up some discussion as to whether it had been considered or not, and any reasons why it owuldn't be benefitial.

I understand your concerns about performance, but I do not think this would be as big an issue as you would think. A lightweight simplistic system would just call the functions on objects that have registered for an event, so with the example of a courseview event, 2 modules may have registered for the event, this is just two extra function calls.

Now, I realise these functions could take a long time to execute, but my argument here is this; those calls would be made anyway if that functionality is required, but they would be made by hacking a function call in the appropriate place in the code instead, which is a much worse situation.

I don't think the process of actually triggering an event would be processor intensive, or at least it shouldn't need to be - I've not actually had a chance to look at the code behind the events in 1.9, which I'll try and look at when I next get the chance, but thanks for pointing that out!
In reply to Paul Stanyer

Re: Triggering Events / Hooks

by Tim Hunt -
Picture of Core developers Picture of Documentation writers Picture of Particularly helpful Moodlers Picture of Peer reviewers Picture of Plugin developers
You don't say much about what types of system you have worked on in the past. (Which makes it hard for me to use point 4. of Pedagogy#Social_Constructionism_as_a_Referent to target my reply).

I have done enough Java programming to agree with you that the Observer pattern is great - for standalone desktop application. It is a great way to keep the state of various things synchronised in memory.

However, Moodle is a multi-user, online application, using a stateless protocol (namely HTTP).

Therefore, Moodle works by keeping all its state in the database, with each page view acting a bit like a mini transaction. That neatly deals with all the complex multi-user issues.

If one bit of code needs to know some fact about the current state of things, it queries it from the DB as part of serving the page. And significant information about what users are doing to with Moodle (e.g. a new forum post, logging information, user_lastaccess) is updated in the database as the as the request is handled. And all the in-memory state is discarded after serving each request (with the small exception of session, which can mostly be seen as a performance cache.)
In reply to Tim Hunt

Re: Triggering Events / Hooks

by gonen r -
Hi Tim, Paul,

I don't exactly know what Paul is referring to, but I do understand the need of hooks.

As a Drupal developer, I have the freedom to interfere with the basic behavior of the system, and that without touching the core at all.

As an example, let's say I'd like to add a CAPTCHA field to all forms in the system.
In Drupal, all I have to do is develop a small module which implements 1 function called
hook_form_alter()
with this function I can add/remove/change fields in every form which is being generated in Drupal (no matter by who it is being generated), as well as deal with validation of all forms (to check the captcha after submit).

As far as I could see, in moodle I don't have the option to do such thing without changing some core files.

As I see it, these kind of "triggers" do not rely on DB (since it's a runtime render thing) and I believe it could improve the modularity of moodle.

In reply to gonen r

Re: Triggering Events / Hooks

by Tim Hunt -
Picture of Core developers Picture of Documentation writers Picture of Particularly helpful Moodlers Picture of Peer reviewers Picture of Plugin developers
I would really like to know more about Drupal, because from the little I have seen, it has an interesting architecture.

However, the one time I did want to hack something in Drupal, I found it impossible. There is so much clever indirection and dispatching going on that after much futile banging-head-against-a-wall, I had to give up. I just could not work out which bits of code were being executed when a particular page was being rendered. Therefore, I could not work out what I should change.

Now, with Moodle, if you want to know what code is executed when you are posting to a forum, well, you look at the URL, and you can see it is mod/forum/post.php - and you can walk through that code and see what library functions it calls.

That makes working out how to tweak the code much easier, even if you have to change core code to change what you wnat.

Of course, this is an unfair comparison, I have been working on Moodle code for years. I looked at Drupal code for a few hours. Of course I am better at finding my way around Moodle code.

However, in a open source project, there is a lot be to said for simple-minded code that anyone can understand, rather that deep code that requires a computer science degree to make head or tail of.
In reply to Tim Hunt

Re: Triggering Events / Hooks

by gonen r -
I would add to Frank, and say that Drupal has a weird learning curve.

At the beginning you feel like banging the head in the wall (been there, done that),

After a while (lets say 2 weeks of playing, trying and learning) you think you are a drupal master (well, you're NOT - been there, done that too smile)

When you leave the "I'm a drupal master" phase you realize that Drupal has much to offer and you have much more to learn (although it's easier at this point)

If you want some more info (or help or some guidance) I'd be more than happy to help.

Regarding your last comment (about easy-code is good when open-source), I do not fully agree with you.
Although having a simple code might help you get "hardcore" faster, a smart system (although with a deep code) can allow maximum modularity in a way that you only need to learn the architecture and you don't have to look at even 1 line of core code in order to extend the product (not to mention much easier upgrades when you don't worry about breaking anything in the core).




In reply to gonen r

Re: Triggering Events / Hooks

by Dan Poltawski -
I worked with drupal before moodle and agree with the positives and negatives mentioned here.

The drupal learning curve is steep, but the 'everything is a hook' design brings great power & i've frequently thought it would be useful in moodle.

Example: I've been asked various times for ways to control the messaging feature - limiting who can talk to who, hours of the day they can talk to each other and that sort of thing. Its not currently possible to do this without hacking core. Another example might be the recent post about reauthorisation which Jason Cole posted about.

The approach in moodle is generally to find the points where extensibility is needed and create a plugin types for these areas which can be extended. As moodle is a very structured learning environment rather than a general purpose content management system this seems to be a good way of keeping the experience pretty consistent, the learning curve less steep and doesn't present a huge limitation in the context of moodle.
In reply to Paul Stanyer

Re: Triggering Events / Hooks

by Martin Dougiamas -
Picture of Core developers Picture of Documentation writers Picture of Moodle HQ Picture of Particularly helpful Moodlers Picture of Plugin developers Picture of Testers
I think possibly what has been missed here is that we already have an events API:

Development:Events

That will give you the gist of it. Unfortunately some proper "how to use" documentation has not been written yet.

If there are events that people really want added to core, file new issues in Moodle Tracker please and vote on them. (eg MDL-9983 was one in the past)

However, for one-off purposes these events are really easy to add (hack) to your local install. The code is minimal.
Average of ratings: Useful (1)
In reply to Martin Dougiamas

Re: Triggering Events / Hooks

by Frank Ralf -
Hello, Martin,

Thanks for the hint!

The only thing which strikes me as odd is the fact that this documentation is categorized as Obsolete Design:

"This article is a design document which is no longer in use, the code it describes having been written and added to the Moodle codebase, or simply considered then abandoned. The information it contains is likely to be out of date, especially API and Database Schema specifications."

I suppose the API description is still valid?

Kind regards,
Frank
In reply to Frank Ralf

Re: Triggering Events / Hooks

by Martín Langhoff -

Looking at the wiki I just found the same 'obsolete' marker on the page. The code is in 1.9 and CVS HEAD, and roughly matches the API described there. And apparently the Portfolio uses it (maybe Penny has patches to eventslib in a git repo somewhere...?)

My suspicion is that it's marked obsolete because the API as designed is flawed and we'll want to change it. Nico marked it obsolete in October, right after the moodlemoots.

The "one event per object" model is good for very small systems, and Moodle has irreversibly moved into the very large installations realm. It needs triggers on the edge condition not on every event. (More about that in my recent post about the 10K messages...)

Right now I'm drafting code that uses the 1.9 API (so I guess I'll learn whether it's actually badly broken) but I need it to scale well. So my plan is to

  • Register an event handler that just logs things. Possibly set it to 'cron'.
  • Add code in admin/cron.php that execs after eventslib and aggregates the logged events and acts on them.
In reply to Martín Langhoff

Re: Triggering Events / Hooks

by Penny Leach -
Did somebody say my name? wink

Yes, the portfolio uses it in 2.0. Petr told me off for using events to do scheduling, but as we don't have a better way to schedule things, tough smile

As far as I know it works fine in 1.9 , I was working with it recently. I seem to remember the event queue not being flushed in cron (!?) and maybe I fixed that. I also added support for local/ event handers.

See MDL-17442
In reply to Paul Stanyer

Re: Triggering Events / Hooks

by Juho Jaakkola -

I know this is a pretty old thread but I just decided to open up the subject again.

I've just started working as Moodle plugin developer (with Moodle 2.3.1) and I'm disappointed that I haven't found the kind of hooks system and modularity as I was expecting from Moodle.

 

Some examples

1. When user requests a new password, instead of just sending an email Moodle core would ask if plugins have anything to say for this. There could for example be a plugin that would want to send an SMS message instead of an email.

2. I would like to dynamically add any new menu items from my plugin. For example: My Courses > Some course > Myplugin stuff.

3. I go to page My courses > Some course > Participants. On this page it is possible to select users and then choose an action from the dropdown box with the options "Send message", "Add a new note" and "Add a common note". I would like to add a new option to the list, but this is impossible since the options list has been hard coded intsead of being dynamically generated.

At the moment I can't do any of these without messing with the core code.

For some people the solution is to just hack the core. However if you are a Moodle hosting company with n hundred customers, it is not an option. It is a nightmare if you have to manually reapply and test your hacks in the core every time you want to upgrade your Moodle version.

 

Performance

It' been said in this thread that firing events for minor things would hurt performance. Well it would if there were 100 plugins and each of them wanted to run their own functionalities every time an event is triggered. In practise however there really wouldn't be that many events per one action. And if the event handlers would be registered in advance the calling event trigger wouldn't have to ask each of the 100 plugins whether they want to do something but instead it would just trigger the event handlers in the 1-3 plugins that have registered for that event.

 

Implementation in Elgg

Lately I have been working a lot with Elgg (which is a open source social networking engine) so I use it as an example. Elgg has both an events system and a plugin hook system. 

Events are triggered when anything is created, updated or deleted or when the Elgg framework is loading. http://docs.elgg.org/wiki/Elgg_Events

Plugin hooks are more general purpose than events but basically they are triggered when an action has occurred and parts of that action can be added to or overridden by a plugin. http://docs.elgg.org/wiki/Plugin_Hooks

Here's a list of all available Elgg events: http://docs.elgg.org/wiki/What_events_are_available_in_the_Elgg_core%3F
And plugin hooks: http://docs.elgg.org/wiki/What_plugin_hooks_are_available_in_the_Elgg_core%3F

Similar kind of system is something I would like Moodle to also have.

(Drupal also has a very flexible hooks system but I haven't worked with Drupal for a long time so I won't pick any examples from there.)

 

Plans for Moodle?

Are there currently any long terms plans for adding more flexible and extensive hooks system(s)?