I'm working on a frontend form in wordpress to create a custom post type and upload a picture attached to that post.
Below is my code so far. The post is created, but problem is that the images are not uploaded to the server either attached to that post. On the other hand I would like the images to be pre-visualized before sending the form, in the same way wordpress works for the admin area.
if ( 'POST' == $_SERVER['REQUEST_METHOD'] && !empty( $_POST['new_cpt_action'] ) && $_POST['new_cpt_action'] == "new_cpt" && isset( $_POST['new_cpt-form'] ) && wp_verify_nonce( $_POST['new_cpt-form'], 'create_new_cpt' ) ){
if (isset($_POST['submit'])) {
$error = "";
if (!empty($_POST['s_name'])) {
$s_name = $_POST['s_name'];
} else {
$error = 'Please insert a name';
}
if (empty($error)) {
$new_post = array(
'post_title' => $s_name,
'post_status' => 'pending',
'post_type' => 'my_cpt',
);
//Save the post
$post_id = wp_insert_post($new_post);
if( ! empty( $_FILES ) ) {
foreach( $_FILES as $file ) {
if( is_array( $file ) ) {
$attachment_id = wp_insert_attachment($file, $post_id);
}
}
}
//Redirect to the new post
if ( $post_id ) {
wp_redirect(home_url('site/'.$post_id));
exit;
}
}
}
}
And the form:
<form id="new_post" name="new_post" method="post" action="" class="" enctype="multipart/form-data">
<input type="text" id="s_name" name="s_name"/>
<input type="file" name="s_image" id="s_image" tabindex="25" />
<input type="submit" value="Create post and upload image" id="submit" name="submit"/>
<input type="hidden" id="new_cpt_action" name="new_cpt_action" value="new_cpt" />
</form>
If you could please let me know what I'm missing would be great.
Thanks
I managed to include the attachments in the wp media library with this code:
if ( $_FILES ) {
$files = $_FILES["file"];
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 ("file" => $file);
foreach ($_FILES as $file => $array) {
$newupload = frontend_handle_attachment( $file, $post_id );
}
}
}
}
Which calls the function frontend_handle_attachment:
function frontend_handle_attachment($file_handler,$post_id) {
// 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, $post_id );
// Set featured image
set_post_thumbnail($post_id, $attach_id);
return $attach_id;
}
This works fine with a simple input in the form as follows:
<input type="file" name="file[]" multiple="multiple" />
As for the progress bar and pre-visualization of the images, I'm trying to implement dropzone, but no luck so far. At least the simple approach works.
Related
I have an issue with submitting custom post from frontend with image.
I have a form with post title, description and image, that should be featured image of the post.
So when user submitting post, it actually creates with title and description, but without image, even in media library the image doesn't appear.
Here is my form:
<form id="_themename-advert-create-form" method="post" enctype="multipart/form-data">
<?php wp_nonce_field('_themename_submit_advert_action','__themename_submit_advert_nonce'); ?>
<input type="hidden" name="_themename-advert-create-check" value="1" />
<label for="_themename-advert-create-title">Title</label>
<input id="_themename-advert-create-title" type="text" name="_themename-advert-create-title" />
<label for="_themename-advert-create-content">Sample Content</label>
<textarea id="_themename-advert-create-content" rows="8" name="_themename-advert-create-content"></textarea>
<label for="_themename-advert-create-image">Upload Post Image</label>
<input type="file" id="_themename-advert-create-image" name="_themename-advert-create-image" />
<input type="submit" id="_themename-advert-create-submit" value="SUBMIT" name="_themename-advert-create-submit" />
</form>
Here is my function that creates custom post:
add_action('init', '_themename_create_new_post');
function _themename_create_new_post(){
if('POST' == $_SERVER['REQUEST_METHOD'] && isset($_POST['_themename-advert-create-check']) && wp_verify_nonce( $_POST['__themename_submit_advert_nonce'], '_themename_submit_advert_action')) {
$current_user = wp_get_current_user();
$user_id = $current_user->ID;
$new_post_title = sanitize_text_field($_POST['_themename-advert-create-title']);
$new_post_content = sanitize_textarea_field($_POST['_themename-advert-create-content']);
$new_post = array();
$new_post['post_author'] = $user_id;
$new_post['post_title'] = $new_post_title;
$new_post['post_content'] = $new_post_content;
$new_post['post_status'] = 'pending';
$new_post['post_name'] = 'pending';
$new_post['post_type'] = 'jana_usa';
$post_success = wp_insert_post($new_post);
if ( $_FILES ) {
$files = $_FILES["_themename-advert-create-image"];
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 ("_themename-advert-create-image" => $file);
foreach ($_FILES as $file => $array) {
// $newupload = frontend_handle_attachment( $file, $post_success );
if ($_FILES[$file]['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, $post_success );
// Set featured image
set_post_thumbnail($post_success, $attach_id);
}
}
}
}
}
}
After submittin I'm getting an error Warning: Invalid argument supplied for foreach() in ... on line 43. This line:
foreach ($files['name'] as $key => $value) { ...
I can't find how to solve it. What am I doing wrong?
The problem was here:
<input type="file" id="_themename-advert-create-image" name="_themename-advert-create-image" />
It should be:
<input type="file" id="_themename-advert-create-image" name="_themename-advert-create-image[]" />
Still can't understand why I should add [] in my name, but now everything is working.
Here's the issue: I am trying to add multiple customer uploaded images to a woocommerce product order.
This is what my current function looks like to generate the fields before the add cart button (This displays properly and allows for a customer to select a file from their computer to upload):
function my_special_fields(){
if (get_the_title() == "My Special Product"){
echo '<table>
<tbody>
<tr>
<td>
<input type="file" name="my_image_upload" id="my_image_upload" multiple="false" />
</td>
</tr>
</tbody>
</table>';
}
}
Which I call with the hook:
add_filter('woocommerce_before_add_to_cart_button', 'my_special_fields');
I then use another hook for adding the item data to the cart:
add_action( 'woocommerce_add_cart_item_data', 'save_my_special_fields', 10, 2 );
And the function called with that hook looks like this:
function save_my_special_fields( $cart_item_data, $product_id ) {
// I save a lot of fields in here that are working fine so ignoring those for now
// This is where I try and find my file to upload
if( ! empty( $_FILES ) ) {
foreach( $_FILES as $file ) {
if( is_array( $file ) ) {
$attachment_id = upload_user_file( $file );
}
}
}
}
It calls this piece of code I found for uploading files into wordpress: https://hugh.blog/2014/03/20/wordpress-upload-user-submitted-files-frontend/
function upload_user_file( $file = array() ) {
require_once( ABSPATH . 'wp-admin/includes/admin.php' );
$file_return = wp_handle_upload( $file, array('test_form' => false ) );
if( isset( $file_return['error'] ) || isset( $file_return['upload_error_handler'] ) ) {
return false;
} else {
$filename = $file_return['file'];
$attachment = array(
'post_mime_type' => $file_return['type'],
'post_title' => preg_replace( '/\.[^.]+$/', '', basename( $filename ) ),
'post_content' => '',
'post_status' => 'inherit',
'guid' => $file_return['url']
);
$attachment_id = wp_insert_attachment( $attachment, $file_return['url'] );
require_once(ABSPATH . 'wp-admin/includes/image.php');
$attachment_data = wp_generate_attachment_metadata( $attachment_id, $filename );
wp_update_attachment_metadata( $attachment_id, $attachment_data );
if( 0 < intval( $attachment_id ) ) {
return $attachment_id;
}
}
return false;
}
Right now I am not assigning to any post or doing anything with the image other than trying to get it to upload so that as an Admin I can view it in my media folder.
I think the issue is that the woocommerce form for the add to cart fields might not have this encoding:
enctype="multipart/form-data
Any help on implementing this without getting additional woocommerce plugins would be much appreciated.
Can someone tell me why this function is not moving the uploaded files anywhere.
function handle_logo_upload($option){
if(!function_exists('wp_handle_upload'))
{
require_once(ABSPATH .'wp-admin/includes/file.php');
}
if(!empty($_FILES["site_logo_custom"])){
$theFile=$_FILES["site_logo_custom"];
$overrides=array('test_form'=>false);
$urls=wp_handle_upload($theFile,$overrides);
$temp=$urls["url"];
return $temp;
}
return $option;
}
I can't really find too much about wp_handle_upload function.
Thankss!!!
I assume your form is formatted kinda like this :
form action="" enctype="multipart/form-data" method="post"> //action is current post
<input type="file" name="file">
<input type="submit" name="submit">
</form>
And to upload the file to the wordpress upload folder using wp_handle_upload(); function you may use below code....
function handle_logo_upload($file){
require_once(ABSPATH.'wp-admin/includes/file.php');
$uploadedfile = $file;
$movefile = wp_handle_upload($uploadedfile, array('test_form' => false));
if ( $movefile ){
echo $movefile['url'];
//or return
return $movefile['url'];
}
}
if (isset($_POST['submit'])) {
handle_logo_upload($_FILES['file']);
}
Guessing that your function is called perfectly.
function handle_logo_upload($option){
if(!function_exists('wp_handle_upload'))
{
require_once(ABSPATH .'wp-admin/includes/file.php');
}
//you are using empty version make sure your php version is higher than 5.2
if(!empty($_FILES["site_logo_custom"])){
$move_logo = wp_handle_upload( $_FILES["site_logo_custom"], array('test_form' => false) );
if ( $move_logo && !isset($move_logo['error']) ) {
$wp_upload_dir = wp_upload_dir();
$attachment = array(
'guid' => $wp_upload_dir['url'] . '/' . basename($move_logo['file']),
'post_mime_type' => $move_logo['type'],
'post_title' => preg_replace( '/\.[^.]+$/', '', basename($move_logo['file']) ),
'post_content' => '',
'post_status' => 'inherit'
);
$logo_attach_id = wp_insert_attachment($attachment, $move_logo['file']);
$image_attributes = wp_get_attachment_image_src( $logo_attach_id );
if ( $image_attributes ) {
return $image_attributes[0];
}
else
{
return $option;
}
}else{
return $option;
}
}else{
return $option;
}
}
Please read my comments written in code
require_once(ABSPATH . '/wp-load.php');
require_once(ABSPATH . '/wp-admin/includes/file.php');
require_once(ABSPATH . '/wp-admin/includes/image.php');
$upload_overrides = array( 'test_form' => FALSE );
$count_files = count( $_FILES['my_files'] );
$uploads = wp_upload_dir();
foreach ( range( 0, $count_files ) as $i ) {
// create an array of the $_FILES for each file
$file_array = array(
'name' => $_FILES['files']['name'][$i],
'type' => $_FILES['files']['type'][$i],
'tmp_name' => $_FILES['files']['tmp_name'][$i],
'error' => $_FILES['files']['error'][$i],
'size' => $_FILES['files']['size'][$i],
);
// check to see if the file name is not empty
if ( !empty( $file_array['name'] ) ) {
// upload the file to the server
$uploaded_file = wp_handle_upload( $file_array, $upload_overrides );
// checks the file type and stores in in a variable
$wp_filetype = wp_check_filetype( basename( $uploaded_file['file'] ), null );
if ( $uploaded_file && !isset( $uploaded_file['error'] ) ) {
$ufiles = get_post_meta( $post_id, 'my_files', true );
if( empty( $ufiles ) ) $ufiles = array();
$ufiles[] = $uploaded_file;
update_post_meta( $post_id, 'my_files', $ufiles );
}
}
}
I am able to download files to metabox thanks to this code.
Output of the database is looks like what i show in the below
a:2:{i:0;a:3:{s:4:"file";s:48:"D:xampphtdocswp/wp-content/uploads/2016/08/2.jpg";s:3:"url";s:52:"http://localhost/wp/wp-content/uploads/2016/08/2.jpg";s:4:"type";s:10:"image/jpeg";}i:1;a:3:{s:4:"file";s:59:"D:xampphtdocswp/wp-content/uploads/2016/08/2da83a4s-960.jpg";s:3:"url";s:63:"http://localhost/wp/wp-content/uploads/2016/08/2da83a4s-960.jpg";s:4:"type";s:10:"image/jpeg";}}
I want to delete the images that i dont want with delete_post_meta method while i am selecting checkboxes on my update page.
$galleri = get_post_meta($id,'my_files',true);
<div class="galeri">
<?php
foreach($galleri as $galeri){
echo "<div style='margin:10px;display:inline-block;'><input type='checkbox' name='car_image_delete[]' value='".$galeri['url']."' /><img src='".$galeri['url']."' width='150' height='150'/></div>";
}
?>
</div>
I appreciate if you help me
Try this:
Use update_post_meta() function instead of delete_post_meta().
While using delete_post_meta(), it will delete custom fields.
So if you want to delete particular one file. You need to use update_post_meta().
$string = 'a:2:{i:0;a:3:{s:4:"file";s:48:"D:xampphtdocswp/wp-content/uploads/2016/08/2.jpg";s:3:"url";s:52:"http://localhost/wp/wp-content/uploads/2016/08/2.jpg";s:4:"type";s:10:"image/jpeg";}i:1;a:3:{s:4:"file";s:59:"D:xampphtdocswp/wp-content/uploads/2016/08/2da83a4s-960.jpg";s:3:"url";s:63:"http://localhost/wp/wp-content/uploads/2016/08/2da83a4s-960.jpg";s:4:"type";s:10:"image/jpeg";}}';
$arr = unserialize($string); //USE get_post_meta() function instead of
$index = array_search('http://localhost/wp/wp-content/uploads/2016/08/2da83a4s-960.jpg',array_column( $arr, 'url')); //search index
echo $index;
if (array_key_exists($index,$arr))
{
unset($arr[$index]); //remove array index
}
print_r($arr); //array with only value.
//use array_values() to reindex
update_post_meta($post_id, 'my_files', $arr); //update post meta
I'm going to break my brain..
I've created a new metabox for my custom post type "book".
I'm using a lot of different type of fields like input text, checkbox, select, textarea, taxonomy select and repeatable and everything work great!
But now I'd like to do a more difficult step..
Is it possible to do a repeatable field with 2 fields inside it?
I would like have a select and an input text near it.. inside the select admin can choose the shop (es. Ibs or Amazon) and in the input field he can write the url for sell the book.
This is my code:
/* META Book */
function add_mycustom_meta_box() {
add_meta_box(
'custom_meta_box',
'Info book',
'show_custom_meta_box', // $callback
'product',
'normal',
'high');
}
// Field Array
$prefix = 'custom_';
$custom_meta_fields = array(
array(
'label' => 'Link vendita',
'desc' => 'Inserisci l url dei siti esterni',
'id' => $prefix.'repeatable',
'type' => 'repeatable',
'options' => array(
'amazon' => array(
'label' => 'Amazon',
'value' => 'amazon'
),
'ibs' => array(
'label' => 'Ibs',
'value' => 'ibs'
)
)
)
);
// Callback
function show_custom_meta_box() {
global $custom_meta_fields, $post;
// Use nonce for verification
echo '<input type="hidden" name="custom_meta_box_nonce" value="'.wp_create_nonce(basename(__FILE__)).'" />';
// Build metabox
echo '<table class="form-table">';
foreach ($custom_meta_fields as $field) {
// get value of this field if it exists for this post
$meta = get_post_meta($post->ID, $field['id'], true);
// begin a table row with
echo '<tr>
<th><label for="'.$field['id'].'">'.$field['label'].'</label></th>
<td>';
switch($field['type']) {
// if repeatable
case 'repeatable':
echo '<a class="repeatable-add button" href="#">+</a>
<ul id="'.$field['id'].'-repeatable" class="custom_repeatable">';
$i = 0;
if ($meta) {
foreach($meta as $row) {
echo '<li><span class="sort hndle">|||</span>';
// Select ibis or amazon
echo '<select name="'.$field['id'].'" id="'.$field['id'].'">';
foreach ($field['options'] as $option) {
echo '<option', $row == $option['value'] ? ' selected="selected"' : '', ' value="'.$option['value'].'">'.$option['label'].'</option>';
}
echo '</select>';
// end select
echo '<input type="text" name="'.$field['id'].'['.$i.']" id="'.$field['id'].'" value="'.$row.'" size="30" data-shop="'.$option.'" />
<a class="repeatable-remove button" href="#">-</a></li>';
$i++;
}
} else {
echo '<li><span class="sort hndle">|||</span>';
// Select ibis o amazon
echo '<select name="'.$field['id'].'" id="'.$field['id'].'">';
foreach ($field['options'] as $option) {
echo '<option', $row == $option['value'] ? ' selected="selected"' : '', ' value="'.$option['value'].'">'.$option['label'].'</option>';
}
echo '</select>';
// Fine select
echo '<input type="text" name="'.$field['id'].'['.$i.']" id="'.$field['id'].'" value="" size="30" />
<a class="repeatable-remove button" href="#">-</a></li>';
}
echo '</ul>
<span class="description">'.$field['desc'].'</span>';
break;
} //end switch
echo '</td></tr>';
} // end foreach
echo '</table>';
}
// Save the Data
function save_custom_meta($post_id) {
global $custom_meta_fields;
// verify nonce
if (!wp_verify_nonce($_POST['custom_meta_box_nonce'], basename(__FILE__)))
return $post_id;
// check autosave
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE)
return $post_id;
// check permissions
if ('page' == $_POST['post_type']) {
if (!current_user_can('edit_page', $post_id))
return $post_id;
} elseif (!current_user_can('edit_post', $post_id)) {
return $post_id;
}
// loop through fields and save the data
foreach ($custom_meta_fields as $field) {
$old = get_post_meta($post_id, $field['id'], true);
$new = $_POST[$field['id']];
if ($new && $new != $old) {
update_post_meta($post_id, $field['id'], $new);
} elseif ('' == $new && $old) {
delete_post_meta($post_id, $field['id'], $old);
}
} // end foreach
}
add_action('save_post', 'save_custom_meta');
The repeatable field generate an array and it is ok, but what I can do to store the select value also?
Hope someone can help me
Thanks
I'm sure you can put in dynamic fields into custom Metaboxes inside the edit screen of any post type.
I build this for the Language Field Plugin into the admin page on http://wordpress.org/plugins/language-field/
I was relying on this example
http://www.mustbebuilt.co.uk/2012/07/27/adding-form-fields-dynamically-with-jquery/
Generally take these steps
Add custom Meta box with this example
http://codex.wordpress.org/Function_Reference/add_meta_box#Examples
when it comes to these lines
$mydata = sanitize_text_field( $_POST['myplugin_new_field'] );
// Update the meta field in the database.
update_post_meta( $post_id, '_my_meta_value_key', $mydata );
loop thru the fields created with example above.