I have Suppliers which have their own products. WP backend is almost redesigned and there I have a page(with form) where 'admin' can add new supplier and I need to create unique a reference number for each supplier when form will be submitted.
Plus, I have a "Sort by" dropdown and one of the sorting options is by "Reference number".
At first, I thought to use the POST ID as reference number, but don't think that this can be best solution, as POST IDs will be different when some posts will be removed. Also I was thinking to use uniqid() function with some digit limit and only digits.
What is best to reach this? Any ideas?
You can specify a new custom meta field for (i.e. supplier_id) and create a function which ensure that this supplier_id is unique. This function will be executed every time when a supplier form submitted.
The action hook save_post is triggered whenever a post or page is created or updated. So we can use it for this purpose.
From the documentation:
save_post is an action triggered whenever a post or page is created or updated, which could be from an import, post/page edit form, xmlrpc, or post by email. The data for the post is stored in $_POST, $_GET or the global $post_data, depending on how the post was edited. For example, quick edits use $_POST.
Since this action is triggered right after the post has been saved, you can easily access this post object by using get_post($post_id)
Example:
function save_supplier_id( $post_id, $post, $update ) {
$post_type = get_post_type($post_id);
if ( "supplier" != $post_type ) return;
if ( isset( $_POST['supplier_id'] ) ) {
$my_supplier_id = $_POST['supplier_id'];
if ( ! is_int( $my_supplier_id ) ) $my_supplier_id = 1;
$all_other_suppliers = get_posts(array(
'posts_per_page' => -1,
'post_type' => 'supplier',
'post__not_in' => array( $post_id )
));
$all_other_ids = array_map( function( $supplier ) { return $supplier->ID; }, all_other_suppliers );
if ( count( $all_other_ids ) && in_array( $my_supplier_id, $all_other_ids ) ) {
// ID is already in use by another supplier, let's create an new one
$my_supplier_id = max( $all_other_ids ) + 1;
}
update_post_meta( $post_id, 'supplier_id', $my_supplier_id ) );
}
}
add_action( 'save_post', 'save_supplier_id', 10, 3 );
Explantion:
The format for supplier_idis simple a consecutive number. If the provided id is not an integer, we set it to 1. Now we get all other supplier id's and check if the give id no occur twice. If so, the we get the max id and increase it by 1.
Related
I've created a form in frontend part , which users can add vehicle listings and all related vehicle information .
I've created a taxonomy called "vehicle_make" and inside that taxonomy I've added categories like this from backend .
Audi
A5
A7
Mercedes
e320
s500
So user have to select a Make first then Model number will show up. Which I managed to do this and can get both Make $_POST slug value and Model $_POST slug value without a problem .
Now after I check user $_POST , I can save all other information , I can set the Make "AUDI" as term , but cannot set "A5" or "A7" as child of that term .
I've tried this code ..
<pre>
if ( isset( $_POST['submitted'] ) && isset( $_POST['hidden'] ) && wp_verify_nonce( $_POST['hidden'], 'hidden' ) ) {
if ( trim( $_POST['listing_vehicle_make'] ) != '' )
// This will store Vehicle Make Slug
$listing_vehicle_make_slug = $_POST['listing_vehicle_make'];
if ( trim( $_POST['listing_vehicle_model'] ) != '' )
// This will store vehicle model slug
$listing_vehicle_model_slug = $_POST['listing_vehicle_model'];
$post = array(
'post_title' => wp_strip_all_tags( $listing_title ),
'post_content' => $listing_description, // Didn't add the code
'post_status' => 'pending', // Didn't add the code
'post_type' => 'vehicles' // Didn't add the code
);
$post_id = wp_insert_post( $post );
wp_set_object_terms( $post_id, $listing_vehicle_make_slug , 'vehicle_make');
</pre>
I've googled for many hours now and couldn't find something that I thought it would help me .
If anyone can contribute it would help me a lot guys .
Thank you .
Yes, the wp_set_object_terms function is very tricky as it can returns error for many reasons and pretty hard to debug from my experience.
However you can try a few things to make it work, first take a look on the returned value :
$set_terms = wp_set_object_terms( $post_id, $listing_vehicle_make_slug , 'vehicle_make');
print_r($set_terms);
So you can understand what's the error.
Another advice, which we actually use a lot (I'm creating frontend exclusive WP theme) is to set the terms by ID and not by slug. It'll work much more easily.
Here is the idea :
// We get the term's object :
$type_catgeory_object = get_term_by( 'slug', $listing_vehicle_make_slug, 'vehicle_make');
// If we find something :
if($type_catgeory_object != false){
// Get its id :
$term_id = $type_catgeory_object->id;
// Add it :
$value_set = wp_set_post_terms( $post_id, array($term_id), 'vehicle_make');
}
More details can be found on the doc : https://codex.wordpress.org/Function_Reference/wp_set_post_terms
We have an in-house WordPress plugin that creates content using a custom-post-type. Essentially, the content created is, for all intents and purposes, identical to WordPress 'Pages'.
The idea is that we add these custom 'pages' - via our plugin - and then deploy/update them for whomever is using the plugin. We've used our plugin to create a series of these pages, but the question is how to port this custom content with the plugin.
Initially we were thinking that since our posts have a custom post-type, we can easily identify them in the DB. In fact, we use that to remove our custom content when uninstalling the plugin.
But how do we do the inverse? Ideally we'd like to update the plugin, and with it, any custom content that we've added or modified.
Originally we were thinking of just using MySQL scripts to add this custom post content, but after a bit of research, this doesn't seem like the right way to do it.
I know WordPress has a wp_insert_post() function, but I'm just not sure of how it all fits together.
Ideally, the answer would be an overview of the process for updating our custom content. For instance, should there be a function in our plugin that, upon installation, looks for a sql file and creates new posts from it?
Thanks!
If I understand this correctly and you are trying to keep content sync'ed across multiple installations via plugin updates you will need to create a unique ID for all of your content. When you do updates programatically you are updating by the post ID but each installation will have different post IDs. You could use a post meta field to give each post a unique ID specific to your plugin. You can then query the posts based on your unique meta field.
I would code the plugin so it checks to see if there is a post with your unique ID. If it is not found then you insert a new post. If it is found then you update the post.
Let's say you have created your first piece of content and it's unique id is going to be jgohil_1. Your plugin might use something like the following to check for that unique id and then update or insert depending on if it exists.
<?php
// our meta key/value pair for our unique id
$meta_key = 'jgohil_unique_id';
$meta_value = 'jgohil_1';
// set our new content
$new_content = 'The new content here';
$new_title = 'The new title here';
// check the database to see if we have created the post already by querying for our unique id
global $wpdb;
$sql = $wpdb->prepare (
"SELECT post_id
FROM $wpdb->postmeta
WHERE meta_key = %s
AND meta_value = %s",
$meta_key,
$meta_value
);
$post_id = $wpdb->get_var( $sql );
// if we got a post id then update else insert
if ( $post_id ) {
// set up the data for updating
$data = array(
'ID' => $post_id,
'post_content' => $new_content,
'post_title' => $new_title,
);
// update the post
$updated = wp_update_post( $data );
if ( is_wp_error( $updated ) ) {
// do some error handling here
}
} else {
$data = array(
'post_title' => $new_title,
'post_content' => $new_content
'post_type' => 'your_custom_post_type'
);
$post_id = wp_insert_post( $data );
// if the insert worked give the post the unique meta id
if ( ! is_wp_error( $post_id ) && $post_id !== 0 ) {
update_post_meta( $post_id, $meta_key, $meta_value );
} else {
// do some error handling here
}
}
If you need to handle multiple pieces of content at once you would want to use a loop and change the meta value each time.
I want to make a notification bar in my Wordpress website, that will be displayed when there is a new post published. Unfortunately, I have some problems with getting the code work.
GOAL
What the goal is, is to let the user know that there are new posts available for them on the website with a notification bar. So the code should check if the amount of posts is increased. If yes, I want to show the notification bar on the website for two days.
THE PROBLEM
The following code will only outputs the total number of posts from each post type that I have specified in the $post_types array. The if statement doesn’t work correctly. When I publish a new post, delete it and post another, it will not update the number in the database. Only if I post after I delete an older one, the value will increase.
MY CODE
The code below will now only echos the post type name and number of posts.
$args = array(
'public' => true,
'_builtin' => false
);
$post_types = array( 'post', 'roosters', 'downloads', 'reglements', 'alv' );
foreach ( $post_types as $post_type ) {
// variable
$postCountTotal = wp_count_posts( $post_type )->publish;
echo '<strong>' . $post_type . '</strong>';
echo ' has total posts of : ' . $postCountTotal;
echo '<br>';
// First read the previous post count value from the databse so we can compare the old value with the new one
// EDIT: use 0 as the default value if no data in database - first run
$previousCount = get_option( 'post_count_total', 0 );
if ( $postCountTotal != $previousCount ) {
//echo 'New post detected';
update_option( 'post_count_total', $postCountTotal );
} elseif ( '' == $postCountTotal && $previousCount ) {
delete_option( 'post_count_total', $previousCount );
}
}
echo $postCountTotal;
Counting posts to determine if there is a new post is wasting resources and not accurate as a transition in post status can influence the count. For example, as you said, if a post is deleted and a new one is published, the count will stay the same
To make this work, we need to follow the following worksflow
WORKSFLOW
We need to determine when a post is published. This can be done via the transition_post_status action hook. This hook is fired every time a post's status is changed. Even if a post is updated, it's status is changed.
We should only do something when a new post is published, so we need to check the post's status before and after it is published ( the 'new' status here does not work as I have expected it to work, so I scrapped that idea).
Next will be to save the new post object in the wp_options table where we can get it later in a template and use it to display the notification bar. The functions to use here would be add_option() to create our option if it does not exist and update_option() if the option already exist.
The post object is now saved in the wp_options table. We must now retrieve that option in an function or template file. We will use get_option(). From the post object saved we will need to get the post_date_gmt in order to use it for comaprison and we need to determine the exact time 2 days later
We also need the current time which we can get with current_time()
In the final stretch, we can now compare the dates and if the dates we are comparing is less than two days, we need to make things happen, show the notification bar, if the comparison is more than two days, we either shows nothing or something else
THE CODE
Here is the final code. I have commented it well so that you can follow it
In your functions.php, add the following
add_action( 'transition_post_status', function ( $new_status, $old_status, $post )
{
//Check if our post status then execute our code
if ( $new_status == 'publish' && $old_status != 'publish' ) {
if ( get_option( 'new_post_notification' ) !== false ) {
// The option already exists, so we just update it.
update_option( 'new_post_notification', $post );
} else {
add_option( 'new_post_notification', $post );
}
}
}, 10, 3 );
Now, in your template or in a custom function if you wish, add the following
// Get the new_post_notification which holds the newest post
$notification = get_option( 'new_post_notification' );
if( false != $notification ) {
//Get the post's gmt date. This can be changed to post_date
$post_date = strtotime( $notification->post_date_gmt );
//Get the current gmt time
$todays_date = current_time( 'timestamp', true );
//Set the expiry time to two days after the posts is published
$expiry_date = strtotime('+2 day', $post_date);
if( $expiry_date > $todays_date ) {
// Display your notification if two days has not been passed
}
}
There is built-in WP function for that:
<?php
$count_posts = wp_count_posts();
?>
Good documentation available on the WP Codex:
http://codex.wordpress.org/Function_Reference/wp_count_posts
You should be able to simplify your code if you only want the total of all posts.
I Needed to count the posts in the current language. Here's my code:
$allpost_arg = array(
'numberposts' => -1,
'post_type' => 'post',
'suppress_filters' => 0,
);
$allposts = get_posts( $allpost_arg );
if($allposts){
$count_the_posts = 0;
foreach ($allposts as $allpost){
$count_the_posts++;
}
}
echo $count_the_posts;
Copy and paste the following code to your theme’s functions.php file or a site-specific plugin to create a shortcode:
function wpb_total_posts() {
$total = wp_count_posts()->publish;
return $total;
}
add_shortcode('total_posts','wpb_total_posts');
Now you can use the shortcode [total_posts] to display the total number of posts in any posts, pages, or sidebar widgets.
I am using WordPress's Advanced Custom Fields 5 plugin to create a front-end form. I would like to save the post title as one of the fields on my form. For example, one of my form fields is 'name' so I would like the post title to be 'John Smith'.
Looking at the ACF documentation it gives example code (copied below) where pre_save_post can be hooked into achieve this. Hoewver, I have included this function and the title still fails to save.
Any ideas what I am doing wrong?
Here is the code:
function my_pre_save_post( $post_id )
{
// check if this is to be a new post
if( $post_id != 'new' )
{
return $post_id
}
// Create a new post
$post = array(
'post_status' => 'draft' ,
'post_title' => $_POST['fields']['field_123'] ,
'post_type' => 'post' ,
);
// insert the post
$post_id = wp_insert_post( $post );
// return the new ID
return $post_id;
}
add_filter('acf/pre_save_post' , 'my_pre_save_post', 10, 1 );
I am using exactly the same method and it works fine.
Just a note that field_123 in your example is not the user defined field name in the wp back end but its actually the field name assigned in the meta_key value in the wp_postmeta table of you db.
Trying to recursively select database fields based on parent IDs of current selection in a WordPress environment.
On the WordPress side:
I'm doing a pre_get_posts filter to retrieve only the posts associated with a user meta. This was simple, until I realized that these posts could have parents and that would break the interface. Answers involving fixing the WP_List_Table sorting algorithm to allow children to be re-sorted hierarchically may be accepted. Without including parents, the table looks like this:
The meta query looks like this:
// pre_get_posts
$meta_query = $query->get('meta_query');
$meta_query[] = array(
'key' => '_my_meta_key',
'value' => get_user_meta( $user_id, '_my_meta_key' ),
);
$query->set('meta_query', $meta_query );
On the MySQL side, adding the parents to this query would work just as well. As it stands, the query above works like the first select clause of the SQL fiddle here:
SQL Fiddle
A) In my limited SQL knowledge, I haven't figured out how to use the first query's id column as a parameter. Here, I've copy and pasted the entire thing to use as an IN parameter, which runs the query twice. Is there a way to alias the first query to use the id field in the second query?
B) How can I also include the parents of the parents (and so on) returned in the second SELECT statement?
I ended up manually adding the parents back into the result after wp_query is parsed. So far, I haven't run into any issues. It's not exactly what I wanted, as it produces extra (not too many in this case) and thought there might be a more efficient way, but it is what it is. I'll leave this open a while in case anyone comes up with anything better.
Note that since the user cannot edit these posts, they are not editable (awesome!)
Example code:
// users must see parent pages on the Edit screen
// even when they can't edit them
// to preserve hierarchy
add_action( 'the_posts', 'add_post_parents_not_in_meta_query'), 10, 2 );
function add_post_parents_not_in_meta_query( $posts, $query ) {
// only on pages with screen
if ( ! function_exists( 'get_current_screen' ) )
return $posts;
$screen = get_current_screen();
// only on edit screen
if ( $screen->base !== 'edit')
return $posts;
// only during main query
if ( ! $query->is_main_query() )
return;
// get an array of found IDs
$post_ids = wp_list_pluck( $posts, 'ID' );
foreach( $posts as $post ) {
// check to see if exists, and if we already got this post
while ( ! empty( $post->post_parent ) && ! in_array( $post->post_parent, $post_ids ) ) {
$post = get_post( $post->post_parent );
if ( ! empty( $post ) ) {
$posts[] = $post;
$post_ids[] = $post->ID;
}
}
}
return $posts;
}
Result: