diff --git a/includes/form.inc b/includes/form.inc index 14cf618..acac38d 100644 --- a/includes/form.inc +++ b/includes/form.inc @@ -1322,25 +1322,30 @@ function _form_validate(&$elements, &$form_state, $form_id = NULL) { } // Make sure a value is passed when the field is required. - if (isset($elements['#needs_validation']) && $elements['#required']) { - // A simple call to empty() will not cut it here as some fields, like - // checkboxes, can return a valid value of '0'. Instead, check the - // length if it's a string, and the item count if it's an array. - // An unchecked checkbox has a #value of integer 0, different than string - // '0', which could be a valid value. - $is_empty_multiple = (!count($elements['#value'])); - $is_empty_string = (is_string($elements['#value']) && drupal_strlen(trim($elements['#value'])) == 0); - $is_empty_value = ($elements['#value'] === 0); - if ($is_empty_multiple || $is_empty_string || $is_empty_value) { - // Although discouraged, a #title is not mandatory for form elements. In - // case there is no #title, we cannot set a form error message. - // Instead of setting no #title, form constructors are encouraged to set - // #title_display to 'invisible' to improve accessibility. - if (isset($elements['#title'])) { - form_error($elements, $t('!name field is required.', array('!name' => $elements['#title']))); - } - else { - form_error($elements); + if (isset($elements['#needs_validation']) && $elements['#required']) { + + // Specialized check for file type uploads, which store their + // value in the $_FILES array. + if ($elements['#type'] !== 'file' || empty($_FILES['files']['name'][$elements['#parents'][0]])) { + // A simple call to empty() will not cut it here as some fields, like + // checkboxes, can return a valid value of '0'. Instead, check the + // length if it's a string, and the item count if it's an array. + // An unchecked checkbox has a #value of integer 0, different than string + // '0', which could be a valid value. + $is_empty_multiple = (!count($elements['#value'])); + $is_empty_string = (is_string($elements['#value']) && drupal_strlen(trim($elements['#value'])) == 0); + $is_empty_value = ($elements['#value'] === 0); + if ($is_empty_multiple || $is_empty_string || $is_empty_value) { + // Although discouraged, a #title is not mandatory for form elements. In + // case there is no #title, we cannot set a form error message. + // Instead of setting no #title, form constructors are encouraged to set + // #title_display to 'invisible' to improve accessibility. + if (isset($elements['#title'])) { + form_error($elements, $t('!name field is required.', array('!name' => $elements['#title']))); + } + else { + form_error($elements); + } } } } diff --git a/modules/simpletest/tests/file.test b/modules/simpletest/tests/file.test index 9dbe546..b1c2e4a 100644 --- a/modules/simpletest/tests/file.test +++ b/modules/simpletest/tests/file.test @@ -673,6 +673,26 @@ class FileSaveUploadTest extends FileHookTestCase { } /** + * Test the file_save_upload() function with required file field. + */ + function testRequired() { + // Reset the hook counters to get rid of the 'load' we just called. + file_test_reset(); + + // Upload a second file. + $max_fid_before = db_query('SELECT MAX(fid) AS fid FROM {file_managed}')->fetchField(); + $image2 = current($this->drupalGetTestFiles('image')); + $edit = array('files[file_test_upload]' => drupal_realpath($image2->uri)); + $this->drupalPost('file-test/upload/1', $edit, t('Submit')); + $this->assertResponse(200, t('Received a 200 response for posted test file.')); + $this->assertRaw(t('You WIN!')); + + $this->drupalPost('file-test/upload/1', array(), t('Submit')); + $this->assertResponse(200, t('Received a 200 response for posted test file.')); + $this->assertRaw(t('field is required')); + } + + /** * Test extension handling. */ function testHandleExtension() { diff --git a/modules/simpletest/tests/file_test.module b/modules/simpletest/tests/file_test.module index b3c43e0..f9b6ccf 100644 --- a/modules/simpletest/tests/file_test.module +++ b/modules/simpletest/tests/file_test.module @@ -48,10 +48,11 @@ function file_test_stream_wrappers() { /** * Form to test file uploads. */ -function _file_test_form($form, &$form_state) { +function _file_test_form($form, &$form_state, $required = FALSE) { $form['file_test_upload'] = array( '#type' => 'file', '#title' => t('Upload a file'), + '#required' => $required, ); $form['file_test_replace'] = array( '#type' => 'select',