function node_form

Form constructor for the node add/edit form.

See also

node_form_validate()

node_form_submit()

node_form_build_preview()

node_form_delete_submit()

Related topics

1 string reference to 'node_form'
node_forms in modules/node/node.module
Implements hook_forms().

File

modules/node/node.pages.inc, line 107

Code

function node_form($form, &$form_state, $node) {
    global $user;
    // During initial form build, add the node entity to the form state for use
    // during form building and processing. During a rebuild, use what is in the
    // form state.
    if (!isset($form_state['node'])) {
        if (!isset($node->title)) {
            $node->title = NULL;
        }
        node_object_prepare($node);
        $form_state['node'] = $node;
    }
    else {
        $node = $form_state['node'];
    }
    // Some special stuff when previewing a node.
    if (isset($form_state['node_preview'])) {
        $form['#prefix'] = $form_state['node_preview'];
        $node->in_preview = TRUE;
    }
    else {
        unset($node->in_preview);
    }
    // Identify this as a node edit form.
    // @todo D8: Remove. Modules can implement hook_form_BASE_FORM_ID_alter() now.
    $form['#node_edit_form'] = TRUE;
    $form['#attributes']['class'][] = 'node-form';
    if (!empty($node->type)) {
        $form['#attributes']['class'][] = 'node-' . $node->type . '-form';
    }
    // Basic node information.
    // These elements are just values so they are not even sent to the client.
    foreach (array(
        'nid',
        'vid',
        'uid',
        'created',
        'type',
        'language',
    ) as $key) {
        $form[$key] = array(
            '#type' => 'value',
            '#value' => isset($node->{$key}) ? $node->{$key} : NULL,
        );
    }
    // Changed must be sent to the client, for later overwrite error checking.
    $form['changed'] = array(
        '#type' => 'hidden',
        '#default_value' => isset($node->changed) ? $node->changed : NULL,
    );
    // Invoke hook_form() to get the node-specific bits. Can't use node_invoke(),
    // because hook_form() needs to be able to receive $form_state by reference.
    // @todo hook_form() implementations are unable to add #validate or #submit
    //   handlers to the form buttons below. Remove hook_form() entirely.
    $function = node_type_get_base($node) . '_form';
    if (function_exists($function) && ($extra = $function($node, $form_state))) {
        $form = array_merge_recursive($form, $extra);
    }
    // If the node type has a title, and the node type form defined no special
    // weight for it, we default to a weight of -5 for consistency.
    if (isset($form['title']) && !isset($form['title']['#weight'])) {
        $form['title']['#weight'] = -5;
    }
    // @todo D8: Remove. Modules should access the node using $form_state['node'].
    $form['#node'] = $node;
    $form['additional_settings'] = array(
        '#type' => 'vertical_tabs',
        '#weight' => 99,
    );
    // Add a log field if the "Create new revision" option is checked, or if the
    // current user has the ability to check that option.
    $form['revision_information'] = array(
        '#type' => 'fieldset',
        '#title' => t('Revision information'),
        '#collapsible' => TRUE,
        // Collapsed by default when "Create new revision" is unchecked
'#collapsed' => !$node->revision,
        '#group' => 'additional_settings',
        '#attributes' => array(
            'class' => array(
                'node-form-revision-information',
            ),
        ),
        '#attached' => array(
            'js' => array(
                drupal_get_path('module', 'node') . '/node.js',
            ),
        ),
        '#weight' => 20,
        '#access' => $node->revision || user_access('administer nodes'),
    );
    $form['revision_information']['revision'] = array(
        '#type' => 'checkbox',
        '#title' => t('Create new revision'),
        '#default_value' => $node->revision,
        '#access' => user_access('administer nodes'),
    );
    // Check the revision log checkbox when the log textarea is filled in.
    // This must not happen if "Create new revision" is enabled by default, since
    // the state would auto-disable the checkbox otherwise.
    if (!$node->revision) {
        $form['revision_information']['revision']['#states'] = array(
            'checked' => array(
                'textarea[name="log"]' => array(
                    'empty' => FALSE,
                ),
            ),
        );
    }
    $form['revision_information']['log'] = array(
        '#type' => 'textarea',
        '#title' => t('Revision log message'),
        '#rows' => 4,
        '#default_value' => !empty($node->log) ? $node->log : '',
        '#description' => t('Provide an explanation of the changes you are making. This will help other authors understand your motivations.'),
    );
    // Node author information for administrators
    $form['author'] = array(
        '#type' => 'fieldset',
        '#access' => user_access('administer nodes'),
        '#title' => t('Authoring information'),
        '#collapsible' => TRUE,
        '#collapsed' => TRUE,
        '#group' => 'additional_settings',
        '#attributes' => array(
            'class' => array(
                'node-form-author',
            ),
        ),
        '#attached' => array(
            'js' => array(
                drupal_get_path('module', 'node') . '/node.js',
                array(
                    'type' => 'setting',
                    'data' => array(
                        'anonymous' => variable_get('anonymous', t('Anonymous')),
                    ),
                ),
            ),
        ),
        '#weight' => 90,
    );
    $form['author']['name'] = array(
        '#type' => 'textfield',
        '#title' => t('Authored by'),
        '#maxlength' => 60,
        '#autocomplete_path' => 'user/autocomplete',
        '#default_value' => !empty($node->name) ? $node->name : '',
        '#weight' => -1,
        '#description' => t('Leave blank for %anonymous.', array(
            '%anonymous' => variable_get('anonymous', t('Anonymous')),
        )),
    );
    $form['author']['date'] = array(
        '#type' => 'textfield',
        '#title' => t('Authored on'),
        '#maxlength' => 25,
        '#description' => t('Format: %time. The date format is YYYY-MM-DD and %timezone is the time zone offset from UTC. Leave blank to use the time of form submission.', array(
            '%time' => !empty($node->date) ? date_format(date_create($node->date), 'Y-m-d H:i:s O') : format_date($node->created, 'custom', 'Y-m-d H:i:s O'),
            '%timezone' => !empty($node->date) ? date_format(date_create($node->date), 'O') : format_date($node->created, 'custom', 'O'),
        )),
        '#default_value' => !empty($node->date) ? $node->date : '',
    );
    // Node options for administrators
    $form['options'] = array(
        '#type' => 'fieldset',
        '#access' => user_access('administer nodes'),
        '#title' => t('Publishing options'),
        '#collapsible' => TRUE,
        '#collapsed' => TRUE,
        '#group' => 'additional_settings',
        '#attributes' => array(
            'class' => array(
                'node-form-options',
            ),
        ),
        '#attached' => array(
            'js' => array(
                drupal_get_path('module', 'node') . '/node.js',
            ),
        ),
        '#weight' => 95,
    );
    $form['options']['status'] = array(
        '#type' => 'checkbox',
        '#title' => t('Published'),
        '#default_value' => $node->status,
    );
    $form['options']['promote'] = array(
        '#type' => 'checkbox',
        '#title' => t('Promoted to front page'),
        '#default_value' => $node->promote,
    );
    $form['options']['sticky'] = array(
        '#type' => 'checkbox',
        '#title' => t('Sticky at top of lists'),
        '#default_value' => $node->sticky,
    );
    // Add the buttons.
    $form['actions'] = array(
        '#type' => 'actions',
    );
    $form['actions']['submit'] = array(
        '#type' => 'submit',
        '#access' => variable_get('node_preview_' . $node->type, DRUPAL_OPTIONAL) != DRUPAL_REQUIRED || !form_get_errors() && isset($form_state['node_preview']),
        '#value' => t('Save'),
        '#weight' => 5,
        '#submit' => array(
            'node_form_submit',
        ),
    );
    $form['actions']['preview'] = array(
        '#access' => variable_get('node_preview_' . $node->type, DRUPAL_OPTIONAL) != DRUPAL_DISABLED,
        '#type' => 'submit',
        '#value' => t('Preview'),
        '#weight' => 10,
        '#submit' => array(
            'node_form_build_preview',
        ),
    );
    if (!empty($node->nid) && node_access('delete', $node)) {
        $form['actions']['delete'] = array(
            '#type' => 'submit',
            '#value' => t('Delete'),
            '#weight' => 15,
            '#submit' => array(
                'node_form_delete_submit',
            ),
        );
    }
    // This form uses a button-level #submit handler for the form's main submit
    // action. node_form_submit() manually invokes all form-level #submit handlers
    // of the form. Without explicitly setting #submit, Form API would auto-detect
    // node_form_submit() as submit handler, but that is the button-level #submit
    // handler for the 'Save' action. To maintain backwards compatibility, a
    // #submit handler is auto-suggested for custom node type modules.
    $form['#validate'][] = 'node_form_validate';
    if (!isset($form['#submit']) && function_exists($node->type . '_node_form_submit')) {
        $form['#submit'][] = $node->type . '_node_form_submit';
    }
    $form += array(
        '#submit' => array(),
    );
    field_attach_form('node', $node, $form, $form_state, entity_language('node', $node));
    return $form;
}

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.