I was trying to add an image field to the woocommerce account settings section so that users could upload their avatars.
With a bit of research here on stack I came across this question that worked and gave the solution to my problem: Add a profile picture (file upload) on My account > edit account in WooCommerce
However, other questions have arisen and I have thought about extending the question to try to improve the final result as I believe it is a very common situation.
So I hope someone can answer this.
Will the uploaded image not appear for the post comments section or woocommerce product reviews? Do we need to change the meta image for this? It would be very useful to be able to view the uploaded image anywhere on the site, including the comments and reviews section.
If the user wants to remove the image and go back to the default how can he do it? There is no remove image button. Is there a way to insert a button and remove the image uploaded ?
Is there a way to set upload limit? For example, uploaded images must be jpeg or png and must not exceed 1mb in size.
The biggest problem is the directory where the images are saved, can it be different from the default media library? Furthermore, when the user changes multiple images, the previous one is not deleted and will remain forever in the media library taking up space unnecessarily.
I believe the answer to these questions completes something that the woocommerce world lacks by default. This may be a standard solution for most users.
For convenience, I report the code of the previous question:
// Add field
function action_woocommerce_edit_account_form_start() {
?>
<p class="woocommerce-form-row woocommerce-form-row--wide form-row form-row-wide">
<label for="image"><?php esc_html_e( 'Image', 'woocommerce' ); ?> <span class="required">*</span></label>
<input type="file" class="woocommerce-Input" name="image" accept="image/x-png,image/gif,image/jpeg">
</p>
<?php
}
add_action( 'woocommerce_edit_account_form_start', 'action_woocommerce_edit_account_form_start' );
// Validate
function action_woocommerce_save_account_details_errors( $args ){
if ( isset($_POST['image']) && empty($_POST['image']) ) {
$args->add( 'image_error', __( 'Please provide a valid image', 'woocommerce' ) );
}
}
add_action( 'woocommerce_save_account_details_errors','action_woocommerce_save_account_details_errors', 10, 1 );
// Save
function action_woocommerce_save_account_details( $user_id ) {
if ( isset( $_FILES['image'] ) ) {
require_once( ABSPATH . 'wp-admin/includes/image.php' );
require_once( ABSPATH . 'wp-admin/includes/file.php' );
require_once( ABSPATH . 'wp-admin/includes/media.php' );
$attachment_id = media_handle_upload( 'image', 0 );
if ( is_wp_error( $attachment_id ) ) {
update_user_meta( $user_id, 'image', $_FILES['image'] . ": " . $attachment_id->get_error_message() );
} else {
update_user_meta( $user_id, 'image', $attachment_id );
}
}
}
add_action( 'woocommerce_save_account_details', 'action_woocommerce_save_account_details', 10, 1 );
// Add enctype to form to allow image upload
function action_woocommerce_edit_account_form_tag() {
echo 'enctype="multipart/form-data"';
}
add_action( 'woocommerce_edit_account_form_tag', 'action_woocommerce_edit_account_form_tag' );
To display the image (can be used anywhere, provided you adjust the desired hook)
// Display
function action_woocommerce_edit_account_form() {
// Get current user id
$user_id = get_current_user_id();
// Get attachment id
$attachment_id = get_user_meta( $user_id, 'image', true );
// True
if ( $attachment_id ) {
$original_image_url = wp_get_attachment_url( $attachment_id );
// Display Image instead of URL
echo wp_get_attachment_image( $attachment_id, 'full');
}
}
add_action( 'woocommerce_edit_account_form', 'action_woocommerce_edit_account_form' );
// Save
function action_woocommerce_save_account_details( $user_id ) {
if ( isset( $_FILES['image'] ) ) {
require_once( ABSPATH . 'wp-admin/includes/image.php' );
require_once( ABSPATH . 'wp-admin/includes/file.php' );
require_once( ABSPATH . 'wp-admin/includes/media.php' );
function wp_set_custom_upload_folder($uploads) {
$uploads['path'] = $uploads['basedir'] . '/custom-folder';
$uploads['url'] = $uploads['baseurl'] . '/custom-folder';
if (!file_exists($uploads['path'])) {
mkdir($uploads['path'], 0755, true);
}
return $uploads;
}
add_filter('upload_dir', 'wp_set_custom_upload_folder');
$attachment_id = media_handle_upload( 'image', 0 );
if ( is_wp_error( $attachment_id ) ) {
update_user_meta( $user_id, 'image', $_FILES['image'] . ": " . $attachment_id->get_error_message() );
} else {
$old_attachment_id = get_user_meta( $user_id, 'image', true );
wp_delete_attachment($old_attachment_id);
update_user_meta( $user_id, 'image', $attachment_id );
}
}
}
add_action( 'woocommerce_save_account_details', 'action_woocommerce_save_account_details', 10, 1 );
Set custom upload directory for profile image uploads
// Display function
function action_woocommerce_edit_account_form() {
// Get current user id
$user_id = get_current_user_id();
// Get attachment id
$attachment_id = get_user_meta($user_id, 'image', true);
// True
if ($attachment_id) {
$original_image_url = wp_get_attachment_url($attachment_id);
// Display Image instead of URL
echo wp_get_attachment_image($attachment_id, 'full');
if (isset($_GET['rm_profile_image_id'])) {
if ($attachment_id == $_GET['rm_profile_image_id']) {
wp_delete_attachment($attachment_id);
delete_user_meta($user_id, 'image');
?> <script>
window.location='<?php echo wc_get_account_endpoint_url('edit-account') ?>';
</script>
<?php
exit();
}
} else {
echo '<a href=' . wc_get_account_endpoint_url('edit-account') . '?rm_profile_image_id=' . $attachment_id . '> ' . __('Remove') . ' </a>';
}
}
}
When I have some free time I want to work on these issues. I'm not very good with codes I'm just a fan, but with study, research and practice I hope to make my contribution to this topic.
I publish this answer to update it every time I find a new solution. I'm sure someone can offer more efficient solutions, so corrections and answers that improve the topic are welcome.
Solution to problem n1 - Set the uploaded image anywhere on the site
Set the get_avatar filter (responsible for displaying the avatar in the comments section and other section of website) and assign it the url stored in the image meta_key.
add_filter( 'get_avatar', 'my_custom_avatar', 10, 6 );
function my_custom_avatar( $avatar, $id_or_email, $size, $default, $alt, $args ) {
// What is the custom image field's meta key?
// Set this value to match the meta key of your custom image field.
$meta_key = "image";
// Nothing really to change below here, unless
// you want to change the <img> tag HTML.
$user = false;
if ( is_numeric( $id_or_email ) ) {
$user = get_user_by( 'id' , (int)$id_or_email );
}
elseif ( is_object( $id_or_email ) ) {
if ( ! empty( $id_or_email->user_id ) ) {
$id = (int)$id_or_email->user_id;
$user = get_user_by( 'id' , $id );
}
} else {
$user = get_user_by( 'email', $id_or_email );
}
if ( $user && is_object( $user ) ) {
$post_id = get_user_meta( $user->ID, $meta_key, true );
if ( $post_id ) {
$attachment_url = wp_get_attachment_url( $post_id );
// HTML for the avatar <img> tag. This is WP default.
$avatar = wp_get_attachment_image($post_id, $size = array('50', '50'));
}
}
return $avatar;
}
Solution to problem n3 - Set a size limit for files
Thanks to this question Limit the size of a file upload (html input element) I found the solution to limit the file size in bytes. So here's what I did:
I assigned the input type file the id file
<input id="file" type="file" class="woocommerce-Input" name="image" accept="image/x-png,image/gif,image/jpeg">
I then applied the script below
/* Limit File Size for Avatar Upload (size in bytes) */
var uploadField = document.getElementById("file");
uploadField.onchange = function() {
// Put size in Bytes
if(this.files[0].size > 100000){
alert("File is too big!");
this.value = "";
};
};
The code provided by #mujuonly looks promising, however, please take the following into consideration:
Add a remove_filter after the else block in 1st code. Else all the website uploads will happen in that directory.
To do so, use:
remove_filter('upload_dir', 'wp_set_custom_upload_folder');
after else block.
2nd code should check if the user meta was deleted successfully or not. The line delete_user_meta($user_id, 'image'); should be wrapped in if condition like so:
if (delete_user_meta($user_id, 'image')){
wp_delete_attachment($attachment_id);
}
This way you don't delete the image first and make it unavailable for failed delete_user_meta.
Related
I have a function for woocommerce (Add a profile picture (file upload) on My account > edit account in WooCommerce) that allows users to upload their frontend avatars from the account> settings section. Everything works fine but the images are loaded into the default media library. Is it possible to somehow change the directory by creating a new one for the purpose?
I appreciate any help and thank you for any replies.
Here is my code:
// Add field
function action_woocommerce_edit_account_form_start() {
?>
<p class="woocommerce-form-row woocommerce-form-row--wide form-row form-row-wide">
<label for="image"><?php esc_html_e( 'Image', 'woocommerce' ); ?> <span class="required">*</span></label>
<input type="file" class="woocommerce-Input" name="image" accept="image/x-png,image/gif,image/jpeg">
</p>
<?php
}
add_action( 'woocommerce_edit_account_form_start', 'action_woocommerce_edit_account_form_start' );
// Validate
function action_woocommerce_save_account_details_errors( $args ){
if ( isset($_POST['image']) && empty($_POST['image']) ) {
$args->add( 'image_error', __( 'Please provide a valid image', 'woocommerce' ) );
}
}
add_action( 'woocommerce_save_account_details_errors','action_woocommerce_save_account_details_errors', 10, 1 );
// Save
function action_woocommerce_save_account_details( $user_id ) {
if ( isset( $_FILES['image'] ) ) {
require_once( ABSPATH . 'wp-admin/includes/image.php' );
require_once( ABSPATH . 'wp-admin/includes/file.php' );
require_once( ABSPATH . 'wp-admin/includes/media.php' );
$attachment_id = media_handle_upload( 'image', 0 );
if ( is_wp_error( $attachment_id ) ) {
update_user_meta( $user_id, 'image', $_FILES['image'] . ": " . $attachment_id->get_error_message() );
} else {
update_user_meta( $user_id, 'image', $attachment_id );
}
}
}
add_action( 'woocommerce_save_account_details', 'action_woocommerce_save_account_details', 10, 1 );
// Add enctype to form to allow image upload
function action_woocommerce_edit_account_form_tag() {
echo 'enctype="multipart/form-data"';
}
add_action( 'woocommerce_edit_account_form_tag', 'action_woocommerce_edit_account_form_tag' );
the thing with WordPress is that avatars are quite weird. I would suggest adding a plugin for this that uploads avatars since the container for them is different then and it might show up. The problem you have is that the image goes to another container. Overall all images on a site will be uploaded to the gallery
If I understood your question correctly, you want to change the default location of an uploaded file. If this is the case, go to the wp-config.php file in the root directory and specify an address like this:
define( 'UPLOADS', 'blog/wp-content/uploads' );
For detailed information, you can visit the official wp-config.php page of WordPress: https://developer.wordpress.org/apis/wp-config-php/
I solved it like this, I don't know if it's correct and practical but it's working.
// Add field
function action_woocommerce_edit_account_form_start() {
?>
<p class="woocommerce-form-row woocommerce-form-row--wide form-row form-row-wide">
<label for="image"><?php esc_html_e( 'Image', 'woocommerce' ); ?> <span class="required">*</span></label>
<input type="file" class="woocommerce-Input" name="image" accept="image/x-png,image/gif,image/jpeg">
</p>
<?php
}
add_action( 'woocommerce_edit_account_form_start', 'action_woocommerce_edit_account_form_start' );
// Validate
function action_woocommerce_save_account_details_errors( $args ){
if ( isset($_POST['image']) && empty($_POST['image']) ) {
$args->add( 'image_error', __( 'Please provide a valid image', 'woocommerce' ) );
}
}
add_action( 'woocommerce_save_account_details_errors','action_woocommerce_save_account_details_errors', 10, 1 );
// Save
function action_woocommerce_save_account_details( $user_id ) {
if ( isset( $_FILES['image'] ) ) {
require_once( ABSPATH . 'wp-admin/includes/image.php' );
require_once( ABSPATH . 'wp-admin/includes/file.php' );
require_once( ABSPATH . 'wp-admin/includes/media.php' );
$attachment_id = media_handle_upload( 'image', 0 );
if ( is_wp_error( $attachment_id ) ) {
update_user_meta( $user_id, 'image', $_FILES['image'] . ": " . $attachment_id->get_error_message() );
} else {
update_user_meta( $user_id, 'image', $attachment_id );
}
}
}
add_action( 'woocommerce_save_account_details', 'action_woocommerce_save_account_details', 10, 1 );
// Add enctype to form to allow image upload
function action_woocommerce_edit_account_form_tag() {
echo 'enctype="multipart/form-data"';
}
add_action( 'woocommerce_edit_account_form_tag', 'action_woocommerce_edit_account_form_tag' );
I created the a text field in which I can add url of pdf file. Now I'm trying to show it on every post after the content but it only shows the button but not the content. If I remove the_content from add_action, it shows the content but not the download pdf button.
add_action( 'the_content', 'show_download_url' );
function show_download_url() {
$download_pdf = get_post_meta( get_the_ID(), 'download_pdf', true );
if ( $download_pdf ) {
printf( 'Download PDF',
esc_url( $download_pdf )
);
}
}
All you need is to concat your button with existing content. With current code it will override. Check below code for reference:
add_action( 'the_content', 'show_download_url' );
function show_download_url($content) {
$download_pdf = get_post_meta( get_the_ID(), 'download_pdf', true );
if ( $download_pdf ) {
$content .= sprintf( 'Download PDF',
esc_url( $download_pdf )
);
}
return $content;
}
i created a simple gravity form (id = 11) which contains 2 fields:
text field type (name = "my_name")
fileupload type (i could't set the name for it)
and there is the code i want to use for handel this form after submitation. how to change this snippet for handeling submited file?
Please suppose I have to do the manual handling of the form myself
$input_1 = $_POST['myname'];
//how to get sbmitted file?
//$file = ?
$array_of_inputs = array("input_1" => $input_1 , "file_name" => $file);
$gravity_submit_result = submit_in_gravity_form(11 , $array_of_inputs , $api_key , $private_key ,$web_url);
if ($gravity_submit_result){
$response['message'] = $body['response'];
$response['status'] = 'ok';
}
else{
$response['status'] = false;
}
exit(json_encode($response));}
this page contains my gravity form
For solve this issue you can follow this code
add_action( 'gform_after_submission', 'set_post_content', 10, 2 );
function set_post_content( $entry, $form ) {
//if the Advanced Post Creation add-on is used, more than one post may be created for a form submission
//the post ids are stored as an array in the entry meta
$created_posts = gform_get_meta( $entry['id'], 'gravityformsadvancedpostcreation_post_id' );
foreach ( $created_posts as $post )
{
$post_id = $post['post_id'];
$post = get_post( $post_id );
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_id);
if (is_numeric($attach_id)) {
update_option('option_image', $attach_id);
update_post_meta($post_id, '_my_file_upload', $attach_id);
}
update_post_meta($post_id, 'myname', $_POST['myname'];);
}
}
I was using this code from Pastebin here to add a form with a file input field to the user profile admin page and it was working perfectly fine, but the problem is that i can't change it to an array of input files.
I want to change the profile_photo to be an array of photos and implement it to the user profile page.
Can someone help me with this?
add_action( 'user_edit_form_tag','make_uploadable_form');
function make_uploadable_form() {
echo ' enctype="multipart/form-data"';
}
add_action( 'show_user_profile', 'UploadField' );
add_action( 'edit_user_profile', 'UploadField' );
function UploadField( $user ) {
if ( ! current_user_can( 'edit_user' ) )
return false;
$pid = get_user_meta( $user->ID, 'profile_photo', true );
$img = wp_get_attachment_image( $pid );
if ( ! empty( $img ) )
echo "<hr/>".$user->ID;
echo "<hr/>".$pid;
echo( $img );
?>
<h3>Extra profile information</h3>
<table class="form-table">
<tr>
<th><label for="Upload">Upload</label></th>
<td>
<input name="profile_photo" type="file" id="profile_photo" value="" />
</td>
</table>
<?php
}
add_action( 'personal_options_update', 'save_user_custom' );
add_action( 'edit_user_profile_update', 'save_user_custom' );
function save_user_custom($user_id){
if($user_id == false)
return false;
// If the upload field has a file in it
if(isset($_FILES['profile_photo'])){
if(!function_exists('wp_handle_upload'))
require_once(ABSPATH.'wp-admin/includes/file.php');
// Get the type of the uploaded file. This is returned as "type/extension"
$arr_file_type = wp_check_filetype(basename($_FILES['profile_photo']['name']));
$uploaded_file_type = $arr_file_type['type'];
// Set an array containing a list of acceptable formats
$allowed_file_types = array('image/jpg','image/jpeg','image/gif','image/png');
// If the uploaded file is the right format
if(in_array($uploaded_file_type, $allowed_file_types)) {
// Options array for the wp_handle_upload function. 'test_upload' => false
$upload_overrides = array( 'test_form' => false );
// Handle the upload using WP's wp_handle_upload function. Takes the posted file and an options array
$uploaded_file = wp_handle_upload($_FILES['profile_photo'], $upload_overrides);
// If the wp_handle_upload call returned a local path for the image
if(isset($uploaded_file['file'])) {
// The wp_insert_attachment function needs the literal system path, which was passed back from wp_handle_upload
$file_name_and_location = $uploaded_file['file'];
// Generate a title for the image that'll be used in the media library
$file_title_for_media_library = 'your title here';
// Set up options array to add this file as an attachment
$attachment = array(
'post_mime_type' => $uploaded_file_type,
'post_title' => 'Uploaded image ' . addslashes($file_title_for_media_library),
'post_content' => '',
'post_status' => 'inherit'
);
// Run the wp_insert_attachment function. This adds the file to the media library and generates the thumbnails. If you wanted to attch this image to a post, you could pass the post id as a third param and it'd magically happen.
$attach_id = wp_insert_attachment( $attachment, $file_name_and_location );
require_once(ABSPATH . "wp-admin" . '/includes/image.php');
$attach_data = wp_generate_attachment_metadata( $attach_id, $file_name_and_location );
wp_update_attachment_metadata($attach_id, $attach_data);
update_user_meta( $user_id, 'profile_photo', $attach_id );
}
}
}
}
Try this:
if you write your inputs like this:
<input name="profile_photo[1]" type="file" id="profile_photo" value="" />
<input name="profile_photo[2]" type="file" id="profile_photo" value="" />
You'll have an array named profile_photo with your input files.
See there.
I have a custom field(file) in my pagetemplate.
<input type="file" name="head-photo" size="40" class="wpcf7-form-control form-control" id="uploadImage" aria-invalid="false" />
How can i store uploaded file(photo) in to my wordpress database?
if you use this field to save any post detail than, you can save this field value as add_post_meta($post_id, $meta_key, $meta_value, $unique);
for update
update_post_meta($post_id, $meta_key, $meta_value, $prev_value);
Please check https://codex.wordpress.org/Function_Reference/add_post_meta
https://codex.wordpress.org/Function_Reference/update_post_meta
Assuming you are using a simple form with input file you can use media_handle_upload function,
Example handler on form submit
// Load necessary files
require_once( ABSPATH . 'wp-admin/includes/image.php' );
require_once( ABSPATH . 'wp-admin/includes/file.php' );
require_once( ABSPATH . 'wp-admin/includes/media.php' );
// Simple image attachment data
$atts_data = array(
'post_author' => get_current_user_id(), // just an example
);
// Process image upload
$attachment_id = media_handle_upload( 'input-file-name', 0, $atts_data );
// verify upload
if ( !is_wp_error( $attachment_id ) ) {
// Media upload success,
} else {
// Media Upload Fail
}