Shortcode Causing Product Search To Break - php

We have added a live product search shortcode on the top of our website for mobile devices only.
On desktops we have left the live product search in a side bar.
We have a function that only calls and places the shortcode for mobile devices.
Previously when you done a live product search on desktop devices and hit enter, 20 products would be returned and made visible in a grid view on the screen.
Since adding the shortcode for mobile devices, this has broken this feature for desktop devices.
The products still appear in a drop down menu, but previously you could hit enter and they would be moved into a nice grid view display in the centre of the screen.
To achieve this before, to enable the products to appear in the centre of the screen, the following line of code was added:
if (get_option( 'wpsc_default_category' ) == 'list' && isset($wp_query-
>query_vars['search_terms']))
$output = false;
}
Section of code with the above code having been added at the bottom:
function wpsc_display_categories() {
global $wp_query;
$output = false;
if ( !is_numeric( get_option( 'wpsc_default_category' ) ) && ! get_query_var( 'product_tag' ) ) {
if ( isset( $wp_query->query_vars['products'] ) )
$category_id = $wp_query->query_vars['products'];
else if ( isset( $_GET['products'] ) )
$category_id = $_GET['products'];
// if we have no categories, and no search, show the group list
if ( is_numeric( get_option( 'wpsc_default_category' ) ) || (isset( $product_id ) && is_numeric( $product_id )) )
$output = true;
if ( (get_option( 'wpsc_default_category' ) == 'all+list'))
$output = true;
if (get_option( 'wpsc_default_category' ) == 'list' && (!isset($wp_query->query_vars['wpsc_product_category']) || !isset($wp_query->query_vars['product_tag']) && get_option('wpsc_display_categories')))
$output = true;
if (get_option( 'wpsc_default_category' ) == 'list' && isset($wp_query->query_vars['search_terms']))
$output = false;
}
if ( isset( $category_id ) && $category_id > 0 )
$output = false;
if ( get_option( 'wpsc_display_categories' ))
$output = true;
return $output;
}
Not sure why adding the shortcode has broken the products returning in the centre of the screen, from the first line of code shown at the top here?
It's strange as the function we have that adds the shortcode for mobiles, checks that it's a mobile device and only applies the shortcode for mobile devices.
Any thoughts, or ideas on how we can solve this one?
Current filter in functions.php which checks for the mobile devices, and applies the shortcode if a mobile device is detected:
add_action( 'generate_inside_navigation','tu_add_to_mobile_bar' );
function tu_add_to_mobile_bar() {
if (wp_is_mobile()) {
?>
<div class="search">
<?php echo do_shortcode( '[our shortcode in here] ' ); ?>
</div>
<?php
}}

Here's the gist of what I was talking about.
Step #1 - Register a variable with the global query
This isn't technically 100% necessary, but it is generally considered a best practice. You could alternatively just inspect the raw $_GET or $_POST globals.
add_filter(
'query_vars',
function( $vars ) {
$vars[] = 'is_mobile_search';
return $vars;
}
);
Step #2 - Pass the variable
I'm assuming your shortcode actually renders a form, and that you can conditionally change it somehow, maybe [our_shortcode mobile="true"].
<form>
<input type="hidden" name="is_mobile_search" value="true" />
</form>
Step #3 - Use the variable
The contents of this function are your normal stuff, you are just checking is_mobile_search for the literal (but arbitrary) string value of true.
function wpsc_display_categories() {
$is_mobile_search = get_query_var('is_mobile_search') === "true";
}

Related

Limiting Wordpress Tag Pages for Tags with more than 10 associated posts

as the title said, I'm trying to write a custom WordPress filter which limits the creation of Tag pages so that Tag pages are only created if the Tag has more than 10 associated posts. This is because we have so many tags with <10 associated posts, and it's creating a lot of noise.
I've not worked with WordPress for almost 5 years now, so I'm a bit rusty.
Here's what I'm trying, and it's not quite working:
<?php
function limit_taxonomies_by_count( $args, $taxonomy, $object_type ) {
$terms = get_terms('post_tag');
foreach($term in $terms) {
if ($term->count < 10) {
$args = array(
'public' => false
)
}
}
return $args
}
add_filter('register_taxonomy_args', 'limit_taxonomies_by_count' );
?>
Please let me know what I'm missing!
You can do as follows to achieve your job done. You can remove those tags link whose associated posts count are less than 10, so visitors can never click on those tags.
function modify_term_link_url( $links ) {
global $post;
if( !$post ) return $links;
$terms = get_the_terms( $post->ID, 'post_tag' );
if ( is_wp_error( $terms ) ) {
return $terms;
}
if ( empty( $terms ) ) {
return false;
}
$links = array();
foreach ( $terms as $term ) {
if( $term->count < 10 ){
$link = '';
}else{
$link = get_term_link( $term, 'post_tag' );
if ( is_wp_error( $link ) ) {
return $link;
}
}
$links[] = '' . $term->name . '';
}
return $links;
}
add_filter( 'term_links-post_tag', 'modify_term_link_url' );
Codes goes to your active theme's functions.php
Instead of preventing the admins / editors from adding new tags, you could just "hide" Tag archive pages that don't meet the criteria (10 or more posts assigned to them). This way, admins/editors can still create / use new tags that might eventually reach 10 or more posts which will then make them visible to visitors.
To do so, you can use the template_redirect action hook to do something before the Tag archive page is loaded on screen (that something is explained next), then the is_tag() function to check whether the visitor is trying to access a Tag archive page, and finally the wp_redirect() function to do the actual redirection:
/**
* Redirects visitors to the homepage for Tags with
* less than 10 posts associated to them.
*/
function wp76515_tag_maybe_redirect(){
// We're viewing a Tag archive page
if ( is_tag() ) {
// Get Tag object
$tag = get_tag(get_queried_object_id());
// Tag's post count
$post_count = $tag->count;
// This tag has less than 10 posts,
// redirect visitor
if ( $post_count < 10 ) {
wp_redirect(
home_url(), // The URL we're sending the visitor to
'302' // The HTTP status, 302 = 'Moved Temporarily'
);
}
}
}
add_action('template_redirect', 'wp76515_tag_maybe_redirect', 5);
You may want to change the redirect code to 301 (Moved Permanently) to remove existing Tag pages with less than 10 posts from Google's index as well.

Disable a plugin function in Wordpress / Woocommerce

I'm having trouble disabling a function in the Woocommerce Force Sells extension. The function adds some text under the buy button on the frontend product page, that I would like to remove.
I think I have found the function in question in the woocommerce-force-sells.php file:
/**
* Displays information of what linked products that will get added when current
* product is added to cart.
*/
public function show_force_sell_products() {
global $post;
$product_ids = $this->get_force_sell_ids( $post->ID, array( 'normal', 'synced' ) );
$titles = array();
// Make sure the products still exist and don't display duplicates.
foreach( array_values( array_unique( $product_ids ) ) as $key => $product_id ) {
$product = wc_get_product( $product_id );
if ( $product && $product->exists() && 'trash' !== $product->get_status() ) {
$titles[] = version_compare( WC_VERSION, '3.0', '>=' ) ? $product->get_title() : get_the_title( $product_id );
}
}
if ( ! empty( $titles ) ) {
echo '<div class="clear"></div>';
echo '<div class="wc-force-sells">';
echo '<p>' . __( 'This will also add the following products to your cart:', 'woocommerce-force-sells' ) . '</p>';
echo '<ul>';
foreach ( $titles as $title ) {
echo '<li>' . $title . '</li>';
}
echo '</ul></div>';
}
}
I have looked at https://codex.wordpress.org/Function_Reference/remove_action but I can't really figure out how to employ that in the code above.
Thanks a lot in advance!
The easy way to do this is by hiding the content from the page. Look for the class and add
display:none ;
to that class in css.
or
you can edit it in woocommerce template files. it is hard to find from which page it is coming from (look in all possible pages in templates ). once you find it remember to copy that template to child theme.(create a folder in child theme named as woocommerce---add folder path if there is some in actual location). or else you will loose all the edits when woocommerce is updated.
easy way is just hiding it from css
You cannot remove a function, you can only prevent it from being executed. That is not the same as removing an action though. However, if you want to remove text from a button, you are probably better off changing the template file that adds the button to the page.
Here is some more information about changing the template: https://docs.woocommerce.com/document/template-structure/

How to change WooCommerce My Account page titles?

I want to change the page titles (entry titles) for each page in the WooCommerce My Account section so that they relate to the actual page you are on rather than outputting a generic "My Account" on each page.
I have looked around and seen this solution in several places:
function wpb_woo_endpoint_title( $title, $id ) {
if ( is_wc_endpoint_url( 'downloads' ) && in_the_loop() ) { // add your endpoint urls
$title = "Download MP3s"; // change your entry-title
}
elseif ( is_wc_endpoint_url( 'orders' ) && in_the_loop() ) {
$title = "My Orders";
}
elseif ( is_wc_endpoint_url( 'edit-account' ) && in_the_loop() ) {
$title = "Change My Details";
}
return $title;
}
add_filter( 'the_title', 'wpb_woo_endpoint_title', 10, 2 );
This does not work unless you remove the in_the_loop check, which obviously isn't ideal as then it ends up changing other things on the page too.
Then I found this answer, as an example on how to change the title for the "Account Details" page:
add_filter( 'woocommerce_endpoint_edit-account_title', 'change_my_account_edit_account_title', 10, 2 );
function change_my_account_edit_account_title( $title, $endpoint ) {
$title = __( "Edit your account details", "woocommerce" );
return $title;
}
But this didn't work, it didn't even seem to go into the function at all.
Is there a way to do this that actually works?
Changing main my account page title and My account page title sub sections:
1) For "My Account: dashbord (main page):
To change the main "My account" page title, you just need to change the title of the page in backend directly because it's not an endpoint, and to check in Settings > Advanced section that the page (with the renamed title) is still assigned to "My account page".
2) For the other "endpoints" page titles in My account section:
Use woocommerce_endpoint_{$endpoint}_title composite dedicated filter hook, where {$endpoint} need to be replaced by the targeted endpoint (see available endpoints on Settings > Advanced section)
Example: To change My account "orders" endpoint page title you will use:
add_filter( 'woocommerce_endpoint_orders_title', 'change_my_account_orders_title', 10, 2 );
function change_my_account_orders_title( $title, $endpoint ) {
$title = __( "Your orders", "woocommerce" );
return $title;
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
If it doesn't work, it's because something else is making trouble, like your own customizations, your theme's customizations, a plugin or something elseā€¦
Related StackOverFlow answers:
Changing the titles on My Account pages in Woocommerce
Rename My account tabbed menu items in Woocommerce
Reorder menu items in Woocommerce My Account section
Display custom content for a custom account menu item in Woocommerce 3
You can change you MyAccount item titles this way:
/**
* Rename WooCommerce MyAccount menu items
*/
add_filter( 'woocommerce_account_menu_items', 'rename_menu_items' );
function rename_menu_items( $items ) {
$items['downloads'] = 'Download MP3s';
$items['orders'] = 'My Orders';
$items['edit-account'] = 'Change My Details';
return $items;
}
To change the title on each account page as well, you need to add this too:
/**
* Change page titles
*/
add_filter( 'the_title', 'custom_account_endpoint_titles' );
function custom_account_endpoint_titles( $title ) {
global $wp_query;
if ( isset( $wp_query->query_vars['downloads'] ) && in_the_loop() ) {
return 'Download MP3s';
}
if ( isset( $wp_query->query_vars['orders'] ) && in_the_loop() ) {
return 'My Orders';
}
if ( isset( $wp_query->query_vars['edit-account'] ) && in_the_loop() ) {
return 'Change My Details';
}
return $title;
}
If you're using Yoast SEO, you need to add another function to set the correct page titles in the browser tab. If you also need this, I'll expand my answer.
Put this into you functions.php file. Tested and works.
I notice I had some issues implementing the is_wc_endpoint_url() && in_the_loop solution, it did not work out with the && in_the_loop(), removing is not a viable option since it created even more conflicts.
So instead I chose to work on the template file directly, I am sharing this because I noticed that some people had the same issues and this solution might help others achieve the similar results using a different approach.
I basically replaced the header in page-my-account.php with this code:
<header>
<?php
$main_title = get_the_title();
$endpoint = WC()->query->get_current_endpoint();
$endpoint_title = __( WC()->query->get_endpoint_title( $endpoint ), 'text-domain' );
if ( $endpoint_title ){
//If the endpoint exists use itself as the new custom title
$custom_title = $endpoint_title;
}
else{
// Here we can define the custom title for each endpoint we can use home_url() or strpos + add_query_arg()
global $wp;
if( basename( home_url($wp->request) ) == 'points-and-rewards' || ( strpos( (add_query_arg( $wp->query_vars)) , 'points-and-rewards' ) !== false ) ){
$custom_title = __( 'Points and rewards', 'text-domain' );
}
elseif( basename(home_url($wp->request)) == 'payment-methods' ){
$custom_title = __( 'Payment methods', 'text-domain' );
}
elseif( basename(home_url($wp->request)) == 'my-account' ){
$custom_title = __( 'Dashboard', 'text-domain' );
}
//Add more custom titles here
}
if ( !empty( $custom_title ) ){
//If there is a custom title
$new_endpoint_title = sprintf( '<h2>%s > %s</h2>', $main_title, $custom_title );
}
else{
//If there is no custom title default to get_title()
$new_endpoint_title = sprintf( '<h2>%s</h2>' , $main_title );
}
?>
<?php //Echo's the resulting title ?>
<?php echo $new_endpoint_title; ?>
</header>

How do I hide/show certain elements/divs if URL contains a specific string?

I have a large set of pages (page1/) that need to show a certain navigation bar and a second large set of pages (page2/) that need to show a different navigation bar in its place.
I have tried various jQuery to identify if the URL contains a certain word and, if it does, show the corresponding navigation bar - but with no success.
Below is the jQuery I've tried.
<script>
if(strpos($url ,'page1/') !== FALSE) {
echo '#page1-navigation-bar';
}
if(strpos($url ,'page2/') !== FALSE){
echo '#page2-navigation-bar';
}
</script>
This has no effect and I'm not sure whether this is because the coding is wrong, I've inputted it in the wrong place, I need to do something else as well as this coding or a combination of everything plus more.
Also not sure if this will hide one when showing the other?
Please help by stating any code needed and where exactly this needs inputting.
Thanks,
Michael
Maybe try like this in PHP:
<?php
$page = array("page1/" /*, "page2/", "page3/", "all other pages" */ );
if(in_array(strpos($url, $page))
{echo '#page1-navigation-bar';}
else
{echo '#page2-navigation-bar';}
?>
There are a couple ways you can go about this. You can do as WebSon has suggested but with a different approach, you can do it via page templates, or you can do it with custom post metas. Now note, while you're doing something with "ID's," I suggest you change the navigation displayed using wp_nav_menu().
One method with a suggested conditional, instead of ID's.
<?php
$first_array = [ 'page1', 'page3', 'page5' ];
$second_array = [ 'page2', 'page4', 'page6' ];
$wp_nav_args = [ //your default args ];
if ( is_page($first_array ) ) {
// Change the entire array or parts of it.
$wp_nav_args = [];
}
elseif ( is_page($second_array) ) {
// Change the entire array or parts of it.
$wp_nav_args = [];
}
wp_nav_menu($wp_nav_args);
Page Templates
<?php
$wp_nav_args = [ //your default args ];
if ( is_page_template('template-menu-a') ) {
// Change the entire array or parts of it.
$wp_nav_args = [];
}
elseif ( is_page_template('template-menu-b') {
// Change the entire array or parts of it.
$wp_nav_args = [];
}
wp_nav_menu($wp_nav_args);
More complicated way, which doesn't include templates, yet is extendable.
Just wanted to share this way, as you can use this for a few other things as well, by creating custom post metas. This example shows a checkbox in the Update/Publish box.
<?php
function add_custom_meta_field() {
$post_id = get_the_ID();
if ( get_post_type( $post_id ) !== 'page' ) {
return;
}
$value = get_post_meta( $post_id, '_navigation_b', true );
?>
<div class="misc-pub-section misc-pub-section-last">
<input type="checkbox" value="1" <?php checked( $value, true, true ); ?> name="_navigation_b" id="_navigation_b" /><label for="_navigation_b"><?php _e( 'Add To Your Calendar Icons', 'navy' ); ?></label>
</div>
<?php
}
add_action( 'post_submitbox_misc_actions', 'add_custom_meta_field' );
function save_custom_meta_field() {
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
return;
}
if ( ! current_user_can( 'edit_post', $post_id ) ) {
return;
}
if ( isset( $_POST['_navigation_b'] ) ) {
update_post_meta( $post_id, '_navigation_b', $_POST['_navigation_b'] );
} else {
delete_post_meta( $post_id, '_navigation_b' );
}
}
add_action( 'save_post', 'save_custom_meta_field' );

Match multiple attribute terms in Wordpress PHP loop

This seems like a simple enough problem but I'm a novice at PHP and I've been working on this for hours. I'm looping through posts in an archive and showing a different logo for each post based on a certain attribute. Here's my existing function in functions.php:
function show_logo() {
global $post;
$attribute_names = array( 'pa_product-type'
);
foreach ( $attribute_names as $attribute_name ) {
$taxonomy = get_taxonomy( $attribute_name );
if ( $taxonomy && ! is_wp_error( $taxonomy ) ) {
$terms = wp_get_post_terms( $post->ID, $attribute_name );
$terms_array = array();
if ( ! empty( $terms ) ) {
foreach ( $terms as $term ) {
if ( $term->name == 'L1' ) {
// Show L1 Logo
}
elseif ( $term->name == 'M1' ) {
// Show M1 Logo
}
elseif ( $term->name == 'H1' ) {
// Show H1 Logo
}
else {
$full_line = '<span>'. $term->name . '</span>';
}
array_push( $terms_array, $full_line );
}
echo implode( $terms_array );
}
}
}
}
All I want to do is do show a different logo if the post matches multiple terms (e.g. 'L1' AND 'M1'). I have tried many very different things but I have no idea if I'm even on the right track. Any help would be greatly appreciated.
This should be fairly easy, I'm just not exactly sure the full context of all the data involved.
Assuming you are only showing one logo per post, here is one approach:
Right before foreach ( $terms as $term ) { create three boolean variables:
$hasL1 = false;
$hasM1 = false;
$hasH1 = false;
Then when one of your term names matches, instead of just showing the logo set the appropriate variable equal to true, ie $hasL1 = true;
After the foreach is complete, either before or after echo implode( $terms_array ); depending on what makes sense, setup a new if/elseif/else block to decide what logo to show as follows:
if ($hasL1 && $hasM1 && $hasH1) { // Pick logo for all 3 }
elseif ($hasL1 && $hasM1) { // Pick logo for pair }
elseif ($hasL1 && $hasH1) { // Pick logo for pair }
elseif ($hasH1 && $hasM1) { // Pick logo for pair }
elseif ($hasL1) { // Pick logo }
elseif ($hasM1) { // Pick logo }
elseif ($hasH1) { // Pick logo }
else { // default logo }
Of course there are many other ways to implement this too.

Categories