diff --git a/includes/webform.pages.inc b/includes/webform.pages.inc index f75250b..7d3fb03 100644 --- a/includes/webform.pages.inc +++ b/includes/webform.pages.inc @@ -79,7 +79,7 @@ function webform_configure_form($form, &$form_state, $node) { // Submission limit settings. $form['submission']['submit_limit'] = array( '#type' => 'item', - '#title' => t('Submission limit'), + '#title' => t('Submission limit per user'), '#theme' => 'webform_advanced_submit_limit_form', '#description' => t('Limit the number of submissions per user. A user is identified by their user login if logged-in, or by their IP Address and Cookie if anonymous. Use of cookies may be modified in the global Webform settings.', array('!url' => url('admin/config/content/webform'))), ); @@ -108,6 +108,38 @@ function webform_configure_form($form, &$form_state, $node) { '#parents' => array('submit_interval'), ); + // Submission limit settings for all submissions. + $form['submission']['total_submit_limit'] = array( + '#type' => 'item', + '#title' => t('Total Submissions limit'), + '#theme' => 'webform_advanced_total_submit_limit_form', + '#description' => t('Limit the total number of allowed submissions.'), + ); + $form['submission']['total_submit_limit']['enforce_total_limit'] = array( + '#type' => 'radios', + '#options' => array('no' => t('Unlimited'), 'yes' => 'Limit to !count submission(s) !timespan'), + '#default_value' => $node->webform['total_submit_limit'] == -1 ? 'no' : 'yes', + '#parents' => array('enforce_total_limit'), + ); + $form['submission']['total_submit_limit']['total_submit_limit'] = array( + '#type' => 'textfield', + '#maxlength' => 8, + '#size' => 8, + '#default_value' => $node->webform['total_submit_limit'] != -1 ? $node->webform['total_submit_limit'] : '', + '#parents' => array('total_submit_limit'), + ); + $form['submission']['total_submit_limit']['total_submit_interval'] = array( + '#type' => 'select', + '#options' => array( + '-1' => t('ever'), + '3600' => t('every hour'), + '86400' => t('every day'), + '604800' => t('every week'), + ), + '#default_value' => $node->webform['total_submit_interval'], + '#parents' => array('total_submit_interval'), + ); + $form['submission']['status'] = array( '#type' => 'radios', '#title' => t('Status of this form'), @@ -277,6 +309,16 @@ function webform_configure_form_submit($form, &$form_state) { $node->webform['submit_interval'] = $form_state['values']['submit_interval']; } + // Set the total submit limit to -1 if set to unlimited. + if ($form_state['values']['enforce_total_limit'] == 'no') { + $node->webform['total_submit_limit'] = -1; + $node->webform['total_submit_interval'] = -1; + } + else { + $node->webform['total_submit_limit'] = $form_state['values']['total_submit_limit']; + $node->webform['total_submit_interval'] = $form_state['values']['total_submit_interval']; + } + // Set submit notice. $node->webform['submit_notice'] = $form_state['values']['submit_notice']; @@ -331,3 +373,26 @@ function theme_webform_advanced_submit_limit_form($variables) { return drupal_render_children($form); } + +/** + * Theme the total submit limit fieldset on the webform node form. + */ +function theme_webform_advanced_total_submit_limit_form($variables) { + $form = $variables['form']; + $form['total_submit_limit']['#attributes']['class'] = array('webform-set-active'); + $form['total_submit_interval']['#attributes']['class'] = array('webform-set-active'); + // Remove div wrappers around limit options. + $form['total_submit_limit']['#theme_wrappers'] = array(); + $form['total_submit_interval']['#theme_wrappers'] = array(); + $replacements = array( + '!count' => drupal_render($form['total_submit_limit']), + '!timespan' => drupal_render($form['total_submit_interval']), + ); + + $form['enforce_total_limit']['no']['#theme_wrappers'] = array('webform_inline_radio'); + $form['enforce_total_limit']['yes']['#title'] = NULL; + $form['enforce_total_limit']['yes']['#inline_element'] = t('Limit to !count submission(s) !timespan', $replacements); + $form['enforce_total_limit']['yes']['#theme_wrappers'] = array('webform_inline_radio'); + + return drupal_render_children($form); +} diff --git a/includes/webform.submissions.inc b/includes/webform.submissions.inc index 86b00c6..f12c59e 100644 --- a/includes/webform.submissions.inc +++ b/includes/webform.submissions.inc @@ -843,6 +843,42 @@ function _webform_submission_limit_check($node) { } /** + * Check if the total number of submissions has exceeded the limit on this form. + * + * @param $node + * The webform node to be checked. + * @return + * Boolean TRUE if the form has exceeded it's limit. FALSE otherwise. + */ +function _webform_total_submission_limit_check($node) { + + // Check if submission limiting is enabled. + if ($node->webform['total_submit_limit'] == '-1') { + return FALSE; // No check enabled. + } + + // Retrieve submission data from the database. + $query = db_select('webform_submissions') + ->condition('nid', $node->nid) + ->condition('is_draft', 0); + + if ($node->webform['total_submit_interval'] != -1) { + $query->condition('submitted', REQUEST_TIME - $node->webform['total_submit_interval'], '>'); + } + + // Fetch all the entries from the database within the submit interval. + $num_submissions_database = $query->countQuery()->execute()->fetchField(); + + if ($num_submissions_database >= $node->webform['total_submit_limit']) { + // Limit exceeded. + return TRUE; + } + + // Limit not exceeded. + return FALSE; +} + +/** * Preprocess function for webform-submission.tpl.php. */ function template_preprocess_webform_submission(&$vars) { diff --git a/webform.install b/webform.install index 45d85e0..a80b24e 100644 --- a/webform.install +++ b/webform.install @@ -97,6 +97,18 @@ function webform_schema() { 'not null' => TRUE, 'default' => -1, ), + 'total_submit_limit' => array( + 'description' => 'The total number of submissions allowed within an interval. -1 is unlimited.', + 'type' => 'int', + 'not null' => TRUE, + 'default' => -1, + ), + 'total_submit_interval' => array( + 'description' => 'The amount of time in seconds that must pass before another submission can be submitted within the set limit.', + 'type' => 'int', + 'not null' => TRUE, + 'default' => -1, + ), ), 'primary key' => array('nid'), ); @@ -692,3 +704,16 @@ function webform_update_7315() { db_add_field('webform_last_download', 'requested', array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0,)); } } + +/** + * Add additional columns for total submission limit. + */ +function webform_update_7316() { + if (!db_field_exists('webform', 'total_submit_limit')) { + db_add_field('webform', 'total_submit_limit', array('type' => 'int', 'not null' => TRUE, 'default' => -1)); + } + + if (!db_field_exists('webform', 'total_submit_interval')) { + db_add_field('webform', 'total_submit_interval', array('type' => 'int', 'not null' => TRUE, 'default' => -1)); + } +} diff --git a/webform.module b/webform.module index 7c90051..a4ff97a 100644 --- a/webform.module +++ b/webform.module @@ -525,7 +525,7 @@ function webform_theme() { 'render element' => 'webform', ), 'webform_view_messages' => array( - 'variables' => array('node' => NULL, 'teaser' => NULL, 'page' => NULL, 'submission_count' => NULL, 'limit_exceeded' => NULL, 'allowed_roles' => NULL, 'closed' => NULL, 'cached' => NULL), + 'variables' => array('node' => NULL, 'teaser' => NULL, 'page' => NULL, 'submission_count' => NULL, 'limit_exceeded' => NULL, 'total_limit_exceeded' => NULL, 'allowed_roles' => NULL, 'closed' => NULL, 'cached' => NULL), ), 'webform_form' => array( 'render element' => 'form', @@ -602,6 +602,10 @@ function webform_theme() { 'render element' => 'form', 'file' => 'includes/webform.pages.inc', ), + 'webform_advanced_total_submit_limit_form' => array( + 'render element' => 'form', + 'file' => 'includes/webform.pages.inc', + ), // webform.report.inc. 'webform_results_per_page' => array( 'variables' => array('total_count' => NULL, 'pager_count' => NULL), @@ -1136,6 +1140,8 @@ function webform_node_defaults() { 'submit_text' => '', 'submit_limit' => '-1', 'submit_interval' => '-1', + 'total_submit_limit' => '-1', + 'total_submit_interval' => '-1', 'status' => '1', 'record_exists' => FALSE, 'roles' => array('1', '2'), @@ -1381,6 +1387,17 @@ function webform_node_view($node, $view_mode) { } } + // Check if the user can add another submission if there is a limit on total + // submisions. + if ($node->webform['total_submit_limit'] != -1) { // -1: Submissions are never throttled. + module_load_include('inc', 'webform', 'includes/webform.submissions'); + + // Disable the form if the limit is exceeded and page cache is not active. + if (($total_limit_exceeded = _webform_total_submission_limit_check($node)) && !$cached) { + $enabled = FALSE; + } + } + // Check if this user has a draft for this webform. $is_draft = FALSE; if (($node->webform['allow_draft'] || $node->webform['auto_save']) && $user->uid != 0) { @@ -1403,7 +1420,7 @@ function webform_node_view($node, $view_mode) { // Print out messages for the webform. if (empty($node->in_preview) && !isset($node->webform_block) && !$logging_in) { - theme('webform_view_messages', array('node' => $node, 'teaser' => $teaser, 'page' => $page, 'submission_count' => $submission_count, 'limit_exceeded' => $limit_exceeded, 'allowed_roles' => $allowed_roles, 'closed' => $closed, 'cached' => $cached)); + theme('webform_view_messages', array('node' => $node, 'teaser' => $teaser, 'page' => $page, 'submission_count' => $submission_count, 'limit_exceeded' => $limit_exceeded, 'total_limit_exceeded' => $total_limit_exceeded, 'allowed_roles' => $allowed_roles, 'closed' => $closed, 'cached' => $cached)); } // Add the output to the node. @@ -1453,6 +1470,8 @@ function theme_webform_view($variables) { * for anonymous users. * @param $limit_exceeded * Boolean value if the submission limit for this user has been exceeded. + * @param $total_limit_exceeded + * Boolean value if the total submission limit has been exceeded. * @param $allowed_roles * A list of user roles that are allowed to submit this webform. * @param $closed @@ -1466,6 +1485,7 @@ function theme_webform_view_messages($variables) { $page = $variables['page']; $submission_count = $variables['submission_count']; $limit_exceeded = $variables['limit_exceeded']; + $total_limit_exceeded = $variables['total_limit_exceeded']; $allowed_roles = $variables['allowed_roles']; $closed = $variables['closed']; $cached = $variables['cached']; @@ -1511,6 +1531,14 @@ function theme_webform_view_messages($variables) { } $type = 'error'; } + elseif ($total_limit_exceeded && !$cached) { + if ($node->webform['total_submit_interval'] == -1 && $node->webform['total_submit_limit'] > 1) { + $message = t('This form has received the maximum number of entries.'); + } + else { + $message = t('You may not submit another entry at this time.'); + } + } // If the user has submitted before, give them a link to their submissions. if ($submission_count > 0 && $node->webform['submit_notice'] == 1 && !$cached) { @@ -2032,6 +2060,19 @@ function webform_client_form_validate($form, &$form_state) { } } + // Check that the submissions have not exceeded the total submission limit. + if ($node->webform['total_submit_limit'] != -1) { + module_load_include('inc', 'webform', 'includes/webform.submissions'); + // Check if the total number of entries was reached before the user submitted + // the form. + if (!$finished && _webform_total_submission_limit_check($node)) { + // Show the user the limit has exceeded. + drupal_set_message('While you were filling out the form the maximum number of submissions has been reached.', 'error', FALSE); + form_set_error('', NULL); + return; + } + } + // Run all #element_validate and #required checks. These are skipped initially // by setting #validated = TRUE on all components when they are added. _webform_client_form_validate($form, $form_state);