I am building a ajax search that uses wp_query and I need to be able to filter using custom meta and custom taxonomy names. I've gotten the custom meta part working but cannot get it to filter using the taxonomy names. What I've got so far -
$useCustomJoins = false;
add_action( 'pre_get_posts', function( $q )
{
if( $title = $q->get( '_meta_or_title' ) )
{
add_filter( 'get_meta_sql', function( $sql ) use ( $title )
{
global $wpdb;
// Only run once:
static $nr = 0;
if( 0 != $nr++ ) return $sql;
// Modified WHERE
$sql['where'] = sprintf(
" AND ( %s OR %s ) ",
$wpdb->prepare( "{$wpdb->posts}.post_title like '%%%s%%'", $title),
mb_substr( $sql['where'], 5, mb_strlen( $sql['where'] ) )
);
return $sql;
});
}
});
add_filter('posts_join', array('CrownResources', 'filterPostsJoin'), 10, 2);
add_filter('posts_where', array('CrownResources', 'filterPostsWhere'), 10, 2);
add_filter('posts_groupby', array('CrownResources', 'filterPostsGroupby'), 10, 2);
public static function filterPostsJoin($join, $query) {
global $wpdb, $useCustomJoins;
if($useCustomJoins || (is_main_query() && is_search())) {
$join .= "
LEFT JOIN
(
{$wpdb->term_relationships}
INNER JOIN
{$wpdb->term_taxonomy} ON {$wpdb->term_taxonomy}.term_taxonomy_id = {$wpdb->term_relationships}.term_taxonomy_id
INNER JOIN
{$wpdb->terms} ON {$wpdb->terms}.term_id = {$wpdb->term_taxonomy}.term_id
)
ON {$wpdb->posts}.ID = {$wpdb->term_relationships}.object_id ";
}
return $join;
}
public static function filterPostsWhere($where, $query) {
global $wpdb, $useCustomJoins;
if($useCustomJoins || (is_main_query() && is_search())) {
$userWhere = self::getUserPostsWhere();
$queryS = !empty(get_query_var('s')) ? get_query_var('s') : get_query_var('_meta_or_title');
$where .= " OR (
{$wpdb->term_taxonomy}.taxonomy IN('resource_pregnancy_taxonomy', 'resource_counseling_taxonomy', 'resource_classes_taxonomy', 'resource_supplies_taxonomy', 'resource_clothing_taxonomy', 'resource_food_taxonomy', 'resource_housing_taxonomy', 'resource_medical_taxonomy', 'resource_substance_taxonomy', 'adoption_taxonomy', 'employment_taxonomy')
AND
{$wpdb->terms}.name LIKE '%".esc_sql($queryS)."%'
{$userWhere}
)";
}
return $where;
}
protected static function getUserPostsWhere() {
global $wpdb;
$userId = get_current_user_id();
$sql = '';
$status = array("'publish'");
if(0 !== $userId) {
$status[] = "'private'";
$sql .= " AND {$wpdb->posts}.post_author = ".absint($userId);
}
$sql .= " AND {$wpdb->posts}.post_status IN( ".implode(',', $status)." ) ";
return $sql;
}
public static function filterPostsGroupby($groupby, $query) {
global $wpdb, $useCustomJoins;
if($useCustomJoins || (is_main_query() && is_search())) {
$groupby = "{$wpdb->posts}.ID";
}
return $groupby;
}
usage:
global $post, $useCustomJoins;
$original_post = $post;
// query for resource
$queryArgs = array(
'post_type' => 'resource',
'posts_per_page' => -1,
'orderby' => 'menu_order',
'order' => 'ASC',
'post_status' => 'publish'
);
//if taxonomies
if (!empty($atts['taxonomies'])){
$queryArgs['tax_query'] = array();
foreach ($atts['taxonomies'] as $tax){
$queryArgs['tax_query'][] = array(
'taxonomy' => $tax['name'],
'field' => 'term_id',
'terms' => $tax['terms'],
'operator' => 'AND',
);
}
}
// filter by meta as well as title
$meta_query = array();
$meta_query[] = array(
'key' => 'resource_description',
'value' => $atts['search'],
'compare' => 'LIKE'
);
$meta_query[] = array(
'key' => 'resource_address',
'value' => $atts['search'],
'compare' => 'LIKE'
);
$meta_query[] = array(
'key' => 'resource_date_time',
'value' => $atts['search'],
'compare' => 'LIKE'
);
$meta_query[] = array(
'key' => 'resource_phone',
'value' => $atts['search'],
'compare' => 'LIKE'
);
$meta_query[] = array(
'key' => 'resource_email',
'value' => $atts['search'],
'compare' => 'LIKE'
);
$meta_query[] = array(
'key' => 'resource_website',
'value' => $atts['search'],
'compare' => 'LIKE'
);
//if there is more than one meta query 'or' then
if(count($meta_query) > 1) {
$meta_query['relation'] = 'OR';
}
//if there's a search
if (!empty($atts['search'])){
// $queryArgs['s'] = $atts['search'];
$queryArgs['_meta_or_title'] = $atts['search']; //not using 's' anymore
$queryArgs['meta_query'] = $meta_query;
$useCustomJoins = true;
}
$resourceQuery = new \WP_Query($queryArgs);
$useCustomJoins = false;
Any idea on how to get them working together? I can get the meta filter to search properly but once I add the taxonomy it still filters but not correctly.
Related
Scenario:
Variable product has attribute color, term is 'yellow'
Variation with yellow term is disabled
Customer filters product by color 'yellow'
Parent product is displayed even if variation which uses the color 'yellow' is not enabled
Note: Query should contain simple and variation product types.
The query is being called by ajax function, I'm not sure how to use filters if its possible.
The query:
add_action('wp_ajax_getProducts', 'getProducts');
add_action('wp_ajax_nopriv_getProducts', 'getProducts');
function getProducts(){
$input = [
'currentTerm' => $_POST['currentTerm'],
'searchTerms' => $_POST['searchTerms'],
'page' => $_POST['page'],
'color' => $_POST['color'],
'sortBy' => $_POST['sortBy'],
'sortDirection' => $_POST['sortDirection'],
'beltWidth' => $_POST['beltWidth'],
];
// args init
$args = array(
'post_type' => 'product',
'posts_per_page' => 12,
'post_status' => 'publish',
'lang' => pll_current_language()
);
$args['meta_query'] = array(
'relation' => 'AND',
array(
'key' => '_stock_status',
'value' => 'instock'
),
);
$args['tax_query'] = array(
'relation' => 'AND',
);
// 0. Search
if( isset() ) {
$sargs = array(
's' => $input['searchquery'],
);
$args = array_merge($sargs, $args);
}
// 1. Terms
if( isset($input['currentTerm']) ) {
$cat_tax = array(
'taxonomy' => 'product_cat',
'field' => 'id',
'terms' => $input['currentTerm'],
);
array_push($args['tax_query'], $cat_tax);
}
// 2. Page
if( isset($input['page']) ) {
$args['paged'] = $input['page'];
}
// 3. color
if( isset($input['color']) && $input['color'] != 'clear') {
$color_tax = array(
'taxonomy' => 'pa_color',
'field' => 'slug',
'terms' => $input['color'],
'operator' => 'IN'
);
array_push($args['tax_query'], $color_tax);
}
// 4. sort
if ( isset($input['sortBy']) ) {
if ( $input['sortBy'] == 'price' ) {
$args['orderby'] = 'meta_value_num';
$args['meta_key'] = '_price';
} elseif ( $input['sortBy'] == 'name' ) {
$args['orderby'] = 'title';
} else {
$args['orderby'] = 'date';
}
}
if ( isset($input['sortDirection'])) {
if ( $_POST['sortDirection'] == 'asc') {
$args['order'] = 'asc';
} else {
$args['order'] = 'desc';
}
}
// query
$wp_query = new WP_Query( $args );
...
echo json_encode($products);
...
}
The query works fine, and I've found the way to clear results, by filtering the results; but it returns uneven number of products per page, which is not very user friendly.
The solution is to do something like code below within the query arguments, not inside the results loop.
if( isset($input['color']) && $input['color'] != 'clear') {
if ($product['terms']) {
foreach($product['terms'] as $item) {
if ((string) $item['slug'] == $input['color']) {
array_push($products, $product);
}
}
}
}
I've attempted to use the solution #LoicTheAztec provided in their answer at Enable custom taxonomies in WooCommerce product search
function search_product_by_tag( $search, &$query_vars ) {
global $wpdb, $pagenow;
if ( 'edit.php' == $pagenow || empty($search) ) {
return $search;
}
$args = array(
'posts_per_page' => -1,
'post_type' => 'product',
'meta_query' => array(
array(
'key' => 'taxonomy',
'value' => 'product_tag',
'field' => 'name',
'terms' => array($query_vars->query['s']),
'compare' => 'LIKE',
)));
$posts = get_posts( $args );
if ( empty( $posts ) ) return $search;
$get_post_ids = array();
foreach($posts as $post){
$get_post_ids[] = $post->ID;
}
if ( sizeof( $get_post_ids ) > 0 ) {
$search = str_replace( 'AND (((', "AND ((({$wpdb->posts}.ID IN (" . implode( ',', $get_post_ids ) . ")) OR (", $search);
}
return $search;
}
add_filter( 'posts_search', 'search_product_by_tag', 999, 2 );
However, adding the above snippet to functions.php does not work on the front-end and users cannot search successfully by product_tag.
I'm already using separate snippets to reduce the search to only products and SKUs, using the code below.
function search_by_sku( $search, &$query_vars ) {
global $wpdb;
if(isset($query_vars->query['s']) && !empty($query_vars->query['s'])){
$args = array(
'posts_per_page' => -1,
'post_type' => 'product',
'meta_query' => array(
array(
'key' => '_sku',
'value' => $query_vars->query['s'],
'compare' => 'LIKE'
)
)
);
$posts = get_posts($args);
if(empty($posts)) return $search;
$get_post_ids = array();
foreach($posts as $post){
$get_post_ids[] = $post->ID;
}
if(sizeof( $get_post_ids ) > 0 ) {
$search = str_replace( 'AND (((', "AND ((({$wpdb->posts}.ID IN (" . implode( ',', $get_post_ids ) . ")) OR (", $search);
}
}
return $search;
}
add_filter( 'posts_search', 'search_by_sku', 999, 2 );
function searchfilter($query) {
if ($query->is_search && !is_admin() ) {
$query->set('post_type',array('product'));
$query->set('posts_per_page',12);
}
return $query;
}
add_filter('pre_get_posts','searchfilter');
Could these be causing a conflict?
I see your code has the following information
'posts_per_page' => -1,
as well as on another line there is the following code:
if ( sizeof( $get_post_ids ) > 0 ) {
check this too
check this data and try again...
Enable DEBUG and post error log, ok
str_replace( 'AND (((', "AND ((({$wpdb->posts}.ID IN (" . implode( ',', $get_post_ids ) . ")) OR (", $search);
here must be some ' or " missing.
I am trying to query for a string if present in a custom field.
e.g. Within the custom field I have a value like: Milano romani and If I have a string Milano from GET, I should find it. But the following gives me all posts even if no string match in the custom field
<?php
$myTerm = $_GET['cityName'];
$catIds = array();
$args = get_posts(
array(
'post_type' => 'post',
'posts_per_page' => -1,
'meta_query' => array(
array(
'key' => 'usp-custom-23',
'value' => $myTerm,
'compare' => 'LIKE'
)
)
)
);
$query = new WP_Query( $args );
if ( $query->have_posts() ) {
while ( $query->have_posts() ) {
$query->the_post();
$id = get_the_ID();
array_push($catIds, $id);
}
$catIds = implode( ", ", $catIds );
if(count($catIds) > 0){
$arrayFUllCity = "fullCity";
} else {
$arrayFUllCity = "empty";
}
}
var_dump($catIds);
?>
I am making a plugin to display all user info in a DataTables but i am failed to implement Search, filter and Pagination . I have about 20k users. Please help me.
may be I need to change my query to join wp_users and wp_usermeta and get the result for my case. I have fount a question here and a similar tutorial here . I am not good in writing MySQL query. Please help me with this.
I get ajax response like
{
"draw": 1,
"recordsTotal": 1,
"recordsFiltered": 1,
"data": [
[
"example#mail.com",
"Some Name",
"",
"admin",
""
]
]
}
This is my table structure
<table id="user_table" class="display table table-striped table-bordered dataTable" style="width:100%">
<thead class="user-table">
<tr>
<th>Email</th>
<th>Name </th>
<th>Url</th>
<th>nickname</th>
<th>description</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
My script
jQuery(document).ready(function($){
$(window).on('load', function () {
setTimeout(loadtable, 200);
});
function loadtable(){
var ajaxurl = USERAjax.wpajaxusersearch;
var dataTable = $('#user_table').DataTable({
"processing":true,
"serverSide": true,
"order":[],
"pageLength": 10,
"ajax":{
url: ajaxurl,
type:"POST"
},
});
}
});
also added localize script like
function users_assets_scripts(){
wp_register_script( 'jquery_datatables_js', plugins_url( 'asset/js/datatables.min.js' , __FILE__ ), array(),null,true );
wp_enqueue_script( 'jquery_datatables_js' );
wp_register_style( 'jquery_datatables_css', plugins_url( 'asset/css/datatables.min.css' , __FILE__ ));
wp_enqueue_style( 'jquery_datatables_css' );
wp_localize_script( 'jquery', 'USERAjax', array('wpajaxusersearch' => admin_url( 'admin-ajax.php?action=wpajaxusersearch' )) );
}
add_action('wp_enqueue_scripts', 'users_assets_scripts');
and my data fetching function with ajax response
<?php
function wpajaxusersearch(){
$request=$_REQUEST;
global $wpdb;
$sort= "user_registered";
//Build the custom database query to fetch all user IDs
$all_users_id = $wpdb->get_results("SELECT $wpdb->users.ID FROM $wpdb->users ORDER BY $sort ASC LIMIT ".$request['start'].",".$request['length']." " );
$totalData=$wpdb->num_rows;
$data=array();
foreach ( $all_users_id as $i_users_id ) {
$user = get_userdata( $i_users_id->ID);
$email =$user->user_email;
$user_fullname =$user->first_name . ' ' . $user->last_name;
$user_url =$user->user_url;
$user_nickname =$user->nickname;
$user_profile =$user->description;
$sub_array = array();
$sub_array[] = $email;
$sub_array[] = $user_fullname;
$sub_array[] = $user_url;
$sub_array[] = $user_nickname;
$sub_array[] = $user_profile;
$data[] = $sub_array;
}
$json_data=array(
"draw" => (isset($request["draw"]) ? $request["draw"] : 0),
"recordsTotal" => intval($totalData),
"recordsFiltered" => intval($totalData),
"data" => $data
);
echo json_encode($json_data);
wp_die(); //to remove that 0 response
}
add_action( 'wp_ajax_wpajaxusersearch', 'wpajaxusersearch' );
add_action( 'wp_ajax_nopriv_wpajaxusersearch', 'wpajaxusersearch' );
Add these to your theme's 'functions.php' and everything should be fine.
// change user query to treat meta result as OR part
add_action( 'pre_user_query', 'user_meta_OR_search');
function user_meta_OR_search($q){
if ($search = $q->get('_meta_or_search')){
add_filter( 'get_meta_sql', function( $sql ) use ( $search ){
global $wpdb;
// run once
static $nr = 0;
if( 0 != $nr++ ) return $sql;
// modify WHERE
$where = sprintf(
" AND ( %s OR %s OR %s ) ",
$wpdb->prepare( "{$wpdb->users}.user_email like '%%%s%%'", $search),
$wpdb->prepare( "{$wpdb->users}.user_url like '%%%s%%'", $search),
mb_substr( $sql['where'], 5, mb_strlen( $sql['where'] ) )
);
$sql['where'] = $where;
return $sql;
});
}
}
function wpajaxusersearch()
{
$request = $_REQUEST;
$columns = array('user_email','first_name','user_url','nickname','description');
$search = esc_attr( trim( $request['search']['value'] ) );
$args = array();
$limit_args = array( 'number' => $request['length'], 'offset' => $request['start'] );
$order_args = array();
$search_args = array();
if ( isset($request['order']) && count($request['order']) )
{
$sort_column = $request['order'][0]['column'];
$sort_column_name = $columns[$sort_column];
$sort_dir = $request['order'][0]['dir'];
if( stristr( $sort_column_name,'user_' ))
$order_args = array( 'orderby' => $sort_column_name, 'order' => $sort_dir );
else
$order_args = array( 'meta_key' => $sort_column_name, 'orderby' => 'meta_value', 'order' => $sort_dir );
}
else
$order_args = array( 'orderby' => 'user_registered', 'order' => 'ASC' );
$args = $order_args;
if(isset($search) && $search != "")
{
$search_args = array(
'_meta_or_search' => "*{$search}*",
'meta_query' => array(
'relation' => 'OR',
array(
'key' => 'first_name',
'value' => $search,
'compare' => 'LIKE'
),
array(
'key' => 'last_name',
'value' => $search,
'compare' => 'LIKE'
),
array(
'key' => 'nickname',
'value' => $search,
'compare' => 'LIKE'
),
array(
'key' => 'description',
'value' => $search,
'compare' => 'LIKE'
)
)
);
}
$all_users = new WP_User_Query( $args );
$total_users = count($all_users->get_results());
$filtered_users = count($all_users->get_results());
if(isset($search) && $search != "")
{
$args = array_merge($args, $search_args);
$all_users = new WP_User_Query( $args );
$filtered_users = count($all_users->get_results());
}
$args = array_merge($args, $limit_args);
$all_users = new WP_User_Query( $args );
foreach ( $all_users->get_results() as $user ) {
$email = $user->user_email;
$user_fullname = $user->first_name . ' ' . $user->last_name;
$user_url = $user->user_url;
$user_nickname = $user->nickname;
$user_profile = $user->description;
$sub_data = array();
$sub_data[] = $email;
$sub_data[] = $user_fullname;
$sub_data[] = $user_url;
$sub_data[] = $user_nickname;
$sub_data[] = $user_profile;
$data[] = $sub_data;
}
$json_data=array(
"draw" => (isset($request["draw"]) ? $request["draw"] : 0),
"recordsTotal" => intval($total_users),
"recordsFiltered" => intval($filtered_users),
"data" => $data
);
echo json_encode($json_data);
wp_die();
}
add_action( 'wp_ajax_wpajaxusersearch', 'wpajaxusersearch' );
add_action( 'wp_ajax_nopriv_wpajaxusersearch', 'wpajaxusersearch' );
I created a plugin and create a menu by using this code
add_filter('page_template', 'in_page_template');
function in_page_template()
{
global $wpdb;
$new_page_title = 'Packages';
$sql = "SELECT * FROM wp_posts where post_name='" . $new_page_title . "';";
$cnt_post = $wpdb->get_results($sql);
if (!(is_page('Home'))) {
$ppid = $_GET['page_id'];
if (count($cnt_post) != 0) {
$pid = $cnt_post[0]->ID;
if ($pid == $ppid) {
$page_template = dirname(__FILE__) . '/Packages.php';
return $page_template;
}
}
}
}
How can I create submenu for package page
add_action('init', 'create_initial_pages');
function create_initial_pages() {
$pages = array(
array(
'name' => 'post_name',
'title' => 'post_title',
'child' => array(
'page1-1' => 'National',
'page1-2' => 'International'
)
),
);
$template = array(
'post_type' => 'page',
'post_status' => 'publish',
'post_author' => 1
);
foreach( $pages as $page ) {
$exists = get_page_by_title( $page['title'] );
$my_page = array(
'post_name' => $page['name'],
'post_title' => $page['title']
);
$my_page = array_merge( $my_page, $template );
$id = ( $exists ? $exists->ID : wp_insert_post( $my_page ) );
if( isset( $page['child'] ) ) {
foreach( $page['child'] as $key => $value ) {
$child_id = get_page_by_title( $value );
$child_page = array(
'post_name' => $key,
'post_title' => $value,
'post_parent' => $id
);
$child_page = array_merge( $child_page, $template );
if( !isset( $child_id ) ) wp_insert_post( $child_page );
}
}
}
}