I was hoping to add a webform to a recipe, but can not do this with config files - since webforms are nodes and are not currently stored in config files. 

How do I create a Webform node programmatically?


I found an open issue to allow the storage of webform components in config files: https://github.com/backdrop-contrib/webform/issues/192

Until that happens, creating a webform programmatically (in code) is pretty much the same as creating any other type of node in code.  https://forum.backdropcms.org/forum/how-does-one-create-node-programmati...

I went ahead and created a recipe for a Contact Us form that uses the Webform module instead of the core Contact module. Because, I was not able to use config files, I used PHP in the .install file of the module to create the form. Here is the code I used:


(Use link to recipe. I tried to paste code here, but it's a mess. Will open an issue.)

    function contact_us_webform_recipe_install() {

    // Make Contact form with Webform Module.
    $webform = new Node(
        'title' => st("Contact Us"),
        'webform' => array(
            'components' => array(
                    'name' => st("Name"),
                    'form_key' => st("name"),
                    'pid' => 0,
                    'weight' => 0,
                    'type' => st("textfield"),
                    'required' => st('1'),
                    'extra' => array(
                        'private' => 0,
                    'name' => st("Email"),
                    'form_key' => st("email"),
                    'pid' => 0,
                    'weight' => 5,
                    'type' => st("email"),

                    'name' => st("Message"),
                    'form_key' => st("message"),
                    'pid' => 0,
                    'weight' => 10,
                    'type' => st("textarea"),
                    'value' => st('Be sure to configure form settings and emails and delete this default value in "Form Components."'),
            'progressbar_bar' => 0,
        'uid' => 1,
        'status' => 1,
        'promote' => 0,
        'type' => 'webform',
    config_set('node.type.webform', 'settings.node_submitted', 0);

You posted this as I was typing my answer. Have you actually tried what you posted? I don't think creating a node and passing the components to it will work... but maybe I'm wrong.

@argiepiano - You are so very fast. I figured out the answer before posting the question, but wanted to add it to the forum for future reference (next time I need to do this and forgot I did it before). I really thought I would get my answer up before anyone else did. 

It's still interesting, because you provide a different way of doing it that may or may not be better. 

Yes, my way works. I've already tested and released a recipe that creates a webform in the manner I proposed. That doesn't mean it's the best way to do it. 

If my works, do you still think that might be a reason that your way is better?

Take a look at webform_node_insert(), which is a hook implementation that's triggered when a node is saved. If the node is of the webform type, then the rest of the code there is executed. To create a webform programmatically, you could simply create a node of that type programmatically. When you save the node, all of the code in webform_node_insert() will run, resulting on a ready-to-use webform node.

Of course, that will not add fields to the webform. In order to do that, you have to call webform_component_insert() and pass it a component. My guess is that the component will be an array with specific keys. To figure those keys out, you can manually create a webform, add components, and then use devel's dpm() to inspect the node. For example, this is a textfield component:

array (
        'nid' => 7,
        'cid' => '1',
        'pid' => '0',
        'form_key' => 'test',
        'name' => 'Test',
        'type' => 'textfield',
        'value' => 'My value',
        'extra' => 
        array (
          'description' => 'A description!',
          'title_display' => 'before',
          'description_above' => 0,
          'private' => 0,
          'wrapper_classes' => '',
          'css_classes' => '',
          'placeholder' => 'A placeholder!',
          'maxlength' => '100',
          'minlength' => '2',
          'width' => '',
          'field_prefix' => '',
          'field_suffix' => '',
          'disabled' => 0,
          'unique' => 0,
          'attributes' => 
          array (
          'analysis' => false,
        'required' => '1',
        'weight' => '0',
        'page_num' => 1,