Why is this function triggering on all post events? - php

I've made a function that on post create, takes an URL placed in the_content and grabs an image from the URL. Then it uploads the image and attach it to the post. It works as intended. However it should only do it when the post is created, but it does it on edit and delete as well. How can I fix that?
function set_featured_image_from_content_for_galleries( $post_id ) {
$post = get_post( $post_id );
if ( 'gallery' != $post->post_type ) {
return;
}
$content = $post->post_content;
preg_match( '/https?:\/\/[^\s]+/', $content, $matches );
if ( ! empty( $matches[0] ) ) {
$image_url = $matches[0];
$image_url = preg_replace('/^(.+src=")(.+)(".+)$/', '$2', $image_url);
$upload_dir = wp_upload_dir();
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $image_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$image_data = curl_exec($ch);
curl_close($ch);
$filename = uniqid().'.png';
if(wp_mkdir_p($upload_dir['path']))
$file = $upload_dir['path'] . '/' . $filename;
else
$file = $upload_dir['basedir'] . '/' . $filename;
file_put_contents($file, $image_data);
$wp_filetype = wp_check_filetype($filename, null );
$attachment = array(
'post_mime_type' => $wp_filetype['type'],
'post_title' => sanitize_file_name($filename),
'post_content' => '',
'post_status' => 'inherit'
);
$attach_id = wp_insert_attachment( $attachment, $file, $post_id );
require_once(ABSPATH . 'wp-admin/includes/image.php');
$attach_data = wp_generate_attachment_metadata( $attach_id, $file );
wp_update_attachment_metadata( $attach_id, $attach_data );
set_post_thumbnail( $post_id, $attach_id );
// Update post content with the new featured image URL
$image_url = wp_get_attachment_url( $attach_id );
update_post_meta( $post_id, '_post_content', $image_url);
}
}
add_action( 'save_post', 'set_featured_image_from_content_for_galleries' );
Tried to use update_post_meta() instead of the newer tag

You could try using the transition_post_status hook instead, which checks whether the post has changed from one status to another.
So your action would be something like:
add_action( 'transition_post_status', 'set_featured_image_from_content_for_galleries', 10, 3 );
Noting that the hook needs three parameters: $new_status, $old_status, $post, where $post is the post object. So you'd need to update your function declaration as well to:
function set_featured_image_from_content_for_galleries( $new_status, $old_status, $post ) {
And then remove $post = get_post( $post_id ); from the function, since the entire post object is already being passed.
From there you could add a check to your function to determine whether the post has already been published by checking whether it's moving to publish from the auto-draft status that WordPress uses when it initially auto-saves the post:
if ( 'publish' === $new_status && 'auto-draft' === $old_status ) {
// Do stuff...
}
You might have to play around with the logic but it seems like it should work.

Related

file_get_contents() expects parameter 1 to be a valid path when trying to set featured image

I was trying to make a plugin which would get images from instagram API and then put them in shortcodes which would set the featured image in where the shortcode is. I have this code for the function for setting featured images:
<?php
function Generate_Featured_Image( $image_url, $post_id ){
$upload_dir = wp_upload_dir();
$image_data = file_get_contents($image_url);
$filename = basename($image_url);
if(wp_mkdir_p($upload_dir['path'])) $file = $upload_dir['path'] . '/' . $filename;
else $file = $upload_dir['basedir'] . '/' . $filename;
file_put_contents($file, $image_data);
$wp_filetype = wp_check_filetype($filename, null );
$attachment = array(
'post_mime_type' => $wp_filetype['type'],
'post_title' => sanitize_file_name($filename),
'post_content' => '',
'post_status' => 'inherit'
);
$attach_id = wp_insert_attachment( $attachment, $file, $post_id );
require_once(ABSPATH . 'wp-admin/includes/image.php');
$attach_data = wp_generate_attachment_metadata( $attach_id, $file );
$res1= wp_update_attachment_metadata( $attach_id, $attach_data );
$res2= set_post_thumbnail( $post_id, $attach_id );
}
Then I have this code for getting the API and putting the images in an array :
//define Access token
$accesst= "3219594850.1677ed0.cb21f3e34b7c4030a8ba364d35ec284b";
//userid
$userid= 3219594850;
//image count to get
$count=20;
//get api contents
$content = file_get_contents('https://api.instagram.com/v1/users/self/media/recent/?access_token='.$accesst.'&count='.$count);
//converting JSON to object
$standardres = json_decode($content, true);
//array method
$images= array();
foreach($standardres['data'] as $photo) {
$imageData =file_get_contents($photo['images']['standard_resolution']['url']);
array_push ($images, $imageData);
}
This should be the function which makes the post as a featured image:
//create functions for shortcodes with definition
function fone(){
global $post;
$fid = $post->ID;
global $images;
Generate_Featured_Image($images[0], $fid);
}
add_shortcode( 'one', 'fone');
?>
But I only get an error displaying :
Warning: file_get_contents() expects parameter 1 to be a valid path, string given in D:\XEMP\htdocs\xd\wordpress\wp-content\plugins\insta-live\insta-live.php on line 56
Warning: file_put_contents() expects parameter 1 to be a valid path, string given in D:\XEMP\htdocs\xd\wordpress\wp-content\plugins\insta-live\insta-live.php on line 60
...
Any ideas where did I go wrong? Line 56 and 60 is :
$image_data = file_get_contents($image_url);
file_put_contents($file, $image_data);

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 - Hook don't fire until update post manually from backend

I'm trying to run a function that prints watermark on image when a new post is creates from a plugin that generates a new post and associates an uploaded photo as featured image.
Function works well only if i manually update/create posts from back-end and not working when posts is create from front-end.
here my code on functions.php:
// stampa watermark
function stampa_watermark () {
$slug = 'foto';
$post_id = get_the_ID();
$post_type = get_post_type($post_id);
$attachment_id = get_post_thumbnail_id( $post_id, 'full' );
$image_size = 'full';
$filepath = get_attached_file( $attachment_id );
$upload_dir = wp_upload_dir();
if ( $slug != $post_type ) {
return;
}
else {
$IW = new Image_Watermark;
$IW->do_watermark( $attachment_id, $filepath, $image_size, $upload_dir );
}
}
add_action( 'updated_postmeta', 'stampa_watermark' );
add_action( 'save_post', 'stampa_watermark' );
// fine

Copy a Wordpress featured image over multisite

I have the following function to copy across a post as it's created on one site, to then move it over to a specific multisite blog:
function copy_across_to_multisite( $post_id ) {
// If this is just a revision, don't send the email.
if ( wp_is_post_revision( $post_id ) )
return $post_id;
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE)
return $post_id;
if ($post_id && get_current_blog_id() == 1) {
$post = get_post($post_id, ARRAY_A); // get the original post
if ($post->post_status == 'trash' || $post->post_status == 'auto-draft') {
return $post_id;
}
$meta = get_post_meta($post_id);
$post_thumbnail_id = get_post_thumbnail_id($post_id);
$post_thumbnail = get_post($post_thumbnail_id, ARRAY_A);
$post['ID'] = ''; // empty id field, to tell wordpress that this will be a new post
$post_thumbnail['ID'] = '';
switch_to_blog(2); // switch to target blog
$inserted_post_id = wp_insert_post($post); // insert the post
$inserted_thumbnail = wp_insert_post($post_thumbnail);
foreach($meta as $key=>$value) {
update_post_meta($inserted_post_id,$key,$value[0]);
}
set_post_thumbnail($inserted_post_id, $inserted_thumbnail);
restore_current_blog(); // return to original blog
}
}
add_action( 'save_post', 'copy_across_to_multisite' );
This works great, but it doesn't bring across the featured image; I'm assuming because I need to also move the featured image into the upload folder for that multisite? The image does come across in the media library (albeit with no thumbnail and linking back to the other site - which I don't mind) but doesn't 'attach' onto the post and show up as a featured image.
Can anyone help out with this? Has anyone done anything similar? Thanks
Well, finally managed to (pretty much) cobble together a solution.
So in case anyone needs a similar function, it will take a little tweaking depending on your situation (changing the number in the switch_to_blog function as needed).
function copy_across_to_multisite( $post_id ) {
// If this is just a revision, don't send the email.
if ( wp_is_post_revision( $post_id ) )
return $post_id;
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE)
return $post_id;
if ($post_id && get_current_blog_id() == 1) {
$post = get_post($post_id, ARRAY_A); // get the original post
if ($post->post_status['trash'] || $post['post_status'] == 'auto-draft') {
return $post_id;
}
$meta = get_post_meta($post_id);
$post_thumbnail_id = get_post_thumbnail_id($post_id);
$image_url = wp_get_attachment_image_src($post_thumbnail_id, 'full');
$image_url = $image_url[0];
$post['ID'] = ''; // empty id field, to tell wordpress that this will be a new post
switch_to_blog(2); // switch to target blog
$inserted_post_id = wp_insert_post($post); // insert the post
foreach($meta as $key=>$value) {
update_post_meta($inserted_post_id,$key,$value[0]);
}
// Add Featured Image to Post
$upload_dir = wp_upload_dir(); // Set upload folder
$image_data = file_get_contents($image_url); // Get image data
$filename = basename($image_url); // Create image file name
// 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;
}
// Create the image file on the server
file_put_contents( $file, $image_data );
// Check image file type
$wp_filetype = wp_check_filetype( $filename, null );
// Set attachment data
$attachment = array(
'post_mime_type' => $wp_filetype['type'],
'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( $inserted_post_id, $attach_id );
restore_current_blog(); // return to original blog
}
}
add_action( 'save_post', 'copy_across_to_multisite' );

why when I try to insert an image attachment along with a post does wp_get_attachment_url give me a very wrong file path?

I am using a new blog on WPMS (3.0.1, updating is unfortunately not an option at this point in time) to aggregate posts (and their featured image) from a few blogs on the same install, and I have to do it "programmatically" rather than through a pre-made plugin due to firewall restrictions. I've tried several ways of doing it, and feel like this method is most promising. Since my instance seems to be compounding complications, the few documented examples of how to use wp_insert_post and wp_insert_attachment aren't quite getting me all the way there. Here's what I've cooked up:
switch_to_blog(oldblognumber);
$zargs = array( 'numberposts' => 1, 'category_name' => 'featured');
$zlastpost = get_posts( $zargs );
foreach($zlastpost as $post) : setup_postdata($post);
$extrapost = array();
$extrapost['post_title'] = get_the_title();
$extrapost['post_content'] = get_the_content();
$extrapost['comment_status'] = 'closed';
$extrapost['post_status'] = 'publish';
$extrapost['post_date'] = get_the_date( $d = 'Y-m-d H:i:s');
$extrapost['post_category'] = array(catidnumber);
$upload_dir = wp_upload_dir();
$oldid = get_the_ID();
$image_url = wp_get_attachment_url(get_post_thumbnail_id($oldid));
$image_data = file_get_contents($image_url);
$filename = basename($image_url);
switch_to_blog(newblognumber);
$file = $upload_dir['path'] . '/' . $filename; //removed the conditional cuz it was giving me trouble
file_put_contents($file, $image_data);
$post_id = wp_insert_post($extrapost);
$wp_filetype = wp_check_filetype($filename, null );
$attachment = array(
'post_mime_type' => $wp_filetype['type'],
'post_title' => sanitize_file_name($filename),
'post_content' => '',
'post_status' => 'inherit',
);
$attach_id = wp_insert_attachment( $attachment, $file, $post_id );
require_once(ABSPATH . 'wp-admin/includes/image.php');
$attach_data = wp_generate_attachment_metadata( $attach_id, $file );
wp_update_attachment_metadata( $attach_id, $attach_data );
set_post_thumbnail( $post_id, $attach_id );
restore_current_blog();
wp_reset_postdata();
endforeach;
restore_current_blog();
The post insertion works just fine, and it pulls the image alright, but somewhere in there things are getting muddled and it spits out an absurd attachment url:
http://myblogs.com/newblog/wp-content/blogs.dir/newblognumber/files//internet/http/wp-content/blogs.dir/oldblognumber/files/year/month/filename.jpg
Likewise, in the loop where I ask for the_post_thumbnail, I get a broken image whose src is http://myblogs.com/newblog/files//internet/http/wp-content/blogs.dir/oldblognumber/files/year/month/filename-200x100.jpg
For what it's worth, since I'm using a pre set_post_thumbnail version of WP, I just manually define the function in my newblog's functions.php:
function set_post_thumbnail( $post, $thumbnail_id ) {
$post = get_post( $post );
$thumbnail_id = absint( $thumbnail_id );
if ( $post && $thumbnail_id && get_post( $thumbnail_id ) ) {
$thumbnail_html = wp_get_attachment_image( $thumbnail_id, 'thumbnail' );
if ( ! empty( $thumbnail_html ) ) {
update_post_meta( $post->ID, '_thumbnail_id', $thumbnail_id );
return true;
}
}
return false;
}
I've tried fudging GUIDs and using regular expressions to force urls into submission among other things, but all to no avail.
I have also tried an alternate method of setting the post thumbnail of an inserted post, but this simply calls the original file in the oldblog's upload directory, which will not suffice, as I'd like to generate new image sizes for the newblog's Media Library, and I'd prefer to not go through and add them to each of the original oldblogs. Here's that attempt:
switch_to_blog(oldblognumber);
$zargs = array( 'numberposts' => 1, 'category_name' => 'featured');
$zlastpost = get_posts( $zargs );
foreach($zlastpost as $post) : setup_postdata($post);
$extrapost = array();
$extrapost['post_title'] = get_the_title();
$extrapost['post_content'] = get_the_content();
$extrapost['comment_status'] = 'closed';
$extrapost['post_status'] = 'publish';
$extrapost['post_date'] = get_the_date( $d = 'Y-m-d H:i:s');
$extrapost['post_category'] = array(catidnumber);
$oldid = get_the_ID();
$thumbo = get_the_post_thumbnail($oldid);
$filename = wp_get_attachment_url( get_post_thumbnail_id($post->ID) );
switch_to_blog(68);
$post_id = wp_insert_post($extrapost);
$wp_filetype = wp_check_filetype(basename($filename), null );
$wp_upload_dir = wp_upload_dir();
$attachment = array(
'guid' => _wp_relative_upload_path( $filename ),
'post_mime_type' => $wp_filetype['type'],
'post_title' => preg_replace('/\.[^.]+$/', '', basename($filename)),
'post_content' => '',
'post_status' => 'inherit'
);
$attach_id = wp_insert_attachment( $attachment, false, $post_id );
require_once(ABSPATH . 'wp-admin/includes/image.php');
$attach_data = wp_generate_attachment_metadata( $attach_id, $filename );
update_post_meta( $post->ID, '_thumbnail_id', $attachment_id );
wp_update_attachment_metadata( $attach_id, $attach_data );
set_post_thumbnail( $post_id, $attach_id);
restore_current_blog();
wp_reset_postdata();
endforeach;
restore_current_blog();
I've tried feeding a number of things to wp_insert_attachment's $filename parameter, but that doesn't seem to be my answer. Let me know if you've got any good ideas for me!
It turns out I was barking up the wrong (or at least a slightly different) tree by using wp_insert_attachment. media_sideload_image managed to pull attachments from other blogs on the same multisite install, copy them to the aggregating blog's uploads directory, and generate thumbnails, while wp_insert_attachment was doing what it was supposed to, which just happened to not be what I wanted. I realize that this is just a slight variation on other fairly well explained uses of similar functionality, but I figured I'd post my solution here in case anyone happens to have more success applying this particular combination of solutions.
I still get the sense that I'm not doing this in the most efficient way, but it's working for now:
function switch_and_insert($srcblog, $targetcat, $fromcat) {
switch_to_blog($srcblog);
$args = array( 'numberposts' => 1, 'category_name' => $fromcat);
$flastpost = get_posts( $args );
foreach($flastpost as $post) : setup_postdata($post);
$extrapost = array();
$extrapost['post_title'] = get_the_title($post);
$extrapost['post_content'] = get_the_post_thumbnail();
$extrapost['comment_status'] = 'closed';
$extrapost['post_status'] = 'publish';
$extrapost['post_date'] = get_the_date( $d = 'Y-m-d H:i:s');
$extrapost['post_category'] = array($targetcat);
$oldid = get_the_ID();
if ( has_post_thumbnail($oldid)) {
$filename = wp_get_attachment_url( get_post_thumbnail_id($post->ID) );
}
else $filename = $forchomper; // URL of backup image
switch_to_blog($aggregator_blog_id);
$post_id = wp_insert_post($extrapost);
$wp_filetype = wp_check_filetype(basename($filename), null );
$wp_upload_dir = wp_upload_dir();
$attachment = array(
'guid' => _wp_relative_upload_path( $filename ),
'post_mime_type' => $wp_filetype['type'],
'post_title' => preg_replace('/\.[^.]+$/', '', basename($filename)),
'post_content' => '',
'post_status' => 'inherit'
);
require_once(ABSPATH . "wp-admin" . '/includes/media.php');
require_once(ABSPATH . "wp-admin" . '/includes/image.php');
require_once(ABSPATH . "wp-admin" . '/includes/file.php');
$sideloaded = media_sideload_image($filename, $post_id);
$attachments = get_children($post_id);
foreach ( $attachments as $attachment_id => $attachment );
set_post_thumbnail($post_id, $attachment_id);
restore_current_blog();
wp_reset_postdata();
endforeach;
restore_current_blog();
}
It might not be noteworthy, but nevertheless I will mention that using this method provided a very convenient opportunity to apply a placeholder image as a post thumbnail/featured image in the event that the originating post didn't have one, which is a different solution than the more widely suggested one that relies on a conditional within a theme used to display a placeholder, which doesn't actually assign it as a post's thumbnail. I realize that most of the time that is the better solution, but in my case these posts must have their own attached featured images, even if they are duplicates.
Here are a couple of the things that helped:
https://wordpress.stackexchange.com/a/19847/14351
http://old.nabble.com/Uploading-image-attachments-from-the-front-end-td26307647.html

Categories