diff --git a/includes/webform.pages.inc b/includes/webform.pages.inc index 9f61d3d..92d285b 100644 --- a/includes/webform.pages.inc +++ b/includes/webform.pages.inc @@ -83,7 +83,7 @@ function webform_configure_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/settings/webform'))), ); @@ -112,6 +112,38 @@ function webform_configure_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'), @@ -281,6 +313,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']; @@ -308,6 +350,21 @@ function theme_webform_advanced_submit_limit_form($form) { } /** + * Theme the total submit limit fieldset on the webform node form. + */ +function theme_webform_advanced_total_submit_limit_form($form) { + $form['total_submit_limit']['#attributes']['class'] = 'webform-set-active'; + $form['total_submit_interval']['#attributes']['class'] = 'webform-set-active'; + // Remove div wrappers around limit options. + $replacements = array( + '!count' => preg_replace('/(]*>)(.*?)(<\/div>)/s', '$2', drupal_render($form['total_submit_limit'])), + '!timespan' => preg_replace('/(]*>)(.*?)(<\/div>)/s', '$2', drupal_render($form['total_submit_interval'])), + ); + $form['enforce_total_limit']['yes']['#title'] = t('Limit to !count submission(s) !timespan', $replacements); + return drupal_render($form); +} + +/** * Theme the redirection setting on the webform node form. */ function theme_webform_advanced_redirection_form($form) { diff --git a/includes/webform.submissions.inc b/includes/webform.submissions.inc index 0c23634..27d4d67 100644 --- a/includes/webform.submissions.inc +++ b/includes/webform.submissions.inc @@ -772,6 +772,38 @@ 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 for this IP address or username from the database. + $query = 'SELECT count(*) ' . + 'FROM {webform_submissions} ' . + 'WHERE submitted > %d AND nid = %d AND is_draft = 0'; + + // Fetch all the entries from the database within the submit interval with this username and IP. + $num_submissions_database = db_result(db_query($query, ($node->webform['total_submit_interval'] != -1) ? (time() - $node->webform['total_submit_interval']) : $node->webform['total_submit_interval'], $node->nid)); + + 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 d3dbe5b..235cf41 100644 --- a/webform.install +++ b/webform.install @@ -98,6 +98,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'), ); @@ -1325,6 +1337,21 @@ function webform_update_6326() { } /** + * Add additional columns for total submission limit. + */ +function webform_update_6327() { + $ret = array(); + if (!db_column_exists('webform', 'total_submit_limit')) { + db_add_field($ret, 'webform', 'total_submit_limit', array('type' => 'int', 'not null' => TRUE, 'default' => -1)); + } + + if (!db_column_exists('webform', 'total_submit_interval')) { + db_add_field($ret, 'webform', 'total_submit_interval', array('type' => 'int', 'not null' => TRUE, 'default' => -1)); + } + return $ret; +} + +/** * Recursively delete all files and folders in the specified filepath, then * delete the containing folder. * diff --git a/webform.module b/webform.module index a0ff2b8..113757a 100644 --- a/webform.module +++ b/webform.module @@ -584,6 +584,10 @@ function webform_theme() { 'arguments' => array('form' => NULL), 'file' => 'includes/webform.pages.inc', ), + 'webform_advanced_total_submit_limit_form' => array( + 'arguments' => array('form' => NULL), + 'file' => 'includes/webform.pages.inc', + ), // webform.report.inc. 'webform_results_per_page' => array( 'arguments' => array('total_count' => NULL, 'pager_count' => NULL), @@ -1074,6 +1078,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'), @@ -1283,6 +1289,16 @@ function webform_node_view(&$node, $teaser, $page) { $enabled = FALSE; } } + + // Check if the user can add another submission. + 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; @@ -1307,7 +1323,7 @@ function webform_node_view(&$node, $teaser, $page) { // Print out messages for the webform. if ($node->build_mode != NODE_BUILD_PREVIEW && !isset($node->webform_block) && !$logging_in) { - theme('webform_view_messages', $node, $teaser, $page, $submission_count, $limit_exceeded, $allowed_roles, $closed, $cached); + theme('webform_view_messages', $node, $teaser, $page, $submission_count, $limit_exceeded, $total_limit_exceeded, $allowed_roles, $closed, $cached); } if (isset($output)) { @@ -1353,6 +1369,8 @@ function theme_webform_view($node, $teaser, $page, $form, $enabled) { * 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 @@ -1364,7 +1382,7 @@ function theme_webform_view($node, $teaser, $page, $form, $enabled) { * is cached, such as "Submissions for this form are closed", because they * apply to all users equally. */ -function theme_webform_view_messages($node, $teaser, $page, $submission_count, $limit_exceeded, $allowed_roles, $closed, $cached) { +function theme_webform_view_messages($node, $teaser, $page, $submission_count, $limit_exceeded, $total_limit_exceeded, $allowed_roles, $closed, $cached) { global $user; $type = 'notice'; @@ -1408,6 +1426,14 @@ function theme_webform_view_messages($node, $teaser, $page, $submission_count, $ } $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) { @@ -2128,6 +2154,14 @@ function webform_client_form_submit($form, &$form_state) { $node = $form['#node']; + // Check if the total number of entries was reached before the user submitted + // the form. + if (_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); + return; + } + // Check if user is submitting as a draft. $is_draft = !empty($form_state['save_draft']);