function confirm_form

You are here

7 system.module confirm_form($form, $question, $path, $description = NULL, $yes = NULL, $no = NULL, $name = 'confirm')
4.7 system.module confirm_form($form_id, $form, $question, $path, $description = NULL, $yes = NULL, $no = NULL, $name = 'confirm')
5 system.module confirm_form($form, $question, $path, $description = NULL, $yes = NULL, $no = NULL, $name = 'confirm')
6 system.module confirm_form($form, $question, $path, $description = NULL, $yes = NULL, $no = NULL, $name = 'confirm')

Generates a form array for a confirmation form.

This function returns a complete form array for confirming an action. The form contains a confirm button as well as a cancellation link that allows a user to abort the action.

If the submit handler for a form that implements confirm_form() is invoked, the user successfully confirmed the action. You should never directly inspect $_POST to see if an action was confirmed.

Note - if the parameters $question, $description, $yes, or $no could contain any user input (such as node titles or taxonomy terms), it is the responsibility of the code calling confirm_form() to sanitize them first with a function like check_plain() or filter_xss().

Parameters

$form: Additional elements to add to the form; for example, hidden elements.

$question: The question to ask the user (e.g. "Are you sure you want to delete the block <em>foo</em>?"). The page title will be set to this value.

$path: The page to go to if the user cancels the action. This can be either:

  • A string containing a Drupal path.
  • An associative array with a 'path' key. Additional array values are passed as the $options parameter to l().

$description: Additional text to display. Defaults to t('This action cannot be undone.').

$yes: A caption for the button that confirms the action (e.g. "Delete", "Replace", ...). Defaults to t('Confirm').

$no: A caption for the link which cancels the action (e.g. "Cancel"). Defaults to t('Cancel').

$name: The internal name used to refer to the confirmation item.

Return value

The form array.

34 calls to confirm_form()
aggregator_admin_remove_feed in modules/aggregator/aggregator.admin.inc
block_box_delete in modules/block/block.admin.inc
Menu callback; confirm deletion of custom blocks.
book_remove_form in modules/book/book.pages.inc
Menu callback; builds a form to confirm removal of a node from the book.
comment_confirm_delete in modules/comment/comment.admin.inc
Form builder; Builds the confirmation form for deleting a single comment.
comment_multiple_delete_confirm in modules/comment/comment.admin.inc
List the selected comments and verify that the admin really wants to delete them.

... See full list

File

modules/system/system.module, line 1225
Configuration system that lets administrators modify the workings of the site.

Code

function confirm_form($form, $question, $path, $description = NULL, $yes = NULL, $no = NULL, $name = 'confirm') {
  $description = isset($description) ? $description : t('This action cannot be undone.');

  // Prepare cancel link
  $query = $fragment = NULL;
  if (is_array($path)) {
    $query = isset($path['query']) ? $path['query'] : NULL;
    $fragment = isset($path['fragment']) ? $path['fragment'] : NULL;
    $path = isset($path['path']) ? $path['path'] : NULL;
  }
  $cancel = l($no ? $no : t('Cancel'), $path, array('query' => $query, 'fragment' => $fragment));

  drupal_set_title($question);

  // Confirm form fails duplication check, as the form values rarely change -- so skip it.
  $form['#skip_duplicate_check'] = TRUE;

  $form['#attributes'] = array('class' => 'confirmation');
  $form['description'] = array('#value' => $description);
  $form[$name] = array(
    '#type' => 'hidden',
    '#value' => 1,
  );

  $form['actions'] = array(
    '#prefix' => '<div class="container-inline">',
    '#suffix' => '</div>',
  );
  $form['actions']['submit'] = array(
    '#type' => 'submit',
    '#value' => $yes ? $yes : t('Confirm'),
  );
  $form['actions']['cancel'] = array('#value' => $cancel);
  $form['#theme'] = 'confirm_form';
  return $form;
}

Comments

If you are trying to use this function, and just get "Array" as the output, you need to call drupal_get_form() on the return value.

The most common place to do this is in your menu callback for the page displaying the confirm form. For example, instead of:

<?php
  $items
['example_confirm'] = array(
   
'title' => t('An example confirm form'),
   
'page callback' => 'example_confirm_form',
   
'access arguments' => array('access content'),
   
'type' => MENU_CALLBACK,
  );
?>

do:

<?php
  $items
['example_confirm'] = array(
   
'title' => t('An example confirm form'),
   
'page callback' => 'drupal_get_form',
   
'page arguments' => array('example_confirm_form'),
   
'access arguments' => array('access content'),
   
'type' => MENU_CALLBACK,
  );
?>

Hope this helps save someone else some head-scratching. :)

It did save quite a lot of head-scratching ;)

After a lot of head-scratching, I think I finally grasped how to use confirm_form, here are my finds so people can avoid having to reverse engineer the function to understand how to use it.

The key here is that confirm_form does not define a hook, so there's no direct way to use it to confirm a form submission. What it does, is provide you with a standarized $form array, so you get uniform look and feel, and you don't have to know enough about form API to build it yourself (though you'll need to know something about form API anyway, and you should. Form API is very useful, even if the documentation is fragmented and sometimes contradictory).

Since all it provides, is a standarized $form, you'll have to set up a multi-step form (by the means of your choosing, there are multiple, from those in the core, to Chaos Tool form_wizard), or use $form_state['redirect'], and pass the arguments by URL. You'll also have to write your _submit, if you want to do something special on _submit.

I might however be wrong here, if so, someone more knowledgeable on the inner workings of Drupal and confirm_form() will no doubt correct me.

EDIT: Forgot to add, if you need extra parameters for your _submit, add them as #value elements, not as #hidden elements, as the API seems to suggest, in the first argument, since that way, they don't get sent to the browser. Not only this will save you bandwidth, but it will make you more secure, since if you're using them to store information from the previous step, someone could alter them via DOM manipulation before submitting.

Adapted from: http://drupal.org/node/764816#comment-2821212

<?php
function mymodule_form($form_state,$args_from_url = NULL)
{
  if(!isset(
$form_state['storage']['confirm']))
  {
   
// do your normal $form definition here
   
return $form;
  }
  else
  {
   
// ALSO do $form definition here. Your final submit handler (after user clicks Yes, I Confirm) will only see $form_state info defined here. Form you create here passed as param1 to confirm_form

   

return confirm_form($form,'You Sure?','redirect/on/cancel/path','Descr. text...','Yes, nuke em all','Cancel'); //Had better luck leaving off last param 'name'
 
}
}

function

mymodule_form_validate($form, &$form_state)
{
  if(!isset(
$form_state['storage']['confirm']))
  {
   
// put any initial validation here. This only be called the first time through, not when the confirm button has been pushed.
 
}
}

function

mymodule_form_submit($form, &$form_state)
{
    if(!isset(
$form_state['storage']['confirm']))
    {
     
$form_state['storage']['confirm'] = TRUE; // this will cause the form to be rebuilt, entering the confirm part of the form
     
$form_state['rebuild'] = TRUE; // along with this
   
}
    else
    {
     
// this is where you do your processing after they have pressed the confirm button
   
}
}
?>

Leaving out hook_menu with page callback function that returns drupal_get_form(mymodule_form);. All of it standard, with nothing special for confirm_form.

I am very open to suggestions and corrections concerning the use of $form_state['rebuild'] = TRUE;

Works well for me. Thanks!

thanks for the recipe... code is not Drupal standard though and logic is slightly verbose.. so cleaned up version is:

<?php
function mymodule_form($form_state, $args_from_url = NULL) {
  if(isset(
$form_state['storage']['confirm'])) {
    
// ALSO do $form definition here. Your final submit handler (after user clicks Yes, I Confirm) will only see $form_state info defined here. Form you create here passed as param1 to confirm_form 
 
 
return confirm_form($form, 'You Sure?', 'redirect/on/cancel/path', 'Descr. text...', 'Yes, nuke em all', 'Cancel'); //Had better luck leaving off last param 'name'
 
}
 
 
// do your normal $form definition here
 
return $form;
}

function

mymodule_form_validate($form, &$form_state) {
  if(!isset(
$form_state['storage']['confirm'])) {
   
// put any initial validation here. This only be called the first time through, not when the confirm button has been pushed.
 
}
}

function

mymodule_form_submit($form, &$form_state) {
    if(!isset(
$form_state['storage']['confirm'])) {
     
$form_state['storage']['confirm'] = TRUE; // this will cause the form to be rebuilt, entering the confirm part of the form
     
$form_state['rebuild'] = TRUE; // along with this
   
}
    else {
     
// this is where you do your processing after they have pressed the confirm button
   
}
}
?>

<?php
/*
* Specific hook_form_alter for a form with id other_form.  This could be a cck content type
*/
function mymodule_form_other_form_alter(&$form, $form_state) {

 

//Save nid - easier to use later.
 
$nid = NULL;
 
$nid = $form['nid']['#value'];

 

//Reassign the submit and save function
 
$form['buttons']['submit']['#submit'] = array('mymodule_other_form_submit');
 
$form['buttons']['delete']['#submit'] = array('mymodule_other_form_delete');

 

//Only on update
 
if(isset($form_state['storage']['confirm']) && $form_state['values']['op'] == 'Save' && isset($nid)) {
     
//Create confirm form
     
$confirm_form = array();
     
$confirm_form['nid'] = array(
       
'#type' => 'value',
       
'#value' => $nid,
      );

     

//Confirm form as the form
     
$form = confirm_form($confirm_form, 'Warning!', 'node/'.$nid, 'Some warning ...', 'Update', 'Cancel');
    }

  }

 

//On delete
 
if (isset($form_state['storage']['confirm']) && $form_state['values']['op'] == 'Delete') {
     
//Create confirm form
     
$confirm_form = array();
     
$confirm_form['nid'] = array(
       
'#type' => 'value',
       
'#value' => $nid,
      );

     

//Set confirm form as the form
     //This is an example where I did not want to delete the nodes but only unpublish them.
   
$form = confirm_form($confirm_form, 'Set to Inactive?', 'node/'.$nid'Cannot be deleted.  They can only be set inactive.', 'Set to Inactive','Cancel');
  }
}

/*
* Special submit function
*/
function mymodule_other_form_submit($form, &$form_state) {
 
//dpr($form_state);

 

if(!isset($form_state['storage']['confirm'])) {
   
$form_state['storage']['confirm'] = TRUE; // this will cause the form to be rebuilt, entering the confirm part of the form
   
$form_state['rebuild'] = TRUE; // along with this
 
}
  else {
   
//Extra code here will be executed when the users presses the 'Update' button on the confirmation screen.

    //Submit the form for the normal submit.
   

node_form_submit($form, $form_state);
  }
}

/*
* Special delete function
*/
function mymodule_other_form_delete($form, &$form_state) {
   if(!isset(
$form_state['storage']['confirm'])) {
     
$form_state['storage']['confirm'] = TRUE; // this will cause the form to be rebuilt, entering the confirm part of the form
     
$form_state['rebuild'] = TRUE; // along with this
   
}
    else {
     
node_unpublish_action($form['nid']['#value']);
    }
}
?>

I tried the approach you suggested and it works great - except i don't get a form rendered into the html; all the other pieces are there including the Confirm button. But as there is no form; clicking the button does nothing.

even doing drupal_render_form("someid", $form) on the form from confirm_form() does not return a valid form.

try changing

$confirm_form = array();

with

$confirm_form = array('#type'=>'form');

$path can be either:

  • A string containing a Drupal path.
  • An associative array with a 'path' key. Additional array values are passed as the $options parameter to l().

    If using an associative array, note that the only options that will be passed as options are 'query' and 'fragment'. Everything will be ignored (ie: 'attributes' cannot be passed).

  • I may be missing something blatantly obvious, but by looking at the function's code, I can't see where is the part that uses the 'destination=...' from the URL (a feature documented in the page). I also tried it, and the "Cancel" link is always $path, even if 'destination' is set in the URL, and even if $path is set to NULL.

    Can someone clarify please? Or it is a documentation bug?

    If your solution requires you to capture some additional values to augment an acceptance form (maybe a checkbox for to really unlock a TOS agreement? maybe downpayment amount?), use the standard #weight attribute to position your additional form elements above or below the confirmation form.

    <?php
    function mymodule_confirm(&$form_state, $quotenode) {
      ...
     
    $form['nid'] = array(
       
    '#type' => 'value',
       
    '#value' => $quotenode->nid,
      );
     
    $form['signing_values'] = array(
       
    '#type' => 'fieldset',
       
    '#title' => t("Information about signing"),
       
    '#weight' => 1,
      );
     
    $form['signing_values']['credit_code'] = array(
       
    '#type' => 'textfield',
       
    '#title' => t("Credit Code"),
       
    '#description' => t("If provided, add the Homeowner's credit authorization code."),
      );
      ...
      return
    confirm_form(
       
    $form,
      ...
    ?>

    To position form fields above the confirmation form, use -1 and lower, and 1 and higher for below the confirmation text. Wrap your additional fields in a fieldset to set only a single weight attribute.