Index: image.module =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/image/image.module,v retrieving revision 1.295 diff -u -p -r1.295 image.module --- image.module 1 Feb 2009 03:10:33 -0000 1.295 +++ image.module 4 Feb 2009 19:42:12 -0000 @@ -168,66 +168,6 @@ function image_operations_rebuild($nids) } /** - * TODO: document me... - */ -function image_node_form_submit($form, &$form_state) { - // We need to be aware that a user may try to edit multiple image nodes at - // once. By using the $nid variable each node's files can be stored separately - // in the session. - $nid = $form_state['values']['nid'] ? $form_state['values']['nid'] : 'new_node'; - // When you enter the edit view the first time we need to clear our files in - // session for this node. This is so if you upload a file, then decide you - // don't want it and reload the form (without posting), the files will be - // discarded. - if (count($_POST) == 0) { - unset($_SESSION['image_new_files'][$nid]); - } - - // Validators for file_save_upload(). - $validators = array( - 'file_validate_is_image' => array(), - ); - - if ($file = file_save_upload('image', $validators)) { - // Resize the original. - $image_info = image_get_info($file->filepath); - $aspect_ratio = $image_info['height'] / $image_info['width']; - $original_size = image_get_sizes(IMAGE_ORIGINAL, $aspect_ratio); - if (!empty($original_size['width']) && !empty($original_size['height'])) { - $result = image_scale($file->filepath, $file->filepath, $original_size['width'], $original_size['height']); - if ($result) { - clearstatcache(); - $file->filesize = filesize($file->filepath); - drupal_set_message(t('The original image was resized to fit within the maximum allowed resolution of %width x %height pixels.', array('%width' => $original_size['width'], '%height' => $original_size['height']))); - } - } - - // Check the file size limit. - if ($file->filesize > variable_get('image_max_upload_size', 800) * 1024) { - form_set_error('image', t('The image you uploaded was too big. You are only allowed upload files less than %max_size but your file was %file_size.', array('%max_size' => format_size(variable_get('image_max_upload_size', 800) * 1024), '%file_size' => format_size($file->filesize)))); - file_delete($file->filepath); - return; - } - - // We're good to go. - $form_state['values']['images'][IMAGE_ORIGINAL] = $file->filepath; - $form_state['values']['rebuild_images'] = FALSE; - $form_state['values']['new_file'] = TRUE; - - // Call hook to allow other modules to modify the original image. - module_invoke_all('image_alter', $form_state['values'], $file->filepath, IMAGE_ORIGINAL); - $form_state['values']['images'] = _image_build_derivatives((object) $form_state['values'], TRUE); - - // Store the new file into the session. - $_SESSION['image_new_files'][$nid] = $form_state['values']['images']; - } - // Reload new files uploaded in a previous preview. - else if (isset($_SESSION['image_new_files'][$nid])) { - $form_state['values']['images'] = $_SESSION['image_new_files'][$nid]; - } -} - -/** * Implementation of hook_file_download(). * * Note that in Drupal 5, the upload.module's hook_file_download() checks its @@ -353,14 +293,19 @@ function image_form_add_thumbnail($form, } /** - * Implementation of hook_form + * Implementation of hook_form(). */ -function image_form(&$node, &$param) { +function image_form(&$node, $form_state) { _image_check_settings(); + if (!$_POST && !empty($_SESSION['image_upload'])) { + unset($_SESSION['image_upload']); + } + $type = node_get_types('type', $node); - $form['#submit'][] = 'image_node_form_submit'; + $form['#validate'][] = 'image_form_validate'; + $form['#submit'][] = 'image_form_submit'; $form['title'] = array( '#type' => 'textfield', @@ -397,7 +342,7 @@ function image_form(&$node, &$param) { '#access' => (!isset($node->nid) ? FALSE : TRUE), ); - $form['#attributes'] = array("enctype" => "multipart/form-data"); + $form['#attributes'] = array('enctype' => 'multipart/form-data'); $form['image'] = array( '#type' => 'file', '#title' => t('Image'), @@ -412,10 +357,61 @@ function image_form(&$node, &$param) { return $form; } -function image_validate($node) { - $nid = ($node->nid) ? $node->nid : 'new_node'; - if (!isset($node->images[IMAGE_ORIGINAL]) && !isset($_SESSION['image_new_files'][$nid])) { - form_set_error('image', t('You must upload an image.')); +function image_form_validate($form, &$form_state) { + // Avoid blocking deletion of a node with missing image. + if ($form_state['values']['op'] == t('Delete')) { + return; + } + + $validators = array('file_validate_is_image' => array()); + // New image uploads need to be saved in images/temp in order to be viewable + // during node preview. + $temporary_file_path = file_create_path(variable_get('image_default_path', 'images') .'/temp'); + + if ($file = file_save_upload('image', $validators, $temporary_file_path)) { + // Resize the original. + $image_info = image_get_info($file->filepath); + $aspect_ratio = $image_info['height'] / $image_info['width']; + $original_size = image_get_sizes(IMAGE_ORIGINAL, $aspect_ratio); + if (!empty($original_size['width']) && !empty($original_size['height'])) { + $result = image_scale($file->filepath, $file->filepath, $original_size['width'], $original_size['height']); + if ($result) { + clearstatcache(); + $file->filesize = filesize($file->filepath); + drupal_set_message(t('The original image was resized to fit within the maximum allowed resolution of %width x %height pixels.', array('%width' => $original_size['width'], '%height' => $original_size['height']))); + } + } + + // Check the file size limit. + if ($file->filesize > variable_get('image_max_upload_size', 800) * 1024) { + form_set_error('image', t('The image you uploaded was too big. You are only allowed upload files less than %max_size but your file was %file_size.', array('%max_size' => format_size(variable_get('image_max_upload_size', 800) * 1024), '%file_size' => format_size($file->filesize)))); + file_delete($file->filepath); + return; + } + + $form_state['values']['images'][IMAGE_ORIGINAL] = $file->filepath; + $form_state['values']['rebuild_images'] = FALSE; + $form_state['values']['new_file'] = TRUE; + + // Call hook to allow other modules to modify the original image. + module_invoke_all('image_alter', $form_state['values'], $form_state['values']['images'][IMAGE_ORIGINAL], IMAGE_ORIGINAL); + $form_state['values']['images'] = _image_build_derivatives((object) $form_state['values'], TRUE); + + // Store the new file into the session. + $_SESSION['image_upload'] = $form_state['values']['images']; + } + elseif (empty($form_state['values']['images'][IMAGE_ORIGINAL])) { + if (empty($_SESSION['image_upload'])) { + form_set_error('image', t('You must upload an image.')); + } + } +} + +function image_form_submit($form, &$form_state) { + if (!empty($_SESSION['image_upload'])) { + $form_state['values']['images'] = $_SESSION['image_upload']; + $form_state['values']['new_file'] = TRUE; + unset($_SESSION['image_upload']); } } Index: tests/image.test =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/image/tests/image.test,v retrieving revision 1.3 diff -u -p -r1.3 image.test --- tests/image.test 1 Feb 2009 03:10:34 -0000 1.3 +++ tests/image.test 4 Feb 2009 19:48:28 -0000 @@ -81,13 +81,57 @@ class ImageTestCase extends DrupalWebTes // Delete an image. $this->drupalPost('node/' . $node->nid .'/delete', array(), t('Delete')); - $this->assertRaw(t('@type %title has been deleted.', array('@type' => 'Image', '%title' => $edit['title'])), t('Image created.')); + $this->assertRaw(t('@type %title has been deleted.', array('@type' => 'Image', '%title' => $edit['title'])), t('Image deleted.')); $node = node_load(array('title' => $edit['title'])); $this->assertFalse($node, t('Image not found in database.')); $this->assertFalse(file_exists($another_node->images['preview']) || file_exists($another_node->images['_original']) || file_exists($another_node->images['thumbnail']), t('Image deleted.')); } /** + * Verify that images cannot be created without a file. + */ + function testMissingImage() { + $edit = array( + 'title' => $this->randomName(), + 'body' => $this->randomName(), + ); + $this->drupalPost('node/add/image', $edit, t('Save')); + + $this->assertRaw(t('You must upload an image.'), t('Refused node creation without image.')); + + $node = node_load(array('title' => $edit['title'])); + $this->assertFalse($node, t('Image node not found in database.')); + } + + /** + * Verify that images with missing file information can be deleted from edit form. + */ + function testCorruptedNode() { + // Create an image. + $edit = array( + 'title' => $this->randomName(), + 'body' => $this->randomName(), + 'files[image]' => realpath($this->image), + ); + + // Create image. + $this->drupalPost('node/add/image', $edit, t('Save')); + $this->assertRaw(t('@type %title has been created.', array('@type' => 'Image', '%title' => $edit['title'])), t('Image created.')); + $node = node_load(array('title' => $edit['title'])); + $this->assertTrue($node, t('Image found in database.')); + + // Remove {files} row to create corruption condition. + $this->assertTrue(db_query("DELETE f FROM {files} f INNER JOIN {image} i WHERE f.fid = i.fid AND i.nid = %d", $node->nid), t('Image file details deleted.')); + $node = node_load(array('title' => $edit['title'])); + $this->assertFalse($node->images['_original'], t('File details not on re-loaded node.')); + + $this->drupalPost('node/' . $node->nid .'/edit', array(), t('Delete')); + $this->assertRaw(t('Are you sure you want to delete %title?', array('%title' => $edit['title'])), t('Delete confirmation.')); + $this->drupalPost(NULL, array(), t('Delete')); + $this->assertRaw(t('@type %title has been deleted.', array('@type' => 'Image', '%title' => $edit['title'])), t('Image deleted.')); + } + + /** * Test image node creation. */ function testCreateNode() {