Hello, I'm back from honeymoon and subscribed to the development mailing list. Spent the last couple days catching up with personal e-mail, scheduled some Drupal related Skype calls, accepted a number of speaking gigs, and am reading parts (but not all) of the mailing list archives. So, let's rock and roll! PS: thanks for all the congratulations and presents. Much appreciated. -- Dries Buytaert :: http://www.buytaert.net/
One aspect of the FAPI drives me mad: mod_a_ form_alter() { // wants to do something based on what is in the form } mod_b_form_alter() { // adds something to the form which would potentially trigger something in mod_a } The only way to get this to work is by tweaking the weight in the system table. Yuck. There is no way that we will ever resolve all the ordering problems with our hook based system--- they plague every hook we have. --BUT-- Other hooks have help by passing an $op and calling the hook more than once. Perhaps form_alter needs an $op { 'add', 'process' }. Or we need two hooks: hook_form_additions hook_form_alter I predict that the ordering problem in form_alter will become acute very soon. Many people are just waking up to the possibilities the new FAPI holds. cheers, Robert
Op dinsdag 18 april 2006 01:01, schreef Robert Douglass:
One aspect of the FAPI drives me mad: ... The only way to get this to work is by tweaking the weight in the system table. Yuck.
Yes, I was unpeasantly surprised by this rough edge, too.
There is no way that we will ever resolve all the ordering problems with our hook based system--- they plague every hook we have. --BUT-- Other hooks have help by passing an $op and calling the hook more than once. Perhaps form_alter needs an $op { 'add', 'process' }. Or we need two hooks:
hook_form_additions hook_form_alter
I predict that the ordering problem in form_alter will become acute very soon. Many people are just waking up to the possibilities the new FAPI holds.
IMO we should look into two new directions. This will a) bring us closer to (emulating) OOP and b) allow us better control in all places. * roundtrip calls (or any other names): A hook returns roundtrip = TRUE if it wants the hook to be invoked again. mymodule_load() adds something and sets roundtrip = TRUE. node_load() would be re-invoked completely, but now with the additioanl info injected by mymodule_load() * (re) define all the messages that an Object in OOP has. We could/should have hook calls for each and every one of them. Examples: init load create read update insert delete ... Then we make sure that drupal calls ALL these $ops for ANY hook, at ALL times. This wll make hooks more consistent across Drupal, give us a central place to cache/improve/change hooks and so on. Both are big tasks, but if we want to proceed forward, I think this bumb needs to be taken. Drupal is not OOP for a good reason, but that doe not mean we should not take some good parts from OOP and implement them. Weighting modules does not cut it. In fact, I dislike that weighting, because I see it as a hack, that will hold us back from getting 'real' improvemets to the hook system done. Simply because we can now say 'this is not needed, because you can use the weight hack', these improvements are not 'itching' enough anymore. Bèr -- [ End user Drupal services and hosting | Sympal.nl ]
* roundtrip calls (or any other names): A hook returns roundtrip = TRUE if it wants the hook to be invoked again. mymodule_load() adds something and sets roundtrip = TRUE. node_load() would be re-invoked completely, but now with the additioanl info injected by mymodule_load() yes, might work, but is not going to improve by much the current state
* (re) define all the messages that an Object in OOP has. We could/should have hook calls for each and every one of them. Examples: init load create read update insert delete ... Then we make sure that drupal calls ALL these $ops for ANY hook, at ALL times. This wll make hooks more consistent across Drupal, give us a central place to cache/improve/change hooks and so on. $ops are messages, hooks are a kind of a message as well. Implementing a fixed, well defined set of messages called on every single hook call will make it a performance nightmare.
A far better solution, from a flexiibility point of view, is to be able to schedule for invoke a new hook. For example, if something wants to run before load, it can schedule in init "my_post_init_hook". This way it is guaranteed to run after init and before load. It houldn't be a lot of work, and addresses, at least partially, the flexible page workflow ramblings. The dowenside of this is that it will make debugging code harder. But that is quite hard anyway, and needs to be addressed. Cheers, Vlado
Op dinsdag 18 april 2006 11:14, schreef drupal:
$ops are messages, hooks are a kind of a message as well. Implementing a fixed, well defined set of messages called on every single hook call will make it a performance nightmare.
I do NOT want to turn this into an OOP flamewar, so if you want to say anything against of for OOP please open a new thread. That said, one thing i was impressed by, is that modules in a Ruby on Rails environment (railfrog, or typo) are extremely small. A typical module weights only four or five lines of code. The biggest reason is its OOP implementation. Messages sent to objects are, indeed, a very very powerfull tool. Because you need not implement all sorts of checks and you need not know anything about the object. All you need to know is the part you want to modify/add to/remove etc and do that. The good part is that automagically everything (users, categories, posts, comments), sort-of, becomes a node, with a sort-of nodeapi and a sort-of node-lifecycle and even a sort-of modular access control. However, when I brainstormed about how such power could be implemented into a Drupal hook system, I came to Valdo's conclusion: having an object oriented system built as hook system into Drupal, on top of PHP is simply never going to cut it, performance being the biggest issue. My only solution for this was caching and registration (see below).
A far better solution, from a flexiibility point of view, is to be able to schedule for invoke a new hook. For example, if something wants to run before load, it can schedule in init "my_post_init_hook". This way it is guaranteed to run after init and before load. It houldn't be a lot of work, and addresses, at least partially, the flexible page workflow ramblings. The dowenside of this is that it will make debugging code harder. But that is quite hard anyway, and needs to be addressed.
Whether we go for a set of predefined $ops or in some post-during-pre hook system does not really matter. The fact that a module registers hooks does matter. For performance that is. This, however, is a standalone project, and has little to do with the initial thought of this thread, to make form_alter more flexible. (Though it is a requirement if we go for a huge set of 'messages'/$ops and hooks). Back to the point: What if we re-do the lifecycle of a node ins the form system? That would mean you have form_alter($op) with: $op = load (collecting the form, change) $op = view (theming, changing the behaviour, reordering and so) $op = insert (data is inserted) $op = validate (valdation) At least, this gives consistency wit hthat part we all (should) know: nodeapi. Bèr -- PGP ber@webschuur.com http://www.webschuur.com/sites/webschuur.com/files/ber_webschuur.asc PGP berkessels@gmx.net http://www.webschuur.com/sites/webschuur.com/files/ber_gmx.asc
Back to the point: What if we re-do the lifecycle of a node ins the form system? That would mean you have form_alter($op) with: $op = load (collecting the form, change) $op = view (theming, changing the behaviour, reordering and so) $op = insert (data is inserted) $op = validate (valdation)
I think that syntax is a bit inconsistent with form api, but the idea is right on. I'll work on a patch for 4.8 (if noone beats me to it) that gets of the insert/update/validate ops of nodeapi. They will be replaced with #submit and $#validate handlers. Fapi is yet ready to handle view and load hooks but I would not be surprised if it goes in that direction. When it does, those nodeapi ops will be deprecated as well. The formn api is a nice callback system just like whats needed here.
Fapi is yet ready to handle view and load hooks but I would not be surprised if it goes in that direction. When it does, those nodeapi ops will be deprecated as well. The formn api is a nice callback system just like whats needed here. yes, that's spot on. Actually you can use fapi, even now, for an alternative view and load functionality - you just don't have default "views" for those. The problem is it doesn't know of the default view and load hooks. But as you say, the nodeapi can easily get deprecated.
Back to the point: What if we re-do the lifecycle of a node ins the form system? That would mean you have form_alter($op) with: $op = load (collecting the form, change) $op = view (theming, changing the behaviour, reordering and so) $op = insert (data is inserted) $op = validate (valdation)
Not a good idea. form_alter has nothing to do with "view" or "insert". If you want form_alter ordering then do form_alter ordering. Phases: a) Calling form_alter with $op, let's say "collect". Returned are information "I want to be called after X". b) build a directed graph out of it. c) create a walk.
I think that syntax is a bit inconsistent with form api, but the idea is right on. I'll work on a patch for 4.8 (if noone beats me to it) that gets of the insert/update/validate ops of nodeapi. They will be replaced with #submit and $#validate handlers.
This actually has nothing to do with form_alter but yes, this direction is natural. Btw. the http://api.drupal.org/api/head/function/hook_nodeapi speaks about 'execute' instead of 'submit', someone plz correct it.
Karoly Negyesi wrote:
Back to the point: What if we re-do the lifecycle of a node ins the form system? That would mean you have form_alter($op) with: $op = load (collecting the form, change) $op = view (theming, changing the behaviour, reordering and so) $op = insert (data is inserted) $op = validate (valdation)
Would I be all wet to suggest the following as a thought exercise? In the name of performance, as well as to enable ordering and repeat callbacks, a lot more sophistication and work could be done at module enable time. What if, instead of "call module hook if it exists" calls, we built an ordered list of callbacks for each hook at module enable time, and did our hook calls by walking that list (graph)? Enabling a module would add its hooks to lists stored in a compact, high-performance format in a cache / db table. Callbacks would walk those lists. Necessary enable logic would allow module to place itself in a list more than once if needed for re-invoking / roundtrip scenarios. This might even improve bootstrap performance. Does such a scheme help? Or have I missed some crucial point? :-/ ..chrisxj
On 18 Apr 2006, at 5:42 PM, Chris Johnson wrote:
What if, instead of "call module hook if it exists" calls, we built an ordered list of callbacks for each hook at module enable time, and did our hook calls by walking that list (graph)? Enabling a module would add its hooks to lists stored in a compact, high- performance format in a cache / db table. Callbacks would walk those lists. Necessary enable logic would allow module to place itself in a list more than once if needed for re-invoking / roundtrip scenarios.
Which is why i mentioned hook_callback, and hooks as automatic callbacks. The only problem with caching callbacks, is the callback arguments. They are set when you cache the callbacks, and not when you call the callbacks. -- Adrian Rossouw Drupal developer and Bryght Guy http://drupal.org | http://bryght.com
On 18 Apr 2006, at 11:14 AM, drupal wrote:
$ops are messages, hooks are a kind of a message as well. Implementing a fixed, well defined set of messages called on every single hook call will make it a performance nightmare. my idea is to separate the callback registration out of the menu system, and make all the callbacks we can address (ie: nodeapi/load) be stacked onto the callbacks via the forms api callback format. Hooks are just automatic callbacks.
ie: $callbacks['nodeapi/load']['my_function_here'] = array('args', 'here'); Also, keep in mind these are flat lists. not nested arrays like forms api. They don't need to be processed into the tree like the menu array does. -- Adrian Rossouw Drupal developer and Bryght Guy http://drupal.org | http://bryght.com
Adrian Rossouw wrote:
my idea is to separate the callback registration out of the menu system,
Putting aside the specifics of this thread topic and zeroing in on Adrian's context-setting comment, I think this is a _great_ idea. When I finally had the time to dig into and learn Drupal as a (non-OOP) framework, it took me a long time to really understand the _generality_ of Drupal's callback registration system. Its "home" in the menu system suggested that as callbacks were all (and only) about the menuing. I believe Adrian's suggestion would have the effect of easing new developers into the fold without them having to learn our secret handshake ("Well, it's there because, well, it's always been there..."). --Sohodojo Jim--
Robert Douglass wrote:
hook_form_additions hook_form_alter
Alternatively, you can do what I've done and add an '#after_build' to which will do almost exactly what you want. <?php my_hook_form_alter(...) { $form['my_addition'] = array(...stuff...); $form['my_addition']['#after_build'] = 'my_function_call'; // or maybe the key => args notation once after_build is modified to be an array of calls like everything else. } The downside of course is that you can only have one #after_build...per form element. But each form element can have one.
On Tue, 2006-04-18 at 07:41 -0700, Earl Miles wrote:
Robert Douglass wrote:
hook_form_additions hook_form_alter
Alternatively, you can do what I've done and add an '#after_build' to which will do almost exactly what you want.
<?php
my_hook_form_alter(...) { $form['my_addition'] = array(...stuff...); $form['my_addition']['#after_build'] = 'my_function_call'; // or maybe the key => args notation once after_build is modified to be an array of calls like everything else. }
The downside of course is that you can only have one #after_build...per form element. But each form element can have one.
The upside... the way FormAPI is built we don't have to iterate through all the modules looking for 'my_function_call'. unrolling some inner loops would probably be good for drupal, expecially in our callback systems. Even then Drupal's hooks, whether anyone has stated it or not, are events. A lot of event driven systems do make their modules register callbacks to events. I'm sure some of the more mature event systems have developed ways to cope with ordering issues. FormAPI is a really nice since in a way it provides callback registration. btw, I'm in the form_alter phases camp.. form_alter($op,$node, $form) or similar.
On Mon, 2006-04-17 at 10:09 +0200, Dries Buytaert wrote:
Hello,
I'm back from honeymoon and subscribed to the development mailing list. Spent the last couple days catching up with personal e-mail, scheduled some Drupal related Skype calls, accepted a number of speaking gigs, and am reading parts (but not all) of the mailing list archives. So, let's rock and roll!
PS: thanks for all the congratulations and presents. Much appreciated.
-- Dries Buytaert :: http://www.buytaert.net/
While you were away we made Drupal object oriented and ported it to java. ;)
Darrel O'Pry wrote:
On Mon, 2006-04-17 at 10:09 +0200, Dries Buytaert wrote:
Hello,
I'm back from honeymoon and subscribed to the development mailing list. Spent the last couple days catching up with personal e-mail, scheduled some Drupal related Skype calls, accepted a number of speaking gigs, and am reading parts (but not all) of the mailing list archives. So, let's rock and roll!
PS: thanks for all the congratulations and presents. Much appreciated.
-- Dries Buytaert :: http://www.buytaert.net/
While you were away we made Drupal object oriented and ported it to java. ;)
You should've seen the design he drew up for Scheme.
participants (15)
-
Adrian Rossouw -
Bèr Kessels -
Chris Johnson -
Darrel O'Pry -
Dries Buytaert -
drupal -
Earl Miles -
Gildas Cotomale -
Karoly Negyesi -
Khalid B -
Konstantin Käfer -
Moshe Weitzman -
Robert Douglass -
Sohodojo Jim -
Vladimir Zlatanov