It's not an untypical situation: You'd like to use an existing Drupal CMS form as base for a custom form under a separate URL. In our example case we will decorate the Registration form "user_register_form" and create a separate registration form under a separate URL. This might be a custom alternative to modules like https://www.drupal.org/project/multiple_registration if they don't match your requirements.
While hook_form_alter helps to alter an existing form and will also be useful for us, we'd like to have our completely separate form with own form_id but prepopulated with the field and logic of the base form. Le'ts see how we can do this in Drupal 7:
First we'll create a separate page containing our custom form, using hook_menu() to make the form
/**
* Implements hook_menu().
*/
function MY_MODULE_menu() {
$items['my/custom/form-path'] = array(
'title' => 'My example form decorator page',
'page callback' => 'MY_MODULE_user_register_form_wrapper_page',
'access callback' => 'user_register_access',
'type' => MENU_CALLBACK,
);
return $items;
}
?>
Next we define our form wrapper using hook_forms(). Read the API Documentation for the different methods it offers:
/**
* Implements hook_forms().
*/
function MY_MODULE_forms($form_id, $args) {
// Wrap user register form to use it as form base for our custom form:
$forms['MY_MODULE_user_register_form'] = array(
// Use user_register_form as form base:
'callback' => 'user_register_form'
);
return $forms;
}
?>
What we do here is to "create" a custom form with form_id "MY_MODULE_user_register_form" which uses "user_register_form" as base form.
This is the form we'll call in drupal_get_form() in our page callback now to render our wrapped form instead of the user_register_form:
/**
* Custom user register form page callback.
*/
function MY_MODULE_user_register_form_wrapper_page() {
$form = drupal_get_form('MY_MODULE_user_register_form');
return $form;
}
?>
Last but not least we alter our custom form now using hook_form_FORM_ID_alter():
/**
* Implements hook_form_FORM_ID_alter().
* Decorated / wraps MY_MODULE_user_register_form.
*/
function MY_MODULE_form_MY_MODULE_user_register_form_alter(&$form, &$form_state, $form_id){
// Add a custom field to the wrapped form
$form['example_field'] = array(
'#type' => 'textfield',
'#title' => t('Example field'),
'#required' => TRUE,
'#weight' => 20,
);
// Optionally add validation / submit handlers or alter them:
$form['#validate'][] = 'MY_MODULE_user_register_form_validate';
$form['#submit'][] = 'MY_MODULE_user_register_form_submit';
}
?>
That's it! Now we've created a separate registration form with form_id "MY_MODULE_user_register_form" which acts like a native Drupal form but is based on user_register_form.
Of course this kind of decorator can be used with every other Drupal form.
The final code:
/**
* @file Example implementation for decorating / wrapping the user_register_form
* with a custom form on a custom page.
*/
/**
* Implements hook_menu().
*/
function MY_MODULE_menu() {
$items['my/custom/form-path'] = array(
'title' => 'My example form decorator page',
'page callback' => 'MY_MODULE_user_register_form_wrapper_page',
'access callback' => 'user_register_access',
'type' => MENU_CALLBACK,
);
return $items;
}
/**
* Implements hook_forms().
*/
function MY_MODULE_forms($form_id, $args) {
// Wrap user register form to use it as form base for our custom form:
$forms['MY_MODULE_user_register_form'] = array(
// Use user_register_form as form base:
'callback' => 'user_register_form'
);
return $forms;
}
/**
* Implements hook_form_FORM_ID_alter().
* Decorated / wraps MY_MODULE_user_register_form.
*/
function MY_MODULE_form_MY_MODULE_user_register_form_alter(&$form, &$form_state, $form_id){
// Add a custom field to the wrapped form
$form['example_field'] = array(
'#type' => 'textfield',
'#title' => t('Example field'),
'#required' => TRUE,
'#weight' => 20,
);
$form['#validate'][] = 'MY_MODULE_user_register_form_validate';
$form['#submit'][] = 'MY_MODULE_user_register_form_submit';
}
/**
* Custom user register form page callback.
*/
function MY_MODULE_user_register_form_wrapper_page() {
$form = drupal_get_form('MY_MODULE_user_register_form');
return $form;
}
/**
* Implements hook_form_validate().
* @see MY_MODULE_user_register_validate()
*/
function MY_MODULE_user_register_form_validate($form, &$form_state){
// Custom validation for MY_MODULE_user_register_form().
}
/**
* Implements hook_form_submit().
* @see MY_MODULE_user()
*/
function MY_MODULE_user_register_form_submit($form, &$form_state){
// Custom submission logic for MY_MODULE_user_register_form().
}
?>