WordPress Uploading Thumbnail for Custom Post Meta - php

I have set up a custom post meta field for Thumbnail on each of my posts. This function is being called correctly, and everything works up until the very last line of update_post_meta
What's interesting is that I can echo out $imageURL and get the correct address, and the file uploads fine. I can even update_post_meta with any other value whether it be a string, or another variable within the function but as soon as I try to use $imageURL or $uploaded_file['url'] it just sets the post meta to a blank string.
I've used this snippet on projects that were developed with WordPress earlier than 3.1, but this one is 3.1. Could that have something to do with it? I kind of doubt it, since this seems to be one of those super weird bugs.
function tcr_save_thumbnail($post_id, $post) {
if ( !wp_verify_nonce( $_POST['eventmeta_noncename'], plugin_basename(__FILE__) )) {
return $post->ID;
}
if ( !current_user_can( 'edit_post', $post->ID ))
return $post->ID;
if(!empty($_FILES['tcr_thumbnail_meta']['name'])) { //New upload
require_once( ABSPATH . 'wp-admin/includes/file.php' );
$override['action'] = 'editpost';
$uploaded_file = wp_handle_upload($_FILES['tcr_thumbnail_meta'], $override);
$post_id = $post->ID;
$attachment = array(
'post_title' => $_FILES['tcr_thumbnail_meta']['name'],
'post_content' => '',
'post_type' => 'attachment',
'post_parent' => $post_id,
'post_mime_type' => $_FILES['tcr_thumbnail_meta']['type'],
'guid' => $uploaded_file['url']
);
// Save the data
$id = wp_insert_attachment( $attachment,$_FILES['tcr_thumbnail_meta'][ 'file' ], $post_id );
wp_update_attachment_metadata( $id, wp_generate_attachment_metadata( $id, $_FILES['tcr_thumbnail_meta']['file'] ) );
$imageURL = $uploaded_file['url'];
update_post_meta($post->ID, "tcr_thumbnail_meta", $imageURL);
}
}

This is a functionality that has already been implemented in a plugin. try it http://wordpress.org/extend/plugins/taxonomy-images/ It is so complete!

Related

Wordpress: wp_update_attachment_metadata returns empty array

I manually uploaded some images in uploads subfolder with products sku as filename and I am trying to create a function to assign these images to the products.
But while I can see the image in the media list if I open one there is no photo inside (although in the list I can see the thumbnail). After debuging I narrowed the problem down to the wp_update_attachment_metadata which returns an empty array. How I can solve this? What am I doing wrong?
Here is the code :
function assign_images(){
require_once(ABSPATH . 'wp-admin/includes/media.php');
require_once(ABSPATH . 'wp-admin/includes/file.php');
require_once(ABSPATH . 'wp-admin/includes/image.php');
$args = array(
'orderby' => 'name',
);
$products = wc_get_products( $args );
//get the dir where the photos are
$upload_dir = wp_upload_dir();
$udir = $upload_dir['basedir'].'/photos_manual/Users/dev/Dropbox/new product photos/';
foreach( $products as $p ){
$sku = $p->get_sku();
if($p->get_id() == 2982){ //for testing reasons
$filename = $sku.'.jpg';
$wp_filetype = wp_check_filetype( $udir.$filename, null );
$attachment = array(
'post_mime_type' => 'image/jpeg',
'post_title' => sanitize_file_name( preg_replace( '/\.[^.]+$/', '', $filename) ),
'post_content' => '',
'post_status' => 'inherit'
);
$file = $udir.$filename;
$attach_id = wp_insert_attachment( $attachment, $file );
$attach_data = wp_generate_attachment_metadata( $attach_id, $file ); //$attach_data is empty array
wp_update_attachment_metadata( $attach_id, $attach_data );
set_post_thumbnail($p->get_id(), $attach_id); //die();
}
}
exit();
wp_die(); // ajax call must die to avoid trailing 0 in your response
}
In general, the return value of wp_update_attachment_metadata() function is int|false as you can see in the documentation.
But if you really get an empty array value from the function, there might be 2 reasons.
add_post_metadata filter is defined somewhere in your plugins or theme, and it returns an empty array. wp_update_attachment_metadata() function calls apply_filters( "add_post_metadata", ... ) behind. This is the only reason for the issue on proper WordPress install.
You edited one of the following 4 functions in WordPress core that can affect the return value. wp_update_attachment_metadata(), update_post_meta(), update_metadata(), add_metadata(). If you didn't edit the core files, this is not the case, but it's nice to double check the functions.

Run function on custom post type array only

I would like to run following code only on a given custom post types. now its running only on one specific custom type 'file' .
I tried to add the function in an array but i am quiet sure it wasn't the right thing
// For deleting attachments when Deleting POSTS
add_action( 'before_delete_post', 'mtp_delete_attached_thumbnail_for_trashed_product', 20, 1 );
function mtp_delete_attached_thumbnail_for_trashed_product( $post_id ) {
// gets ID of post being trashed
$post_type = get_post_type( $post_id );
// does not run on other post types
if ( $post_type != 'file' ) {
return true;
}
// get ID of featured image
$post_thumbnail_id = get_post_thumbnail_id( $post_id );
// delete featured image
wp_delete_attachment( $post_thumbnail_id, true );
}
for example only if the custom post type is 'file' or 'share' or 'folder' then the featured image will be deleted when deleting the post.
You can use the in_array() to simplify this.
// For deleting attachments when Deleting POSTS
add_action( 'before_delete_post', 'mtp_delete_attached_thumbnail_for_trashed_product', 20, 1 );
function mtp_delete_attached_thumbnail_for_trashed_product( $post_id ) {
// List of post types.
$post_types = array(
'file',
'share',
'folder',
);
// gets ID of post being trashed
$post_type = get_post_type( $post_id );
// does not run on other post types
if ( ! in_array( $post_type, $post_types, true) ) {
return true;
}
// get ID of featured image
$post_thumbnail_id = get_post_thumbnail_id( $post_id );
// delete featured image
wp_delete_attachment( $post_thumbnail_id, true );
}
https://www.w3schools.com/php/func_array_in_array.asp

Import remote image to wordpress, then set to custom field

I'm trying to import images from a remote server and set it to custom fields.
Importing and generating a attachment id is working, but something is messing with the custom fields. I don't know if is a thread issue or something.
Here's my code:
$sql = 'SELECT * FROM produto';
$retval = mysql_query( $sql, $connection) ;
while($row = mysql_fetch_array($retval, MYSQL_ASSOC))
{
$file = $row['imagem'];
$filename = basename($file);
$upload_file = wp_upload_bits($filename, null, file_get_contents($file));
if (!$upload_file['error']) {
$wp_filetype = wp_check_filetype($filename, null );
$attachment = array(
'post_mime_type' => $wp_filetype['type'],
'post_parent' => $parent_post_id,
'post_title' => preg_replace('/\.[^.]+$/', '', $filename),
'post_content' => '',
'post_status' => 'inherit'
);
$attachment_id = wp_insert_attachment( $attachment, $upload_file['file'], $parent_post_id );
$imgs[$row['modelo']][]['imagem'] = $attachment_id;
if (!is_wp_error($attachment_id)) {
require_once(ABSPATH . "wp-admin" . '/includes/image.php');
$attachment_data = wp_generate_attachment_metadata( $attachment_id, $upload_file['file'] );
wp_update_attachment_metadata( $attachment_id, $attachment_data );
}
}
}
foreach ($imgs as $key => $value) {
$args = array(
'post_type' => 'produto',
'meta_key' => 'identifier1',
'meta_value' => $key);
// The Query
$the_query = new WP_Query( $args );
if ( $the_query->have_posts() ) {
while ( $the_query->have_posts() ) {
$the_query->the_post();
update_field('imagens', $value, get_the_ID());
}
}
/* Restore original Post Data */
wp_reset_postdata();
}
If I try to set 20 itens on this custom field, it works perfectly. But when I need to run this loop with 250 results, it breaks.
What am I doing wrong?
Thanks!
I had to migrate one non wp database to a wp ready database, and the database had over 10k images. I also set up the import to do it all at once (I just uploaded not only posts, but images and all the meta data, pages, etc.).
The thing is that importing something at once will most likely time out the server, and you'll get only first n imported images, the rest won't work because of the timeout or some similar error.
The workaround is to put your script in a function that will be called with AJAX, and will import one image at the time. You just need to tweak it a bit to fetch one image at the time.
I'd first check if the $imgs array is full - all your images from old database are present with all the data attached.
If it is, you just need to add something like this
<?php
add_action( 'wp_ajax_import_image', 'import_image_callback' );
add_action( 'wp_ajax_nopriv_import_image', 'import_image_callback' ); // this is only if you're importing from the front end. If in the back end this is not necessary
/**
* AJAX callback iumport image function
*
*/
function import_image(){
$img = $_POST['img'];
$args = array(
'post_type' => 'produto',
'meta_key' => 'identifier1',
'meta_value' => $img
);
// The Query
$image_query = new WP_Query( $args );
if ( $image_query->have_posts() ) {
while ( $image_query->have_posts() ) {
$image_query->the_post();
update_field('imagens', $img['image_value'], get_the_ID());//You'll need to see what you need from the array value here, I just placed dummy image_value as I don't know what the $img array contains
}
}
/* Restore original Post Data */
wp_reset_postdata();
}
Then you'll call this function using AJAX. Now you'll probably have to save your images as JSON object and localize it. That way you'll be able to use that array in your JavaScript to fetch one image at the time with something like this:
jQuery(document).ready(function($) {
"use strict";
var images = localized_object.images_array; //JSON array
for (var i = 0; i < images.length; i++) {
var img = images[i]; //something like this - you'll see if this works 100%, but the gist is the same
upload_image(img); // Call the AJAX callback function
}
function upload_image(image){
$.ajax({
type: "POST",
url: localized_object.ajaxurl, //localize this if you're doing this from the from the front end. If you're using it in back end just use ajaxurl.
data: {
'action': 'import_image',
'img': image,
},
success: function(response) {
console.log('Image imported');
},
error : function (jqXHR, textStatus, errorThrown) {
console.log(jqXHR + ' :: ' + textStatus + ' :: ' + errorThrown);
}
});
}
});
Now since I don't know how your DB dump looks like this is not 100% guaranteed to work, but it gives you a good idea how to do it.
Hope this helps :)

Wordpress mysql and functions

My aim is to import posts from a node.js server to the wordpress database, thus is due to the large amount of records it will be trawling daily..
Do you know of any cheat sheets that show the mysql that a wordpress function uses?
For example
wp_insert_post()
//The above function uses this sql
INSERT INTO wp_posts VALUES(field1) etc etc
Thanks in advance
Auto generating content... Hmmm lets try ..
<?php
//First you need the required files...
include('../wp-load.php' );
require_once('../wp-admin/includes/media.php');
require_once('../wp-admin/includes/file.php');
require_once('../wp-admin/includes/taxonomy.php');
require_once('../wp-includes/taxonomy.php');
// Flush the wordpress db...
$wpdb->flush();
// Get your data from any feed. and lets say you will process it in a foreach loop..
foreach($somedata as $key => $value){
// i don't know your data structure so i give a symbolic example..
$post = array(
'post_author' => 2,
'post_content' => $post_content,
'post_excerpt' => $post_excerpt,
'post_status' => 'publish',
'post_title' => $post_title, // aware & ' so something to escape...
'post_type' => 'post',
'post_date' => $pub_date, // Y-m-d H:i:s
'tags_input' => $tags // comma separated tags..
);
$post_id = wp_insert_post( $post, $wp_error );
wp_set_object_terms( $post_id, $cat_ids, 'category' ); // $cat_ids is an array!
}
?>
The code above will add posts for you.. running it via cron and setting parameters to avoid duplicates your job..
Well if you need to import a remote image and add it to the post as featured you need a function like this..
function somatic_attach_external_image( $url = null, $post_id = null, $thumb = null, $filename = null, $post_data = array(),$resimdesc=null ) {
if ( !$url || !$post_id ) return new WP_Error('missing', "Need a valid URL and post ID...");
require_once( ABSPATH . 'wp-admin/includes/file.php' );
// Download file to temp location, returns full server path to temp file, ex; /home/user/public_html/mysite/wp-content/26192277_640.tmp
$tmp = download_url( $url );
// If error storing temporarily, unlink
if ( is_wp_error( $tmp ) ) {
#unlink($file_array['tmp_name']); // clean up
$file_array['tmp_name'] = '';
return $tmp; // output wp_error
}
preg_match('/[^\?]+\.(jpg|JPG|jpe|JPE|jpeg|JPEG|gif|GIF|png|PNG)/', $url, $matches); // fix file filename for query strings
$url_filename = basename($matches[0]); // extract filename from url for title
$url_type = wp_check_filetype($url_filename); // determine file type (ext and mime/type)
// override filename if given, reconstruct server path
if ( !empty( $filename ) ) {
$filename = sanitize_file_name($filename);
$tmppath = pathinfo( $tmp ); // extract path parts
$new = $tmppath['dirname'] . "/". $filename . "." . $tmppath['extension']; // build new path
rename($tmp, $new); // renames temp file on server
$tmp = $new; // push new filename (in path) to be used in file array later
}
// assemble file data (should be built like $_FILES since wp_handle_sideload() will be using)
$file_array['tmp_name'] = $tmp; // full server path to temp file
if ( !empty( $filename ) ) {
$file_array['name'] = $filename . "." . $url_type['ext']; // user given filename for title, add original URL extension
} else {
$file_array['name'] = $url_filename; // just use original URL filename
}
// set additional wp_posts columns
if ($resimdesc) {
$post_data['post_title'] = $resimdesc; // just use the original filename (no extension)
}
// make sure gets tied to parent
if ( empty( $post_data['post_parent'] ) ) {
$post_data['post_parent'] = $post_id;
}
// required libraries for media_handle_sideload
require_once(ABSPATH . 'wp-admin/includes/file.php');
require_once(ABSPATH . 'wp-admin/includes/media.php');
require_once(ABSPATH . 'wp-admin/includes/image.php');
// do the validation and storage stuff
$att_id = media_handle_sideload( $file_array, $post_id, null, $post_data ); // $post_data can override the items saved to wp_posts table, like post_mime_type, guid, post_parent, post_title, post_content, post_status
// If error storing permanently, unlink
if ( is_wp_error($att_id) ) {
#unlink($file_array['tmp_name']); // clean up
return $att_id; // output wp_error
}
// set as post thumbnail if desired
if ($thumb) {
set_post_thumbnail($post_id, $att_id);
}
return $att_id;
}
You will use this function inside the foreach.. $imgsrc is the url of the image...
$attach_id = somatic_attach_external_image( $imgsrc, $post_id, $thumb = null, $filename = null, $post, $title );
add_post_meta($post_id, '_thumbnail_id', $attach_id, true);
Good luck...

Get attachment urls for a post - WordPress

I am trying to create a list of PDFs (newsletters created each month). I have created a custom post type named 'newsletters' and restricted it to only supporting a 'title'.
I have then used the advanced custom fields plugin to add a file upload button to this post type. Therefore each post has a title and a button to upload the pdf.
I have then written the below function to output the list of attachments.
function list_newsletters(){
$args = array( 'post_type' => 'newsletters' );
$loop = new WP_Query( $args );
while ( $loop->have_posts() ) : $loop->the_post();
$permalink = get_permalink();
$title = get_the_title();
$id = get_the_ID();
$attachment = wp_get_attachment_url($id);
echo '<li><a href="'.$attachment.'">'.$title.'</li>';
endwhile;
}
However the wp_get_attachment_url($id) doesn't seem to work. I think this is because I am supposed to be supplying the attachment ID rather than the post ID. I have looked around online and cannot find a clear way of finding the attachment ID for a specific post.
Just to clarify each post will only contain one attached file.
Thank you in advance
This example taken from the get_posts() Codex page
$attachments = get_posts(array(
'post_type' => 'attachment',
'numberposts' => -1,
'post_status' =>'any',
'post_parent' => $post->ID
));
if ($attachments) {
foreach ( $attachments as $attachment ) {
echo apply_filters( 'the_title' , $attachment->post_title );
the_attachment_link( $attachment->ID , false );
}
}

Categories