How to use custom search function in Wordpress - wordpress

I discovered this custom function in WordPress blog, and it seems to do exactly what I need. The only problem is I don't know what to pass as the second parameter. It's asking for a query but doesn't the query happen INSIDE of this function? What query would I pass it?
I've searched for over an hour and I keep finding similar functions, so it's my WordPress novice coming into play here.
BTW the function is supposed to accept a search term (the first parameter) and return all posts that have titles LIKE the search param.
function custom_search( $search, &$wp_query )
{
global $wpdb;
if ( empty( $search ) )
return $search; // skip processing - no search term in query
$q = $wp_query->query_vars;
$n = ! empty( $q['exact'] ) ? '' : '%';
$search =
$searchand = '';
foreach ( (array) $q['search_terms'] as $term ) {
$term = esc_sql( like_escape( $term ) );
$search .= "{$searchand}($wpdb->posts.post_title LIKE '{$n}{$term}{$n}')";
$searchand = ' AND ';
}
if ( ! empty( $search ) ) {
$search = " AND ({$search}) ";
if ( ! is_user_logged_in() )
$search .= " AND ($wpdb->posts.post_password = '') ";
}
return $search;
}
add_filter( 'c_search', 'custom_search', 500, 2 );

Basically the second argument in the function would be a reference. You can read about it at the following link:
http://www.php.net/manual/en/functions.arguments.php
In your case if you remove the second argument for the function about and define
global $wp_query;
And then inside the function the code should still work but you will also have to change the add_filter( 'c_search', 'custom_search', 500, 1 );
Or you can keep the function as is and define the global $wp_query; anywhere in your functions.php, if its not already defined and pass that as the parameter

Actually, you shouldn't need to pass any parameters... the key to that code it's on the last line; what it does it's that it adds a call to a function that will modify the data that it will receive... the arguments for add_filter are:
the point where the data will be filtered
the function that will receive and filter the data
the priority of execution (lower is first)
the number of arguments that the function defined in (2) will receive
so those arguments are always passed on to the function
the filter that code it's referencing it's probably not part of the wordpress core but of some custom plugin, framework or theme
if you want to create a custom query for your own theme/plugin/whatever, take a look at http://codex.wordpress.org/Plugin_API/Filter_Reference/request

You can also make search by following code:
function __search_custom( $search, &$wp_query )
{
global $wpdb;
if ( empty( $search ) )
return $search; // skip processing - no search term in query
$q = $wp_query->query_vars;
$n = ! empty( $q['exact'] ) ? '' : '%';
$search =
$searchand = '';
foreach ( (array) $q['search_terms'] as $term ) {
$term = esc_sql( like_escape( $term ) );
$search .= "{$searchand}(($wpdb->posts.post_title LIKE '{$n}{$term}{$n}') OR ($wpdb->posts.post_content LIKE '{$n}{$term}{$n}'))";
$searchand = ' AND ';
}
if ( ! empty( $search ) ) {
$search = " AND ({$search}) ";
if ( ! is_user_logged_in() )
$search .= " AND ($wpdb->posts.post_password = '') ";
}
return $search;
}
add_filter( 'posts_search', '__search_custom', 500, 2 );
if you want to search only by title then replace $search with following code:
$search .= "{$searchand}($wpdb->posts.post_title LIKE '{$n}{$term}{$n}')";

Related

WP Job Manager - Search Job Titles Only

WP Job Manager doesn’t provide an option for users to search jobs by job title only. This, the results of a job search can be widely off the mark as the search queries the post content by default.
I’ve found some code which works with WordPress posts, it limits the general site search to query post titles only.
My question is, I need it to work with the custom post type for WP Job Manager, which I believe is job_listing. Any thoughts appreciated.
function __search_by_title_only( $search, &$wp_query )
{
global $wpdb;
if ( empty( $search ) )
return $search; // skip processing - no search term in query
$q = $wp_query->query_vars;
$n = ! empty( $q['exact'] ) ? '' : '%';
$search =
$searchand = '';
foreach ( (array) $q['search_terms'] as $term ) {
$term = esc_sql( like_escape( $term ) );
$search .= "{$searchand}($wpdb->posts.post_title LIKE '{$n}{$term}{$n}')";
$searchand = ' AND ';
}
if ( ! empty( $search ) ) {
$search = " AND ({$search}) ";
if ( ! is_user_logged_in() )
$search .= " AND ($wpdb->posts.post_password = '') ";
}
return $search;
}
add_filter( 'posts_search', '__search_by_title_only', 500, 2 );

How to filter BuddyPress member loop by ACF field?

PHP newb here, looking for some guidance. I am working with BuddyPress and Advanced Custom Fields (ACF). I have an ACF field 'new_user' with a value of true/false. I am trying to filter my BuddyPress Members Loop to only display users with a value of 'new_user' = true.
There are 2 code samples here.
The standard BP Members Loop. My thought here, is how do I first query my users by ACF ‘new_user’ = true and then start the bp member loop?:
if ( bp_has_members() ) :
// some code goes here
endif;
while ( bp_members() ) : bp_the_member();
//OUTPUT MEMBERS LIST HERE
endwhile;
This is a BP function to filter by Buddypress extended user fields. The idea here I believe is to replace the code in the middle specific to xprofile_get_field with the proper ACF code:
function my_custom_ids( $field_name, $field_value = '' ) {
if ( empty( $field_name ) )
return '';
global $wpdb;
$field_id = xprofile_get_field_id_from_name( $field_name );
if ( !empty( $field_id ) )
$query = "SELECT user_id FROM " . $wpdb->prefix . "bp_xprofile_data WHERE field_id = " . $field_id;
else
return '';
if ( $field_value != '' )
$query .= " AND value LIKE '%" . $field_value . "%'";
/*
LIKE is slow. If you're sure the value has not been serialized, you can do this:
$query .= " AND value = '" . $field_value . "'";
*/
$custom_ids = $wpdb->get_col( $query );
if ( !empty( $custom_ids ) ) {
// convert the array to a csv string
$custom_ids_str = 'include=' . implode(",", $custom_ids);
return $custom_ids_str;
}
else
return '';
}
Of course, I am open to solving this in another way as well. I hope this is clear.

Woocommerce custom product search in product category

I am using a custom woocommerce product search in my wordpress site where it searchs only in product titles. I would like to include the search in category names too. So if someone search a text, and if that's exists in product category name, all those products under that category also need to be listed.
Here is code I am using:
function wc_filter_search_by_title_only( $search, &$wp_query ) {
global $wpdb;
$not_allowed_post_types = apply_filters( 'wc_filter_search_not_allowed_array', array(
'product', //Default WooCommerce products post type
'shop_webhook', //MyStyle Custom post type
) );
if ( empty( $search ) || ! in_array( $wp_query->query_vars['post_type'], $not_allowed_post_types ) ) {
return $search; // skip processing - no search term in query
}
$q = $wp_query->query_vars;
$n = ! empty( $q['exact'] ) ? '' : '%';
$search =
$searchand = '';
foreach ( (array) $q['search_terms'] as $term ) {
$term = esc_sql( $wpdb->esc_like( $term ) );
$search .= "{$searchand}($wpdb->posts.post_title LIKE '{$n}{$term}{$n}')";
$searchand = ' AND ';
}
if ( ! empty( $search ) ) {
$search = " AND ({$search}) ";
if ( ! is_user_logged_in() )
$search .= " AND ($wpdb->posts.post_password = '') ";
}
return $search;
}
add_filter( 'posts_search', 'wc_filter_search_by_title_only', 500, 2 );
Kindly let me know if anyway I can implement this.
Thank you in advance.
The easiest way really is to use SearchWP with its WooCommerce extension. Besides, it gives you a lot more functionality than just that.

WP rest API get post by title

I'm trying to check by a post title if post exist or not.
For some reason when i try something like:
http://domain.com/wp-json/wp/v2/posts?filter[post-title]=table
I want if post with the name table exist, to get the post, if not, get an empty response. But for some reason when post with title not exist i get all posts back.
How could get empty when no post exist and the post when it exist.
Unfortunately it is not possible, but you can use slug instead. Slug is editable part of the URL when writing a post and they can represent title of the page (or it can be changed into this).
http://example.com/wp-json/wp/v2/posts?slug=table
More details:
https://developer.wordpress.org/rest-api/reference/pages/#arguments
According to http://v2.wp-api.org/, some have to use search keyword :
http://domain.com/wp-json/wp/v2/posts?search=table.
You cannot do this through wp json, please copy the following code in the functions.php:
function __search_by_title_only( $search, &$wp_query ) {
global $wpdb;
if ( empty( $search ) )
return $search; // skip processing - no search term in query
$q = $wp_query->query_vars;
$n = ! empty( $q['exact'] ) ? '' : '%';
$search =
$searchand = '';
foreach ( (array) $q['search_terms'] as $term ) {
$term = esc_sql( like_escape( $term ) );
$search .= "{$searchand}($wpdb->posts.post_title LIKE '{$n}{$term}{$n}')";
$searchand = ' AND ';
}
if ( ! empty( $search ) ) {
$search = " AND ({$search}) ";
if ( ! is_user_logged_in() )
$search .= " AND ($wpdb->posts.post_password = '') ";
}
return $search;
}
add_filter( 'posts_search', '__search_by_title_only', 500, 2 );

How to the get the Wordpress Media Search to include tags?

I've added tags to all Media items with this code:
function wptp_add_tags_to_attachments() {
register_taxonomy_for_object_type( 'post_tag', 'attachment' );
}
add_action( 'init' , 'wptp_add_tags_to_attachments' );
It works great expect one thing. If I search for a media file in the Admin Media Library it does not work with tags.
How can I get the Admin Media Library to include the tags in the search?
You can do this using WordPress action hooks. You need to update the WordPress default search query when searching attachments using hooks posts_where, posts_join and posts_groupby.
Please add below to your themes functions.php
function custom_attachments_join( $join, $query )
{
global $wpdb;
//if we are not on admin or the current search is not on attachment return
if(!is_admin() || (!isset($query->query['post_type']) || $query->query['post_type'] != 'attachment'))
return $join;
// if current query is the main query and a search...
if( is_main_query() && is_search() )
{
$join .= "
LEFT JOIN
{$wpdb->term_relationships} ON {$wpdb->posts}.ID = {$wpdb->term_relationships}.object_id
LEFT JOIN
{$wpdb->term_taxonomy} ON {$wpdb->term_taxonomy}.term_taxonomy_id = {$wpdb->term_relationships}.term_taxonomy_id
LEFT JOIN
{$wpdb->terms} ON {$wpdb->terms}.term_id = {$wpdb->term_taxonomy}.term_id ";
}
return $join;
}
add_filter( 'posts_join', 'custom_attachments_join', 10, 2 );
function custom_attachments_where( $where, $query )
{
global $wpdb;
//if we are not on admin or the current search is not on attachment return
if(!is_admin() || (!isset($query->query['post_type']) || $query->query['post_type'] != 'attachment'))
return $where;
// if current query is the main query and a search...
if( is_main_query() && is_search() )
{
// explictly search post_tag taxonomies
$where .= " OR (
( {$wpdb->term_taxonomy}.taxonomy IN('post_tag') AND {$wpdb->terms}.name LIKE '%" . $wpdb->escape( get_query_var('s') ) . "%' )
)";
}
return $where;
}
add_filter( 'posts_where', 'custom_attachments_where', 10, 2 );
function custom_attachments_groupby( $groupby, $query )
{
global $wpdb;
//if we are not on admin or the current search is not on attachment return
if(!is_admin() || (!isset($query->query['post_type']) || $query->query['post_type'] != 'attachment'))
return $groupby;
// if current query is the main query and a search...
if( is_main_query() && is_search() )
{
// assign the GROUPBY
$groupby = "{$wpdb->posts}.ID";
}
return $groupby;
}
add_filter( 'posts_groupby', 'custom_attachments_groupby', 10, 2 );
What these functions does is:
custom_attachments_join functions joins term_relationships and term_taxonomy for giving us ability to search for tags
custom_attachments_where function modifies the WordPress default where condition to include our search terms to search for taxonomy or terms fields
custom_attachments_groupby adds group by condition to remove duplicate posts if any.
These functions also check whether we are searching for attachment and if we are performing the search in the WordPress admin area.
Please check with this links for more reference on the hooks I have used.
posts_join
posts_where
posts_groupby
Hope this helps you
This plugin's changelog page says that it searches media tags added by its program:
http://wordpress.org/plugins/media-tags/changelog/
If you're building your own plugin, I recommend grabbing their code and seeing what they're doing. Otherwise, their plugin seems to be exactly what you're looking for.
Unfortunately Sabari's solution doesn't work for the search-form in the "Add Media" - section.
I am using the following function in my functions.php (code based on the "Media Search Enhanced" plugin by Yoren Chang):
function myprefix_posts_clauses( $pieces ) {
global $wp_query, $wpdb;
$vars = $wp_query->query_vars;
if ( empty( $vars ) ) {
$vars = ( isset( $_REQUEST['query'] ) ) ? $_REQUEST['query'] : array();
}
// Rewrite the where clause
if ( ! empty( $vars['s'] ) && ( ( isset( $_REQUEST['action'] ) && 'query-attachments' == $_REQUEST['action'] ) || 'attachment' == $vars['post_type'] ) ) {
$pieces['where'] = " AND $wpdb->posts.post_type = 'attachment' AND ($wpdb->posts.post_status = 'inherit' OR $wpdb->posts.post_status = 'private')";
if ( class_exists('WPML_Media') ) {
global $sitepress;
//get current language
$lang = $sitepress->get_current_language();
$pieces['where'] .= $wpdb->prepare( " AND wpml_translations.element_type='post_attachment' AND wpml_translations.language_code = %s", $lang );
}
if ( ! empty( $vars['post_parent'] ) ) {
$pieces['where'] .= " AND $wpdb->posts.post_parent = " . $vars['post_parent'];
} elseif ( 0 === $vars['post_parent'] ) {
// Get unattached attachments
$pieces['where'] .= " AND $wpdb->posts.post_parent = 0";
}
if ( ! empty( $vars['post_mime_type'] ) ) {
// Use esc_like to escape slash
$like = '%' . $wpdb->esc_like( $vars['post_mime_type'] ) . '%';
$pieces['where'] .= $wpdb->prepare( " AND $wpdb->posts.post_mime_type LIKE %s", $like );
}
if ( ! empty( $vars['m'] ) ) {
$year = substr( $vars['m'], 0, 4 );
$monthnum = substr( $vars['m'], 4 );
$pieces['where'] .= $wpdb->prepare( " AND YEAR($wpdb->posts.post_date) = %d AND MONTH($wpdb->posts.post_date) = %d", $year, $monthnum );
} else {
if ( ! empty( $vars['year'] ) && 'false' != $vars['year'] ) {
$pieces['where'] .= $wpdb->prepare( " AND YEAR($wpdb->posts.post_date) = %d", $vars['year'] );
}
if ( ! empty( $vars['monthnum'] ) && 'false' != $vars['monthnum'] ) {
$pieces['where'] .= $wpdb->prepare( " AND MONTH($wpdb->posts.post_date) = %d", $vars['monthnum'] );
}
}
// search for keyword "s"
$like = '%' . $wpdb->esc_like( $vars['s'] ) . '%';
$pieces['where'] .= $wpdb->prepare( " AND ( ($wpdb->posts.ID LIKE %s) OR ($wpdb->posts.post_title LIKE %s) OR ($wpdb->posts.guid LIKE %s) OR ($wpdb->posts.post_content LIKE %s) OR ($wpdb->posts.post_excerpt LIKE %s)", $like, $like, $like, $like, $like );
$pieces['where'] .= $wpdb->prepare( " OR ($wpdb->postmeta.meta_key = '_wp_attachment_image_alt' AND $wpdb->postmeta.meta_value LIKE %s)", $like );
$pieces['where'] .= $wpdb->prepare( " OR ($wpdb->postmeta.meta_key = '_wp_attached_file' AND $wpdb->postmeta.meta_value LIKE %s)", $like );
// Get taxes for attachements
$taxes = get_object_taxonomies( 'attachment' );
if ( ! empty( $taxes ) ) {
$pieces['where'] .= $wpdb->prepare( " OR (tter.slug LIKE %s) OR (ttax.description LIKE %s) OR (tter.name LIKE %s)", $like, $like, $like );
}
$pieces['where'] .= " )";
$pieces['join'] .= " LEFT JOIN $wpdb->postmeta ON $wpdb->posts.ID = $wpdb->postmeta.post_id";
// Get taxes for attachements
$taxes = get_object_taxonomies( 'attachment' );
if ( ! empty( $taxes ) ) {
$on = array();
foreach ( $taxes as $tax ) {
$on[] = "ttax.taxonomy = '$tax'";
}
$on = '( ' . implode( ' OR ', $on ) . ' )';
$pieces['join'] .= " LEFT JOIN $wpdb->term_relationships AS trel ON ($wpdb->posts.ID = trel.object_id) LEFT JOIN $wpdb->term_taxonomy AS ttax ON (" . $on . " AND trel.term_taxonomy_id = ttax.term_taxonomy_id) LEFT JOIN $wpdb->terms AS tter ON (ttax.term_id = tter.term_id) ";
}
$pieces['distinct'] = 'DISTINCT';
$pieces['orderby'] = "$wpdb->posts.post_date DESC";
}
return $pieces;
}
add_filter( 'posts_clauses', 'myprefix_posts_clauses', 20 );
The solution benedikt works fine, but the language filter is with the wpml plugin.
I use Polylang and looking for the right way to do the same filter, I can not find a solution even with the Polylang documentation...
There is just this part to change :
if ( class_exists('WPML_Media') ) {
global $sitepress;
//get current language
$lang = $sitepress->get_current_language();
$pieces['where'] .= $wpdb->prepare( " AND wpml_translations.element_type='post_attachment' AND wpml_translations.language_code = %s", $lang );
}
by something like that :
if ( function_exists( 'pll_current_language' ) ) {
//get current language
$lang = pll_current_language();
$pieces['where'] .= $wpdb->prepare( here I don't know how to write it... );
}
If someone can help ?

Resources