WooCommerce - include custom fields in the search function - wordpress

So I'm looking to include the functionality of displaying content by its custom fields as well as its title and content.
I need to be able to search for orders, as well as subscriptions, on WooCommerce by custom field as well as the normal method. Is there any way I can, without adding additional search forms or booleans, simply get Wordpress to display posts that match with the search term by their custom fields, too?
I have used the following code thanks to a responder on here:
function custom_search_query( $query ) {
$custom_fields = array(
// put all the meta fields you want to search for here
"gender",
"birthdate"
);
$searchterm = $query->query_vars['s'];
// we have to remove the "s" parameter from the query, because it will prevent the posts from being found
$query->query_vars['s'] = "";
if ($searchterm != "") {
$meta_query = array('relation' => 'OR');
foreach($custom_fields as $cf) {
array_push($meta_query, array(
'key' => $cf,
'value' => $searchterm,
'compare' => '=='
));
}
$query->set("meta_query", $meta_query);
};
}
add_filter( "pre_get_posts", "custom_search_query");
This works great when searching orders, but what I need to search is subscriptions, where it doesn't work.
Help would be much appreciated!

Related

ACF - filter relationship query to display WooCommerce product available in this category

I'm trying to create a custom category product sort order in WooCommerce using Advanced Custom Fields.
I have found a great guide to set it up. The approach is:
Add the ACF relationship field to the category page.
Config it to display only products.
Add a function that orders the category page based on the products you've added.
It works great!
The problem I have is that it always displays all the available products and not only the product available in this category.
I'm trying to use this function but the tag_id is not working.
add_filter('acf/fields/relationship/query', 'my_acf_fields_relationship_query', 10, 3);
function my_acf_fields_relationship_query( $args, $field, $post_id ) {
$args['tag_id'] = $category_id;
return $args;
}
Any suggestions?
You want to filter by product category terms, so you should not use:
[tag_id]
But instead use:
[term_id]
You follwed the tutorial, but the filter function is not working. You have created the custom field and inserted the function to create your custom product order. What is not working, if I got your question the right way, is the function that fetches an array of all the product IDs within a specific category. So you are getting all the available products and not the ones of the category you selected.
This should have been part of your question so others can find a solution:
This is the code from the tutorial you used: https://www.igoo.co.uk/2016/10/setting-a-custom-category-specific-product-sort-order-in-woocommerce-using-advanced-custom-fields/
function my_custom_product_order($q) {
if(!is_admin())
{
// fetch current category id from active query
$category_id = $q->get_queried_object_id();
// get array of all product IDs in current category
$product_ids = get_category_product_ids($category_id);
// get preferred order from ACF field
$product_ids_order_preferred = get_field('product_order', 'product_cat_' . $category_id);
// if we have some product sort order set…
if($product_ids_order_preferred)
{
// merge our preferred category ids array with the array of all products ids, and remove duplicates
$product_ids = array_unique(array_merge($product_ids_order_preferred, $product_ids));
}
// set the 'posts__in' argument to the new array of post IDs (unfortunately wordpress doesn’t let you just pass an array of IDs straight in here)
$q->set('post__in', $product_ids);
// set the query orderby value to observe the posts__in field
$q->set('orderby', 'post__in');
}
remove_action('woocommerce_product_query', 'custom_pre_get_posts_query');
}
add_action('woocommerce_product_query', ‘my_custom_product_order’);
In Line 7 of the code above, you are using the "get_category_product_ids($category_id)" function and give the $category_id as a parameter.
The "get_category_product_ids" function in your tutorial looks like this:
// helper function to fetch all product IDs from a specific category ID
function get_category_product_ids($category_id) {
$args = array(
'post_type' => 'product',
'post_status' => 'publish',
'fields' => 'ids',
'posts_per_page' => -1,
'tax_query' => array(
array(
'taxonomy' => 'product_cat',
'field' => 'term_id',
'terms' => $category_id,
'operator' => 'IN'
)
)
);
$ids = get_posts($args);
return $ids;
}
This function gets the parameter $category_id and uses it to make a post query and saving the resulting ids of the tax query.
This is the actual answer, which might help you:
If you want to find out why it is not working, you should first have a look at the $category_ id variable, because this value is the most important to make it work. So you can have a look if there is data inside the variable with var_dump inside your function after setting the variable:
var_dump($category_id)
Is the variable set correctly and do have data when the "my_custom_product_order" function is called? You should get the id of the current viewed category.
If you not get an id inside my_custom_product_order
you should have a look at the "get_queried_object_id()" function. It is possible to get this value with another way. The "get_queried_object()" function returns a WP_Term object. So you can also do:
$category_id = $q->get_queried_object();
$category_id = $category_id->term_id;
Maybe you now have the id you need.
If not, you should check the parameter $q, what is it for? Maybe this could cause the problem. You can try something like:
if (is_product_category()) {
$q = get_queried_object();
$term_id = $q->term_id;
}
If you are getting an id inside my_custom_product_order
then you should have a look at the "get_category_product_ids" function. Does the parameter work? Try var_dump inside this function and see if there is value handed over to the function. If not, you could get the variable another way. This seems redundantly and makes the parameters useless, but this way you can make sure that there is a category ID for your tax query. Put this at the start of your "my_category_product_ids":
$category_id = get_queried_object();
$category_id = $category_id->term_id;
Hope this will help you finding out why it's not working. Without knowing that it will be hard to fix the problem. If I'm right, the problem is with your $category_id not having a value for making the functions work.

Event Espresso Query Modification?

I am using Event Espresso with WordPress.
May u help me out in further query modification?
Hope you will :)
I want to use meta_query to list events on page.
Somewhat like below code.
$atts = array(
'title' => NULL,
'limit' => 10,
'css_class' => NULL,
'show_expired' => FALSE,
'month' => NULL,
'category_slug' => NULL,
'order_by' => 'start_date',
//'order_by' => 'end_date',
'sort' => 'DESC',
'meta_query' => array(
array(
'key' => 'start_date',
'value' => '2017-01-08 08:00:00',
'type' => 'DATETIME',
'compare' => '>=',
),
)
);
I want to implement search functionality for Event Espresso and i have those fields:
State - Dropdown (How to list all state? May be Venue)
Category - Dropdown
Start Date - Datepicker
End Date - Datepicker
Keyword - input
On submit those values will be submitted and based on those , i will get filtered events that are related with those values.
So how to implement this?
Please help.
Thanks in Advance
A slightly delayed response to this...
First, this depends on the version of EE you're using. They support both EE3 and EE4. I use EE4, so any reference to code I make is specific to version 4.
In order to create an events archive with a filtering functionality, you'd need to use the EE events archive. EE uses custom database tables and a lot of different post types to achieve what you see, so creating a simple archive with these filters won't work very well. Very little is stored in the _posts and _postmeta tables and you need to get post meta from related post types and tables that aren't laid out like WP_Query likes. They have a shortcode for the events list, which is laid out here and has a lot of the filters you're looking for, but no search functionality.
Their support forum has a lot of snippets and such created by their staff and there's a (long) related post about formatting the events archive page here. You'll also need to go through this documentation to see about their custom methods and hooks.
You could copy over and modify the archive templates they describe in a child theme to add search functionality to the top of the page. This would allow you to directly override the archive. You'll need to make use of some fancy filters, which are covered pretty clearly over on WPMU Dev.
The pieces of information you're looking for for filtering are here, minus keyword:
<?php
if( have_posts() ){
while ( have_posts() ){ the_post(); // enter the WordPress loop
$id = get_the_ID(); // get the ID of the current post in the loop, post ID = EVT_ID
$terms = get_the_terms( $id, 'espresso_event_categories' ); // get the event categories for the current post
if ( $terms && ! is_wp_error( $terms ) ) {
$cats = array();
foreach ( $terms as $term ) {
// do something
}
}
$event = EEM_Event::instance()->get_one_by_ID( $id ); // get the event OBJECT using EE's existing method
$venue = $event->venue(); // get the venue object for the current event
$state = $venue instanceof EE_Venue ? $venue->state_abbrev(); // get the event venue's state, but you can use state_name() to get the full name
// using the event to get the first and last date for the entire event. Sub $datetime for $event to do it per datetime
$start_date = $event->start_date('j M Y');
$end_date = $event->end_date('j M Y');
$start_time = $event->start_time(get_option('time_format'));
$end_time = $event->end_time(get_option('time_format'));
?>
<!-- Do some awesome layout stuff here -->
<?php
}
}
espresso_pagination();
?>
This will give you the meta for each post within the loop as variables, but you may want to pull them into pre_get_posts. You can just as easily create an array of $events and then filter it using the variables.
I'm not sure what your exact needs are regarding keyword. Do you mean tags? Title keywords? Description search? You'll need to narrow down exactly what you need this to do in order to write a function for it.

Wordpress query posts with exclusion

This is what I have to query all events...
query_posts("post_type=marcato_show&meta_key=marcato_show_start_time_unix&orderby=meta_value&order=ASC&posts_per_page=999" );
and this works, just getting the community events...
query_posts( "post_type=marcato_show&showtype=community-events&meta_key=marcato_show_start_time_unix&orderby=meta_value&order=ASC&posts_per_page=999" );
how do I go about getting all the events WITHOUT the community events?
Rather than using query_posts(), which can cause a number of issues (see here and here), I'd recommend using the WP_Query class.
This will avoid some obscure bugs, speed up the query for you, and also make it easier to make changes like excluding posts assigned to a certain term (in this case, the community-events term of the showtype taxonomy).
Be sure to read up on the WP_Query documentation as it covers a lot of useful arguments you may need in the future. But for now, here's how you'd run your same query, excluding those posts in community-events:
$posts = new WP_Query(array(
"post_type" => "marcato_show",
"meta_key" => "marcato_show_start_time_unix",
"orderby" => "meta_value",
"order" => "ASC"
"posts_per_page" => 999, // you can also use `-1` to return unlimited results
"tax_query" => array(
array(
"taxonomy" => "showtype",
"field" => "slug",
"terms" => "community-events",
"operator" => "NOT IN",
),
),
));
if($posts->have_posts()){
while($posts->have_posts()){
$posts->the_post();
// DISPLAY YOUR POSTS HERE
}
wp_reset_postdata(); // restore original post data
This is querying with the same arguments you used in your original post, with the added tax_query to query posts not in that custom taxonomy term. Scroll down to Taxonomy Parameters at the WP_Query documentation linked above for full details on how this works.

Wp eCommerce meta information search

This is a repeat of this question as I get quicker answers on SO.
Out of the box, WP eCommerce does not support Meta search. This is a big problem if you are selling books online and need clients to be able to search by the most important Meta tag, Author!
Can someone please tell me how I could go about including the meta information search or is there a better plugin that does not cost an arm and a leg to search for meta information too?
EDIT:
I have since found a plugin that will do a better search called Relevanssi and Alexander Gieg extended it a little further with his own code:
add_filter('relevanssi_excerpt_content','wpscproductexcerpt',10,3);
function wpscproductexcerpt($content, $post, $query) {
if ( 'wpsc-product' == relevanssi_get_post_type($post->ID) ) {
$content = $post->post_content . ( !empty($post->post_excerpt) ? " $post->post_excerpt" : '' );
if ( 'on' == get_option('relevanssi_expand_shortcodes') ) {
$content = do_shortcode($content);
} else {
$content = strip_shortcodes($content);
}
// The line below fixes a minor bug in Relevanssi 2.9.14 custom excerpt generating code:
$content = preg_replace("/\t/", ' ', $content);
}
return $content;
}
I need to be able to extend this a little further now since I am user Visser Lab's Custom Field's plugin to make up for the deficiencies of WP eCommerce and need to figure out how to include the meta information from this plugin?
Many thanks
From what it turns out, WP eCommerce is using the default WordPress query for displaying it's search results. That's great because this makes it really easy to modify this query to fit our needs. Here is an example code:
function mySearchFilter($query) {
// is_wp_ecommerce_search() is not an actual function - if you know how to check if the search is from WP eCommerce - you might want to do that, so that you don't modify the normal WordPress search
if ( $query->is_search /* && is_wp_ecommerce_search() */ ) {
$query->set('meta_query', array( array( 'key' => 'custom_key', 'value' => $_GET['custom_key'], 'compare' => 'LIKE' ) ) );
};
return $query;
};
add_filter('pre_get_posts','mySearchFilter');
I'm not sure of an exact function for checking whether this is a WP eCommerce search, that's why the && is_wp_ecommerce_search() is commented-out.
You will have to adjust:
'key' => 'custom_key' part - enter the name of your custom field that you'll be looking for.
'value' => $_GET['custom_key'] - enter the value that you'll be looking for. I assume that it will be coming from a $_GET argument, but your case might differ.
'compare' => 'LIKE' - the link bellow will give details about the structure of the meta_query argument, but basically this will look for custom fields with value similar to the searched one.
You can find more details on the meta_query query argument at the Class Reference/WP Query WordPress codex page.

Wordpress: How to integrate the media uploader with a custom meta box field?

I'm writing a plugin which creates a custom post_type called "dictionary_entry" which has several custom meta boxes and fields. I'd like to add an addition field which allows the custom post author to upload an audio clip.
I've done some digging and tried the code offered here but I can't get it to work.
I think one possible answer to my question would be the "type" parameter for fields. I've seen "text", "textarea", "time", "color", "radio", etc. but I haven't been able to find a list of all the possibilities. Is it wishful thinking that there might be a field type: "file" or "upload"?
I'm going to skip the code for adding the custom post_type, but here's an example of my code for adding the meta boxes (in case somebody else is trying to use this, remember to use your custom post_type in the 'pages' parameter):
//meta box code
$meta_boxes = array();
$meta_boxes[] = array(
'id' => 'examples', // meta box id, unique per meta box
'title' => 'Examples', // meta box title
'pages' => array('dictionary_entry'), // post types, accept custom post types as well, default is array('post'); optional
'context' => 'normal', // where the meta box appear: normal (default), advanced, side; optional
'priority' => 'high', // order of meta box: high (default), low; optional
'fields' => array( // list of meta fields
array(
'name' => 'Example 1', // field name
'desc' => 'Use it in a sentence? EX: Kanien\'kéha kahrónkha.', // field description, optional
'id' => $prefix . 'example1', // field id, i.e. the meta key
'type' => 'text', // text box
'std' => '', // default value, optional
'validate_func' => 'check_apos' // validate function, created below, inside RW_Meta_Box_Validate class
),
array(
'name' => 'Translation 1', // field name
'desc' => 'What does the sentence mean? EX: I speak Mohawk.', // field description, optional
'id' => $prefix . 'ex_translation1', // field id, i.e. the meta key
'type' => 'text', // text box
'std' => '', // default value, optional
'validate_func' => 'check_apos' // validate function, created below, inside RW_Meta_Box_Validate class
)
)
);
foreach ($meta_boxes as $metabox) {
add_meta_box... //see the codex for add_meta_box()
}
I figured out how to do this by digging into the code found here. If you take a look, you'll recognize parts of my code quoted above. I was originally using this class, but didn't fully realize it. It's a custom class which can be called to add various meta boxes / fields.
It turns out that the "type" parameter I was wondering about actually belongs to this Class (as opposed to the Wordpress API) and that it does allow for a type: 'file' which brings up a default file picker window (not the built-in media uploader). For my purposes this is okay, because I don't need all the slick options.
If you're reading this, you've probably already googled this question and seen a wide variety of posts that partially explain how to do this. For what it's worth, I found this to be the easiest way to add this functionality that ALSO works for custom post_types (without a fair amount of hacking). I hope this is useful to someone else.

Resources