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.
Firing events for minor things like course view would hurt performance a lot.
What exactly are you trying to do?
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!
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.)
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
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.
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.
As one of the Drupal advocates around here I will also add my two cents.
For online documentation for a seasoned developer like you the Drupal API Reference might be the best place to start.
And for reading away from the screen I would recommend Pro Drupal Development, Second Edition by John K. VanDyk.
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 )
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).
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.
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.
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?
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.
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
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.
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.
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.
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)?