I'm saving an image to uploads folder, but I'm using file_put_contents instead of wp_handle_upload - because I get an image in base64 and not as a file in $_FILES.
Image and certain post data are saved/updated as they should be using this functions:
The problem is when I want to remove an old image (when saving a new one).
wp_delete_attachment does not remove the image (it does seem to remove stuff in db though..). I am thinking the problem lies in not using wp_handle_upload. (when I upload an image via upload btn and receive it using $_FILES and then upload it with wp_handle_upload - removing works)
Does anyone have an idea of what might be the right way to remove an image in my case? Perhaps I can save it properly using wp_handle_upload even if I have an image in base64?
Thanks for any info.
EDIT: I also tried saving image with wp_upload_bits and wp_delete_attachment still did not work.
Another thing I checked: the code of wp_handle_upload function located in wp-admin/includes/file.php
: I don't see an easy way to modify or copy the existing function and add a custom one which would accept base64 image instead of a file as in $_FILES. Someone has a "base64 to $_FILES" workaround perhaps?
as @KamilP said, WP inserts records in wp_posts
and wp_postmeta
tables.
So first you have to save your base64 images in temporary directory, then by using it's relative path and other data you can insert record in database by using wp_insert_attachment
, link contains appropriate example.
This function will add image to media library.
To generate more thumbnails you can use wp_generate_attachment_metadata
function. This function will update wp_postmeta table also with all details of image and thumbnails.
After this you can use wp_delete_attachment
function to delete image from directory and database as well.
wp_handle_upload
$_FILES array's structure is like this
array(5) {
'name' => string(8) "file name.extension" // file name with extension
'type' => string(0) "" // mime type of file, i.e. image/png
'tmp_name' => string(0) "" // absolute path of file on disk.
'error' => int(2) // 0 for no error
'size' => int(0) // size in bytes
}
You can create array like above with all details, use various file handling PHP functions to get size and mime type. Name is whatever you want to put, and tmp_name is a path of file on server where file is exists, in your case location of folder where you save your file from base64 string.
See updated link above for function which will give you image from base64 string.
I actually accomplished this before I saw an answer here, so I'm providing a solution here if someone runs into the same problem. I used the function below (first one) and also using wp_delete_attachment after just to be sure all stuff got removed.
/**
* Attempt at removing all images in uploads folder by providing an image url
* Example:
* - Provide http://mypage.com/wp-content/themes/mytheme/uploads/2015/12/testImage.jpg
* - this should remove all its images created when uploading:
* - testImage-150x150.jpg, testImage-300x300.jpg etc and also the provided original image
*
* We'r doing this because wp_delete_attachment() will not remove an image that was uploaded via a
* custom mytheme_upload_image() function (which is providing base64 image instead of file in $_FILES)
*
* TODO TODO mytheme_get_image_sizes() does not return ALL IMAGES THAT WERE CREATED (all sizes)
*/
function mytheme_remove_all_image_sizes_from_uploads($primary_image_url) {
$pi = pathinfo($primary_image_url);
$img_dirname = $pi['dirname'];
$img_dirname_exploded = explode('/',$img_dirname);
$last_dir = array_pop($img_dirname_exploded); // month usually (two digits)
$second_last_dir = array_pop($img_dirname_exploded); // year usually (4 digits)
$basename = $pi['basename']; // without trailing /
$img_name = $pi['filename'];
$img_extension = $pi['extension'];
$uploads = wp_upload_dir();
$base_uploads_dir = $uploads['basedir']; // without trailing /
$path_to_appropriate_uploads_dir = $base_uploads_dir.'/'.$second_last_dir.'/'.$last_dir.'/';
$img_name_to_remove = $img_name.'.'.$img_extension; // UNLINK
if(!@unlink($path_to_appropriate_uploads_dir.$img_name_to_remove)) {
// this image was not removed
}
$image_sizes = mytheme_get_image_sizes();
foreach($image_sizes as $size) {
$img_name_to_remove = $img_name.'-'.$size.'.'.$img_extension; // UNLINK
$img_path = $path_to_appropriate_uploads_dir.$img_name_to_remove;
if(mytheme_image_on_url_exists($img_path) && !@unlink($img_path)) {
// this image was not removed
}
}
}
/**
* Get size information for all currently-registered image sizes.
* Found an example of this on one of the wordpress' example pages ..
*
* @global $_wp_additional_image_sizes
* @uses get_intermediate_image_sizes()
* @return array $sizes Data for all currently-registered image sizes.
* TODO TODO mytheme_get_image_sizes() does not return ALL IMAGES THAT WERE CREATED (all sizes)
*/
function mytheme_get_image_sizes() {
global $_wp_additional_image_sizes;
$sizes = array();
foreach ( get_intermediate_image_sizes() as $_size ) {
if ( in_array( $_size, array( 'thumbnail', 'medium', 'large' ) ) ) {
$width = get_option( "{$_size}_size_w" );
$height = get_option( "{$_size}_size_h" );
} elseif ( isset( $_wp_additional_image_sizes[ $_size ] ) ) {
$width = $_wp_additional_image_sizes[ $_size ]['width'];
$height = $_wp_additional_image_sizes[ $_size ]['height'];
}
$img_name_end = $width."x".$height;
if(!in_array($img_name_end,$sizes)) {
$sizes[] = $img_name_end;
}
}
// ADD CUSTOM SIZES (this one is not returned otherwise?!)
$sizes[] = '300x200';
return $sizes;
}
The simple solution is probably to just manually add _wp_attached_file
meta value to your attachment.
Set it to the file you want deleted when the attachment is deleted.
The logic behind this is according to https://core.trac.wordpress.org/browser/tags/4.4/src/wp-includes/post.php#L0:
get_attached_file
returns that value to wp_delete_attachment
which sets it as $file
And at the end of wp_delete_attachment
it calls wp_delete_file($file)
So I'm guessing the underlying issue is that, you are never setting a value for the meta key _wp_attached_file
.
The only downside is that I'm not sure what other processes in wp might be using that value. But you might get lucky, perhaps none, and/or it doesn't mess anything up by setting it manually.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With