When I delete one attribute and save it does not delete the variations associated with that attribute.
I really would like to delete automatically the variations associated with the attributes that i have deleted.
My situation :
I have three values of the Ship from attribute, I want to keep only China .
But when I delete US and Europe that does not delete the others variations associated with US and Europe.
Any idea as to how I can do this for each product I want to change. Many thanks https://ibb.co/G0cc1cL
add this function to you functions.php file.
function kotsh_delete_variations_with_no_parent() {
$variations = new WP_Query( array(
'post_type' => 'product_variation',
'posts_per_page' => -1
) );
if ( $variations->have_posts() ) {
while ( $variations->have_posts() ) {
$variations->the_post();
$parent = wp_get_post_parent_id( get_the_id() );
if ( false === get_post_status( $parent ) ) {
wp_delete_post( get_the_id(), true );
}
}
}
wp_reset_postdata();
}
add_action( 'init', 'kotsh_delete_variations_with_no_parent', 10 );
Related
So today, all my websites were updated to the new release of WordPress 5.9.1. Good good. However, my custom blocks in Gutenberg that are containing an image element are breaking the style of the media modal (where you can add an image directly in the post).
I started a new project, just to test if it was my theme, or the plugins, but even without any plugin (except ACF Pro) and on the Twenty Twenty-Two theme, if I add my registration code in the functions.php file of 2022 theme, I get the same problem.
Here's the register-block code:
add_action('acf/init', 'my_acf_init_block_types');
function my_acf_init_block_types() {
if( function_exists('acf_register_block_type') ) {
acf_register_block_type(array(
'name' => 'carousel',
'title' => __('Carrousel'),
'description' => __(''),
'render_template' => 'web/blocks/carousel.php',
'category' => 'custom-blocks',
'icon' => 'images-alt',
'keywords' => array( 'carousel', 'carrousel'),
'supports' => array( 'anchor' => true),
));
}
}
And I've created a Field group trying the image with the array annnnnd the one using only the URL.
What I tried:
no plugins (except ACF)
WP theme (2022)
custom theme with no functions
adding the registration code to 2022 theme (same error)
Please, help a sister our here.
I think it was cause by the 5.9.1 update
You can use this in functions.php as temporary fix
function fix_media_views_css() {
echo '<link rel="stylesheet" id="fix-media-views-css" href="'.get_bloginfo('url').'/wp-includes/css/media-views.min.css?ver=5.9.1" media="all">';
}
add_action('admin_footer', 'fix_media_views_css');
I've added that piece of code to my functions.php file (at the end, no biggy).
function acf_filter_rest_api_preload_paths( $preload_paths ) {
if ( ! get_the_ID() ) {
return $preload_paths;
}
$remove_path = '/wp/v2/' . get_post_type() . 's/' . get_the_ID() . '?context=edit';
$v1 = array_filter(
$preload_paths,
function( $url ) use ( $remove_path ) {
return $url !== $remove_path;
}
);
$remove_path = '/wp/v2/' . get_post_type() . 's/' . get_the_ID() . '/autosaves?context=edit';
return array_filter(
$v1,
function( $url ) use ( $remove_path ) {
return $url !== $remove_path;
}
);
}
add_filter( 'block_editor_rest_api_preload_paths', 'acf_filter_rest_api_preload_paths', 10, 1 );
It works perfectly like before. I've tried to downversion it to 5.9 and it worked as well, but it takes more time/effort and many mistakes can happen.
Hope it helps more than one.
ACF is aware of the issue: https://github.com/AdvancedCustomFields/acf/issues/612
Here is the temp fix, paste in your functions.php:
function acf_filter_rest_api_preload_paths( $preload_paths ) {
global $post;
$rest_path = rest_get_route_for_post( $post );
$remove_paths = array(
add_query_arg( 'context', 'edit', $rest_path ),
sprintf( '%s/autosaves?context=edit', $rest_path ),
);
return array_filter(
$preload_paths,
function( $url ) use ( $remove_paths ) {
return ! in_array( $url, $remove_paths, true );
}
);
}
add_filter( 'block_editor_rest_api_preload_paths', 'acf_filter_rest_api_preload_paths', 10, 1 );
I am trying to find a way to hide a product from the Woocommerce shop page. If the logged in user has already purchased said product.
I have already been able to block the user from purchasing again using woocommerce_is_purchasable, and woocommerce_variation_is_purchasable. But I would like to hide it all together not even shown to them in the shop page. I have been coming up empty on this one. So any help would be appreciated.
You can change the product query using the pre_get_posts action hook and then you can get current user products that they already purchased. pass all products id to post__not_in. check the below code. code will go active theme function.php file.
add_action( 'pre_get_posts', 'hide_product_from_shop_page_if_user_already_purchased', 20 );
function hide_product_from_shop_page_if_user_already_purchased( $query ) {
if ( ! $query->is_main_query() ) return;
if ( ! is_admin() && is_shop() ) {
$current_user = wp_get_current_user();
if ( 0 == $current_user->ID ) return;
$customer_orders = get_posts( array(
'numberposts' => -1,
'meta_key' => '_customer_user',
'meta_value' => $current_user->ID,
'post_type' => 'shop_order',
'post_status' => array( 'wc-processing', 'wc-completed' ),
) );
if ( ! $customer_orders ) return;
$product_ids = array();
foreach ( $customer_orders as $customer_order ) {
$order = wc_get_order( $customer_order->ID );
if( $order ){
$items = $order->get_items();
foreach ( $items as $item ) {
$product_id = $item->get_product_id();
$product_ids[] = $product_id;
}
}
}
$product_ids = array_unique( $product_ids );
$query->set( 'post__not_in', $product_ids );
}
}
Bhautik's answer is technically correct based on the question asked. Hide product if user bought before.
However as mentioned in my question I'm already disabling purchase of said products using woocommerce_is_purchasable .
Meaning the logic of what should be hidden is already in the software. Using his idea as a template I have made the answer more generic to operate off of woocommerce_is_purchasable . Meaning I only have to implement any conditional logic in that function and the shop will reflect by hiding said products (that are not purchasable).
I am posting this as a second answer in case it helps others searching this problem. But will keep his as the selected answer to the question.
add_action( 'woocommerce_product_query', 'hide_product_from_shop_page_if_user_already_purchased', 20 );
function hide_product_from_shop_page_if_user_already_purchased( $query ) {
//Get all the products in the store.
$products = wc_get_products(['limit' => -1]);
//Blank exclusion array.
$product_ids = array();
//Check each product to see if it is purchasable or not.
foreach($products as $product){
if(!$product->is_purchasable()){
//If product is not purchasable then add to exclusion array.
$product_ids[] = $product->get_id();
}
}
//Use array of id's to exclude products in the shop page.
$query->set( 'post__not_in', $product_ids );
}
i have included 2 custom columns in the metadata of media entries called 'photographer' and 'copyright'. I have included both columns in the admin view of the media library and made them sortable. But when i sort by one of them the results exclude entries with a NULL value in that column
adding custom fields to admin panel media view
//Custom columns in Media Admin view
add_filter('manage_media_columns', 'media_additional_columns', 1);
function media_additional_columns($defaults){
$defaults['photographer'] = __('Photographer');
$defaults['copyright'] = __('Copyright');
return $defaults;
}
//Fill Custom Media Admin Columns with content
add_action('manage_media_custom_column', 'media_custom_columns_attachment_id', 1, 2);
function media_custom_columns_attachment_id($column_name, $post_id){
switch ( $column_name ) {
case 'photographer':
echo get_post_meta( $post_id, 'photographer', true );
break;
case 'copyright':
echo get_post_meta( $post_id, 'copyright', true );
break;
}
}
make custom columns in admin panel media view sortable
//make custom columns sortable
//add custom columns to array sortable columns
add_filter('manage_upload_sortable_columns', 'as_add_custom_column_sortable');
function as_add_custom_column_sortable($columns) {
$columns['photographer'] = 'photographer';
$columns['copyright'] = 'copyright';
return $columns;
}
//alter the post query in case stuff gets sorted by custom columns
add_action( 'pre_get_posts', 'as_custom_column_orderby' );
function as_custom_column_orderby( $query ) {
if( ! is_admin() || ! $query->is_main_query() ) {
return;
}
switch ($query->get( 'orderby')) {
case 'photographer':
$query->set( 'orderby', 'meta_value' );
$query->set( 'meta_key', 'photographer' );
break;
case 'copyright':
$query->set( 'orderby', 'meta_value' );
$query->set( 'meta_key', 'copyright' );
break;
}
}
I want to include the entries with NULL value in the sorted table, after the entries with non-NULL values.
I have found this post that answers the same question for the Posts and for Users. I thought the answer applicable for Posts would work also for media since media are basically posts of the type attachment but it doesnt, my media library turns up completely empty.
I am just starting with php, help would be much appreciated!
alrighty i circumvented the problem by putting the code into a plugin file instead of functions.php directly and adding code that updates the values of the custom columns for all images that already exist in the media library once the plugin is activated
////update all images with default values for custom fields "Photographer" and "Copyright"
// Run the loop when the plugin is activated
register_activation_hook(__FILE__, 'as_update_my_metadata');
function as_update_my_metadata(){
$args = array(
'post_type' => 'attachment', // Only get the posts
'post_status' => 'publish' OR 'private', // Only the posts that are published
'posts_per_page' => -1 // Get every post
);
$posts = get_posts($args);
foreach ( $posts as $post ) {
// Run a loop and update every meta data
update_post_meta( $post->ID, 'photographer', 'unknown' );
update_post_meta( $post->ID, 'copyright', 'not defined' );
}
}
I have a site that has tens of thousands of orders, which I need to compare the billing and customer/user emails and show a flag if they don't match. One of the stipulations is that I'm unable to add any metadata to the orders. So my solution is to just add a custom column, and compare the emails on the fly when the orders list is rendered. That works just fine.
add_filter( 'manage_edit-shop_order_columns', 'mismatched_orders_column' );
function mismatched_orders_column( $columns ) {
$columns['mismatched'] = 'Mismatched';
return $columns;
}
add_action( 'manage_shop_order_posts_custom_column', 'mismatched_orders_column_data' );
function mismatched_orders_column_data( $column ) {
global $post;
if ( 'mismatched' === $column ) {
$order = new WC_Order( $post->ID );
$customer = $order->get_user();
$result = '';
$billing_email = strtolower ( $order->get_billing_email() );
$customer_email = '';
if ($customer) $customer_email = strtolower ( $customer->user_email );
if ( $customer && ( $billing_email != $customer_email ) ) {
$result = '<span class="mismatched-order" title="Possible order mismatch">Yes</span>';
}
echo $result;
}
}
My issue is when trying to add sorting. Because I'm not accessing any post metadata, I don't have any easy data to sort via the main query. My solution here was originally to hook into pre_get_posts, grab all the orders in a new WP_Query, then loop through them and add the ones that had mismatched emails to an array for use in post__in.
This works/worked fine on my small dev site, but throws fatal memory errors when trying to loop over any more than about 8 or 9 thousand posts (out of a total of 30-40 thousand). Increasing memory isn't really an option.
add_filter( 'manage_edit-shop_order_sortable_columns', 'mismatched_orders_column_sortable');
function mismatched_orders_column_sortable( $columns ) {
$columns['mismatched'] = 'mismatched';
return $columns;
}
add_action( 'pre_get_posts', 'mismatched_emails_posts_orderby' );
function mismatched_emails_posts_orderby( $query ) {
if( ! is_admin() || ! $query->is_main_query() ) {
return;
}
//Remove the pre_get_posts hook so we don't get stuck in a loop
add_action( 'pre_get_posts', 'mismatched_emails_posts_orderby' );
//Make sure we're only looking at our custom column
if ( 'mismatched' === $query->get( 'orderby') ) {
//Set our initial array for 'post__in'
$mismatched = array();
$orders_list = get_posts(array(
'post_type' => 'shop_order',
'posts_per_page' => -1,
'post_status' => 'any',
'fields' => 'ids'
));
//And here is our problem
foreach( $orders_list as $order_post ) :
//Get our order and customer/user object
$order_object = new WC_Order( $order_post );
$customer = $order_object->get_user();
//Check that billing and customer emails don't match, and also that we're not dealing with a guest order
if ( ( $order_object->get_billing_email() != $customer->user_email ) && $order_object->get_user() != false ) {
$mismatched[] = $order_post;
}
endforeach; wp_reset_postdata();
$query->set( 'post__in', $mismatched );
}
}
I would seriously appreciate any insight into how I could either reduce the expense of the query I'm trying to run, or an alternate approach. Again, just for clarification, adding metadata to the orders isn't an option.
Thanks!
I am wondering if you're able to help me with the following WordPress customization. We're using the WP Job Manager plugin (https://wpjobmanager.com/) and I'd need a little help with a slug/permalink edit.
In the documentation is an article available which explains the following: at the current situation links are generated as follows: domain.com/job/job-name. However, I need the following structure: domain.com/job-category/job-name.
Please check: https://wpjobmanager.com/document/tutorial-changing-the-job-slugpermalink/
The article explains this. Please check the code on: Example: Adding the category to the base URL. When I remove the 'job' in the following code, the job listings are working fine, but the rest of my website returns in a 404 error (also after saving the permalinks).
$args['rewrite']['slug'] = 'job/%category%';
To
$args['rewrite']['slug'] = '%category%';
Full code:
function job_listing_post_type_link( $permalink, $post ) {
// Abort if post is not a job
if ( $post->post_type !== 'job_listing' )
return $permalink;
// Abort early if the placeholder rewrite tag isn't in the generated URL
if ( false === strpos( $permalink, '%' ) )
return $permalink;
// Get the custom taxonomy terms in use by this post
$terms = wp_get_post_terms( $post->ID, 'job_listing_category', array( 'orderby' => 'parent', 'order' => 'ASC' ) );
if ( empty( $terms ) ) {
// If no terms are assigned to this post, use a string instead (can't leave the placeholder there)
$job_listing_category = _x( 'uncat', 'slug' );
} else {
// Replace the placeholder rewrite tag with the first term's slug
$first_term = array_shift( $terms );
$job_listing_category = $first_term->slug;
}
$find = array(
'%category%'
);
$replace = array(
$job_listing_category
);
$replace = array_map( 'sanitize_title', $replace );
$permalink = str_replace( $find, $replace, $permalink );
return $permalink;
}
add_filter( 'post_type_link', 'job_listing_post_type_link', 10, 2 );
function change_job_listing_slug( $args ) {
$args['rewrite']['slug'] = 'job/%category%';
return $args;
}
add_filter( 'register_post_type_job_listing', 'change_job_listing_slug' );
Well, I was also stuck in some type of error once. But in my case, I was creating everything my self. So I change the template accordingly.
However, In you case, I think it relates to URL Re-Writing. Please check out the following links. I hope those will help.
http://www.wpbeginner.com/plugins/how-to-change-custom-post-type-permalinks-in-wordpress/
https://codex.wordpress.org/Rewrite_API/add_rewrite_rule
https://paulund.co.uk/rewrite-urls-wordpress