I have a wordpress photo blog that reposts images from instagram for me.
The posts are created from an IFTTT applet through XML-RPC.
For some reason duplicate posts are often created (this is a bug thats been around for years and ifttt dont seem to care about it).
To get around this, I create each post with a title containing the unique instagram ID of the photo. I would like to use this to compare the new post_title to existing ones.
I have tried hooking into transition_post_status, this works for normal posting but all posts coming though XML-RPC are still published. They seem to bypass that action.
Can I hook into XML-RPC when it creates the post and prevent it if it has an already existing post_title?
Here is the code that works for normal posts:
add_action('transition_post_status', 'check_for_duplicates', 10, 3);
function check_for_duplicates($new_status, $old_status, $post) {
if('publish' === $new_status && 'publish' !== $old_status && $post->post_type === 'post') {
global $post;
global $wpdb ;
$title = $post->post_title;
$post_id = $post->ID ;
$wtitlequery = "SELECT post_title FROM $wpdb->posts WHERE post_status = 'publish' AND post_type = 'post' AND post_title = '{$title}' AND ID != {$post_id} " ;
$wresults = $wpdb->get_results( $wtitlequery) ;
if ( $wresults ) {
$error_message = 'This title is already used. Please choose another';
add_settings_error('post_has_links', '', $error_message, 'error');
settings_errors( 'post_has_links' );
$post->post_status = 'draft';
wp_update_post($post);
wp_die( $error_message );
return;
}
//return $messages;
}
}
Related
I have this is WordPress Post editing Url:
https://example.com/wp-admin/post.php?post=ID&action=edit
and I want to change it to Slug Not the ID Like This:
https://example.com/wp-admin/post.php?post=Slug&action=edit
I was trying to edit the post with this Url but is not working:
https://example.com/wp-admin/post.php?post=MyPostSlug&action=edit
In order to change the edit post link structure, you can use the get_edit_post_link filter like so:
add_filter( 'get_edit_post_link', 'so_73914075_get_edit_post_link', 10, 3);
function so_73914075_get_edit_post_link($link, $post_id, $context) {
$post = get_post( $post_id );
if ( ! in_array( $post->post_type, array( 'post', 'page' ) ) ) {
return $link;
}
$post_type_object = get_post_type_object( $post->post_type );
if ( 'revision' === $post->post_type ) {
$action = '';
} elseif ( 'display' === $context ) {
$action = '&action=edit';
} else {
$action = '&action=edit';
}
if ( 'display' === $context ) {
$post_type = '&post-type=' . $post->post_type;
} else {
$post_type = '&post-type=' . $post->post_type;
}
$custom_edit_link = str_replace( '?post=%d', '?post-name=%s', $post_type_object->_edit_link );
return admin_url( sprintf( $custom_edit_link . $action . $post_type, $post->post_name ) );
}
This will change the edit links for regular posts and pages to something like this:
https://example.com/wp-admin/post.php?post-name=the-post-slug&action=edit&post-type=post
WARNING: make sure you limit this to only the post types you need to change the URL for. Making this change global will almost surely
have unintended effects over other plugins
However, making the admin panel actually load the edit screen is not that easy.
Looking at the source code of the wp-admin/post.php file, you will see that there is no way to hook into the flow and populate the $post_id variable with the post id matching the slug you are sending through.
That means you have 2 options:
RECOMMENDED Update the edit link to whatever format you want and then create an admin redirect function that pulls the slug from the initial URL and redirects to the actual edit page with the ?post=%d in it.
NOT RECOMMENDED Create a new admin edit page that will understand your URL structure and include the wp-admin/post.php after the code that pulls the $post_id based on the slug.
The 2nd method might come with lots of extra code you need to write to cover all the cases and all the instances a post reaches the post.php in the admin panel
I want to make something similar to what Techcrunch have on their site. For now I use wordpress plugin that mark posts as new and think to modified it to achieve similar functionality but the plugin won't work for ajax loading.
What I want to make is when user open new post, automatically after he returns to the front page, title and excerpt of the post to be color faded. How to make this with setting cookie and make it to work for title and excerpt on any page (for post list, grids etc.), instead of single post page. And also I need this to work when new posts are loaded with ajax.
I tried this function and It's work ok, but now I need text label to change to Old after user open the post, and then to inject some css to the title. Also, this is not perfect, because I want all posts to be New on first visit, an then to change to Old after user open them.
function wpb_lastvisit_set_cookie() {
if ( ! is_admin() && ! isset( $_COOKIE['lastvisit'] ) ) {
setcookie( 'lastvisit', $current, time() + 3600 * 24 * 100, COOKIEPATH, COOKIE_DOMAIN, false );
}
}
add_action( 'init', 'wpb_lastvisit_set_cookie');
function wpb_lastvisit_the_title ( $title, $id ) {
if ( !in_the_loop() || is_singular() || get_post_type( $id ) == 'page' ) return $title;
// if no cookie then just return the title
if ( !isset($_COOKIE['lastvisit']) || $_COOKIE['lastvisit'] == '' ) return $title;
$lastvisit = $_COOKIE['lastvisit'];
$publish_date = get_post_time( 'U', true, $id );
if ($publish_date > $lastvisit) $title .= ' New';
if ($publish_date < $lastvisit) $title .= ' Old';
return $title;
}
add_filter( 'the_title', 'wpb_lastvisit_the_title', 10, 2);
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.
I've looked through Woocommerce API Docs to see if there's any way to manipulate the product after it gets inserted in the admin backend of Wordpress but couldn't find any. Maybe I missed it?
I need to pick product data and send it to an external API, and obviously, handle it on update and delete...
Is there any way/hook I can use?
This goes more into what I want. Taken from this answer in WP forum. Thanks to the author
add_action('transition_post_status', 'wpse_110037_new_posts', 10, 3);
function wpse_110037_new_posts($new_status, $old_status, $post) {
if(
$old_status != 'publish'
&& $new_status == 'publish'
&& !empty($post->ID)
&& in_array( $post->post_type,
array( 'product')
)
) {
//add some cde here
}
}
If You add a new product in woocommerce then send product_id
add_action('draft_to_publish','my_product_update');
function my_product_update( $post ) {
if($post->post_type == "product"){
$pid=$post->ID;
//your code
}
}
i try to realize the following: posts with a custom post type should be password-protected by default
i found this which works great
https://wordpress.stackexchange.com/questions/4952/forcing-all-posts-associated-with-a-custom-post-type-to-be-private
but i dont want the posts to be private so i chanced
$post->post_status = 'private';
$post->post_password = 'some_default_password';
to
$post->post_status = 'published';
$post->post_password = 'some_default_password';
but then there is no password protection
how can i get this done?
The following code does this, but it only works when a new post (post_type) is created.
If we don't check for empty($data['post_name']), which indicates that a new post is being created, it locks all posts with the some_default_password password.
Code based in this WordPress StackExchange Q&A.
add_filter( 'wp_insert_post_data' , 'so_13517851_filter_handler' , '99', 2 );
function so_13517851_filter_handler( $data , $postarr )
{
// creating new post and correct post_type
if( empty( $data['post_name'] ) && 'post' == $postarr['post_type'] )
$data[ 'post_password' ] = 'some_default_password';
return $data;
}