Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

QUESTION: woocommerce product search results sort by stock_status #2473

Closed
beazuadmin opened this issue Nov 21, 2021 · 11 comments
Closed

QUESTION: woocommerce product search results sort by stock_status #2473

beazuadmin opened this issue Nov 21, 2021 · 11 comments

Comments

@beazuadmin
Copy link

beazuadmin commented Nov 21, 2021

Is there a way to use _stock_status metadata in a woocommerce product to sort search results such that it shows all out-of-stock products last?

When ElasticPress is not active, the following filter works correctly:

add_filter( 'woocommerce_get_catalog_ordering_args', 'show_instock_first', 9999 );
function show_instock_first( $args ) {
   $args['orderby'] = 'meta_value';
   $args['order'] = 'ASC';
   $args['meta_key'] = '_stock_status';
   return $args;
}

But ElaticPress seems to ignore that.

If I step on the function get_es_posts in includes/classes/Indexable/Post/QueryIntegration.php I can see that the $query is setup correctly, and it has the right _stock_status meta_query set. However, it seems that $query->query_vars has 'orderby' set to false and elastic press never picks up the _stock_status meta query from the query.

Any idea how to make this work?
Thanks

@beazuadmin
Copy link
Author

beazuadmin commented Nov 22, 2021

Just another note. I found that the Woocommerce Feature in ElasticPress is overriding the orderby value in the public function translate_args( $query ) (includes/classes/Feature/WooCommerce/WooCommerce.php)

If I comment the following lines:

			if ( ! empty( $s ) ) {
				// Comment this to avoid overriding orderby stock_status
				// $query->set( 'orderby', false ); // Just order by relevance.

				/**
				 * Default order when doing search in Woocommerce is 'ASC'
				 * These lines will change it to 'DESC' as we want to most relevant result
				 */
				if ( empty( $_GET['orderby'] ) && $query->is_main_query() ) { // phpcs:ignore WordPress.Security.NonceVerification
					// Comment this to avoid outofstock showing before instock
					// $query->set( 'order', 'DESC' );
				}

Then the search results come ordered as intended (ie, in stock products come before out of stock).

But I can see that by doing the ASC order I might be messing with the relevancy of the result.

Can anyone suggest what is the best way to achieve this?
Thanks!

@felipeelia
Copy link
Member

Hi @beazuadmin,

First of all, sorry for the late reply here. The lines you commented out don't seem to be needed anymore, as I outlined in #2577. With those commented out, you can use this code to have the order by stock AND relevance applied:

function show_instock_first( $args ) {
	$args['orderby'] = [
		'meta._stock_status.raw' => 'ASC',
		'relevance'              => 'DESC',
	];

	return $args;
}
add_filter( 'woocommerce_get_catalog_ordering_args', 'show_instock_first', 9999 );

That PR will go through our code review process and will probably get merged for our next release. Until then, for you and any other users facing the same issue, this snippet should be enough:

add_action(
	'pre_get_posts',
	function( $query ) {
		if ( 'product_query' !== $query->get( 'wc_query' ) ) {
			return;
		}

		$query->set(
			'orderby',
			[
				'meta._stock_status.raw' => 'ASC',
				'relevance'              => 'DESC',
			]
		);
	},
	99
);

Thanks!

@felipeelia
Copy link
Member

As #2577 was merged, I'm closing out the issue.

@beazuadmin
Copy link
Author

Hi @felipeelia just to confirm that the temporary solution you outline above works with the current version of the plugin in production. Thanks!

@Ahammed-Navas
Copy link

Hello @felipeelia

The code worked. Now the out-of-stock products are showing at the end of my listing. but when I choose the default order status as “price – low to high”, it does not work. Would you know any workaround to make it work?

Thank you.

@Ahammed-Navas
Copy link

Hello @felipeelia

Is there any update on the above issue?

Thanks

@felipeelia
Copy link
Member

Hi @Ahammed-Navas,

Although I'm leaving an alternative version of the code below, I'd like to set some expectations, so you don't have to wait for our replies.

  • We thrive to reply to all messages here in our GitHub repository but sometimes it may take weeks until we can get back to something, especially when the issue is already closed. You don't need to send a following up message in those cases. In fact, if you really have a different problem, it'd be better to open a new issue.
  • Sometimes we provide snippets and general guidance here in the repo but that is not its main goal. If you need help developing custom code and has any time constraint we would be happy to help you. You can visit https://www.elasticpress.io/elasticpress-consulting/ to schedule an appointment for a consultation.
  • As I stated in that WordPress.org Forum topic we do not provide support there. That said, please, next time let's keep all communications here in the GitHub repo.

Thanks!

add_action(
	'pre_get_posts',
	function( $query ) {
		if ( 'product_query' !== $query->get( 'wc_query' ) ) {
			return;
		}

		if ( ! empty( $_GET['orderby'] ) && 'menu_order' !== $_GET['orderby'] ) { // phpcs:ignore WordPress.Security.NonceVerification
			return;
		}

		$query->set(
			'orderby',
			[
				'meta._stock_status.raw' => 'ASC',
				'relevance'              => 'DESC',
			]
		);
	},
	99
);

@Ahammed-Navas
Copy link

Hello @felipeelia

Thanks for your reply.

I tried adding the code above you shared and unfortunately, it did not work as expected. Sorting now works correctly. However, sorting out-of-stock products last in the archive page is not working. Can you please provide us with the correct code? We need to resolve the issue as soon as possible.

Thank you

@brandwaffle
Copy link
Contributor

Hi @Ahammed-Navas my colleague @felipeelia has very nicely explained to you that this work is custom development well outside the scope of our free, open source plugin support that we provide here for bug fixes and feature requests.

If you would like to someone else to write code for you, we can provide custom consulting on a paid basis. You may also prefer to use Codeable which has several ElasticPress experts available: https://www.codeable.io/developers/?developer_search=elasticpress

@Ahammed-Navas
Copy link

Hi @brandwaffle ,
Okay, But When ElasticPress plugin is not active on the site, the following filter works correctly:

function order_by_stock_status($posts_clauses) { global $wpdb; // only change query on WooCommerce loops if (is_woocommerce() && (is_shop() || is_product_category() || is_product_tag() || is_product_taxonomy())) { $posts_clauses['join'] .= " INNER JOIN $wpdb->postmeta istockstatus ON ($wpdb->posts.ID = istockstatus.post_id) "; $posts_clauses['orderby'] = " istockstatus.meta_value ASC, " . $posts_clauses['orderby']; $posts_clauses['where'] = " AND istockstatus.meta_key = '_stock_status' AND istockstatus.meta_value <> '' " . $posts_clauses['where']; } return $posts_clauses; }

Therefore, the issue is due to ElasticPress. That's why I asked you about it. Would you mind checking the code again? I hope we can resolve it.

Thanks

@brandwaffle
Copy link
Contributor

@Ahammed-Navas it works without ElasticPress because you have written a direct SQL query and as we've explained to you before, ElasticPress integrates with WP_Query. ElasticPress doesn't support 100% of all themes and plugins in the WordPress ecosystem, and it certainly can't support custom code that circumvents the WP Query API, because that's impossible. I'm sorry you're not able to make it work for your purposes, but we do not provide custom development support here, as I've stated numerous times.

If you have legitimate issues to share on this repo, you are welcome to do so. However, if you continue to request individualized support for your specific integration, we may have to take additional action up to and including blocking your ability to submit tickets to our repo.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants