Attach media to post WordPress hook - wordpress

I need an action to be triggered when a detached media is being attached to a post.
It seems that this behavior is handled in wp-admin/upload.php on line 76 by setting the parent of the attachment post with a DB query. There are no hooks in the file.
Is there a way to get an action triggered on this event (some low level DB write hook or whatever) in which I could get the ID of the parent post to which the attachment is being attached?

You could hook into wp_redirect and get the parent post ID from the $_REQUEST. The following is based on an answer I gave here:
add_filter( 'wp_redirect', 'so16798615_wp_redirect', 25, 1 );
function so16798615_wp_redirect( $location )
{
if( ! is_admin() )
return $location;
global $pagenow;
if( 'upload.php' == $pagenow && isset( $_REQUEST['found_post_id'] ) )
{
$parent_id = (int) $_REQUEST['found_post_id'];
if ( ! $parent_id )
return $location;
$parent = get_post( $parent_id );
// do stuff with parent
}
return $location;
}

Related

Creating a WordPress post publish button on the front end

How can I create a button in the frontend that when the user clicks on the button, the post changes from draft to published?
I use the default function to generate the shortcode but it doesn't work
In fact, the post that is currently available and in the draft status in the front form, the user clicks on the button to publish it.
function wp_publish_post( $post ) {
global $wpdb;
$post = get_post( $post );
if ( ! $post ) {
return;
}
if ( 'publish' === $post->post_status ) {
return;
}
$post_before = get_post( $post->ID );
add_shortcode('publish_post','wp_publish_post');
tanks

WPML how to add a featured image without duplicate to a translated post (wordpress)?

I translated a post using WPML.
The problem is that it doesn't add a featured image to the translated post.
It takes up too many size to duplicate images using a WPML media transltion,
so I'd like to add a featured image without duplicate to a tranlsated post (wordpress).
Would you please let me know how to solve this problem?
Thank you.
In case there is someone who needs this.
I solved the problem using the foolowing code.
add_action( 'wp_insert_post', 'my_duplicate_on_publish' );
function my_duplicate_on_publish( $post_id ) {
global $post;
// don't save for autosave
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
return $post_id;
}
// dont save for revisions
if ( isset( $post->post_type ) && $post->post_type == 'revision' ) {
return $post_id;
}
if ($post->post_type=='your-post-type') {
//we need this to avoid recursion see add_action at the end
remove_action( 'wp_insert_post', 'my_duplicate_on_publish' );
// make duplicates if the post being saved
// #1. itself is not a duplicate of another or
// #2. does not already have translations
$is_translated = apply_filters( 'wpml_element_has_translations', '', $post_id, $post->post_type );
if ( !$is_translated ) {
do_action( 'wpml_admin_make_post_duplicates', $post_id );
}
//must hook again - see remove_action further up
add_action( 'wp_insert_post', 'my_duplicate_on_publish' );
}
}

Trigger action when new post is insert in wordpress

My question is,
Is there any filter or action that trigger when new post is insert in database..?
The reason behind it is I want to add key in post meta when new post is insert from admin side.
I got Action called "save_post" but after refer link .This action trigger in created and update post.
but I only want to add meta key when post is created not at update time
You can use wp_insert_post so you will get post_id as soon as post inserted and you can then use that to add meta_key.
If you are not using wp_insert_post and want to use action then you can simply put below code :
if ( wp_is_post_revision( $post_id ) )
return;
which means that if you are updating the post, then it will return back from function.
EDITED
Method-1 to achieve it.
You can simply check with the get_post method that post is there or not.something like below:
add_action('save_post', 'check_for_post_in_database');
function check_for_post_in_database($post_id) {
//check if the post is in the database or not with get_post( $post_id ) == null
if( get_post( $post_id ) == null ) {
//your code to add meta
}
}
//You can do same thing with publish_post
Method-2 to achieve it.
add_action('publish_post', 'check_for_meta_in_database');
function check_for_meta_in_database($post_id) {
global $wpdb;
$your_meta = get_post_meta($post_id, 'meta_key', true);
if( empty( $your_meta ) && ! wp_is_post_revision( $post_id ) ) {
update_post_meta($post_id, 'meta_key', 'meta_value');
}
}
But as you said there are many meta there, this method will be bit long.
Method-3 to achieve it.
You can do as rnevius suggested which is the one even I would opt. Its like :
add_action( 'transition_post_status', 'check_transition_and_then_add_meta', 10, 3 );
function check_transition_and_then_add_meta( $new_status, $old_status, $post ) {
if ( ( 'draft' === $old_status || 'auto-draft' === $old_status ) && $new_status === 'publish' ) {
add_post_meta($post->ID, 'your_meta_key', 'your_meta_value');
}
}
or else you can do it with draft_to_publish like:
//as rnevius suggested {$old_status}_to_{$new_status}
add_action( 'draft_to_publish', 'add_meta_when_status_change' );
function add_meta_when_status_change() {
add_post_meta($post->ID, 'your_meta_key', 'your_meta_value');
}
You can refer codex for more information about post transition.
You're looking for draft_to_publish.
An {old_status}_to_{new_status} action will execute when a post transitions from {old_status} to {new_status}. The action is accompanied by the $post object.

WooCommerce inquiry if no price available

I'm helping a good friend setting up a WooCommerce shop. Since the shop is going to be bigger and the products are pretty variable and customizable we are not able to provide/configure all prizes from the beginning.
However we would like all products to be in the shop and ad an inquiry lead form in case no price is available.
Since I never programmed with WooCommerce I was wondering that is the right hook to implement such an functionality?
Had the exact same issue and couldn't find a plugin or a solution anywhere so I figured a workaround myself:
You need to edit file
/wp-content/themes/your-theme-name/woocommerce/single-product/add-to-cart/simple.php
(if it's not there just copy it from woocommerce plugin
/wp-content/plugins/woocommerce/templates/single-product/add-to-cart/simple.php)
and on line 14 where it says
if ( ! $product->is_purchasable() ) return;
you need to comment it out and write something like
if ( ! $product->is_purchasable() ) {
// put your code here
return;
}
and in the //put your code here line you can enter for example a shortcode for a form or a more complicated solution would be to put code for a button that when clicked will open up a popup form.
Still working on that ;)
Maybe too late, but I have had same issue currently.
Here is there code, Woocommerce uses to check if a product can be purchased:
https://github.com/woocommerce/woocommerce/blob/master/includes/abstracts/abstract-wc-product.php#L1404
Notice about: && '' !== $this->get_price()
/**
* Returns false if the product cannot be bought.
*
* #return bool
*/
public function is_purchasable() {
return apply_filters( 'woocommerce_is_purchasable', $this->exists() && ( 'publish' === $this->get_status() || current_user_can( 'edit_post', $this->get_id() ) ) && '' !== $this->get_price(), $this );
}
So you need to write a filter like this to override default:
add_filter( 'woocommerce_is_purchasable', function ( $is_purchasable, $product ) {
return $product->exists() && ( 'publish' === $product->get_status() || current_user_can( 'edit_post', $product->get_id() ) );
}, 10, 2 );
Try the following code snippet. You just have to put it in your functions.php. You don't need a plugin or to overwrite WooCommerce files in your child theme.
// Inquiry link if no price available
function add_inquiry_link_instead_price( $price, $product ) {
if ( '' === $product->get_price() || 0 == $product->get_price() ) :
return ''.__( 'Jetzt anfragen' ).'';
endif;
}
add_filter( 'woocommerce_get_price_html', 'add_inquiry_link_instead_price', 100, 2 );

Wordpress Custom Meta Boxes Validation

Is there any way to validate custom meta box fields without using javascript. If it doesn't validate I want to stop the post from being saved to the database.
Since the 'save_post' action is run AFTER publishing and updating, there's really no way of validating custom keys without a hackish alternative.
However, I'm thinking you can mimic the functionality you want by employing 'save_post' in the way Viral suggested, but rather than interrupt or cancel the saving process upon a validation error, you can just delete the post altogether:
add_action('save_post', 'validate_meta');
function validate_meta($post_id)
{
if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE )
return $post_id;
/*USE THIS ONLY IF YOU ARE UTILIZING NONCE FIELDS IN A CUSTOM META BOX
if ( !wp_verify_nonce( $_POST['metabox_nonce'], basename(__FILE__) ) )
return $post_id;*/
/*Use plugin_basename(__FILE__) if this is an actual plugin, rather than
a part of your theme*/
if ( 'page' == $_POST['post_type'] )
{
if ( !current_user_can( 'edit_page', $post_id ) )
return $post_id;
}
else
{
if ( !current_user_can( 'edit_post', $post_id ) )
return $post_id;
}
/*VALIDATE YOUR METADATA HERE HOWEVER YOU LIKE
if(is_valid($_POST['metadata']))
$validated = true;
else
$validated = false;
*/
if(!$validated)
wp_delete_post($post_id, true);
else
return $post_id;
}
The only thing to watch out for with this approach is that it will run upon both Publishing and Updating as well. You may want to consider adding a check to ensure that the post is deleted only for newly published posts, and updated posts are rolled back to a previous version and the invalid revision is deleted.
The wp_insert_post_data filter is what you are looking for. Something like this should do the trick:
add_filter( 'wp_insert_post_data', 'my_validation_function' );
function my_validation_function( $data ) {
// Don't want to do this on autosave
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
return $data;
if ( $data['some_key'] != 'some_value' ||
$_POST['some_meta_key'] != 'some_meta_value' ) {
$data['post_status'] = 'draft'; // or whatever status to revert to
add_filter( 'redirect_post_location', 'remove_message'); // remove the publish success message
}
return $data;
}
function remove_message( $location ) {
return remove_query_arg( 'message', $location);
}
Straight from the WP Codex # http://codex.wordpress.org/Function_Reference/add_meta_box, you call the save_post hook and specify the function that will be run to validate/save your data:
/* Do something with the data entered */
add_action('save_post', 'myplugin_save_postdata');
Then you define that function, which will automatically be passed the post id. Additionally, you can access the $_POST array to get the values in your metaboxes:
/* When the post is saved, saves our custom data */
function myplugin_save_postdata( $post_id ) {
// verify if this is an auto save routine.
// If it is our form has not been submitted, so we dont want to do anything
if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE )
return $post_id;
// verify this came from the our screen and with proper authorization,
// because save_post can be triggered at other times
if ( !wp_verify_nonce( $_POST['myplugin_noncename'], plugin_basename(__FILE__) ) )
return $post_id;
// Check permissions
if ( 'page' == $_POST['post_type'] )
{
if ( !current_user_can( 'edit_page', $post_id ) )
return $post_id;
}
else
{
if ( !current_user_can( 'edit_post', $post_id ) )
return $post_id;
}
// OK, we're authenticated: we need to find and save the data
$mydata = $_POST['myplugin_new_field'];
// Do something with $mydata
// probably using add_post_meta(), update_post_meta(), or
// a custom table (see Further Reading section below)
return $mydata;
}
All of your routines to valid data will be done within this function. In the end, you will likely save the data using something like:
update_post_meta('meta_key', 'meta_value');

Resources