diff -urp --strip-trailing-cr webform623/components/date.inc webform_arian_latest/components/date.inc
--- webform623/components/date.inc 2008-10-08 15:51:40.000000000 -0400
+++ webform_arian_latest/components/date.inc 2008-10-23 15:45:46.000000000 -0400
@@ -319,11 +319,13 @@ function _webform_theme_date() {
* submissions.
*/
function _webform_analysis_rows_date($component) {
- $query = 'SELECT no,data '.
- ' FROM {webform_submitted_data} '.
- ' WHERE nid = %d '.
- ' AND cid = %d '.
- ' ORDER BY sid,no ASC ';
+ $query = 'SELECT sd.no,sd.data '.
+ ' FROM {webform_submitted_data} sd'.
+ ' JOIN {webform_submissions} s ON sd.sid = s.sid'.
+ ' WHERE sd.nid = %d'.
+ ' AND sd.cid = %d'.
+ ' AND s.is_draft != 1'.
+ ' ORDER BY sd.sid,sd.no ASC';
$result = db_query($query, $component['nid'], $component['cid']);
// build an array of timestamps from entered values.
diff -urp --strip-trailing-cr webform623/components/email.inc webform_arian_latest/components/email.inc
--- webform623/components/email.inc 2008-10-06 01:45:10.000000000 -0400
+++ webform_arian_latest/components/email.inc 2008-10-23 14:56:10.000000000 -0400
@@ -179,10 +179,12 @@ function _webform_help_email($section) {
* submissions.
*/
function _webform_analysis_rows_email($component) {
- $query = 'SELECT data '.
- ' FROM {webform_submitted_data} '.
- ' WHERE nid = %d '.
- ' AND cid = %d';
+ $query = 'SELECT sd.data '.
+ ' FROM {webform_submitted_data} sd'.
+ ' JOIN {webform_submissions} s ON sd.sid = s.sid'.
+ ' WHERE sd.nid = %d'.
+ ' AND s.is_draft != 1'.
+ ' AND sd.cid = %d';
$nonblanks = 0;
$submissions = 0;
$wordcount = 0;
diff -urp --strip-trailing-cr webform623/components/file.inc webform_arian_latest/components/file.inc
--- webform623/components/file.inc 2008-10-08 15:51:40.000000000 -0400
+++ webform_arian_latest/components/file.inc 2008-10-31 11:36:11.790625000 -0400
@@ -274,7 +274,7 @@ function _webform_render_file($component
'#prefix' => '
',
'#suffix' => '
',
'#element_validate' => array(
- '_webform_validate_file',
+ '_webform_CHECKALWAYS_validate_file',
'_webform_required_file', // Custom required routine.
),
'#webform_component' => $component,
@@ -287,30 +287,65 @@ function _webform_render_file($component
return $form_item;
}
+/**
+ * If an error occurs on the file field, FF3 dont seem to allow red border on the file form element (FF2 has it very light border for some reason). so this sets another error on the field componant holder
+ * NOTE: if dont care about all browsers, then comment out set_file_componant_error calls
+ */
+function set_file_componant_error($form_key) {
+ drupal_add_js("$(document).ready(function(){
+ $('#webform-component-". $form_key ."').addClass('error');
+ });", "inline"); // adds error class so highlights input field
+}
+
function _webform_required_file($form_element, $form_state) {
$component = $form_element['#webform_component'];
$form_key = $component['form_key'];
+ $fieldname = $component['name'];
+ $required = $component['mandatory'];
- if (empty($_FILES['files']['name'][$form_key]) && $component['mandatory']) {
- form_set_error($form_key, t('%field field is required.', array('%field' => $component['name'])));
+ if ($required) { // make sure if required file that user uploaded a file
+ if ( empty($_FILES['files']['name'][$form_key]) ) { // if didnt upload anything for this field currently, search to see if saved from earlier draft submission
+ $qargs = array( $component['nid'], $form_element['#post']['details']['sid'], $component['cid'] );
+ $result = db_query("SELECT `data` FROM {webform_submitted_data} d WHERE nid=%d and sid=%d and cid=%d", $qargs );
+ if ($row = db_fetch_object($result)) {
+ $current_file = unserialize( $row->data );
+ if ( trim($current_file['filepath']) == "" ) { // no filepath define before, user just saved form before, and hence no filepath values, and since didnt upload anything new, error
+ form_set_error($form_key, t('%field field is required.', array('%field' => $fieldname)));
+ set_file_componant_error($form_key); //set * errors on file field, needed to manually add this before i thought for some reason in drupal5 but i am unsure of this now, Dont think I need this anymore, but just in case leaving it in commented out
+ }
+ else { // filepath is defined/saved before, but the file itself isnt found, admin possibly manually deleted file
+ if (!file_exists($current_file['filepath']) ) {
+ form_set_error($form_key, t('Your previously uploaded file %filename is not found/lost. The %field field is required so please reupload file.', array('%field' => $fieldname, '%filename' => $current_file['filename'])) );
+ set_file_componant_error($form_key);
+ }
+ }
+ }
+ else { // no old data but no new data and since field is required, error
+ form_set_error($form_key, t('%field field is required.', array('%field' => $fieldname)));
+ set_file_componant_error($form_key);
+ }
+ }
}
}
-function _webform_validate_file($form_element, &$form_state) {
+function _webform_CHECKALWAYS_validate_file($form_element, &$form_state) {
+ // Set the current file as the default.
$component = $form_element['#webform_component'];
$form_key = $component['form_key'];
+ $filtering = $component['extra']['filtering'];
// Set the previous file as the default.
if (isset($form_element['#webform_current_file'])) {
form_set_value(array('#parents' => $form_element['#array_parents']), serialize($form_element['#webform_current_file']), $form_state);
}
- if (empty($_FILES['files']['name'][$form_key])) {
+ // think if nothing uploaded for this componant dont check for requiredness
+ if ( empty($_FILES['files']['name'][ $form_key ]) ) {
return;
}
// Build a human readable list of extensions:
- $extensions = $component['extra']['filtering']['types'];
+ $extensions = $filtering['types'];
if (count($extensions) > 1) {
for ($n = 0; $n < count($extensions) - 1; $n++) {
$extension_list .= $extensions[$n] .", ";
@@ -329,11 +364,23 @@ function _webform_validate_file($form_el
$extension = strtolower(substr($_FILES['files']['name'][$form_key], $dot+1));
if (!in_array($extension, $extensions)) {
form_set_error($form_key, t("Files with the '%ext' extension are not allowed, please upload a file with a %exts extension.", array('%ext' => $extension, '%exts' => $extension_list)));
+ set_file_componant_error($form_key);
}
- // Now let's check the file size (limit is set in KB).
- if ($_FILES['files']['size'][$form_key] > $component['extra']['filtering']['size'] * 1024) {
- form_set_error($form_key, t("The file '%filename' is too large (%filesize KB). Please upload a file %maxsize KB or smaller.", array('%filename' => $_FILES['files']['name'][$form_key], '%filesize' => (int)($_FILES['files']['size'][$form_key]/1024), '%maxsize' => $component['extra']['filtering']['size'])));
+ if ( $php_default_file_validation_msg = _webform_php_file_errors($form_key) ) { // noticed the file size check didnt work in a certain case but php reported the error silently, so using new function to report php's file error info.
+ form_set_error($form_key, t($php_default_file_validation_msg, array('%filename' => $_FILES['files']['name'][$form_key]) ));
+ set_file_componant_error($form_key);
+ }
+ else {
+ // Now let's check the file size (limit is set in KB)
+ if ($_FILES['files']['size'][$form_key] > $filtering['size']*1024) {
+ form_set_error($form_key, t("The file '%filename' is too large (%filesize KB). Please upload a file %maxsize KB or smaller.", array('%filename' => $_FILES['files']['name'][$form_key], '%filesize' => (int)($_FILES['files']['size'][$form_key]/1024), '%maxsize' => $filtering['size'])));
+ set_file_componant_error($form_key);
+ }
+ else if ($_FILES['files']['size'][$form_key] <= 0) { // a 0byte 'fake' file or nonexistant file on server, if posting with IE6, the ajax 'file does not exist error' wont occur, however FF works. This test case is for IE6, possibly 7
+ form_set_error($form_key, t("The file '%filename' does not seem to exist on your computer (or is an empty file). Please click the Browse button and repick a file, and make sure to not modify the text that auto-fills the textfield.", array('%filename' => $_FILES['files']['name'][$form_key]) ));
+ set_file_componant_error($form_key);
+ }
}
}
@@ -348,23 +395,37 @@ function _webform_validate_file($form_el
* @return
* Nothing.
*/
-function _webform_submit_file(&$data, $component) {
+function _webform_submit_file(&$data, $component, $nid, $form_values = NULL ) {
$current_file = unserialize($data);
- $upload_dir = file_directory_path() ."/webform/". $component['extra']['savelocation'];
+ $current_data = $data; // to pass into delete function
+ if ( trim($component['extra']['savelocation']) == '' ) {
+ $upload_dir_pre = file_directory_path() ."/webform/". $nid; // standardized structure to find files easily
+ // $upload_dir_append = "/". $sid; // makes sense to put file in directory structore of nid/sid i think so easier to find on server... not sure how to make this database safe, so left out, leave this if statement in case someone can help, iniatially checked db for next sid available and added to $upload_dir, but not multi-user safe
+ $upload_dir = $upload_dir_pre;
+ $dodetailedpath = TRUE;
+ }
+ else {
+ $upload_dir = file_directory_path() ."/webform/". $component['extra']['savelocation'];
+ }
+
if (!empty($_FILES['files']['name'][$component['form_key']])) {
- if (file_check_directory($upload_dir, FILE_CREATE_DIRECTORY)) {
- $file_saved = file_save_upload($component['form_key'], array(), $upload_dir);
+ if ( ($path = file_create_path($upload_dir)) && file_check_directory($path, FILE_CREATE_DIRECTORY) ) { // creates the directory if not already there
+ $file_saved = file_save_upload($component['form_key'], array(), $upload_dir, FILE_EXISTS_RENAME);
if (!$file_saved) {
drupal_set_message(t("The uploaded file %filename was unable to be saved. The destination directory may not be writable.", array('%filename' => $file_saved['filename'])), "error");
}
else {
file_set_status($file_saved, FILE_STATUS_PERMANENT);
$data = serialize((array)$file_saved);
- file_delete($current_file['filepath']);
+ _webform_delete_file($current_data, $componant, TRUE);
+ if (isset($current_file['fid']))
+ drupal_set_message(t("Uploaded new file '%filename_new' and Deleted old file: '%filename_old'", array('%filename_new' => $file_saved->filename, '%filename_old' => basename($current_file['filepath']))) );
+ else
+ drupal_set_message(t("Uploaded new file '%filename_new' successfully", array('%filename_new' => $file_saved->filename)) );
}
}
else {
- drupal_set_message(t("The uploaded file was unable to be saved. The destination directory does not exist."), "error");
+ drupal_set_message(t("The uploaded file was unable to be saved. The destination directory '%path' does not exist.", array('%path' => $path)), "error");
}
}
}
@@ -398,7 +459,7 @@ function theme_webform_mail_file($data,
* @return
* Textual output formatted for human reading.
*/
-function _webform_submission_display_file($data, $component, $enabled = false) {
+function _webform_submission_display_file($data, $component, $enabled = false, $sid) { // RECHECK: should pass whole $submission instead?, or sending to every display_$componant will be bad usage
$filedata = unserialize($data['value'][0]);
$form_item = _webform_render_file($component);
if (!$enabled) {
@@ -408,10 +469,22 @@ function _webform_submission_display_fil
$form_item['#default_value'] = empty($filedata['filepath']) ? $filedata['error'] : $filedata['filepath'];
}
if ($filedata['filename']) {
- $form_item['#suffix'] = ' Download '. $filedata['filename'] .'' . $form_item['#suffix'];
+ $suffix_link = 'Download '. $filedata['filename'] .'';
+ $node = node_load($form_item['#webform_component']['nid']);
+ $submission = webform_menu_submission_load($sid, $node->nid);
+ // drupal_set_message($node->nid .' '. $sid);
+ if ( $enabled && webform_submission_access($node, $submission, 'edit') ) { // if can update node, then give link to delete, maybe change to user_access?
+ $suffix_link .= ' Delete '. $filedata['filename'] .'';
+ }
+ $form_item['#suffix'] .= $suffix_link . $form_item['#suffix'];
if ($enabled) {
$form_item['#description'] = t('Uploading a new file will replace the current file.');
$form_item['#webform_current_file'] = $filedata;
+ if ( $form_item['#webform_component']['mandatory'] == 1 ) {
+ drupal_add_js("$(document).ready(function(){
+ $('#webform-component-". $component['form_key'] ." label .form-required').append(' (Dont submit new file unless want to replace current file.)'); // some clarification, as when I see the * character, i tend to think i didnt upload something previously. the description is small, and user may not notice hyperlink... Hence why I put this here; You may remove if dont like.
+ });", "inline");
+ }
}
}
return $form_item;
@@ -427,12 +500,17 @@ function _webform_submission_display_fil
* An array of information describing the component, directly correlating to
* the webform_component database schema.
*/
-function _webform_delete_file($data, $component) {
+function _webform_delete_file($data, $component, $custom = FALSE) {
// Delete an individual submission file.
- $filedata = unserialize($data['value']['0']);
+ if ($custom) {
+ $filedata = unserialize($data); //for reusing this function for deleting the file componant. like if uploading new file, deletes old file
+ }
+ else {
+ $filedata = unserialize($data['value']['0']);
+ }
+ db_query("DELETE FROM {files} WHERE fid = %d", $filedata['fid']);
if (isset($filedata['filepath']) && is_file($filedata['filepath'])) {
unlink($filedata['filepath']);
- db_query("DELETE FROM {files} WHERE filepath = '%s'", $filedata['filepath']);
}
}
@@ -472,10 +550,12 @@ function _webform_theme_file() {
* submissions.
*/
function _webform_analysis_rows_file($component) {
- $query = 'SELECT data '.
- ' FROM {webform_submitted_data} '.
- ' WHERE nid = %d '.
- ' AND cid = %d';
+ $query = 'SELECT sd.data '.
+ ' FROM {webform_submitted_data} sd'.
+ ' JOIN {webform_submissions} s ON sd.sid = s.sid'.
+ ' WHERE sd.nid = %d'.
+ ' AND s.is_draft != 1'.
+ ' AND sd.cid = %d';
$nonblanks = 0;
$submissions = 0;
$wordcount = 0;
@@ -565,3 +645,109 @@ function webform_file_url($filepath) {
}
return isset($file_url) ? $file_url : '';
}
+function _webform_delete_submitted_file_data($nid, $sid, $cid, $filename = NULL) { // dont make copy of node as could be wasteful possibly
+ $result2 = db_query("DELETE FROM {webform_submitted_data} WHERE nid = %d AND sid = %d AND cid = %d", $nid, $sid, $cid);
+ if ($result2) {
+ drupal_set_message("File form data '". $filename ."' deleted successfully.");
+ }
+ else {
+ drupal_set_message("File form data '". $filename ."' not deleted successfully.", "error");
+ watchdog(WATCHDOG_WARNING, "Form form data '". $filename ."' not deleted successfully.");
+ }
+}
+
+/*
+ * Reports back php file errors: I ran into a case where php error log reported error when trying to validate file but webform doesn't check php file errors?
+ */
+function _webform_php_file_errors($form_key) {
+ //drupal_set_message( 'fileerrors='. print_r($_FILES["files"]["error"],true));
+ $error = $_FILES["files"]["error"][$form_key];
+
+ if ($error == UPLOAD_ERR_INI_SIZE)//1
+ return "The uploaded file '%filename' exceeds the upload_max_filesize directive in php.ini.";
+ else if ($error == UPLOAD_ERR_FORM_SIZE)//2
+ return "The uploaded file '%filename' exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.";
+ else if ($error == UPLOAD_ERR_PARTIAL)//3
+ return "The uploaded file '%filename' was only partially uploaded. Please reupload.";
+ else if ($error == UPLOAD_ERR_NO_TMP_DIR)//6
+ return "Cannot save '%filename'. Missing temporary folder.";
+ else if ($error == UPLOAD_ERR_CANT_WRITE) //7
+ return "Failed to write file '%filename' to disk.";
+}
+
+/*
+ * Confirmation page for deleting a file from the webform
+ */
+function _webform_delete_file_confirm(&$form_state, $node, $submission, $cid, $fid) {
+ $nid = $node->nid;
+ $sid = $submission->sid;
+ $form['nid'] = array('#type' => 'value', '#value' => $nid);
+ $form['sid'] = array('#type' => 'value', '#value' => $sid);
+ $form['cid'] = array('#type' => 'value', '#value' => $cid);
+ $form['fid'] = array('#type' => 'value', '#value' => $fid);
+ $form['#submit'][] = '_webform_delete_file_confirm_submit';
+//drupal_set_message($nid.'-'.$sid.'-'.$cid.'-'.$fid);
+ $result = db_query("SELECT filename,filepath FROM {files} WHERE fid = %d", $fid);
+ $fileobject = db_fetch_object($result);
+ $filename = $fileobject->filename;
+
+ return confirm_form($form,
+ t('Are you sure you want to delete the file') . (!empty($filename) ? (' '. $filename ) : '' ) .'?',
+ ('node/'. $nid .'/'. intval($sid)),
+ t('This action cannot be undone.'),
+ t('Delete'), t('Cancel'));
+
+}
+
+/**
+ * Deletes the file from system/webform
+ */
+function _webform_delete_file_confirm_submit($form, &$form_state) { //since changed _webform_delete_file to use fid, maybe just call that instead?
+ $nid = $form_state['values']['nid'];
+ $sid = $form_state['values']['sid'];
+ $cid = $form_state['values']['cid'];
+ $fid = $form_state['values']['fid'];
+
+ $result = db_query("SELECT filename,filepath FROM {files} WHERE fid = %d", $fid);
+ // delete the file
+ if ($result && ($fileobject = db_fetch_object($result)) ) {
+ // delete file from drupal database and file itself
+ db_query("DELETE FROM {files} WHERE fid = %d", $fid);
+ $filename = $fileobject->filename;
+ $filepath = $fileobject->filepath; //relative or full filepath depending on public/private filesystem
+ // delete data from webform_submission_data, possible case if file already deleted or not in database, so just get rid now from form data
+ _webform_delete_submitted_file_data($nid, $sid, $cid, $filename );
+ if (isset($filepath) && is_file($filepath)) {
+ unlink($filepath);
+ }
+ else {
+ drupal_set_message("File '". $filename ."' could not be deleted since it was not found. Contact Administrator", "error");
+ watchdog(WATCHDOG_WARNING, "File '". $filename ."' could not be deleted since it was not found. Contact Administrator");
+ }
+ drupal_goto('node/'. $nid .'/submission/'. intval($sid) .'/edit' ); // probably want to redirect to the edit submission page
+ }
+ else { //Edge case: if file still there just not in database for some reason
+ _webform_delete_submitted_file_data($nid, $sid, $cid, $filename );
+ // unlink() would be nice to delete the file also but... Don't unlink as, if uploaded a file called file.doc, and someone deleted off server. someone else (or same user for different question) could have uploaded resume.doc and hence it will have same filename as the one you want to delete
+ drupal_set_message("File database information could not be deleted for file id: '". $fid .".", "error");
+ watchdog(WATCHDOG_WARNING, "File database information not found for file id: ". $fid .".");
+ drupal_goto('node/'. $nid .'/submission/'. intval($sid) .'/edit' );
+ }
+}
+
+/**
+ * Checks if another file was uploaded when an error occured. User wont know his file didnt upload, if field wasnt required, or if saved a draft with another file, this is a problem, as submitting will work after previous error is fixed. This just informs user on that error page to make sure to resubmit the file.
+ */
+function _webform_check_error_and_newfile($form_state, $node) {
+ $form_errors = form_get_errors();
+ if ( count($_FILES['files']['size']) > 0 ) { //need to check if no files upload in this form, dont check, otherwise foreach warns FILES not array/invalid arg
+ foreach ( $_FILES['files']['size'] as $form_key => $size) { // see if submitted new file
+ if (($size > 0)) { //&& there was an error
+ if ( $form_errors && (!array_key_exists($form_key, $form_errors)) ) { // error occured on a required textfield for example. but file isnt uploaded yet... need some info saying this to the user, so he remembers to reupload his file
+ form_set_error( $form_key, t('An error occured on another question so unfortunately your file upload was lost. Please correct the other field and also re-upload %filename.', array('%filename' => $_FILES['files']['name'][$form_key]) ) );
+ set_file_componant_error($form_key);
+ }
+ }
+ }
+ }
+}
diff -urp --strip-trailing-cr webform623/components/grid.inc webform_arian_latest/components/grid.inc
--- webform623/components/grid.inc 2008-10-08 15:51:40.000000000 -0400
+++ webform_arian_latest/components/grid.inc 2008-10-30 16:00:24.978125000 -0400
@@ -241,12 +241,14 @@ function _webform_analysis_rows_grid($co
$questions = array_values(_webform_grid_options($component['extra']['questions']));
// Generate a lookup table of results.
- $query = 'SELECT no, data, count(data) as datacount '.
- ' FROM {webform_submitted_data} '.
- ' WHERE nid = %d '.
- ' AND cid = %d '.
- " AND data != '0' AND data != '' ".
- ' GROUP BY no, data';
+ $query = 'SELECT sd.no, sd.data, count(sd.data) as datacount '.
+ ' FROM {webform_submitted_data} sd'.
+ ' JOIN {webform_submissions} s ON sd.sid = s.sid'.
+ ' WHERE sd.nid = %d'.
+ ' AND sd.cid = %d'.
+ " AND sd.data != '0' AND sd.data != ''".
+ ' AND s.is_draft != 1'.
+ ' GROUP BY sd.no, sd.data';
$result = db_query($query, $component['nid'], $component['cid']);
$counts = array();
while ($data = db_fetch_object($result)) {
diff -urp --strip-trailing-cr webform623/components/hidden.inc webform_arian_latest/components/hidden.inc
--- webform623/components/hidden.inc 2008-09-06 16:51:40.000000000 -0400
+++ webform_arian_latest/components/hidden.inc 2008-10-23 14:52:38.000000000 -0400
@@ -117,10 +117,12 @@ function _webform_help_hidden($section)
* submissions.
*/
function _webform_analysis_rows_hidden($component) {
- $query = 'SELECT data '.
- ' FROM {webform_submitted_data} '.
- ' WHERE nid = %d '.
- ' AND cid = %d';
+ $query = 'SELECT sd.data '.
+ ' FROM {webform_submitted_data} sd'.
+ ' JOIN {webform_submissions} s ON sd.sid = s.sid'.
+ ' WHERE sd.nid = %d'.
+ ' AND s.is_draft != 1'.
+ ' AND sd.cid = %d';
$nonblanks = 0;
$submissions = 0;
$wordcount = 0;
diff -urp --strip-trailing-cr webform623/components/select.inc webform_arian_latest/components/select.inc
--- webform623/components/select.inc 2008-10-22 15:38:58.000000000 -0400
+++ webform_arian_latest/components/select.inc 2008-10-23 15:56:10.000000000 -0400
@@ -301,12 +301,14 @@ function _webform_theme_select() {
function _webform_analysis_rows_select($component) {
$options = _webform_select_options($component['extra']['items']);
- $query = 'SELECT data, count(data) as datacount '.
- ' FROM {webform_submitted_data} '.
- ' WHERE nid = %d '.
- ' AND cid = %d '.
- " AND data != '0' AND data != '' ".
- ' GROUP BY data ';
+ $query = 'SELECT sd.data, count(sd.data) as datacount '.
+ ' FROM {webform_submitted_data} sd'.
+ ' JOIN {webform_submissions} s ON sd.sid = s.sid'.
+ ' WHERE sd.nid = %d'.
+ ' AND sd.cid = %d'.
+ ' AND s.is_draft != 1'.
+ " AND sd.data != '0' AND sd.data != ''".
+ ' GROUP BY sd.data';
$result = db_query($query, $component['nid'], $component['cid']);
$rows = array();
while ($data = db_fetch_array($result)) {
diff -urp --strip-trailing-cr webform623/components/textarea.inc webform_arian_latest/components/textarea.inc
--- webform623/components/textarea.inc 2008-09-06 16:51:40.000000000 -0400
+++ webform_arian_latest/components/textarea.inc 2008-10-20 16:48:34.000000000 -0400
@@ -138,10 +138,12 @@ function _webform_help_textarea($section
* submissions.
*/
function _webform_analysis_rows_textarea($component) {
- $query = 'SELECT data '.
- ' FROM {webform_submitted_data} '.
- ' WHERE nid = %d '.
- ' AND cid = %d';
+ $query = 'SELECT sd.data '.
+ ' FROM {webform_submitted_data} sd'.
+ ' JOIN {webform_submissions} s ON sd.sid = s.sid'.
+ ' WHERE sd.nid = %d'.
+ ' AND sd.cid = %d'.
+ ' AND s.is_draft != 1';
$nonblanks = 0;
$submissions = 0;
$wordcount = 0;
diff -urp --strip-trailing-cr webform623/components/textfield.inc webform_arian_latest/components/textfield.inc
--- webform623/components/textfield.inc 2008-10-14 14:20:02.000000000 -0400
+++ webform_arian_latest/components/textfield.inc 2008-10-23 15:58:36.000000000 -0400
@@ -195,10 +195,13 @@ function _webform_help_textfield($sectio
* submissions.
*/
function _webform_analysis_rows_textfield($component) {
- $query = 'SELECT data '.
- ' FROM {webform_submitted_data} '.
- ' WHERE nid = %d '.
- ' AND cid = %d';
+ $query = 'SELECT sd.data '.
+ ' FROM {webform_submitted_data} sd'.
+ ' JOIN {webform_submissions} s ON sd.sid = s.sid'.
+ ' WHERE sd.nid = %d'.
+ ' AND sd.cid = %d'.
+ ' AND s.is_draft != 1';
+
$nonblanks = 0;
$submissions = 0;
$wordcount = 0;
diff -urp --strip-trailing-cr webform623/components/time.inc webform_arian_latest/components/time.inc
--- webform623/components/time.inc 2008-10-08 15:51:40.000000000 -0400
+++ webform_arian_latest/components/time.inc 2008-10-23 15:59:30.000000000 -0400
@@ -270,11 +270,13 @@ function _webform_theme_time() {
* submissions.
*/
function _webform_analysis_rows_time($component) {
- $query = 'SELECT no,data '.
- ' FROM {webform_submitted_data} '.
- ' WHERE nid = %d '.
- ' AND cid = %d '.
- ' ORDER BY sid,no ASC ';
+ $query = 'SELECT sd.no,sd.data '.
+ ' FROM {webform_submitted_data} sd'.
+ ' JOIN {webform_submissions} s ON sd.sid = s.sid'.
+ ' WHERE sd.nid = %d'.
+ ' AND sd.cid = %d'.
+ ' AND s.is_draft != 1'.
+ ' ORDER BY sd.sid,sd.no ASC';
$result = db_query($query, $component['nid'], $component['cid']);
// build an array of timestamps from entered values.
diff -urp --strip-trailing-cr webform623/webform.install webform_arian_latest/webform.install
--- webform623/webform.install 2008-10-08 15:51:40.000000000 -0400
+++ webform_arian_latest/webform.install 2008-10-23 16:04:52.000000000 -0400
@@ -804,7 +804,24 @@ function webform_update_20() {
}
return $ret;
}
-
+/*
+ * Update if running 'Save Draft' Webform patch
+ */
+function webform_update_21() {
+ $ret = array();
+ switch ($GLOBALS['db_type']) {
+ case 'mysqli':
+ case 'mysql':
+ $ret[] = update_sql("ALTER TABLE {webform_submissions} ADD is_draft tinyint not null default '0'");
+ $ret[] = update_sql("ALTER TABLE {webform} ADD allow_draft tinyint not null default '0'");
+ break;
+ case 'pgsql':
+ $ret[] = update_sql("ALTER TABLE {webform_submissions} ADD is_draft smallint not null default '0'");
+ $ret[] = update_sql("ALTER TABLE {webform} ADD allow_draft smallint not null default '0'");
+ break;
+ }
+ return $ret;
+}
/**
* Set the upgrade
*/
diff -urp --strip-trailing-cr webform623/webform.module webform_arian_latest/webform.module
--- webform623/webform.module 2008-10-14 17:51:42.000000000 -0400
+++ webform_arian_latest/webform.module 2008-10-31 11:40:46.243750000 -0400
@@ -89,10 +89,10 @@ function webform_menu() {
);
// Node page tabs.
- $items['node/%webform_menu/done'] = array(
+ $items['node/%webform_menu/done/submission/%sid'] = array( // prefer not sending the sid in GET, just a preference
'title' => 'Webform confirmation',
'page callback' => '_webform_confirmation',
- 'page arguments' => array(1),
+ 'page arguments' => array(1, 4),
'access callback' => 'node_access',
'access arguments' => array('view', 1),
'type' => MENU_CALLBACK,
@@ -119,7 +119,7 @@ function webform_menu() {
// Node component forms.
$items['node/%webform_menu/edit/components/%webform_menu_component'] = array(
- 'load arguments' => array(1, 5),
+ 'load arguments' => array(1, 5), //5 needed in this item? is NULL anyway?
'page arguments' => array('webform_component_edit_form', 1, 4, FALSE),
'access callback' => 'node_access',
'access arguments' => array('update', 1),
@@ -216,7 +216,7 @@ function webform_menu() {
'title' => 'Webform submission',
'load arguments' => array(1),
'page callback' => 'webform_client_form_load',
- 'page arguments' => array(1, 3, FALSE, FALSE),
+ 'page arguments' => array(1, 3, FALSE, FALSE), // array('webform_client_form_'. $node->nid, $node, $submission, FALSE, FALSE, FALSE, $submission->is_draft), // call is_draft via loading the submission which should have is_draft added
'access callback' => 'webform_submission_access',
'access arguments' => array(1, 3, 'view'),
'type' => MENU_CALLBACK,
@@ -252,6 +252,28 @@ function webform_menu() {
'type' => MENU_LOCAL_TASK,
);
+ $items['node/%webform_menu/draft_saved/%webform_menu_submission']= array(
+ 'title' => t('Draft saved'),
+ 'load arguments' => array(1),
+ 'page callback' => '_webform_draft_confirmation',
+ 'page arguments' => array(1, 3),
+ 'access callback' => 'webform_submission_access',
+ 'access arguments' => array(1, 3, 'view'),
+ 'type' => MENU_CALLBACK,
+ );
+
+ $items['node/%webform_menu/%webform_menu_submission/%/%/delete_file']= array(
+ 'title' => t('Delete Webform File'),
+ 'load arguments' => array(1),
+ 'page callback' => 'drupal_get_form',
+ 'page arguments' => array('_webform_delete_file_confirm', 1, 2, 3, 4), // node, question id, file id args (node id should be loaded automatically, calling _load)
+ 'access callback' => 'webform_submission_access',
+ 'access arguments' => array(1, 2, 'edit'), // make sure if going to this link that user is allowed to update the webform if he is allowed to update it
+ 'file' => 'file.inc',
+ 'file path' => drupal_get_path('module', 'webform') .'/components/',
+ 'type' => MENU_CALLBACK,
+ );
+
return $items;
}
@@ -295,19 +317,32 @@ function webform_menu_component_load($ci
return $component;
}
-function webform_submission_access($node, $submission, $op = 'view', $account = NULL) {
+function webform_submission_access($node, $submission = NULL, $op = 'view', $account = NULL) { // might not need submission if checking is should access submissions page ('list'), or in 'edit' if should have rights to 'edit webform submissions', aka not just /edit page for a specific submission, but all your submissons in general for that $node
global $user;
$account = isset($account) ? $account : $user;
+ $draft_count = db_result(db_query("SELECT count(*) FROM {webform_submissions} WHERE nid = %d AND uid = %d AND is_draft = 1", $node->nid, $user->uid)); // get number of drafts for user. if he has more than 1, show him a list to other drafts. if just one dont show him the list as he doesnt need it (the last draft prepopulates the webform anyway). use $user btw as we never check for someone elses priveledges in 'list' situations
+
+ $allowed_roles = array();
+ foreach ($node->webform['roles'] as $rid) {
+ $allowed_roles[$rid] = isset($user->roles[$rid]) ? TRUE : FALSE;
+ }
+ if ((array_search(TRUE, $allowed_roles) === FALSE) && ($user->uid != 1)) {
+ $role_is_not_allowed = TRUE;
+ }
+ module_load_include('inc', 'webform', 'webform_submissions');
+ $limit_exceeded = _webform_submission_limit_check($node);
+ $access_errors = $role_is_not_allowed || $limit_exceeded; // for determinging if user should have access to drafts
+
switch ($op) {
case 'view':
- return user_access('access webform results') || (user_access('access own webform submissions') && ($account->uid == $submission->uid));
+ return user_access('access webform results') || (user_access('access own webform submissions') && ($account->uid == $submission->uid)) || ($submission->is_draft && ($account->uid == $submission->uid) && (!$access_errors)); // even if doesnt have rights to access own finalized webform submission, at this point if it is a draft, allow them to view still or delete file they uploaded in a draft
case 'edit':
- return user_access('edit webform submissions') || (user_access('edit own webform submissions') && ($account->uid == $submission->uid));
+ return user_access('edit webform submissions') || (user_access('edit own webform submissions') && ($account->uid == $submission->uid)) || ($submission->is_draft && ($account->uid == $submission->uid) && (!$access_errors)); // even if doesnt have rights to edit own finalized webform submission, at this point if it is a draft, allow them to edit still if they are allowed to submit the form
case 'delete':
- return user_access('edit webform submissions') || (user_access('edit own webform submissions') && ($account->uid == $submission->uid)) || user_access('clear webform results');
- case 'list':
- return user_access('access webform results') || user_access('access webform submissions') || (user_access('access own webform submissions') && $user->uid);
+ return user_access('edit webform submissions') || (user_access('edit own webform submissions') && ($account->uid == $submission->uid)) || user_access('clear webform results') || ($submission->is_draft && ($account->uid == $submission->uid) && (!$access_errors)); // allow user to delete the submission if its still in draft form and user is allowed to submit form (no link to do this currently if user has 1 draft saved but shouldnt be needed as if will submit form, the draft prepopulated for him. only issue if wants to clear data as he doesnt want his info in our system. he can just manually clear all his data for now, until admin deletes non-completed webforms)
+ case 'list':// get submissions for this user or all users
+ return (($draft_count > 1) && $user->uid && (!$access_errors)) || user_access('access webform results') || user_access('access webform submissions') || (user_access('access own webform submissions') && $user->uid); // allow non-anonymous users that have drafts saved to goto Submissions page to at least see their unsubmitted drafts, edge case as last saved draft always gets populated and have to submit it, although administrator may put a saved submission back into Draft state (submitted submissions on that page may be not seen if they dont have 'access webform submissions' rights to see them. Change in webform_results_submissions() to take this into account)
}
}
@@ -315,7 +350,8 @@ function webform_submission_access($node
* Implementation of hook_perm().
*/
function webform_perm() {
- return array("create webforms", "edit own webforms", "edit webforms", "access webform results", "clear webform results", "access own webform submissions", "edit own webform submissions", "edit webform submissions", "use PHP for additional processing");
+ return array("create webforms", "edit own webforms", "edit webforms", "access webform results", "clear webform results", "access own webform submissions", "edit own webform submissions", "edit webform submissions", "use PHP for additional processing"); // "access webform submissions" is still used in the module?, maybe cause "access webform results" seems to have replaced it. I use both just in case in my checks and left in hook_perm
+
}
/**
@@ -328,7 +364,7 @@ function webform_theme() {
'arguments' => array('node' => NULL, 'teaser' => NULL, 'page' => NULL, 'form' => NULL, 'enabled' => NULL),
),
'webform_view_messages' => array(
- 'arguments' => array('node' => NULL, 'teaser' => NULL, 'page' => NULL, 'submission_count' => NULL, 'limit_exceeded' => NULL, 'allowed_roles' => NULL),
+ 'arguments' => array('node' => NULL, 'teaser' => NULL, 'page' => NULL, 'submission_count' => NULL, 'limit_exceeded' => NULL, 'allowed_roles' => NULL, 'submission' => NULL),
),
'webform_form' => array(
'arguments' => array('form' => NULL),
@@ -387,6 +423,9 @@ function webform_theme() {
'webform_results_table' => array(
'arguments' => array('node' => NULL, 'components' => NULL, 'submissions' => NULL, 'node' => NULL),
),
+ 'webform_draft_confirmation' => array(
+ 'arguments' => array('node' => NULL, 'sid' => NULL),
+ ),
);
// Theme functions in all components.
$components = webform_load_components(TRUE);
@@ -444,12 +483,60 @@ function webform_forms($form_id) {
*
* Only allow users with view webform submissions to download files.
*/
-function webform_file_download($file) {
+function webform_file_download($file) { // possibly check access rights first to save time?
+
$file = file_check_location(file_directory_path() .'/'. $file, file_directory_path() .'/webform/');
- if ($file && user_access('access webform results')) {
- $info = image_get_info(file_create_path($file));
- return array('Content-type: '. $info['mime_type']);
+ $pathinfo_file_path_url = pathinfo($file);
+ // Makes sense that if they save their submission and want to recome back to it to check on it... that they can dl and view their file to see if they want to replace it, also give access to anyone who can edit webform submissions
+ global $user;
+ if ( strpos( realpath($pathinfo_file_path_url['dirname']), realpath(file_directory_path() .'/webform/') ) === 0 ) { // scope it to webform module, do not reject other module's file download
+ $webform_access_download = ( user_access('access webform results')
+ || (user_access('edit own webform submissions') && ($file_uid==$user->uid))
+ || (user_access('access own webform submissions') && ($file_uid==$user->uid))
+ || user_access('edit webform submissions') );
+
+ if (!$webform_access_download)
+ return -1;
+
+ // Get sid of file so can figure out uid of who submitted this file as an answer (to base permissions off of)
+ $result = db_query("SELECT * FROM {files} f where status=1"); // No need to get files from other modules setting temp files, Possibly create a webform_files db too, for faster look ups on what nid,sid belongs to an fid, Or can just not look at {files} and use webform_submitted_data for files because going to look in there anyway if a file match is found
+ $num_files = 0;
+ while ( $row = db_fetch_object($result) ) {
+ $path_info_db = pathinfo($row->filepath);
+ // So making sure the database entry is same filepath if requested file
+ if ( (realpath($pathinfo_file_path_url['dirname'])==realpath($path_info_db['dirname'])) && ($pathinfo_file_path_url['basename']==$path_info_db['basename']) ) { // base on filedir, and then filename cause some modules dont normalize data and might have funky filenames like C:\files/webform/1/2/node1submissionfile.blah, checks to make sure same file in same directory... Maybe can substitute file_check_path but sometimes makes mistakes like c: and C:, so hence why i just use realpath()
+ $fid = $row->fid;
+ $num_files++;
+ if ($num_files>1) // Drupal says their are 2 matching filepaths in its system. Shouldnt be possible, maybe a module forgot to delete its file. One should be deleted.
+ break;
+ }
+ }
+
+ if ( $num_files == 1 ) { // Found a match, now lets see if the user can access it by being an webformadmin-type person or if matches the user who submitted that file
+ $result = db_query("SELECT wsd.`data`, wsd.nid, wsd.sid FROM {webform_submitted_data} wsd JOIN {webform_component} wc ON wsd.cid=wc.cid WHERE wc.`type`='file'");
+ while ( $row = db_fetch_object($result)) { // search for this node
+ $data = unserialize($row->data);
+ if ( intval($data['fid']) == intval($fid) ) {
+ $sid = $row->sid;
+ $nid = $row->nid;
+ break;
+ }
+ }
+
+ if (($nid>0) && ($sid>0)) {
+ $file_uid = db_result(db_query("SELECT uid FROM {webform_submissions} ws WHERE sid=%d AND nid=%d", $sid, $nid)); // Could also use {files} uid, but sticking with webforms data
+ if ($file && $webform_access_download) {
+ $info = image_get_info(file_create_path($file));
+ return array('Content-type: '. $info['mime_type']);
+ }
+ }
+ }
+ else if ( $num_files > 1)
+ drupal_set_message( 'There are 2 of files with same filepath in the database for some reason so we are not sure if you are allowed to access this file. Please ask website administrator to fix so you may get access.' ) ;
+ else
+ drupal_set_message( 'File cannot be found. Contact Website administrator.'); // Not sure if ever gets here, in drupal 5, if file not found, hook wont get called it seems?
}
+ return NULL; // explicitly saying dont handle download. not needed.
}
/**
@@ -464,7 +551,7 @@ function webform_insert($node) {
}
// Insert the Webform.
- db_query("INSERT INTO {webform} (nid, confirmation, teaser, submit_text, submit_limit, submit_interval, email, email_from_name, email_from_address, email_subject, additional_validate, additional_submit) VALUES (%d, '%s', %d, '%s', %d, %d, '%s', '%s', '%s', '%s', '%s', '%s')", $node->nid, $node->webform['confirmation'], $node->webform['teaser'], $node->webform['submit_text'], $node->webform['submit_limit'], $node->webform['submit_interval'], $node->webform['email'], $node->webform['email_from_name'], $node->webform['email_from_address'], $node->webform['email_subject'], $node->webform['additional_validate'], $node->webform['additional_submit']);
+ db_query("INSERT INTO {webform} (nid, confirmation, teaser, submit_text, submit_limit, submit_interval, email, email_from_name, email_from_address, email_subject, additional_validate, additional_submit, allow_draft) VALUES (%d, '%s', %d, '%s', %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', %d)", $node->nid, $node->webform['confirmation'], $node->webform['teaser'], $node->webform['submit_text'], $node->webform['submit_limit'], $node->webform['submit_interval'], $node->webform['email'], $node->webform['email_from_name'], $node->webform['email_from_address'], $node->webform['email_subject'], $node->webform['additional_validate'], $node->webform['additional_submit'], $node->webform['allow_draft']);
// Insert the components into the database. Used with clone.module.
if (isset($node->webform['components']) && !empty($node->webform['components'])) {
@@ -819,6 +906,14 @@ function webform_form(&$node, &$param) {
'#default_value' => $node->webform['submit_text'],
'#description' => t('By default the submit button on this form will have the label Submit. Enter a new title here to override the default.'),
);
+
+ // Allow save draft
+ $form['webform']['advanced']['allow_draft'] = array(
+ '#type' => 'checkbox',
+ '#title' => t('Allow users to save a draft'),
+ '#default_value' => $node->webform['allow_draft'],
+ );
+
if (user_access('use PHP for additional processing')) {
$form['webform']['advanced']['additional_validate'] = array(
'#type' => 'textarea',
@@ -1076,13 +1171,40 @@ function webform_view(&$node, $teaser =
}
// Get a count of previous submissions by this user.
- if ($user->uid && (user_access('access own webform submissions') || user_access('access webform results') || user_access('access webform submissions'))) {
- $submission_count = db_result(db_query("SELECT count(*) FROM {webform_submissions} WHERE nid = %d AND uid = %d", $node->nid, $user->uid));
+ $submission_count = db_result(db_query("SELECT count(*) FROM {webform_submissions} WHERE nid = %d AND uid = %d AND is_draft <> 1", $node->nid, $user->uid)); // get submission count where not a draft, otherwise user with 1 draft and 1 form limit
+
+ // Check if this user has a draft for this webform.
+ $is_draft = FALSE;
+ if ($node->webform['allow_draft'] && $user->uid != 0) { // drafts shouldnt be allowed for anonymous users, so dont autofill last saved draft form for them
+ // Draft found - display form with draft data for further editing.
+ if ($_draft_sid = _webform_fetch_draft_sid($node->nid, $user->uid)) {
+ // if is_draft, but dont have rights
+ include_once(drupal_get_path('module', 'webform') ."/webform_submissions.inc");
+ $submission = webform_get_submission($node->nid, $_draft_sid);
+ if ( webform_submission_access($node, $submission, 'edit') ) {
+ $enabled = TRUE;
+ $is_draft = TRUE;
+ }
+ else {
+ $enabled = FALSE;
+ $is_draft = TRUE;
+ }
+
+ }
}
// Render the form and generate the output.
- $form = drupal_get_form('webform_client_form_'. $node->nid, $node, $submission, $enabled, $preview);
- $output = theme('webform_view', $node, $teaser, $page, $form, $enabled);
+ if ( ($submission->is_draft && webform_submission_access($node, $submission, 'view')) ) { // is a draft and has access so at least display the draft (maybe be able to submit based if $enabled set above for drafts)
+ $form = drupal_get_form('webform_client_form_'. $node->nid, $node, $submission, $enabled, $preview, NULL, $is_draft);
+ $output = theme('webform_view', $node, $teaser, $page, $form, $enabled);
+ }
+ else if ( ($submission->is_draft && (!webform_submission_access($node, $submission, 'view'))) ) { // does not have access to see draft prefilled out
+ $node->body = 'Webform not available';
+ }
+ else { // regular case
+ $form = drupal_get_form('webform_client_form_'. $node->nid, $node, $submission, $enabled, $preview, NULL, $is_draft);
+ $output = theme('webform_view', $node, $teaser, $page, $form, $enabled);
+ }
// Remove the surrounding