Hi, In the following page http://api.drupal.org/api/HEAD/function/hook_nodeapi it says: "If you are writing a node module, do not use this hook to perform actions on your type of node alone. Instead, use the hooks set aside for node modules, such as hook_insert() and hook_form()." My question is why is it better to use the standalone functions instead of the centralized one? Regards, Fernando Silva
In the following page http://api.drupal.org/api/HEAD/function/hook_nodeapi it says: "If you are writing a node module, do not use this hook to perform actions on your type of node alone. Instead, use the hooks set aside for node modules, such as hook_insert() and hook_form()."
My question is why is it better to use the standalone functions instead of the centralized one?
Node hooks are run before nodeapi hooks. Other modules that are hooking into your node type expect your module to have done its work already.
Fernando, I too had trouble with this concept when I first started working with Drupal. The most simplistic description I can give of the difference is that hook_insert()/hook_update() and friends are for use in a module that defines a node type. hook_nodeapi() is for use in modules that augment or extend node types defined by other modules. By example, the page module defines a node of type 'page'. The event module augments any node type, including page, to add date information to the node. Scott Fernando Silva wrote:
Hi,
In the following page http://api.drupal.org/api/HEAD/function/hook_nodeapi it says: "If you are writing a node module, do not use this hook to perform actions on your type of node alone. Instead, use the hooks set aside for node modules, such as hook_insert() and hook_form()."
My question is why is it better to use the standalone functions instead of the centralized one?
Regards, Fernando Silva
In Drupal 5.0, the difference between hook_insert() / hook_update() and friends, and hook_nodeapi(), is smaller than ever; and there is less need than ever to actually still have the former in core. With the new CCK-partially-in-core features, it's likely that before long, there will be no such thing as module-defined node types. There will only be user-defined node types. All four of the module-defined node types that are still in 5.0 core (blog, book, forum, and poll) can and should be made history, and in their place we can just have hook_nodeapi() implementations, that allow the same functionality to be available to custom node types (there's also a push to make poll a CCK field type, rather than a node-type-ish thing). To, in summary: your confusion is understandable! And, since we're pushing for more widespread use of custom content types, I would advise trying to use only hook_nodeapi() in your contrib modules from now on, unless you have a use case where module-defined node types are really appropriate (and such use cases are rare). Cheers, Jaza. On 1/3/07, Fernando Silva <fsilva.pt@gmail.com> wrote:
Hi,
In the following page http://api.drupal.org/api/HEAD/function/hook_nodeapi it says: "If you are writing a node module, do not use this hook to perform actions on your type of node alone. Instead, use the hooks set aside for node modules, such as hook_insert() and hook_form()."
My question is why is it better to use the standalone functions instead of the centralized one?
Regards, Fernando Silva
I add my voice to Jaza. Unifying these two APIs in the future is a good thing.
node_load() if ($extra = node_invoke($node, 'load')) { foreach ($extra as $key => $value) {$node->$key = $value;}} if ($extra = node_invoke_nodeapi($node, 'load')) { foreach ($extra as $key => $value) {$node->$key = $value;}} node_save() node_invoke($node, 'insert'); node_invoke_nodeapi($node, 'insert'); node_invoke($node, 'update'); node_invoke_nodeapi($node, 'update'); node_delete() node_invoke($node, 'delete'); node_invoke_nodeapi($node, 'delete'); The conclusion is that the "nodeapi" is the way to do things, and that the other way was just keeped as unnecessary compatibility, and should be quickly deprecated. Also, I think that http://api.drupal.org/api/HEAD/function/hook_nodeapi should be updated to state that there is really no diference between those two APIs, and that the later is much more complete than the former. Thanks, Fernando Silva On 1/3/07, Khalid B <kb@2bits.com> wrote:
I add my voice to Jaza. Unifying these two APIs in the future is a good thing.
Fernando Silva wrote:
node_load() if ($extra = node_invoke($node, 'load')) { foreach ($extra as $key => $value) {$node->$key = $value;}} if ($extra = node_invoke_nodeapi($node, 'load')) { foreach ($extra as $key => $value) {$node->$key = $value;}}
node_save() node_invoke($node, 'insert'); node_invoke_nodeapi($node, 'insert'); node_invoke($node, 'update'); node_invoke_nodeapi($node, 'update');
node_delete() node_invoke($node, 'delete'); node_invoke_nodeapi($node, 'delete');
The conclusion is that the "nodeapi" is the way to do things, and that the other way was just keeped as unnecessary compatibility, and should be quickly deprecated.
I don't think that this is a valid conclusion. /If/ you create your own node type and it has an extra table you should use the basic hooks. Because then your node will already be fully populated once it gets into nodeapi and other modules can act on the full node. Cheers, Gerhard
I do not quite understand that. Let's assume the "example.module" that creates a new node type. I'll must use the "example_load()" hook to load some data from an extra table: function example_load($node) { $additions = db_fetch_object(db_query('SELECT * FROM {mytable} WHERE nid = %s', $node->nid)); return $additions; } But then, if I use "example_nodeapi()" instead the code should be something like this: function example_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) { switch ($op) { case 'load': $additions = db_fetch_object(db_query('SELECT * FROM {mytable} WHERE nid = %s', $node->nid)); return $additions; } } It's the exact same code, but we also need to have sure that both API functions run at exactly the places. If we go to the node.module, in the node_load() function we have at the lines 525 and 531 we have *exactly* the same code to invoke both APIs. This means, that when the nodeapi() is invoked with other $op it is already loaded. Or else, you can be saying that if another module (eg. "intercept.module") wants to intercept the 'load', the node will not be 'loaded': * example.module implements a new node type * node_load() will load example.module new node type by doing hook_load() * intercept.module will do something to the example.module node by using nodeapi() Is this a correct conclusion, or I am missing something? This seems to me a bit strange, because in this case the only reason we have hook_load() and hook_nodeapi('load') is because we can't get a way to enforce the correct 'loading' order with hook_nodeapi. Or can we?! If with the new "install system" we have module dependencies, why can't we have a way to give priorities to those dependencies... As a side note, this behaviour is implemented since Drupal 4.6 Thanks, Fernando Silva On 1/3/07, Gerhard Killesreiter <gerhard@killesreiter.de> wrote:
Fernando Silva wrote:
node_load() if ($extra = node_invoke($node, 'load')) { foreach ($extra as $key => $value) {$node->$key = $value;}} if ($extra = node_invoke_nodeapi($node, 'load')) { foreach ($extra as $key => $value) {$node->$key = $value;}}
node_save() node_invoke($node, 'insert'); node_invoke_nodeapi($node, 'insert'); node_invoke($node, 'update'); node_invoke_nodeapi($node, 'update');
node_delete() node_invoke($node, 'delete'); node_invoke_nodeapi($node, 'delete');
The conclusion is that the "nodeapi" is the way to do things, and that the other way was just keeped as unnecessary compatibility, and should be quickly deprecated.
I don't think that this is a valid conclusion. /If/ you create your own node type and it has an extra table you should use the basic hooks. Because then your node will already be fully populated once it gets into nodeapi and other modules can act on the full node.
Cheers, Gerhard
Fernando, It is, as you suggested about halfway down, about guaranteeing the calling order. If I write a module that defines a new node type, I want to guarantee that my loading code is called before any other module attempts to modify the node through hook_nodeapi(). This is where hook_load()/hook_save() et. al. are necessary. For the purpose of being a module author, hook_nodeapi() is called on every active module in an arbitrary order. While it is the system weights order internally, as a module author you cannot guarantee that your module will be run at a given weight relative to other modules that are using hook_nodeapi() to modify it, even with a fresh new install system. The more modules that are active on a site, the more load-order challenges you may have. I only rely on system weight for modules on sites where I've written a module that will only run on that site and nowhere else. hook_load() is a very simple (and clean) solution to this ordering challenge. For a simple deployment where a node-defining module is not augmented by any other module I can see where one could argue that hook_load() and hook_nodeapi(op=load) are identical. When you get into a site with more than a handful of custom/contributed node types they become different in a crucial and subtle way. Scott www.folkjam.org Fernando Silva wrote:
I do not quite understand that. Let's assume the "example.module" that creates a new node type.
I'll must use the "example_load()" hook to load some data from an extra table: function example_load($node) { $additions = db_fetch_object(db_query('SELECT * FROM {mytable} WHERE nid = %s', $node->nid)); return $additions; }
But then, if I use "example_nodeapi()" instead the code should be something like this: function example_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) { switch ($op) {
case 'load':
$additions = db_fetch_object(db_query('SELECT * FROM {mytable} WHERE nid = %s', $node->nid)); return $additions; } }
It's the exact same code, but we also need to have sure that both API functions run at exactly the places. If we go to the node.module, in the node_load() function we have at the lines 525 and 531 we have *exactly* the same code to invoke both APIs.
This means, that when the nodeapi() is invoked with other $op it is already loaded. Or else, you can be saying that if another module (eg. "intercept.module") wants to intercept the 'load', the node will not be 'loaded': * example.module implements a new node type * node_load() will load example.module new node type by doing hook_load() * intercept.module will do something to the example.module node by using nodeapi()
Is this a correct conclusion, or I am missing something?
This seems to me a bit strange, because in this case the only reason we have hook_load() and hook_nodeapi('load') is because we can't get a way to enforce the correct 'loading' order with hook_nodeapi.
Or can we?! If with the new "install system" we have module dependencies, why can't we have a way to give priorities to those dependencies...
As a side note, this behaviour is implemented since Drupal 4.6
Thanks, Fernando Silva
On 1/3/07, Gerhard Killesreiter <gerhard@killesreiter.de> wrote:
Fernando Silva wrote:
node_load() if ($extra = node_invoke($node, 'load')) { foreach ($extra as $key => $value) {$node->$key = $value;}} if ($extra = node_invoke_nodeapi($node, 'load')) { foreach ($extra as $key => $value) {$node->$key = $value;}}
node_save() node_invoke($node, 'insert'); node_invoke_nodeapi($node, 'insert'); node_invoke($node, 'update'); node_invoke_nodeapi($node, 'update');
node_delete() node_invoke($node, 'delete'); node_invoke_nodeapi($node, 'delete');
The conclusion is that the "nodeapi" is the way to do things, and that the other way was just keeped as unnecessary compatibility, and should be quickly deprecated.
I don't think that this is a valid conclusion. /If/ you create your own node type and it has an extra table you should use the basic hooks. Because then your node will already be fully populated once it gets into nodeapi and other modules can act on the full node.
Cheers, Gerhard
All four of the module-defined node types that are still in 5.0 core (blog, book, forum, and poll) can and should be made history, and in their place we can just have hook_nodeapi() implementations I definitely agree, but envision some module ordering/weighting issues that will need to be worked out as we begin to unify these since you lose the pre-nodeapi hooks and have everything going at the same "time". chx has done some prelim work on this at http://cvs.drupal.org/viewcvs/drupal/contributions/sandbox/chx/weights.php?r... but not sure how far along it is.
Rob Roy Barreca Founder and COO Electronic Insight Corporation http://www.electronicinsight.com rob@electronicinsight.com Jeremy Epstein wrote:
In Drupal 5.0, the difference between hook_insert() / hook_update() and friends, and hook_nodeapi(), is smaller than ever; and there is less need than ever to actually still have the former in core. With the new CCK-partially-in-core features, it's likely that before long, there will be no such thing as module-defined node types. There will only be user-defined node types.
All four of the module-defined node types that are still in 5.0 core (blog, book, forum, and poll) can and should be made history, and in their place we can just have hook_nodeapi() implementations, that allow the same functionality to be available to custom node types (there's also a push to make poll a CCK field type, rather than a node-type-ish thing).
To, in summary: your confusion is understandable! And, since we're pushing for more widespread use of custom content types, I would advise trying to use only hook_nodeapi() in your contrib modules from now on, unless you have a use case where module-defined node types are really appropriate (and such use cases are rare).
Cheers, Jaza.
On 1/3/07, Fernando Silva <fsilva.pt@gmail.com> wrote:
Hi,
In the following page http://api.drupal.org/api/HEAD/function/hook_nodeapi it says: "If you are writing a node module, do not use this hook to perform actions on your type of node alone. Instead, use the hooks set aside for node modules, such as hook_insert() and hook_form()."
My question is why is it better to use the standalone functions instead of the centralized one?
Regards, Fernando Silva
On Tue, 2007-01-02 at 17:03 -0800, Rob Barreca wrote:
All four of the module-defined node types that are still in 5.0 core (blog, book, forum, and poll) can and should be made history, and in their place we can just have hook_nodeapi() implementations I definitely agree, but envision some module ordering/weighting issues that will need to be worked out as we begin to unify these since you lose the pre-nodeapi hooks and have everything going at the same "time". chx has done some prelim work on this at http://cvs.drupal.org/viewcvs/drupal/contributions/sandbox/chx/weights.php?r... but not sure how far along it is.
Rob Roy Barreca Founder and COO Electronic Insight Corporation http://www.electronicinsight.com rob@electronicinsight.com
We shouldn't head towards eliminating the default node hooks. They're really useful, and simple interfaces for building good content types. We shouldn't drop good, reliable, and simple because we've added super flexible on top. The features aren't exclusive. I could even see CCK using node hooks for purely user defined content types, and nodeAPI for extended content types. Some ordering problems can be overcome with the way the nodeAPI and node hooks currently work. I see the initial inclusion of custom fields in core as probably using a hook between the node hook invocation and nodeAPI invocation. Weights couldn't cleanly solve the ordering issues we have, especially where different API's implemented by the same module should be ran in different orders.
Speaking from personal experience, and having been confused by this duplication in the past, the problems as I see them are: a. More than one way of doing things. This means that there is duplication between the hook_something() and hook_nodeapi('something'). b. This duplication causes confusion to many developers (myself included). I will leave others to comment on the details codewise, but here are the options, in order of (my) preference: 1. Restricting node hooks to one way of doing things (hook_nodeapi). This means deprecating all hook_something() for node operations. This way there is no confusion. 2. Eliminating all the hook_something() that are duplicated by hook_nodeapi('something') and do not suffer the drawbacks listed above. This may mean leaving the node_load() hook, and maybe others, and that is fine by me. Less confusion. 2a. Same as 2, but eliminate the nodeapi('something') that has an indispensible hook_something() equivalent. This way we are back to one way of doing things. 3. If the present scheme MUST stay as it is, then I don't know if documentation improvement will be enough to overcome the drawbacks. Other ideas?
2a. Same as 2, but eliminate the nodeapi('something') that has an indispensible hook_something() equivalent. This way we are back to one way of doing things. But, we'll always need hook_nodeapi() so that my module can act on nodes defined by other modules. The confusion arises because you technically "could" write mynodemodule_nodeapi('insert') { if ($node->type == 'mynodemodule') ... } instead of mynodemodule_insert(), even though as it's been stated here that other nodeapi modules wouldn't have the full node available to them.
Rob Roy Barreca Founder and COO Electronic Insight Corporation http://www.electronicinsight.com rob@electronicinsight.com Khalid B wrote:
Speaking from personal experience, and having been confused by this duplication in the past, the problems as I see them are:
a. More than one way of doing things. This means that there is duplication between the hook_something() and hook_nodeapi('something').
b. This duplication causes confusion to many developers (myself included).
I will leave others to comment on the details codewise, but here are the options, in order of (my) preference:
1. Restricting node hooks to one way of doing things (hook_nodeapi). This means deprecating all hook_something() for node operations. This way there is no confusion.
2. Eliminating all the hook_something() that are duplicated by hook_nodeapi('something') and do not suffer the drawbacks listed above. This may mean leaving the node_load() hook, and maybe others, and that is fine by me. Less confusion.
2a. Same as 2, but eliminate the nodeapi('something') that has an indispensible hook_something() equivalent. This way we are back to one way of doing things.
3. If the present scheme MUST stay as it is, then I don't know if documentation improvement will be enough to overcome the drawbacks.
Other ideas?
Confusion arises from the fact that we misnamed hook_load etc. as they are not hooks. For these we find the one function we need to call and call it, case closed. They are even less of a hook since you can define what 'hook' will replaced with. In the past, it was the module name, unconditionally, thus it really showed some semblance to a hook but now can define it with a (real) hook. (Can't remember at 1am whether 4.7 had this already but 5.0 has it for sure) Compare its behaviour with hook_menu , hook_form_alter etc. Here, we iterate the modules that implement the hook. An arbitrary number of modules will be called. 'hook' is replaced with the implementing module name. I would kindly suggest steering the discussion towards better naming of hook_load & co. 'Callbacks with a predefined prefix' somewhat does not sound spiffy. Regards NK
On 1/3/07, Karoly Negyesi <karoly@negyesi.net> wrote:
(Can't remember at 1am whether 4.7 had this already but 5.0 has it for sure)
Not going to let you go easy. This is about lunchtime for you ;-) Compare its behaviour with hook_menu , hook_form_alter etc. Here, we iterate
the modules that implement the hook. An arbitrary number of modules will be called. 'hook' is replaced with the implementing module name.
I would kindly suggest steering the discussion towards better naming of hook_load & co. 'Callbacks with a predefined prefix' somewhat does not sound spiffy.
Thanks for the explanation. The point remains though that from a module developer point of view, they look the same. What Drupal does with them may be different, but as far as my module is concerned, they are points of call from Drupal to the module, and they overlap often. For the rename you are proposing, would something like this work? - move all hook_load() and friends into hook_othernodeapi($op), where $op is load, insert, delete, ...etc. - So, we have one real hook (hook_nodeapi($op)), and one callback (hook_othernodeapi($op)). (of course, othernodeapi has to be something better) This has the advantage of having only a maximum of two functions per module, with ops of course. One for node creation modules, and the other the regular nodeapi we know today. How about that?
For the rename you are proposing, would something like this work?
- move all hook_load() and friends into hook_othernodeapi($op), where $op is load, insert, delete, ...etc. - So, we have one real hook (hook_nodeapi($op)), and one callback (hook_othernodeapi($op)).
(of course, othernodeapi has to be something better) Good point Khalid. That type of consolidation would clear it up from a new developer's point of view. I think that has been a big part of the confusion that nodeapi is a mutli-function hook, while hook_insert/update/delete are separate. I think this is a good intermediary step.
AFAICT we're going to need some type of hook ordering/weighting like chx is proposing. But, I guess that is farther down the line and I should just shut up until that system comes to the forefront and we can analyze if there is any further simplification needed then. Rob Roy Barreca Founder and COO Electronic Insight Corporation http://www.electronicinsight.com rob@electronicinsight.com Khalid B wrote:
On 1/3/07, *Karoly Negyesi* <karoly@negyesi.net <mailto:karoly@negyesi.net>> wrote:
(Can't remember at 1am whether 4.7 had this already but 5.0 has it for sure)
Not going to let you go easy. This is about lunchtime for you ;-)
Compare its behaviour with hook_menu , hook_form_alter etc. Here, we iterate the modules that implement the hook. An arbitrary number of modules will be called. 'hook' is replaced with the implementing module name.
I would kindly suggest steering the discussion towards better naming of hook_load & co. 'Callbacks with a predefined prefix' somewhat does not sound spiffy.
Thanks for the explanation.
The point remains though that from a module developer point of view, they look the same. What Drupal does with them may be different, but as far as my module is concerned, they are points of call from Drupal to the module, and they overlap often.
For the rename you are proposing, would something like this work?
- move all hook_load() and friends into hook_othernodeapi($op), where $op is load, insert, delete, ...etc. - So, we have one real hook (hook_nodeapi($op)), and one callback (hook_othernodeapi($op)).
(of course, othernodeapi has to be something better)
This has the advantage of having only a maximum of two functions per module, with ops of course. One for node creation modules, and the other the regular nodeapi we know today.
How about that?
On Wednesday 03 January 2007 7:01 pm, Khalid B wrote:
For the rename you are proposing, would something like this work?
- move all hook_load() and friends into hook_othernodeapi($op), where $op is load, insert, delete, ...etc. - So, we have one real hook (hook_nodeapi($op)), and one callback (hook_othernodeapi($op)).
(of course, othernodeapi has to be something better)
This has the advantage of having only a maximum of two functions per module, with ops of course. One for node creation modules, and the other the regular nodeapi we know today.
How about that?
Except as chx noted, they're not hooks. Frankly I don't understand the obsession with one function with a huge switch statement over multiple functions in the first place. :-) I haven't really had much issue with _load() vs nodeapi('load') et al, to be honest. _load(), etc. map pretty well to pseudo-methods of a node object, conceptually. Many non-OO-syntax systems use that methodology. _nodeapi() is a real hook, and part of Drupal's non-OO-syntax multiple-inheritance magic. :-) Of course, the trick is that it's not just 2 locations where things could happen, but 3. How long ago was it that we debated _load() vs. FAPI, and whether or not we needed to keep node_save() because form could just do the saving themselves? (I didn't like that idea either, honestly. <g>) With CCK and CCK fields migrating into core bit by bit (is that a 4th method?), what is the future of value-add modules (event, taxonomy, og, etc.)? What about manually-defined node types? And if FAPI 3 turns everything inside out anyway, what then? I don't have code to offer or even answers; I'm just pointing out the scope of the issue is more than just hook_nodeapi(). -- Larry Garfield AIM: LOLG42 larry@garfieldtech.com ICQ: 6817012 "If nature has made any one thing less susceptible than all others of exclusive property, it is the action of the thinking power called an idea, which an individual may exclusively possess as long as he keeps it to himself; but the moment it is divulged, it forces itself into the possession of every one, and the receiver cannot dispossess himself of it." -- Thomas Jefferson
On 1/4/07, Khalid B <kb@2bits.com> wrote:
1. Restricting node hooks to one way of doing things (hook_nodeapi). This means deprecating all hook_something() for node operations. This way there is no confusion.
2. Eliminating all the hook_something() that are duplicated by hook_nodeapi('something') and do not suffer the drawbacks listed above. This may mean leaving the node_load() hook, and maybe others, and that is fine by me. Less confusion.
2a. Same as 2, but eliminate the nodeapi('something') that has an indispensible hook_something() equivalent. This way we are back to one way of doing things.
3. If the present scheme MUST stay as it is, then I don't know if documentation improvement will be enough to overcome the drawbacks.
Other ideas?
Interesting ideas, Khalid. Your suggestions triggered me to think of another possibility for how to overcome the node hooks problem: 4. We could remove all the hook_something() hooks, and for every hook_nodeapi('something'), we could create a new hook_nodeapi('something_alter'). Yep, that's right: YAAH (Yet Another Alter Hook :P). When you think about it, hook_nodeapi() really is already an 'alter' hook - why not change its name to more accurately reflect its behaviour? Module authors would then be encouraged to use hook_nodeapi('something') only for node types that are 'owned' by their module (but if module-defined node types disappear, then the ownership will not be formal), and to use hook_nodeapi('something_alter') for working with node types that are 'owned' by other modules. Obviously, all hook_nodeapi('something') implementations will then run before hook_nodeapi('something_alter'). The advantage of this over the current system, is that modules can assume ownership of user-defined node types, instead of only owning node types that they formally define through hook_node_info(). For example, event.module might assume ownership of custom node types that have been set to be event types, and so it would use hook_nodeapi('something'). Whereas upload.module wouldn't assume ownership, and so it would use hook_nodeapi('something_alter'). The biggest disadvantage of this (which is quite obvious from looking at the above example) is that it will be difficult to say when a module should or shouldn't assume ownership of node types, and that it will be easy for multiple modules to all assume ownership of node types, which would basically render the ordering of the hooks redundant (since none of them choose to use 'alter'). Cheers, Jaza.
Suggestion 4 is interesting, and seems to be a viable solution too. The biggest disadvantage of this (which is quite obvious from looking
at the above example) is that it will be difficult to say when a module should or shouldn't assume ownership of node types, and that it will be easy for multiple modules to all assume ownership of node types, which would basically render the ordering of the hooks redundant (since none of them choose to use 'alter').
Agreed. Moreover, if event module is pointing to CCK, then who owns the node type? CCK or event? Suggestion 5 builds on what Karoly said, which I am summarizing below. - move all hook_load() and friends into hook_othernodeapi($op), where $op is load, insert, delete, ...etc. - So, we have one real hook (hook_nodeapi($op)), and one callback (hook_othernodeapi($op)). (of course, othernodeapi has to be something better) This has the advantage of having only a maximum of two functions per module, with ops of course. One for node creation modules, and the other the regular nodeapi we know today. Your suggestion (#4) has the advantage of collapsing everything in one hook_nodeapi() though.
Moreover, if event module is pointing to CCK, then who owns the node type? CCK or event? In content module you have all the content_insert, content_load, content_*, so it looks like content.module owns those types and defines those node hooks (and funky load callbacks). :-)
Rob Roy Barreca Founder and COO Electronic Insight Corporation http://www.electronicinsight.com rob@electronicinsight.com Khalid B wrote:
Suggestion 4 is interesting, and seems to be a viable solution too.
The biggest disadvantage of this (which is quite obvious from looking at the above example) is that it will be difficult to say when a module should or shouldn't assume ownership of node types, and that it will be easy for multiple modules to all assume ownership of node types, which would basically render the ordering of the hooks redundant (since none of them choose to use 'alter').
Agreed.
Moreover, if event module is pointing to CCK, then who owns the node type? CCK or event?
Suggestion 5 builds on what Karoly said, which I am summarizing below.
- move all hook_load() and friends into hook_othernodeapi($op), where $op is load, insert, delete, ...etc. - So, we have one real hook (hook_nodeapi($op)), and one callback (hook_othernodeapi($op)).
(of course, othernodeapi has to be something better)
This has the advantage of having only a maximum of two functions per module, with ops of course. One for node creation modules, and the other the regular nodeapi we know today.
Your suggestion (#4) has the advantage of collapsing everything in one hook_nodeapi() though.
Rob Barreca a ecrit le 04/01/2007 02:34:
In content module you have all the content_insert, content_load, content_*, so it looks like content.module owns those types and defines those node hooks (and funky load callbacks). :-)
This was true in 4.7, where content.module did have the ownership of the content type. In 5.0, CCK does not define any content type, but "just" extends existing content types owned by other modules (node.module, audio.module, whatever...). So now it does its stuff through hook_nodeapi.
We shouldn't head towards eliminating the default node hooks. They're really useful, and simple interfaces for building good content types. We shouldn't drop good, reliable, and simple because we've added super flexible on top.
That makes sense, but I do feel that once we get to a point where we have a solid hook ordering (chx just started a thread) that we shouldn't just keep hook_insert/update/delete because they are convenient should we? Why not clean those out and head towards a unified nodeapi hook where you could act on *any* node type and register a super low weight/order/first when acting on on mymodule's node type? Rob Roy Barreca Founder and COO Electronic Insight Corporation http://www.electronicinsight.com rob@electronicinsight.com Darrel O'Pry wrote:
On Tue, 2007-01-02 at 17:03 -0800, Rob Barreca wrote:
All four of the module-defined node types that are still in 5.0 core (blog, book, forum, and poll) can and should be made history, and in their place we can just have hook_nodeapi() implementations
I definitely agree, but envision some module ordering/weighting issues that will need to be worked out as we begin to unify these since you lose the pre-nodeapi hooks and have everything going at the same "time". chx has done some prelim work on this at http://cvs.drupal.org/viewcvs/drupal/contributions/sandbox/chx/weights.php?r... but not sure how far along it is.
Rob Roy Barreca Founder and COO Electronic Insight Corporation http://www.electronicinsight.com rob@electronicinsight.com
We shouldn't head towards eliminating the default node hooks. They're really useful, and simple interfaces for building good content types. We shouldn't drop good, reliable, and simple because we've added super flexible on top. The features aren't exclusive. I could even see CCK using node hooks for purely user defined content types, and nodeAPI for extended content types.
Some ordering problems can be overcome with the way the nodeAPI and node hooks currently work. I see the initial inclusion of custom fields in core as probably using a hook between the node hook invocation and nodeAPI invocation. Weights couldn't cleanly solve the ordering issues we have, especially where different API's implemented by the same module should be ran in different orders.
On Tuesday 02 January 2007 4:34 pm, Jeremy Epstein wrote:
In Drupal 5.0, the difference between hook_insert() / hook_update() and friends, and hook_nodeapi(), is smaller than ever; and there is less need than ever to actually still have the former in core. With the new CCK-partially-in-core features, it's likely that before long, there will be no such thing as module-defined node types. There will only be user-defined node types.
I hope we don't go quite that far. I can see all-nodes-are-CCK as a nice future, but I still want to be able to provide a pre-defined node type as part of my module. Not everything should be a recipe. The ideal, methinks, would be import/export/hook support for CCK the same way Views has. Then many modules simply become a pre-packaged node (user editable), some pre-packaged views (user-editable), maybe a pre-packaged field type if needed, and a little glue code. That would be terrific. Not allowing modules to define nodes at all but relying on the user, that would be ugly. -- Larry Garfield AIM: LOLG42 larry@garfieldtech.com ICQ: 6817012 "If nature has made any one thing less susceptible than all others of exclusive property, it is the action of the thinking power called an idea, which an individual may exclusively possess as long as he keeps it to himself; but the moment it is divulged, it forces itself into the possession of every one, and the receiver cannot dispossess himself of it." -- Thomas Jefferson
I hope we don't go quite that far. I can see all-nodes-are-CCK as a nice future, but I still want to be able to provide a pre-defined node type as part of my module. Not everything should be a recipe.
We're not heading towards recipe-city, but actually just a cleaner, more abstract way of defining node types and value-adder modules. Currently, we are almost (see http://drupal.org/node/104763) defining page and story in default.profile which means we could do the same for node type 'foo' in our module's hook_enable() and then lock the type and use a unified hook_nodeapi() if we needed to do some extra stuff. Rob Roy Barreca Founder and COO Electronic Insight Corporation http://www.electronicinsight.com rob@electronicinsight.com Larry Garfield wrote:
On Tuesday 02 January 2007 4:34 pm, Jeremy Epstein wrote:
In Drupal 5.0, the difference between hook_insert() / hook_update() and friends, and hook_nodeapi(), is smaller than ever; and there is less need than ever to actually still have the former in core. With the new CCK-partially-in-core features, it's likely that before long, there will be no such thing as module-defined node types. There will only be user-defined node types.
I hope we don't go quite that far. I can see all-nodes-are-CCK as a nice future, but I still want to be able to provide a pre-defined node type as part of my module. Not everything should be a recipe.
The ideal, methinks, would be import/export/hook support for CCK the same way Views has. Then many modules simply become a pre-packaged node (user editable), some pre-packaged views (user-editable), maybe a pre-packaged field type if needed, and a little glue code.
That would be terrific. Not allowing modules to define nodes at all but relying on the user, that would be ugly.
The ideal, methinks, would be import/export/hook support for CCK the same way Views has. Then many modules simply become a pre-packaged node (user editable), some pre-packaged views (user-editable), maybe a pre-packaged field type if needed, and a little glue code.
your ideal was committed a few days ago to core cck. see content_copy.module.
As mentioned in another thread, we're still in an intermediate state moving from the old node system to a CCK-like node system. It's not an ideal situation to be in, but it is important we tackle this one step at a time. The old system might still have its purpose though; when performance matters, writing your own node type might be less intrusive in terms of CPU-usage. Plus, the CCK can easily become a very complex beast that is difficult to grok (no hackability, no simple interface, impossible to understand in 20 minutes). That are the two things that worry me, and I'll guard these concerns when reviewing patches. When I proposed and wrote the node system 4 years ago (or so), people had mixed feelings about it ... :) I'm glad that today there is a consensus about how to transform the node system. Probably because we can see and test what the CCK has to offer. Now we know what needs to be done, I can only hope there will be enough people willing to write actual code in a relative short time (i.e. the last active development cycle was 3 months). Ideally, all your modules are ported to Drupal 5, and you're already working on code for Drupal 6. ;-) I'll open up the new development branch real soon now. Go, go! -- Dries Buytaert :: http://www.buytaert.net/
participants (13)
-
Darrel O'Pry -
Dries Buytaert -
Fernando Silva -
Gerhard Killesreiter -
Jeremy Epstein -
John VanDyk -
Karoly Negyesi -
Khalid B -
Larry Garfield -
Moshe Weitzman -
Rob Barreca -
Scott McLewin -
Yves CHEDEMOIS