array(
'title' => t('Administer all forms'),
'restrict access' => TRUE,
),
'view all forms submissions' => array(
'title' => t('View all forms submissions'),
'restrict access' => TRUE,
),
'edit all forms submissions' => array(
'title' => t('Edit all forms submissions'),
'restrict access' => TRUE,
),
'delete all forms submissions' => array(
'title' => t('Delete all forms submissions'),
'restrict access' => TRUE,
),
);
}
/**
* Implements hook_menu().
*/
function forms_menu() {
$items = array();
// Front end section.
$items['form/%forms'] = array(
'page callback' => 'forms_submission_edit',
'page arguments' => array(1, NULL),
'access callback' => 'forms_submission_access_callback',
'access arguments' => array(1),
'file' => 'forms_submission.pages.inc',
'title callback' => 'forms_page_title',
'title arguments' => array(1),
);
$items['form/%forms/form'] = array(
'title' => 'Form',
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -10,
);
// Submissions.
$items['form/%forms/submission/%forms_submission'] = array(
'page callback' => 'forms_submission_page_view',
'page arguments' => array(1, 3),
'access arguments' => array('view all forms submissions'),
'file' => 'forms_submission.pages.inc',
'title callback' => 'forms_page_title',
'title arguments' => array(1, 'Submission for form @form_name'),
);
$items['form/%forms/submission/%forms_submission/view'] = array(
'title' => 'View',
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -10,
);
$items['form/%forms/submission/%forms_submission/edit'] = array(
'title' => 'Edit',
'page callback' => 'forms_submission_edit',
'page arguments' => array(1, 3),
'access arguments' => array('edit all forms submissions'),
'type' => MENU_LOCAL_TASK,
'file' => 'forms_submission.pages.inc',
);
$items['form/%forms/submission/%forms_submission/delete'] = array(
'title' => 'Delete',
'page callback' => 'drupal_get_form',
'page arguments' => array('forms_submission_delete_confirm', 1, 3),
'access arguments' => array('delete all forms submissions'),
'type' => MENU_LOCAL_TASK,
'weight' => 10,
'file' => 'forms_submission.pages.inc',
);
// Submission overview.
$items['form/%forms/submissions'] = array(
'page callback' => 'forms_submission_list_view',
'page arguments' => array(1),
'access arguments' => array('view all forms submissions'),
'file' => 'forms.admin.inc',
'title' => 'Submissions',
'type' => MENU_LOCAL_TASK,
'weight' => 10,
);
// Edit.
$items['form/%forms/edit/form'] = array(
'title' => 'Settings',
'description' => 'Edit basic form settings',
'page callback' => 'drupal_get_form',
'page arguments' => array('forms_form', 1),
'access arguments' => array('administer forms'),
'file' => 'forms.admin.inc',
'type' => MENU_LOCAL_TASK,
'weight' => 100,
);
// Delete.
$items['form/%forms/delete'] = array(
'title' => 'Delete',
'description' => 'Delete a form',
'page callback' => 'drupal_get_form',
'page arguments' => array('forms_delete_confirm', 1),
'access arguments' => array('administer forms'),
'file' => 'forms.admin.inc',
'type' => MENU_LOCAL_TASK,
'weight' => 100,
);
// Admin section.
$items['admin/structure/forms'] = array(
'title' => 'Forms',
'description' => 'Manage frontend forms.',
'page callback' => 'forms_overview',
'access arguments' => array('administer forms'),
'file' => 'forms.admin.inc',
);
$items['admin/structure/forms/list'] = array(
'title' => 'List',
'description' => 'Manage frontend forms.',
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -10,
);
$items['admin/structure/forms/add'] = array(
'title' => 'Add a form',
'description' => 'Add a form.',
'page callback' => 'drupal_get_form',
'page arguments' => array('forms_form'),
'access arguments' => array('administer forms'),
'type' => MENU_LOCAL_ACTION,
'file' => 'forms.admin.inc',
);
return $items;
}
/**
* Implements hook_menu_alter.
*/
function forms_menu_alter(&$items) {
if (isset($items['form/%forms/edit/fields'])) {
$items['form/%forms/edit'] = $items['form/%forms/edit/fields'];
$items['form/%forms/edit/fields'] = array(
'title' => $items['form/%forms/edit']['title'],
'type' => MENU_DEFAULT_LOCAL_TASK,
);
$items['form/%forms/edit']['title'] = 'Edit';
$items['form/%forms/edit']['weight'] = 20;
}
}
/**
* Implements hook_theme().
*/
function forms_theme() {
return array(
'forms_admin_overview' => array(
'variables' => array('forms' => NULL),
),
);
}
/**
* Implements hook_preprocess_page.
*
* TODO: find a better way to display tabs on the 3rd level.
* It is now pushed in the $content of the page.
*/
function forms_preprocess_page(&$vars) {
if (arg(0) == 'form' && arg(2) == 'edit') {
$tabs = menu_local_tasks(2);
if ($tabs['tabs']['count'] > 1) {
drupal_add_css(drupal_get_path('module', 'forms') . '/forms.css');
$vars['page']['content']['system_main']['forms_tabs_tertiary'] = $tabs['tabs']['output'];
$vars['page']['content']['system_main']['forms_tabs_tertiary']['#weight'] = -150;
$vars['page']['content']['system_main']['forms_tabs_tertiary']['#prefix'] = '
';
$vars['page']['content']['system_main']['forms_tabs_tertiary']['#suffix'] = '
';
}
}
}
/**
* Implements hook_admin_paths_alter.
*/
function forms_admin_paths_alter(&$paths) {
$paths['form/*/edit'] = TRUE;
$paths['form/*/edit/*'] = TRUE;
$paths['form/*/delete'] = TRUE;
}
/**
* Access callback. Are we allowed to submit against a forms?
*/
function forms_submission_access_callback($forms) {
$access = FALSE;
if ($forms->page <> 0 && $forms->submissions) {
$access = TRUE;
}
if (!$access && (user_access('administer forms') || user_access('edit all forms submissions'))) {
$access = TRUE;
}
return $access;
}
/**
* Implements hook_entity_info().
*/
function forms_entity_info() {
$entity = array(
'forms_submission' => array(
'label' => t('Forms submission'),
'base table' => 'forms_submission',
'revision table' => 'forms_submission_revision',
'uri callback' => 'forms_submission_uri',
'load hook' => 'form_submission_load',
'fieldable' => TRUE,
'entity keys' => array(
'id' => 'fssid',
'revision' => 'fsvid',
'bundle' => 'form',
'label' => 'name',
),
'bundle keys' => array(
'bundle' => 'form',
),
'bundles' => array(),
'view modes' => array(
'form_submission' => array(
'label' => t('Forms submission'),
'custom settings' => FALSE,
),
'submissions_overview' => array(
'label' => t('Submissions overview'),
'custom settings' => FALSE,
),
),
),
);
foreach (forms_info() as $form_name => $forms) {
$entity['forms_submission']['bundles'][$form_name] = array(
'label' => $forms->name,
'admin' => array(
'path' => 'form/%forms/edit',
'real path' => 'form/' . str_replace('_', '-', $form_name) . '/edit',
'bundle argument' => 1,
'access arguments' => array('administer forms'),
),
);
}
return $entity;
}
/**
* Implements hook_field_extra_fields.
*/
function forms_field_extra_fields() {
$extra = array();
foreach (forms_info() as $form_name => $forms) {
$extra['forms_submission'][$form_name] = array(
'display' => array(
'ip_address' => array(
'label' => t('IP address'),
'description' => t('The IP address'),
'weight' => 50,
),
'submitted' => array(
'label' => t('Submitted'),
'description' => t('The timestamp of the first submission'),
'weight' => 50,
'entity_property' => 'created',
),
'changed' => array(
'label' => t('Changed'),
'description' => t('The timestamp of the last change on the submission'),
'weight' => 50,
'entity_property' => 'changed',
),
),
);
}
return $extra;
}
/**
* Implements hook_forms_submission_view.
*
* Attach the display of extra fields.
*/
function forms_forms_submission_view($entity, $view_mode, $langcode) {
$entity->build['ip_address'] = array(
'#view_mode' => $view_mode,
'#field_language' => LANGUAGE_NONE,
'#field_translatable' => FALSE,
'#field_name' => 'ip_address',
'#field_type' => 'pseudo',
'#label_display' => 'inline',
'#title' => t('IP address'),
'#entity_type' => 'forms_submission',
'#bundle' => $entity->form,
'#items' => array(array(
'value' => $entity->remote_addr,
'safe_value' => check_plain($entity->remote_addr),
)),
'#theme' => 'field',
0 => array(
'#markup' => check_plain($entity->remote_addr),
),
);
$entity->build['submitted'] = array(
'#view_mode' => $view_mode,
'#field_language' => LANGUAGE_NONE,
'#field_translatable' => FALSE,
'#field_name' => 'submitted',
'#field_type' => 'pseudo',
'#label_display' => 'inline',
'#title' => t('Submitted'),
'#entity_type' => 'forms_submission',
'#bundle' => $entity->form,
'#items' => array(array(
'value' => $entity->created,
'safe_value' => format_date($entity->created, 'short'),
)),
'#theme' => 'field',
0 => array(
'#markup' => format_date($entity->created, 'short'),
),
);
$entity->build['changed'] = array(
'#view_mode' => $view_mode,
'#field_language' => LANGUAGE_NONE,
'#field_translatable' => FALSE,
'#field_name' => 'submitted',
'#field_type' => 'pseudo',
'#label_display' => 'inline',
'#title' => t('Changed'),
'#entity_type' => 'forms_submission',
'#bundle' => $entity->form,
'#items' => array(array(
'value' => $entity->created,
'safe_value' => format_date($entity->changed, 'short'),
)),
'#theme' => 'field',
0 => array(
'#markup' => format_date($entity->changed, 'short'),
),
);
}
/**
* Get the uri for a forms submission.
*/
function forms_submission_uri($forms_submission) {
$forms_url_str = str_replace('_', '-', $forms_submission->form);
return array(
'path' => 'form/' . $forms_url_str . '/submission/' . $forms_submission->fssid,
);
}
/*
* Saves a forms_submission.
*/
function forms_submission_save($forms_submission) {
$transaction = db_transaction();
try {
// Load the stored entity, if any.
if (!empty($forms_submission->fssid) && !isset($forms_submission->original)) {
$forms_submission->original = entity_load_unchanged('forms_submission', $forms_submission->fssid);
}
field_attach_presave('forms_submission', $forms_submission);
global $user;
// Determine if we will be inserting a new submission.
if (!isset($forms_submission->is_new)) {
$forms_submission->is_new = empty($forms_submission->fssid);
}
// Set the timestamp fields.
if (empty($forms_submission->created)) {
$forms_submission->created = REQUEST_TIME;
}
// The changed timestamp is always updated for bookkeeping purposes,
// for example: revisions, searching, etc.
$forms_submission->changed = REQUEST_TIME;
$forms_submission->timestamp = REQUEST_TIME;
$forms_submission->remote_addr = ip_address();
$update = TRUE;
// Let modules modify the submission before it is saved to the database.
module_invoke_all('forms_submission_presave', $forms_submission);
module_invoke_all('entity_presave', $forms_submission, 'forms_submission');
if (!$forms_submission->is_new) {
$forms_submission->old_fsvid = $forms_submission->fsvid;
unset($forms_submission->fsvid);
}
// Save.
drupal_write_record('forms_submission_revision', $forms_submission);
if ($forms_submission->is_new) {
drupal_write_record('forms_submission', $forms_submission);
$op = 'insert';
// resave to save the fssid.
drupal_write_record('forms_submission_revision', $forms_submission, 'fsvid');
}
else {
drupal_write_record('forms_submission', $forms_submission, 'fssid');
$op = 'update';
}
// Save fields.
$function = "field_attach_$op";
$function('forms_submission', $forms_submission);
module_invoke_all('forms_submission_' . $op, $forms_submission);
module_invoke_all('entity_' . $op, $forms_submission, 'forms_submission');
// Clear internal properties.
unset($forms_submission->is_new);
unset($forms_submission->original);
// Clear the static loading cache.
entity_get_controller('forms_submission')->resetCache(array($forms_submission->fssid));
db_ignore_slave();
}
catch (Exception $e) {
$transaction->rollback();
watchdog_exception('forms_submission', $e);
throw $e;
}
}
/**
* Menu argument loader: loads a forms_submission by fssid.
*/
function forms_submission_load($fssid, $reset = FALSE) {
$forms = forms_submission_load_multiple(array($fssid), array(), $reset);
return reset($forms);
}
/**
* Loads multiple entities of the type forms_submission.
*/
function forms_submission_load_multiple($fssids = array(), $conditions = array(), $reset = FALSE) {
return entity_load('forms_submission', $fssids, $conditions, $reset);
}
/**
* Delete a forms submission.
*/
function forms_submission_delete($fssid) {
forms_submission_delete_multiple(array($fssid));
}
/**
* Delete multiple forms submissions.
*/
function forms_submission_delete_multiple($fssids) {
$transaction = db_transaction();
if (!empty($fssids)) {
$forms_submissions = forms_submission_load_multiple($fssids);
try {
foreach ($forms_submissions as $fssid => $forms_submission) {
module_invoke_all('forms_submission_delete', $forms_submission);
module_invoke_all('entity_delete', $forms_submission, 'forms_submission');
field_attach_delete('forms_submission', $forms_submission);
}
db_delete('forms_submission')
->condition('fssid', $fssids, 'IN')
->execute();
db_delete('forms_submission_revision')
->condition('fssid', $fssids, 'IN')
->execute();
}
catch (Exception $e) {
$transaction->rollback();
watchdog_exception('forms_submission', $e);
throw $e;
}
entity_get_controller('forms_submission')->resetCache();
}
}
/**
* Menu argument loader: loads a forms by string.
*
* @param $name
* The machine-readable name of a form to load.
*
* @return $forms
* A form object or FALSE if $form does not exist.
*/
function forms_load($form_name) {
return forms_info(strtr($form_name, array('-' => '_')));
}
/**
* Finds all forms objects optionally filtered.
*/
function forms_info($form_name = NULL) {
$forms = &drupal_static(__FUNCTION__);
if (empty($forms)) {
$forms = array();
$query = db_select('forms', 'f')
->fields('f')
->orderBy('f.form', 'ASC')
->execute();
foreach ($query as $forms_object) {
$forms[$forms_object->form] = $forms_object;
$forms[$forms_object->form]->settings = unserialize($forms[$forms_object->form]->settings);
}
}
if (!empty ($form_name)) {
return (isset($forms[$form_name])) ? $forms[$form_name] : FALSE;
}
return $forms;
}
/**
* Save forms object. Fires hook_forms_update or hook_forms_insert.
*
* @return $status
* Contains a constant SAVED_UPDATED or SAVED_NEW.
*/
function forms_save($info) {
$is_existing = FALSE;
$existing_form = !empty($info->old_form) ? $info->old_form : $info->form;
$is_existing = (bool) db_query_range('SELECT 1 FROM {forms} WHERE form = :form', 0, 1, array(':form' => $existing_form))->fetchField();
$forms = forms_set_defaults($info);
$fields = array(
'form' => (string) $forms->form,
'name' => (string) $forms->name,
'description' => (string) $forms->description,
'module' => $forms->module,
'page' => $forms->page,
'block' => $forms->block,
'submissions' => $forms->submissions,
'settings' => serialize($forms->settings),
);
if ($is_existing) {
db_update('forms')
->fields($fields)
->condition('form', $existing_form)
->execute();
if (!empty($forms->old_form) && $forms->old_form != $forms->form) {
field_attach_rename_bundle('forms_submission', $forms->old_form, $forms->form);
}
module_invoke_all('forms_update', $forms);
$status = SAVED_UPDATED;
}
else {
db_insert('forms')
->fields($fields)
->execute();
field_attach_create_bundle('forms_submission', $forms->form);
module_invoke_all('forms_insert', $forms);
$status = SAVED_NEW;
}
return $status;
}
/**
* Delete forms object. Fires hook_forms_delete.
*/
function forms_delete($form) {
$forms = forms_load($form);
db_delete('forms')
->condition('form', $forms->form)
->execute();
field_attach_delete_bundle('forms_submission', $forms->form);
module_invoke_all('forms_delete', $forms);
}
/**
* Set defaults for a forms object.
*/
function forms_set_defaults($info = array()) {
$info = (array) $info;
$new_forms = $info + array(
'form' => '',
'name' => '',
'description' => '',
'page' => 1,
'block' => 0,
'submissions' => 1,
'settings' => array(
'submit_label' => 'Submit',
'after_submit' => 'display',
'redirect_url' => '',
'confirmation_message' => 'Thank you. Your submission is saved.',
'display_message' => 'system',
),
);
$new_forms = (object) $new_forms;
if (empty($new_forms->module)) {
$new_forms->module = 'forms';
}
$new_forms->orig_form = isset($info['form']) ? $info['form'] : '';
return $new_forms;
}
/**
* Implements hook_forms().
*
* All forms forms share the same form handler.
*/
function forms_forms($form_id, $args) {
$forms = array();
if ($forms_arr = forms_info()) {
foreach (array_keys($forms_arr) as $form_name) {
$forms[$form_name . '_forms_submission_form']['callback'] = 'forms_submission_form';
$forms[$form_name . '_block_forms_submission_form']['callback'] = 'forms_submission_form';
}
}
return $forms;
}
/**
* Title callback.
*/
function forms_page_title($forms, $string = NULL) {
if (empty($string)) {
$string = '@form_name';
}
return t($string, array('@form_name' => $forms->name));
}
/**
* Implements hook_views_api().
*/
function forms_views_api() {
return array(
'api' => 3.0,
'path' => drupal_get_path('module', 'forms') . '/views',
);
}
/**
* Implements hook_features_api().
*
* Main info hook that features uses to determine what components are provided
* by the implementing module.
*/
function forms_features_api() {
return array(
'forms' => array(
'name' => t('Forms'),
'feature_source' => TRUE,
'default_hook' => 'forms_defaults',
'file' => drupal_get_path('module', 'forms') . '/features/forms.features.inc',
),
);
}
/**
* Trigger events with the provided hooks in forms for rules.
*/
if (module_exists('rules')) {
/**
* Implements hook_forms_submission_insert().
*/
function forms_forms_submission_insert($forms_submission) {
rules_invoke_event('forms_submission_insert', $forms_submission);
}
/**
* Implements hook_forms_submission_update().
*/
function forms_forms_submission_update($forms_submission) {
rules_invoke_event('forms_submission_update', $forms_submission);
}
/**
* Implements hook_forms_submission_presave().
*/
function forms_forms_submission_presave($forms_submission) {
rules_invoke_event('forms_submission_presave', $forms_submission);
}
/**
* Implements hook_forms_submission_delete().
*/
function forms_forms_submission_delete($forms_submission) {
rules_invoke_event('forms_submission_delete', $forms_submission);
}
}
/**
* Implements hook_block_info().
*/
function forms_block_info() {
$blocks = array();
foreach(forms_info() as $forms_name => $forms) {
if ($forms->block) {
$blocks['forms_' . $forms_name] = array(
'info' => t('Form: @forms', array('@forms' => $forms->name)),
'cache' => DRUPAL_NO_CACHE,
);
}
}
return $blocks;
}
/**
* Implements hook_block_view().
*/
function forms_block_view($delta = '') {
global $user;
list ($type, $form_name) = explode('_', $delta);
if ($type == 'forms' && !empty($form_name)) {
$forms = forms_info($form_name);
if ($forms->submissions) {
module_load_include('inc', 'forms', 'forms_submission.pages');
$forms_submission = (object) array(
'uid' => $user->uid,
'form' => $forms->form,
'submit_label' => $forms->settings['submit_label'],
);
return array(
'subject' => t($forms->name),
'content' => drupal_get_form($forms->form . '_block_forms_submission_form', $forms, $forms_submission),
);
}
}
}