Currently there's a lot of inconsistency in how &$node is handled depending upon the $op variable. Two great examples:
1.) $op == 'load'
In most ops $node is passed by reference, so we just alter it as desired and move on with life. The load op however requires that we return an array. My understanding is that $node is then cast as an array, array_merged with our returned array, and then recast as an object. Passing by reference would be much cleaner, and keep this operation consistent with other ops.
2.) $op == 'update'
$node seems to actually be $node = (object) $form_state['values']; in this case. So it completely ignores anything that the load or prepare ops have access to. This is REALLY frustrating. I don't know what the solution is, but it'd be nice to get that fixed.
In addition to this, the docs on api.d.o are really useless in relation to the update op. (I'd be happy to contribute help on this)
Eclipse
| Comment | File | Size | Author |
|---|---|---|---|
| #8 | nodeapi7.1.patch | 881 bytes | eclipsegc |
| #3 | nodeapi7.patch | 1.61 KB | eclipsegc |
| #2 | nodeapi.patch | 1.42 KB | eclipsegc |
Comments
Comment #1
eclipsegc commentedok, so I'll roll a patch for D7 shortly, but I'd really like some feedback on this... http://drupalbin.com/9155
line 6 has been altered to pass the already available $form['#node']
lines 17-21 have been added to parse through $form['#node'] and add any missing information from the load operator.
I appreciate feedback!
Eclipse
PS: blogapi_blogger_edit_post() and blogapi_blogger_new_post() will also both need updates, however I've not looked into that yet.
Comment #2
eclipsegc commentedThis is a patch against D6 as a proof of concept.
Comment #3
eclipsegc commentedI've spent a little time working through a D7 patch on this. My GD isn't working locally so tests on that totally fail, other than that, the php filter is saying it fails too, however I manually tested it and am willing to suggest that the test may have an issue? Turning it on and phpinfo()ing it worked great so...
Anyway, would love some help/feedback on this.
Eclipse
Comment #5
damien tournoud commentedGood move. Making data added by hook_node_load() available to hook_node_(insert|update)() makes total sense.
About the patch, the code should probably go in node_form_submit_build_node(), not in node_submit(), because that's really an operation we need to do when building the $node object from the form values, which is the job of node_form_submit_build_node().
Comment #6
merlinofchaos commentedIn my opinion, this patch is nothing more than an ugly bandaid on a much larger fundamental problem. The bandaid might work but I think it'll serve to help obscure the fundamental problem, which is that our workflow is broken.
The part that's broken in our workflow is that our 'submit' function assumes it will be writing to the database, and that it creates a node object from $form_state['values'] via a cast (object) rather than properly modifying an existing node. This breaks our CRUD (node_save() expects form input, not a true $node object) and it also makes the preview process *hell* because during preview, the $node object you receive isn't a real node, but a converted form array. If you want to see how hellish that is, go check out code in taxonomy.module that exists solely to detect whether the node is being displayed in preview or not because in the normal case, $node->taxonomy is an array of taxonomy term objects; but in the broken preview case, it is an array of taxonomy tids from form input.
IMO Eclipse can fix his problem with a little form_alter, which puts the fields he needs into the $form with '#type' => 'value' -- that requires no core patch at all and 'update' will now get his values just like they were supposed to.
The real fix for this, IMO, is to tell node_form_submit() that its responsibility is NOT to save the form, but instead to build up a node object, and the $form_state can be examined by the caller of the node_form to see what action to take: i.e, display a preview and rerender the form, or save the newly built $node object. node_save already has nodeapi hooks and as a bonus, we can fix our CRUD by removing reliance upon the form for saving data, meaning we might truly be able to build and modify $node objects programmatically without worrying that some module assumes a form only.
Comment #7
merlinofchaos commentedPlease note that one of the purposes of my modifications to FAPI was to allow the possibility of moving node_save() out of the _submit so that our preview path could become sane again.
Comment #8
eclipsegc commented@merlinofchaos
you bring up a ton of points, which are great, and I understand how my work here might "obscure" the problems you're pointing out, but I think my work is also making $node saner to deal with. I want to understand the issues you've brought up because node is the primary foundation we work with daily, so I want to help, but I'm not sure that discontinuing my work here buys us anything. Does it?
Let me know, I don't pretend to understand all the intracacies of the node system by any stretch.
@DamZ
I went ahead and re-rolled the patch per what you've said, I think there's probably a better way to handle the unset()s I did, but I'm unsure what it would be. Thoughts?
Eclipse
Comment #9
yched commentedI'd say the patch in #8 makes sense. This way $node elements not present in the form keep their existing values, instead of currently requiring ugly '#type' => 'value' form elements. Field API works around that by requiring field storage engine not to alter existing values for fields not present in the incoming 'node'.
Also, while you can only agree with merlinofchaos about the awfulness of the dumb 'form values to object' cast, I don't think the patch is closely related. It does its thing aside of the awfulness, but does not add to it, nor takes us in a direction that would make the awfulness harder to clean. If "The real fix for this, IMO, is to tell node_form_submit() that its responsibility is NOT to save the form, but instead to build up a node object", then this task still would have to apply incoming form values onto the existing node to nuild up the new one.
Comment #10
eclipsegc commentedTestbot, come get me!
Comment #11
catchsubscribing.
Comment #12
eclipsegc commentedbetter title
Comment #13
agentrickardThe patch, as is, cleans up a nasty inconsistency with node_submit() that requires contrib modules to use node_load to verify certain aspects of the data. This is a pretty clean solution that adds consistency to the API.
I would, however, like to see what merlinofchaos has in mind, in the form of a patch, so we could compare the two "fixes."
Comment #15
drupal_was_my_past commentedFixed in #592572: Always pass nodes as objects.