I'm writing a plugin which allows a user to upload an image attachment for a custom post type via a public facing form (at client's request, I am aware this is probably a bad idea). The plugin needs to work in a multisite setup. I have attached a screenshot which displays the problem. The image is uploaded, thumbnails are generated (the files on the file system) but the media library shows a blank thumbnail and if you click view, the image is not displayed. Also, the image does not appear as the featured image for the created Reseller post type.
My SE question for this issue has more details : http://wordpress.stackexchange.com/questions/119073/uploaded-image-not-appearing-in-custom-post-type
public function wps_reseller_process_form() {
require_once(ABSPATH . "wp-admin" . '/includes/image.php');
require_once(ABSPATH . "wp-admin" . '/includes/file.php');
require_once(ABSPATH . "wp-admin" . '/includes/media.php');
if ( wp_verify_nonce( $_POST['reseller_user_form'], 'add_reseller_form') &&
!empty( $_POST['reseller-title'] ) &&
!empty( $_POST['reseller-description'] ) &&
!empty( $_FILES['reseller-image']) )
{
//var_dump($_POST); exit;
$file = $_FILES['reseller-image'];
$uploads = wp_upload_dir();//var_dump($uploads); exit;
$new_reseller_profile_data = array(
'post_status' => 'draft',
'post_title' => $_POST['reseller-title'],
'post_content' => $_POST['reseller-description'],
'post_type' => 'wps-reseller'
);
$file_errors = $this->wps_parse_file_errors($file);
$upload_overrides = array( 'test_form' => FALSE );
if($file_errors['error'] == 0) {
if($new_reseller_id = wp_insert_post( $new_reseller_profile_data )){
//$this->wps_process_image($file, $new_reseller_id);exit;
$uploaded_file = wp_handle_upload( $file, $upload_overrides );
$wp_filetype = wp_check_filetype( basename( $uploaded_file['file'] ), null );
$attachment = array(
'post_mime_type' => $wp_filetype['type'],
'post_title' => preg_replace('/\.[^.]+$/', '', basename( $uploaded_file['file'] ) ),
'post_content' => '',
'post_author' => '',
'post_status' => 'inherit',
'post_type' => 'attachment',
'post_parent' => $new_reseller_id,
'guid' => $uploads['baseurl'] . $uploads['subdir'] . '/' . $file['name']
);
echo $uploads['baseurl'].'<br />';
echo $file['name'].'<br />';
var_dump($uploads); exit;
$attachment_id = wp_insert_post( $attachment );
$attach_data = wp_generate_attachment_metadata( $attachment_id, $uploaded_file['file'] );
// update the attachment metadata
wp_update_attachment_metadata( $attachment_id, $attach_data );
set_post_thumbnail( $new_reseller_id, $attachment_id );
}
}
}
//create a new reseller post, make it draft (ensure post type supports this)
//email an admin user
}
Remy answers:
You should create a test on the result of your wp_handle_upload, to see what is returned (see [[LINK href="http://codex.wordpress.org/Function_Reference/wp_handle_upload"]]wp_handle_upload()[[/LINK]])
Also, you should use [[LINK href="http://codex.wordpress.org/Function_Reference/wp_insert_attachment"]]wp_insert_attachment()[[/LINK]] instead of wp_insert_post to insert your image in WP.
A good ressource to look at when uploading files in WP is this [[LINK href="http://ottopress.com/2011/tutorial-using-the-wp_filesystem/"]]tutorial[[/LINK]]
Luke Mackenzie comments:
wp_handle upload returns:
array (size=3)
'file' => string '/path/to/Sites/wordpress/wp-content/uploads/sites/2/2013/10/Screenshot-2013-10-17-08.50.261.png' (length=107)
'url' => string 'http://site2.local.wordpress/wp-content/uploads/sites/2/2013/10/Screenshot-2013-10-17-08.50.261.png' (length=99)
'type' => string 'image/png' (length=9)
Remy comments:
Ok so this is working fine (and you can use the 3rd parameter for the type, instead of using wp_check_filetype)
Did you try to use wp_insert_attachment() instead of wp_insert_post() ?
Luke Mackenzie comments:
This seems to work (file now appears correctly in media library):
$upload_overrides = array( 'test_form' => FALSE );
if($file_errors['error'] == 0) {
if($new_reseller_id = wp_insert_post( $new_reseller_profile_data )){
//$this->wps_process_image($file, $new_reseller_id);exit;
$uploaded_file = wp_handle_upload( $file, $upload_overrides );
$wp_filetype = wp_check_filetype(basename($uploaded_file['file']), null );
$wp_upload_dir = wp_upload_dir();
$attachment = array(
'guid' => $wp_upload_dir['url'] . '/' . basename( $uploaded_file['file'] ),
'post_mime_type' => $wp_filetype['type'],
'post_title' => preg_replace('/\.[^.]+$/', '', basename($file['name'])),
'post_content' => '',
'post_status' => 'inherit'
);
$attach_id = wp_insert_attachment( $attachment, $uploaded_file['file'], $new_reseller_id );
// you must first include the image.php file
// for the function wp_generate_attachment_metadata() to work
$attach_data = wp_generate_attachment_metadata( $attach_id, $uploaded_file['file'] );
wp_update_attachment_metadata( $attach_id, $attach_data );
}
}
BUT the image still does not appear as the featured image for the custom post - perhaps that is as expected? i.e. this attachment is not the same as the featured image?
Remy comments:
You still need to use set_post_thumbnail() to set the image as featured. You can also can run a check on set_post_thumbnail() to see if it returns true or false
Luke Mackenzie comments:
Genius! Now seems to be working
phppoet answers:
You should use something like this
//code to insert post here
$pid = wp_insert_post($new_post);
function insert_attachment($file_handler, $pid,$setthumb='false') {
// check to make sure its a successful upload
if ($_FILES[$file_handler]['error'] !== UPLOAD_ERR_OK) __return_false();
require_once(ABSPATH . "wp-admin" . '/includes/image.php');
require_once(ABSPATH . "wp-admin" . '/includes/file.php');
require_once(ABSPATH . "wp-admin" . '/includes/media.php');
$attach_id = media_handle_upload( $file_handler, $pid );
if ($setthumb) update_post_meta($pid,'_thumbnail_id',$attach_id);
return $attach_id;
}
global $post;
if ( $_FILES ) {
$files = $_FILES['upload_attachment'];
foreach ($files['name'] as $key => $value) {
if ($files['name'][$key]) {
$file = array(
'name' => $files['name'][$key],
'type' => $files['type'][$key],
'tmp_name' => $files['tmp_name'][$key],
'error' => $files['error'][$key],
'size' => $files['size'][$key]
);
$_FILES = array("upload_attachment" => $file);
foreach ($_FILES as $file => $array) {
$newupload = insert_attachment($file,$pid);
}
}
}
}
this code will upload files to as your cpt attachments and image files will be choossen as featured image automatically.you need to modify the code according to your code.
Luke Mackenzie comments:
Thanks, but:
$attach_id = media_handle_upload( $file_handler, $pid ); - this function does not return an id so you code is confusing.
Can you explain how your code is different and solves the problem? I am still stuck
Fahad Murtaza answers:
Can you provide your functions.php file?
Luke Mackenzie comments:
I have the same problem in a bare bones install with 2013 theme and have nothing custom in the functions.php file.
Fahad Murtaza comments:
Hi Luke
I once used this solution on this link. It just works. The only exception to your situation was the requirement for login. And yes, I used for multisite
http://wp.tutsplus.com/tutorials/allow-users-to-submit-images-your-site/
Luke Mackenzie comments:
I based my code on that post and also this one http://matthewaprice.com/upload-image-attach-to-wordpress-post-from-template/