I've seen multiple answers to how to move or remove all custom attributes and there is documentation on how to remove boilerplate attributes like dimension and SKU, but I still can't seem to find a snippet, filter or hook detailing how to go about removing a single specific "custom" attribute.
In our case, the custom attribute we have in use is useful for backend reasons, but we'd rather not show it on the frontend. I'm aware of the tick-box in product data for attributes while in admin making an attribute not visible, but I'm handling over 2,000 products...it just wouldn't be a practical approach to tick it for each one.
(EDIT)
I was finally able to source an example on how to do this.
#helgatheviking hit upon the base of coding needed to make this happen.
function my_attribute_hider ( $attributes ) {
if ( isset( $attributes['pa_attribute-name'] ) ){
unset( $attributes['pa_attribute-name'] );
}
return $attributes;
}
add_filter( 'woocommerce_get_product_attributes', 'my_attribute_hider' );
Be sure to replace attribute-name w/ your attribute's unique slug.
I almost missed the answer that I was looking for because the author has posted it on the question post itself. So I am posting it here.
function my_attribute_hider ( $attributes ) {
if ( isset( $attributes['pa_attribute-name'] ) ){
unset( $attributes['pa_attribute-name'] );
}
return $attributes;
}
add_filter( 'woocommerce_get_product_attributes', 'my_attribute_hider' );
Note: It will not remove the attribute itself, it will just hide it from the product pages. It will just ignore it.
Related
I'm figuring out a filter but can't be figured :)
Just want to change PrimaryImageOfPage value with an og:image value in CollectionPage for Taxonomies.
It may be that I have to use woocommerce_structured_data_product to filter here and look for the image $markup['image'] = $image;
I have created some filters, but it isn't woocommerce_structured_data_product I guess.
One of them was like that but it... nah.
add_filter( 'woocommerce_structured_data_product', function( $markup ) {
$markup['image'] = ('rank_math/opengraph/{$network}/image');
return $markup;
});
What am I doing wrong? I have been doing this whole day -_-
If You inspect the code of the class WC_Structured_Data, You would see that woocommerce_structured_data_product filter is executed inside function generate_product_data
WC Complete Source of the class WC_Structured_Data : https://github.com/woocommerce/woocommerce/blob/b88b868ab8919b7c854173098b7d6d4ab227f9ee/includes/class-wc-structured-data.php
$this->set_data( apply_filters( 'woocommerce_structured_data_product', $markup, $product ) );
And generate_product_data function is executed on action woocommerce_single_product_summary
add_action( 'woocommerce_single_product_summary', array( $this, 'generate_product_data' ), 60 );
So, your code would work on product single page only and not archive/list pages, such as the taxonomy page.
The feature you want to achieve is not feasible out of the box in WC, You will need to customize yourself.
Logically, structured data on a single product page is feasible due to the fact there is only one product and product information is available, on the other hand, product list has more than one product (you might need to consider like you want to show details of first product) so it is ambiguous and not feasible out of the box for WC.
I have several custom page templates in my theme. But I want to hide a few with a plugin, and only show the custom home page template on the page that has been set as the front page "is_front_page" or "is_home". This is what I am using in my plugin to stop some of the page templates from showing up.
This is for a large multisite where there are two tiers of sites, one gets the full set of features, and the other a stunted set. I have everything working as I need except for this.
add_filter( 'theme_page_templates', 'je_remove_page_template' );
function je_remove_page_template( $pages_templates ) {
unset( $pages_templates['page-topimage.php'] );
unset( $pages_templates['page-home.php'] );
return $pages_templates;
}
The code above works totally fine, but I need a conditional in there to show the page-home.php when the page has been set to the home page. I have tried this code, but it doesn't work.
if ( is_front_page() ) :
add_filter( 'theme_page_templates', 'je_remove_page_template' );
function je_remove_page_template( $pages_templates ) {
unset( $pages_templates['page-topimage.php'] );
return $pages_templates;
}
else :
function je_remove_page_template( $pages_templates ) {
unset( $pages_templates['page-topimage.php'] );
unset( $pages_templates['page-home.php'] );
return $pages_templates;
}
endif;
Any ideas on how I can get this to work?
A few things:
One, it appears you've only added the add_filter call to the is_front_page()'s true condition, that's probably part of it.
Second, you should not be defining and/or redefining functions inside if statements!
Third, for WordPress specifically, with it's Action Hook and Filter system, it's generally considered a best practice to add the filters and actions at all times, and run if/else or abort type statements inside the function to allow for easier extensibility.
Edit:
Based on some clarification, I understand a bit better. You need to get the ID of the page that's set to the front page, which is stored as an option named page_on_front in the options table. The is_front_page() function will only work in the scope of the current $wp_query loop.
I think this would solve it for you. Run the je_remove_page_template function on the theme_page_templates filter, and check the current page's ID against the one stored in the page_on_front option:
add_filter( 'theme_page_templates', 'je_remove_page_template' );
function je_remove_page_template( $pages_templates ){
unset( $pages_templates['page-topimage.php'] );
$home_page_id = absint( get_option( 'page_on_front' ) );
$this_page_id = get_the_ID();
// If this isn't the home page, remove `page-home`
if( $this_page_id != $home_page_id ){
unset( $pages_templates['page-home.php'] );
}
return $pages_templates;
}
Also of note would be that is_front_page() is different than is_home() - make sure you're using the correct one! (I believe you are, as generally IFP is what people want)
I added an additional field to my comment section of my wordpress page with the help of a little plugin, based on a tutorial https://www.smashingmagazine.com/2012/05/adding-custom-fields-in-wordpress-comment-form/.
It's only one field I need (ZIP Code).
The plugin works fine, but it adds the custom field on every page. I just want it on one specific page.
I tried to wrap all the plugin code into one function that loads on the specific page:
add_action('template_redirect', 'load-on-certain-page');
function load-on-certain-page(){
if ( is_page(23) ) {
//Complete Plugin Code
}
}
Basically that works, but the check for the empty field isn't working anymore.
add_filter( 'preprocess_comment', 'verify_comment_meta_data' );
function verify_comment_meta_data( $commentdata ) {
if (empty( $_POST['title'] ) )
wp_die( __( 'Fehler: Bitte geben Sie Ihre Postleitzahl ein.' ) );
return $commentdata;
}
If I exclude the field check from my load-on-certain-page() function it checks the field everywhere so thats no solution. I also tried to add an additional condition to the if-statement (is_page()), but that does not work, too.
Can you point me into the right direction how to make my plugin functions work only on that certain page? And what "best practise" is to do it?
Thanks!
You can can possibly add an if/else statement to only show the field on that specific page...
if ( $post->ID === 23 ) {
// Input for zip code on page 23
} else {
// No input for zip code
}
Finally I got it.
The problem is, that is_page() etc. didn't work for the "preprocess_comment" filter.
But you can check the page ID the comment will be assigned to by using:
$post_id = $commentdata['comment_post_ID'];
I want to hook into the save_post function, find out what category the post is in, and then assign a different page template for posts in each category. I've tried about 30 different versions of this with no luck. Will someone please help point me in the right direction?
add_action( 'save_post', 'assign_custom_template' );
function assign_custom_template($post_id) {
$category = get_the_category($post_id);
$cat_id = $category->cat_ID;
if( $cat_id == 1 ) {
update_post_meta($post_id, "_wp_page_template", "template1.php");
}
if( $cat_id == 2 ) {
update_post_meta($post_id, "_wp_page_template", "template2.php");
}
}
You just need to create category-1.php which rendered as template1.php and category-2.php which rendered as template2.php in your theme root.
See template hierarchy for more info.
I tried to emulate the official WP hierarchy scheme among my posts & custom post types, but it just wasn't happening. I ended up using Custom Post Types so that I could assign templates to both the "list" pages and the "individual" pages. And then I wrote some javascript that looks for the post-type string in the URL, and if it's detected, it adds the current_page_parent/ancestor classes to the appropriate menu items. Not perfect or totally future-proof, but it gets the job done.
If someone comes up with a better solution, please post it!
I've added meta boxes to my posts using the action "add_meta_boxes" to add/change custom settings like background-color, etc.
When I enable the custom fields in my screen options, all values of my meta boxes are displayd in these custom fields!
There are also showing up in the selectbox to add a new "custom field".
If you want to hide your post meta data from custom fields metabox, you should start your meta keys with underscore. Example _background-color
Added:
Also you can use is_protected_meta filter, which return boolean value (true - hide, false - show).
Filter parameters: $protected, $meta_key. See wp-includes/meta.php file. function is_protected_meta()
Normally WP hides meta keys that start with an underscore/_ from the Custom Fields (default/core) MetaBox.
Now imagine that you do not want to give the user of your plugin the possibility to alter Post Meta Data through the ugly and user unfriendly Custom Fields meta box. And therefore you build a custom meta box and prefix your meta key with an underscore/_. Then the user changes his mind and deactivates or uninstalls your plugin. What happens now is that the user has exactly no access to any UI to alter the (still present) meta data. This is a really, really bad situation for the user.
So we need a switch to turn off the Custom Fields MetaBox access as long as your plugin is activated. Therefore WP Core got the is_protected_meta() function. It basically consists out of two lines of code:
$protected = ( '_' == $meta_key[0] );
return apply_filters( 'is_protected_meta', $protected, $meta_key, $meta_type );
As it's not nice to only offer a filter to handle that, WordPress today has a simple function that you can use:
register_meta( $meta_type, $key, $sanitize_callback, $auth_callback );
And the last argument, the $auth_callback does the following inside this function:
if ( empty( $auth_callback ) ) {
if ( is_protected_meta( $meta_key, $meta_type ) )
$auth_callback = '__return_false';
else
$auth_callback = '__return_true';
}
if ( is_callable( $auth_callback ) )
add_filter( "auth_{$meta_type}_meta_{$meta_key}", $auth_callback, 10, 6 );
As you can see, you want to just add '__return_false' as $auth_callback to deactivate Custom Fields MetaBox access as long as your plugin is active. When the user removes or deactivates your plugin, he instantly has access to the meta field via the standard Custom Fields MetaBox.
Notes: WP core at v4.0.1 while writing this question. Make use of the $sanitize_callback! Thanks to Trepmal for posting about the is_protected_meta filter on her blog. Else I would have never stumbled upon the use case for that.