WordPress 5.x: Programatically Images upload is not working - php

I'm creating a custom plugin on WordPress to upload my products from my database to WooCommerce. All the logic works perfectly, but when it comes to upload the images and attach them to the product, it is not working.
I have tried using the regular copy from source to a local directory and then creating the media post, but it didn't work.
This is what I'm trying currently:
$image_id = media_sideload_image(
urlencode( $item['ImgPath1'] ),
$post_id,
$item['Title'],
'id'
);
add_post_meta( $post_id, '_thumbnail_id', $image_id );
I have also tried:
$filename = basename( $source ); // Get the filename including extension from the $fileurl e.g. myimage.jpg
$destination = WP_CONTENT_DIR. '/uploads/product_images/' . $filename; // Specify where we wish to upload the file, generally in the wp uploads directory
copy( $source, $destination ); // Copy the file
$filetype = wp_check_filetype( $destination ); // Get the mime type of the file
$attachment = array( // Set up our images post data
'guid' => get_option( 'siteurl' ) . '/wp-content/uploads/product_images/' . $filename,
'post_mime_type' => $filetype['type'],
'post_title' => $filename,
'post_author' => 1,
'post_content' => ''
);
I expect to at least see the images on ftp, but nothing is reported and my product import continues without any issues.

Your second example appears to be incomplete, so I'm gonna ignore it and focus on fixing the first.
The issue with your first example is that media_sideload_image() is designed to be used with an external URL, not a filepath on the same server. However, most of the inner workings of that function actually happen in media_handle_sideload(), which gets called once the file has been downloaded to a temporary location on the local server.
The following code was written mostly from memory and hasn't been tested, but should work:
function insert_media_from_path( $file_path, $attach_to = 0, $title = null, $delete_original = false ) {
if( !file_exists( $file_path ) ) {
return false;
}
$file_array = array(
'name' => basename($file_path),
'tmp_name' => $file_path
);
$id = media_handle_sideload( $file_array, $attach_to, $title );
if( $id && $delete_original ) {
unlink( $file_path );
}
return $id;
}

Related

WordPress / PHP 'Trying to get property 'feeds' of non object when trying to upload image from remote url

I'm trying to scrape some JSON data (that part works fine), but when I try and add the featured image, (a blank icon appears in the media library, with correct filename, but the url field says 'false' & I get this error:-
Notice: Trying to get property 'feeds' of non-object in
/Users/macbook/Documents/www/news_test/wp-includes/post.php on line
4482
Fatal error: Uncaught Error: Call to a member function
using_permalinks() on null in
/Users/macbook/Documents/www/news_test/wp-includes/link-template.php:423
Stack trace: #0
/Users/macbook/Documents/www/news_test/wp-includes/link-template.php(147):
get_attachment_link(Object(WP_Post), false) #1
/Users/macbook/Documents/www/news_test/wp-includes/post.php(4105):
get_permalink(Object(WP_Post)) #2
/Users/macbook/Documents/www/news_test/wp-includes/post.php(5740):
wp_insert_post(Array, false) #3
/Users/macbook/Documents/www/news_test/wp-content/plugins/code-snippets/php/snippet-ops.php(446)
: eval()'d code(92): wp_insert_attachment(Array, '/Users/macbook/...',
293) #4
/Users/macbook/Documents/www/news_test/wp-content/plugins/code-snippets/php/snippet-ops.php(446):
eval() #5
/Users/macbook/Documents/www/news_test/wp-content/plugins/code-snippets/php/snippet-ops.php(534):
execute_snippet('ini_set('displa...', 6) #6
/Users/macbook/Documents/www/news_test/wp-includes/class-wp-hook.php(287):
execute_active_snippets('') #7 /Users/ma in
/Users/macbook/Documents/www/news_test/wp-includes/link-template.php
on line 423 There has been a critical error on your website. Please
check your site admin email inbox for instructions.
Here's the code:
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
global $wpdb;
$json = "http://newsapi.org/v2/top-headlines?country=ie&apiKey=**************";
$response = file_get_contents($json);
$mydecode = json_decode($response, true);
$mydecode = $mydecode['articles'];
// error_log(printf($mydecode));
foreach ($mydecode as $key => $value) {
$title = str_replace("&", "&", $value['title']);
$content = str_replace("&", "&", $value['content']);
//error_log("LOG: " . $title[0]);
// $description = str_replace("&", "&", $mydecode.articles->description);
// $article_url = $mydecode.articles->url;
$image_url = $value['urlToImage'];
// $content = $mydecode.content;
// Insert post
$new_post = array(
'post_title' => $title,
'post_content' => $content,
'post_status' => 'draft',
'post_author' => 1,
'post_category' => array(2),
'post_type' => 'post'
);
// Insert post
$post_id = wp_insert_post($new_post);
// Insert post meta if available
// add_post_meta( $post_id, 'meta_key', 'meta_value' );
// Add Featured Image to Post
// Add Featured Image to Post
// $image_url = $urlToImage; // Define the image URL here
//now to try and get actual image name
$headers = wp_get_http_headers( $image_url );
$mime_type = $headers['content-type'];
$ext = '';
foreach ( wp_get_mime_types() as $exts => $mime ) {
if ( $mime == $mime_type ) {
$ext = $exts;
break;
}
}
//now to apply extension if it didn't have one
if( $ext ){
$exts = explode('|', $ext);
$ext = '.'.$exts[0];
}
$image_name = 'image';
$upload_dir = wp_upload_dir(); // Set upload folder
$image_data = file_get_contents($image_url); // Get image data
$unique_file_name = wp_unique_filename( $upload_dir['path'], $image_name . $ext ); // Generate unique name
$filename = basename( $unique_file_name ); // Create image file name
error_log("Filenames: ".$filename);
// Check folder permission and define file location
if( wp_mkdir_p( $upload_dir['path'] ) ) {
$file = $upload_dir['path'] . '/' . $filename;
} else {
$file = $upload_dir['basedir'] . '/' . $filename;
}
error_log("file: ".$file);
// Create the image file on the server
file_put_contents( $file, $image_data );
// Check image file type
$wp_filetype = $exts[0];
// Set attachment data
$attachment = array(
'post_mime_type' => $wp_filetype,
'post_title' => sanitize_file_name( $filename ),
'post_content' => '',
'post_status' => 'inherit'
);
// Create the attachment
$attach_id = wp_insert_attachment( $attachment, $file, $post_id );
// Include image.php
require_once(ABSPATH . 'wp-admin/includes/image.php');
// Define attachment metadata
$attach_data = wp_generate_attachment_metadata( $attach_id, $file );
// Assign metadata to attachment
wp_update_attachment_metadata( $attach_id, $attach_data );
// And finally assign featured image to post
set_post_thumbnail( $post_id, $attach_id );
}
I'm working on WordPress 5.5, and using the snippets plugin to execute the code.
tl;dr
This is happening because you are calling wp_update_post too early in WordPress lifecycle. Hook your update logic to init and you will be fine.
Long story
This warning is coming from WordPress trying to find a pretty slug for the post, but being unable to do so because the Permalink logic has not loaded yet.
The warning comes from this line: https://github.com/WordPress/WordPress/blob/master/wp-includes/post.php#L4776
As you can see, the $wp_permalink global is populated kinda late in the lifecycle, AFTER plugins_loaded and before init: https://github.com/WordPress/WordPress/blob/master/wp-settings.php#L473-L479
So if you call wp_update_post on a plugin without a hook, the permalink global will not be populated yet.
So you should change your code flow to make sure it only runs wp_update_post after init has fired.

Wordpress image upload from frontend throws 500 internal server error

I have a site with a frontend form where users can add new post. The form has some basic post details and an featured image field. The form also has a few more image fields, which are controlled by acf.
Now the issue is when i use images like png everything works fine. But when i use images like jpg, it gives a internal server error. In acf i have added the accepted file formats as "jpg,png,jpeg". But i am not sure how to add file formats for the featured image.
Here is the code i am using. Here the first image will always be the featured image.
foreach( $_FILES as $file ) {
if( is_array( $file ) ) {
if($count==1){
$featured_image_id = upload_user_file( $file );
}else{
$item_image[] = upload_user_file( $file );
}
}
$count++;
}
And here is the upload_user_file function
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;
}
Ok i solved it. For some reason the allowed file types in acf didn't work for me. So i just removed the types (ie allow all file types) and everything came back to life. I know this might not be suitable for everyone, but i guess this points you in the right direction of where the issue might be.

WordPress - Uploading PDF from own function is failing

I have a script in my functions php, calling a REST-api – which gives me a totally valid PDF. I am using wp_upload_bits(), and it works just as it should. It places the file in the upload folder with filename and all set.
I use the wp_insert_attachment() function too, and it also does return a valid number as an ID for the newly inserted file.
On my FTP, I can see that the wp_upload_bits() places the PDF file correctly. But it does now show up in my Media Library, nor for the post I am trying to attach it to.
Should I not be using wp_insert_attachment() for this kind of file?
Works good though for another function I got for images, but not for PDF.
I have added define('ALLOW_UNFILTERED_UPLOADS', true); in my wp-config.php – even though it feels uncalled for. And I have also added pdf as a mimetype, even though it is already "allowed".
What I am doing wrong here?
// $magic - is the PDF file retrieved from a REST api.
if ($magic) {
$nameOfTheFile = $docID.'-FILE.pdf';
// No errors are given
$attachment = wp_upload_bits( $nameOfTheFile, null, $magic );
if( !empty( $attachment['error'] ) ) {
echo '<br>GETTING DOC FAIL '.$attachment['error'].'<br>';
ob_flush(); flush();
} else {
require_once(ABSPATH . 'wp-admin/includes/media.php');
require_once(ABSPATH . 'wp-admin/includes/file.php');
require_once(ABSPATH . 'wp-admin/includes/image.php');
$filetype = wp_check_filetype( basename( $attachment['file'] ), null );
$postinfo = array(
'post_mime_type' => $filetype['type'],
'post_title' => sanitize_file_name($docID),
'post_excerpt' => $doc['name'],
'post_content' => $doc['name'],
'post_parent' => $post_id,
'post_status' => 'inherit',
);
// print_r($postinfo);
$filename = $attachment['url'];
$attach_id = wp_insert_attachment( $postinfo, $filename, $post_id);
print_r($attach_id); /* ID is successfuly given, but DOES not show up in Media. Even tried omoitting the $post_id, even though it is totallay valid */
// this might only be required for images? But I tried adding it to see if it was needed for the PDF
$attach_data = wp_generate_attachment_metadata( $attach_id, $attachment['url'] );
wp_update_attachment_metadata( $attach_id, $attach_data );
}
}

wp_generate_attachment_metadata returning an empty array

I'm writing a Wordpress plugin to download remote images on my blog.
I made a function to upload a remote image locally, then returning its ID.
All seems OK except that
$attach_data = wp_generate_attachment_metadata( $attach_id, $local_file );
returns me an empty array - and it should not.
wp_generate_attachment_metadata is, among others, responsible of generating the thumbnails of the uploaded image. But I have no thumbnails created when I run my code.
I checked the values I send to the function and they seems correct : I have an ID and an absolute path to the uploaded file, as documented in the codex.
Still, I can't manage to have my code working :
$attach_data should not be empty...
Can anyone help ?
function upload_from_remote_url($url,$post_id){
$url = $this->validate_remote_media_url($url); //check file is not on local server
if (!$url) return false;
if ($existing_id = $this->media_already_exists($url)) return $existing_id; //url already has been downloaded
$upload_dir = wp_upload_dir();
$wp_mime_types = wp_get_mime_types();
//fetch image
$response = wp_remote_get( $url );
//get filename without extension
$filename = basename( $url ); //get filename & extension
$filename_strip = preg_replace('/\.[^.]*$/', '', $filename); //strip extension
//get extension from content type,
//because wp_upload_bits needs an extension and certain url don't have one.
$file_type = wp_remote_retrieve_header( $response, 'content-type' );
$extensions = array_search($file_type,$wp_mime_types);
$extensions_arr = explode('|',$extensions);
$extension = $extensions_arr[0];
$new_filename = $filename_strip.'.'.$extension; //full name
$new_filename = wp_unique_filename($upload_dir['path'], $new_filename); // be sure this name do not exist already
$uploaded = wp_upload_bits($new_filename, '', wp_remote_retrieve_body( $response ) );
if ($uploaded['error']) return false;
$local_file = $uploaded['file'];
$local_filename = basename($local_file);
$local_filetype = wp_check_filetype( $local_filename, null );
//Attachment options
$attachment = array(
'post_title'=> $local_filename,
'post_mime_type' => $local_filetype,
'post_status' => 'inherit'
);
// Add the image to your media library
$attach_id = wp_insert_attachment( $attachment, $local_file, $post_id );
if (!$attach_id) return false;
$attach_data = wp_generate_attachment_metadata( $attach_id, $local_file );
wp_update_attachment_metadata( $attach_id, $attach_data );
//save source link so we do not import several times the same media
update_post_meta($attach_id, 'grm_source', $url);
return $attach_id;
}
BTW, if any WP gourou had anything to say about this code... I'll be happy to read it, as the WP documentation about uploading files is a bit messy. I needed some specific stuff here, as being able to retrieve the file extension. I ended up to this but maybe you have some better ideas !
I've had a similar problem where mime type was missing. Since I use only one mime type, it was fixed by
'post_mime_type' => 'image/jpeg'
After that, it was still not updating the metadata, but forcing the update with "wp_update_attachment_metadata" solved the problem:
$attach_data = wp_generate_attachment_metadata($attach_id, $file_path);
wp_update_attachment_metadata($attach_id, $attach_data);
This is, what finally fixed it for me:
apply_filters('wp_handle_upload', array(
'file' => $file_path,
'url' => $file_url,
'type' => $file_type),
'upload');
Explanation: I'm not quite sure why this fixed the error for me, but I assume that this either has something to do with plugins using the wp_handle_upload hook or that the filters add meta-data to the attachment, which otherwise would be missing in the wp_generate_attachment_metadata function.
Full function:
function add_to_media_lib($file_url, $file_path, $parent_post_id)
{
require_once(ABSPATH . 'wp-admin/includes/image.php');
require_once(ABSPATH . 'wp-admin/includes/file.php');
// Check the type of tile. We'll use this as the 'post_mime_type'.
$file_type = wp_check_filetype(basename($file_url), null);
// Get the path to the upload directory.
$wp_upload_dir = wp_upload_dir();
// Prepare an array of post data for the attachment.
$attachment = array(
'guid' => $wp_upload_dir['url'] . '/' . basename($file_url),
'post_mime_type' => $file_type['type'],
'post_title' => preg_replace('/\.[^.]+$/', '', basename($file_url)),
'post_content' => '',
'post_status' => 'inherit',
'post_parent' => $parent_post_id
);
// Insert the attachment.
$attach_id = wp_insert_attachment($attachment, $file_url, $parent_post_id);
// apply filters (important in some environments)
apply_filters('wp_handle_upload', array('file' => $file_path, 'url' => $file_url, 'type' => $file_type), 'upload');
// Generate the metadata for the attachment, and update the database record.
if ($attach_data = wp_generate_attachment_metadata($attach_id, $file_path)) {
wp_update_attachment_metadata($attach_id, $attach_data);
} else {
echo '<div id="message" class="error"><h1>Failed to create PDF-thumbnail Meta-Data</h1><pre>' . print_r($attach_data) . '</pre></div>';
}
return $attach_id;
}
I know the topic is old but I was facing a similar issue and what worked for me was enabling the Crop thumbnail to exact dimensions (normally thumbnails are proportional) under Settings >> Media. I am using the media_handle_sideload() function by the way.

WordPress file "upload" from plugin

I'm trying to create plugin importing posts to WordPress. Imported articles (XML) contain "image-name" attribute and this image is already uploaded to the server.
I would like to, however, make WordPress do its "magic" and import the image to the system (create thumbnails, attach it to the post, place it under the wp-uploads directory scheme)... I found function media_handle_upload($file_id, $post_id, $post_data, $overrides) but it requires array $_FILES to be filled with actual upload (and I'm not uploading file - it is already placed on the server) so it's not very useful
Do you have any hint how to proceed?
Thanks
Check the following script to get the idea. (It does work.)
$title = 'Title for the image';
$post_id = YOUR_POST_ID_HERE; // get it from return value of wp_insert_post
$image = $this->cache_image($YOUR_IMAGE_URL);
if($image) {
$attachment = array(
'guid' => $image['full_path'],
'post_type' => 'attachment',
'post_title' => $title,
'post_content' => '',
'post_parent' => $post_id,
'post_status' => 'publish',
'post_mime_type' => $image['type'],
'post_author' => 1
);
// Attach the image to post
$attach_id = wp_insert_attachment( $attachment, $image['full_path'], $post_id );
// update metadata
if ( !is_wp_error($attach_id) )
{
/** Admin Image API for metadata updating */
require_once(ABSPATH . '/wp-admin/includes/image.php');
wp_update_attachment_metadata
( $attach_id, wp_generate_attachment_metadata
( $attach_id, $image['full_path'] ) );
}
}
function cache_image($url) {
$contents = #file_get_contents($url);
$filename = basename($url);
$dir = wp_upload_dir();
$cache_path = $dir['path'];
$cache_url = $dir['url'];
$image['path'] = $cache_path;
$image['url'] = $cache_url;
$new_filename = wp_unique_filename( $cache_path, $filename );
if(is_writable($cache_path) && $contents)
{
file_put_contents($cache_path . '/' . $new_filename, $contents);
$image['type'] = $this->mime_type($cache_path . '/' . $new_filename); //where is function mime_type() ???
$image['filename'] = $new_filename;
$image['full_path'] = $cache_path . '/' . $new_filename;
$image['full_url'] = $cache_url . '/' . $new_filename;
return $image;
}
return false;
}

Categories