Wordpress filter on adding meta? - wordpress

In wordpress, I need to program it such that anytime someone enters or updates a post meta called "start_date", a bit of code is run on what is entered before it is saved.
I need to take what is entered and convert it to a unix timestamp.
Is there a way to do this?
If not, is there a way to add the code on publish or update of the post such that it checks for that meta and updates it if needed?

Assuming you're creating the metaboxes and custom fields with your plugin, you can do the following. Otherwise, it depends on how their saving the data as it could overwrite yours.
Here's something to get you started though depending on what the case is.
add_action('save_post', 'update_the_post_meta', 100, 2);
function update_the_post_meta($post_id, $post) {
if ( defined('DOING_AJAX') && DOING_AJAX ) { return; }
if ( defined('DOING_CRON') && DOING_CRON ) { return; }
if ($post->post_type == 'revision') { return; }
if ( isset($_REQUEST['start_date']) ) :
//do your timestamp code here and save it in $timestamp
add_post_meta($post_id, 'start_date', $timestamp, true) or update_post_meta($post_id, 'start_date', $timestamp);
else :
delete_post_meta($post_id, 'start_date');
endif;
}
Right now the priority of the add_action is set to 100 (the higher the number, the less priority it has). So, if you're trying to override someone else's function, you may need to increase the priority number. Also, this is assuming the name of the input field is "start_date".

Related

Updating an ACF field after creating a Woocommerce attribute

I have a set of products (courses) that are dependent on a calendar.
The calendar is generated by a post type date which has an ACF field date_start and an associated_product
The logic is; the user creates a post-type Date which adds an attribute term to the associated product's attribute pa_dates.
I have hooked save_post and so far so good, the attribute is written to the product.
I then need to copy the date field to the term created $term_set this section doesn't produce anything. (I need this date to order the terms in my product)
Part of the problem is I have no way of interrogating the variables as this is all happening in a hook that has no way of printing output. (I have tried fwrite but with no result)
// Add terms on Date save.
function add_terms_to_date($post_ID) {
if ('date' !== get_post_type() ) {
return;
} else {
$product_id = get_field('associated_product',$post_ID);
$term_name = get_the_title($post_ID);
$taxonomy = 'pa_dates';
$term_set = wp_set_post_terms( $product_id, $term_name, $taxonomy, true );
// up to here, works fine.
// now need to identify that term ($term_set)
// Then I need to write copy the date field to its ACF field in my Date attribute
$selector = "term_date_start"; // the ACF field in the term
$date_start = get_field('date_start', $post_ID); // the date field to be copied
$value = $date_start;
// This next line caused the issue leading to the question so is commented out
// update_field($selector, $value, $term_set);
// and this line is correct
update_field($selector, $value, $taxonomy."_".$term_set);
}
}
add_action('save_post', 'add_terms_to_date');
So, complicated question, simple answer.
The last line should read;
update_field($selector, $value, $taxonomy."_".$term_set);
to avoid confusion with post IDs (RTFM) ACF has a different system for identifying terms. ($taxonomy comes from the earlier line and is pa_dates)
I have edited the post above, just in case it can provide help to someone.

How set value of existing product attribute in Wordpress?

My every product in WooCommerce has several attributes. One of them is named my-availability and I need to change its value dynamically depending on stock change and some condition logic. So when the amount of pieces on stock is changed (usually decreased by order), the value of my-availability attribute will change. It should not add any new attributes, just change the value of the existing one. I do not use product variations at all.
I am total beginner and trying to build this piece of code for few days using a lot of googling. Now I have something like this:
function changeatt( $order )
{
$items = $order->get_items();
foreach( $items as $item ) {
$value2 = get_field( "naceste", $item['product_id']); //need to get value of custom field "naceste"
$value = get_post_meta( $item['product_id'], '_stock', true ); //need to get how many pcs is on stock
if ($value == 0 && $value2 > 0)
{$avl = 'Coming soon';}
if ($value == 0 && $value2 == 0)
{ $avl = 'Not in stock';}
if ($value > 0)
{ $avl = 'In stock';}
// update_post_meta( $item['product_id'], 'my-availability', $avl );
wp_set_object_terms( $item['product_id'], $avl, 'pa_my-availability', false);
}
}
add_action( 'woocommerce_reduce_order_stock', changeatt );
This code actually creates new custom field my-availability with the correct value, but I need to save it to existing attribute named my-availability instead. What am I missing?
I found it! update_post_meta did not work for changing attributes, do not know why. wp_set_object_terms must be used instead and pa_ must be added to the name of the attribute. I have edited the code in the question to the working version. The previous not-working line has been removed by // for other beginners, who will be solving the same situation to learn from this one. It took me few days to solve this.
Now I am pretty curious, how to find out, which types of variables can be changed using update_post_meta and which types using wp_set_object_terms.

WP Rest API get post by slug with special characters (ex: !&')

I have posts with slugs with special characters. One of them is the following:
http://localhost/wp-json/wp/v2/posts?slug=my-post!
Unfortunately, WP REST API not showing the content since it has (!) within the slug.
Is there any solution you guys would recommend?
I have found the solution (at least for my case), not sure if it'll work for you but may indicate you the way to go. We need to tap into the function used to sanitize the slugs, as I said in my comment, by default is wp_parse_slug_list. Looking at the code the function that actually sanitizes the slug is sanitize_title.
Looking at the source code, wp_parse_slug_list calls sanitize_title with only one argument, which means that the context used is save. This means that, for posts that were already saved without being sanitized by this function, the slug won't match and the post will be inaccessible through the API. The solution is to change the sanitizing function slightly by adding a filter:
add_filter('rest_post_collection_params', function($query_params) {
$query_params['slug']['sanitize_callback'] = 'sanitize_rest_api_slug';
return $query_params;
}, 20, 1);
function sanitize_rest_api_slug( $list ) {
if ( ! is_array( $list ) ) {
$list = preg_split( '/[\s,]+/', $list );
}
foreach ( $list as $key => $value ) {
$list[ $key ] = sanitize_title( $value, '', 'query' );
}
return array_unique( $list );
}
The filter is actually being applied on the function get_collection_params() on the class-wp-rest-posts-controller class, but if you look at the source code, the filter has a variable depending on the post_type, so if you have another special kind of posts defined (besides post) you need to add/change a filter for that kind as well.
I hope this helps somebody else like me, even if it's too late for your issue.

How to make Woocommerce checkout page fields to read-only

For edit woocommerce (WordPressss plugin) account page fields and make to read-only, easy edit woocommerce/templates/myaccount/form-edit-account.php file and only add read-only to end of fields tags end (sorry my English and programming is not professional and good)
But for edit woocommerce checkout page fields and make one, or two and more fields, for example, email field, to read-only, cannot do the previous way
Please help me to do it, I have not idea.
It would be much better if, teach me to do it from functions.php easy and better and durable way (if it is possible).
thank you again
You can use the following code in your theme's "function.php" file.
add_action('woocommerce_checkout_fields','customization_readonly_billing_fields',10,1);
function customization_readonly_billing_fields($checkout_fields){
$current_user = wp_get_current_user();;
$user_id = $current_user->ID;
foreach ( $checkout_fields['billing'] as $key => $field ){
if($key == 'billing_address_1' || $key == 'billing_address_2'){
$key_value = get_user_meta($user_id, $key, true);
if( strlen($key_value)>0){
$checkout_fields['billing'][$key]['custom_attributes'] = array('readonly'=>'readonly');
}
}
}
return $checkout_fields;
}
This function will check if the address fields have value (i.e. if the address is specified), and if it has value, makes the field/s readonly. Else keeps the fields open to add data for the user. You can apply the same concept for each required fields.
Hope this helps.
Thank You!
very thank you for answer mr amritosh pandey
this code work correctly
for only email field , remove:
if($key == 'billing_address_1' || $key == 'billing_address_2'){
and i change to
if($key == 'billing_email'){
and work perfect and correctly
my new queston is > if use for two field , example: mobile (tel) and email or more field
Should i repeat all codes?
from add_action to return $checkout_fields; }
or can repeat
if($key line 2 or 3 or more?
example:
...
...
if($key == 'billing_email'){
if($key == 'billing_phone'){
if($key == 'billing_postcode'){
...
...
thank you

wordpress remove post status count from cms

I want to remove the post status count from WordPress edit.php.
My WordPress CMS have more than 500,000 posts. The publish count is loaded every time you open the page. The following query is fired every time.
This makes my Wordpress CMS loading very slow.
SELECT post_status, COUNT( * ) AS num_posts FROM wp_posts WHERE post_type = 'post' GROUP BY post_status
By tracing the code, I've worked up the only solution that I can see.
The filter bulk_post_updated_messages is ONLY called on the edit.php screen.
The counts are not calculated (in class-wp-posts-list-table.php, get_views method) if the global variable $locked_post_status is not empty.
By gluing these two pieces of information together, I've got a solution that you can use by dropping it into your theme's functions.php file:
// Hook this filter, only called on the `edit.php` screen.
// It's not the "correct" filter, but it's the only one we can leverage
// so we're hijacking it a bit.
add_filter('bulk_post_updated_messages', 'suppress_counts', 10, 2);
// We need to let the function "pass through" the intended filter content, so accept the variable $bulk_messages
function suppress_counts($bulk_messages) {
// If the GET "post_type" is not set, then it's the "posts" type
$post_type = (isset($_GET['post_type'])) ? $_GET['post_type'] : 'post';
// List any post types you would like to KEEP counts for in this array
$exclude_post_types = array('page');
// Global in the variable so we can modify it
global $locked_post_status;
// If the post type is not in the "Exclude" list, then set the $locked variable
if ( ! in_array($post_type, $exclude_post_types)) {
$locked_post_status = TRUE;
}
// Don't forget to return this so the filtered content still displays!
return $bulk_messages;
}
i came up with this solution.
//Disable Article Counter - query runs for about 1-2 seconds
add_filter('admin_init', function () {
foreach (get_post_types() as $type) {
$cache_key = _count_posts_cache_key($type, "readable");
$counts = array_fill_keys(get_post_stati(), 1);
wp_cache_set($cache_key, (object)$counts, 'counts');
}
}, -1);
add_action('admin_head', function () {
$css = '<style>';
$css .= '.subsubsub a .count { display: none; }';
$css .= '</style>';
echo $css;
});
the post counter uses the wp-cache, the idea behind this approach is, to prefill the cache with the "correct" object containing 1's (0 would skip the status from being clickable) - at the earliest moment.
it results in all stati being displayed - with 1's and the query is not run et-all
in addition it returns a css snippet to hide the (1)

Resources