I'm building a Drupal based site that requires the communication of a node ID to a seperate web service. This web service handles the uploading of files to a seperate server (from the one Drupal is on).
This creates a problem where in if I create a new node, the Node ID is not generated until the form is submitted - meaning I can't attach the files until I save the node and open it back up to edit it. I'd like to remove that step.
Is it possible to create a two step node creation process where the basics of the node are submitted and saved, and then the form re-directs to step two where I can attach the files?
I'd also consider an AJAX enabled node submission form - but that seems to add even more complexity to the situation.
Any advice, examples will be appreciated!
you could do this with a multi-step form. see http://pingv.com/blog/ben-jeavons/2009/multi-step-forms-drupal-6-using-variable-functions for the canonical way to do this (besides the code, also check the comments).
you could also do it by adding a second submit handler to the form. the first, default one (node_form_submit) saves your node (including the attached file) the standard Drupal way. the second handler could upload the file to the separate server, do upload error checking, delete the file from the Drupal DB, etc. you can add an additional submit handler to a Drupal 6 form by adding it to the form's #submit property, either in the form definition or via hook_form_alter / hook_form_FORM_ID_alter.
Depending on what exactly you want to do, you might use hook_nodeapi on its 'insert' operation. It is fired after successful node creation, so the node object will contain the newly assigned nid there already.
NOTE: The wording of the API documentation is a bit ambiguous concerning the 'insert' and 'update' operations:
"insert": The node is being created
(inserted in the database).
This sounds like it is right in the middle of the process, whereas the node has already been created at this point.
I guess the node_save function can help you.
I ran into exactly this same issue and did it the wrong way. I added the hook myself.
http://drupal.org/node/313389
Related
Is there an API for adding to the Form Results that results from standard Forms are added to from an External Form?
I want to try avoid adding to the tables btform, btformanswers, etc. manually
No.
See https://github.com/concrete5/concrete5/blob/master/web/concrete/core/controllers/blocks/form.php#L354-L415 -- the core's form block updates the table manually.
As johjoh says, you could theoretically mimic a post to a form block, by instantiating it and then calling action_submit_form(), but that's just as fraught with difficulty, too... you'd have to keep the "form" in sync with your data, and possibly worry about the token and block ID and all that....
What's your exact use case? New block type? Some sort of external API? The form viewing interface in the dashboard is nice, but nothing that special. I think most people want to get data out of it, not in....
here is more detailed explanation:
i am using the ubercart module with the file download feature module (the uc_file module ).
i have created a product class (which is a new content-type as far as the drupal system) and add a cck file field to it.
what i want to achive is the following behavior:
once a user saves a new node of my product class, i want the uploaded file to be added as a file download feature to the product class automatically.
i know i can hack the function uc_file_feature_form_submit($form, &$form_state), do what it does in my module code, but i rather ivoke it since i'll have easier life with future changes to the uc_file module (since i am calling it's function, i dont care if it will change in the future).
so, to invoke the uc_file_feature_form_submit function i need to build fake $form, &$form_state parameters, i know i can print_r those arrays, and build it from there, the thing is that there are a lot of data in those arrays that is not mandatory, i was wondering what are those mandatory fields that i have to build on my own.
thank you...
Short answer: Look at the submit function you are trying to invoke. The form values that it's using are the ones you need.
Long answer . . . need more info before I can give a better answer.
You can use drupal_execute() to programatically execute a form. I am not sure if it works with files though.
I have a content type which has a lot of fields 50+. 30 or so are required fields. I want my user to be able so save the node before all the required fields have been filled in. The node can not be published until all the required fields have been filled in. Is there a way I can do this.
Not directly. Required fields are exactly that. You'll need to make your fields optional and handle the node save event and prevent publishing until each of the fields has been filled in. If you don't feel like all that php, Rules module can handle this kind of thing very nicely - http://drupal.org/project/rules.
Another alternative is that you might be better off with something like a webform - http://drupal.org/project/webform, though I don't know if it has any save and resume functionality out of the box so you might need to check that out first.
This module will do the job:
http://drupal.org/project/multistep
You can split your form to steps and only the fields in the current step have to be filled by the user.
I am building a custom module that will allow my users to do a simple query against an MS SQL database. I've built the form using hook_form() and have gotten validation to work.
I'm planning on retrieving the data from hook_form_submit(), but once I've done that, how do I append it below the form? It does not appear that I have access to $output from hook_form_submit(). I'm at a loss as to what to do next.
Thanks
Dana
When you are rendering the form you should check for $form_state['values'] to see if the user has already submitted a form when you're rendering the form. Then you could paint the form results in the same step as painting the form.
The first time the user loads the form page the $form_state variable won't contain any submitted form info so you can render an empty results table.
There's a good illustration of the Drupal Form API workflow on Drupal.org here: Form API Internal Workflow Illustration
The problem in trying to output data in the hook_form() method is that the method gets invoked twice which clears the post values the second time through. Throw a dpm($form_state) in the hook_form() function and you'll see two sets of post data. One with values and one without.
So after dissecting the built in Search module, which pretty much operates exactly the way I want my form to work, I figured out how this is done. Well, at least one way you can do it.
What Search module does is take the values from $form_state in hook_form_submit() and pastes them into the URL, then it sets the $form_state['redirect'] to that new URL, effectively storing those variables in the URL and changing the POST to a GET.
Now, in the callback, they extract those values from the URL, do the search on them, THEN they call drupal_get_form(), append the results to the end and return it.
There's another solution HERE where they use SESSION to store the values until the second trip through. Weird, but it works.
I need a form which will allow creation of several related nodes at the same time. All of the nodes involve CCK fields.
I would like to use as much of CCK's built-in validation, submission, input widget, and security functionality as possible/practical.
What is the best way to accomplish this in Drupal 6? Are there 'best practices' or docs anywhere?
Here are 3 possibilities I can see. I would love feedback on whether any of these would work, or if there are even better options.
1.
start with the standard node creation form for content type foo.
modify the form by adding fields for content type bar, using hook form_alter [can cck widgets for content type bar be inserted directly?]
use a custom submit handler to create node of type bar when the form is submitted
[can the standard cck handler be called? or do i need to 'manually' construct the node object, do my own validation, and use node_save?]
2.
create a new, custom form that concatenates the 'normal' node creation forms for the relevant content types.
then use hook form_alter to modify the forms as necessary.
allow standard cck submit handlers to do the work of creating the nodes.
3.
create a custom form from scratch
create the nodes in my own submit handlers, using node prepare, node save, etc.
If found documentation on re-using the standard node creation form, but creating multiple nodes at the same time is not mentioned.
Using hook nodeapi and hook form_alter is documented in a post on advomatic's site, but the particular method descrube seems to require polluting one of the content types with 'dummy' fields.
Thank you very much for your help!
The advomatic guys posted a nice solution to this.
http://www.advomatic.com/blogs/jonathan-delaigle/multiple-nodes-single-node-submission
why not just use hook_nodeapi to handle the node creation for certain content types.
just set up a test condition to see if $node->type = 'foo', and then run a function to create two nodes or however many, using the values from the predefined fields. you can even set hook_nodeapi to only run when the $op is almost ready to insert the node into the database, thus ensuring the object has been run through appropriate validation before being passed on to the new nodes that need to be created.
http://api.drupal.org/api/function/hook_nodeapi/6 this page has a list of all available operations for the $op variable and what they do.
I hope that helps
If the 2nd type bar needs only one or two additional inputs (fields) from the user, I would go with your approach one.
But given your clarification it seems that foo and bar are sufficiently different and complex, so your approach two seems more reasonable.
Concatenate both forms into one and hide the bar fields that you want to populate from the foo fields (or node, after you created it). In the forms validate and submit functions, you'll have to separate the forms again so that you can call the standard validation/submit handlers for both separately.
I have not done this yet, so I'm not sure how well this will play with the cck functionality, but I would expect it to work reasonably well to give it a try.