I'm using the following query/code for a custom WordPress search-plugin.
add_filter( 'posts_where', 'title_like_posts_where', 10, 2 );
function title_like_posts_where( $where, &$wp_query ) {
global $wpdb;
if ( $post_title_like = $wp_query->get( 'post_title_like' ) ) {
$where .= ' AND ' . $wpdb->posts . '.post_title LIKE \'' . esc_sql( $wpdb->esc_like( $post_title_like ) ) . '%\'';
}
return $where;
}
But it is only searching in the post-titles, where I want it to search in both the title and the content.
If I simply change the word 'title' with the word 'content', it doesn't work.
Anyone knows what I have to do in order to make the query search in both the title and the content?
Related
Im using the searchWP plugin in my wordpress site but the results of the keyword is showing html tags in the description. (see picture)
Is it possible to use a filter to remove those tags from showing up but still show the text without the tags?
The tags are inside the wordpress wysiwyg editor.
Update.
The search-form uses vue.
So if it is possible to trim the html tags from the results using vue i would prefer that.
I'm not tested try this.
function wpse159789_posts_search( $search, $query ) {
global $wpdb;
if ( ! preg_match( '/' . $wpdb->posts . '\.post_content LIKE \'%(.+)%\'/', $search, $matches, PREG_OFFSET_CAPTURE ) ) {
return $search;
}
$search_str = stripslashes( $matches[1][0] );
// Cater for closed angle pairs embedded in the search string.
for ( $i = 0, $len = mb_strlen( $search_str ); $i < $len; $i++ ) {
$q_searches[] = '(<[^>]*>)?' . preg_quote( mb_substr( $search_str, $i, 1 ) );
}
$q_search = implode( '', $q_searches );
$regexs[] = '^[^<]*' . $q_search; // Before any angle bracket.
$regexs[] = '(<[^>]*>)[^<]*' . $q_search; // After any closed angle bracket pair.
array_unshift( $regexs, implode( ' OR ', array_fill( 0, count( $regexs ), $wpdb->posts . '.post_content RLIKE %s' ) ) );
$search_replace = call_user_func_array( array( $wpdb, 'prepare' ), $regexs );
$search = substr( $search, 0, $matches[0][1] ) . $search_replace . substr( $search, $matches[0][1] + strlen( $matches[0][0] ) );
return $search;
}
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.
I would like to filter the products on a category products so that it shows only the products of a certain author or multiple authors.
I already have the following code. This works as it filters the products. The correct products are displayed. Except the Woocommerce filters on in the left sidebar are not affected by the filter. The filters on the left side are showing all the original products in the category (also from other users) so the count isn't correct and also attributes from products that are filtered are showing. This shouldn't be the case. Do I have to add another pre_get_posts for the filters?
<?php
function pre_get_posts_by_author( $q ) {
if ( ! $q->is_main_query() ) return;
if ( ! $q->is_post_type_archive() ) return;
$cat_obj = $q->get_queried_object();
if($cat_obj->name == 'Nieuw')
{
$q->set( 'author_ids', '2086,2084');
}
}
add_action( 'pre_get_posts', 'pre_get_posts_by_author' );
add_filter( 'posts_where', 'author_posts_where', 10, 2 );
function author_posts_where( $where, &$wp_query )
{
global $wpdb;
if ( $wp_query->get( 'author_ids' ) ) {
$where .= ' AND ' . $wpdb->posts . '.post_author IN (' . $wp_query->get( 'author_ids' ) .')';
}
return $where;
}
?>
Thanks for helping out!
Probabaly a better way to do this is by setting 'author__in' argument in your query which will take an array of authors the query will return products of.
function pre_get_posts_by_author( $q ) {
if ( ! $q->is_main_query() || !$q->is_post_type_archive() ) return;
$cat_obj = $q->get_queried_object();
if( $cat_obj->name == 'Nieuw' ){
$q->set( 'author__in', array(2086,2084));
}
}
add_action( 'pre_get_posts', 'pre_get_posts_by_author' );
My updated solution: still dirty as it modifies Woocommerce's core files (2.2.4), but it works:
in the pre_get_posts-hook I retrieve the ids of the products I want to exclude with the following code:
$_SESSION['total_excluded'] = get_objects_in_term( $term_ids, $taxonomies, $args )`
(reference: http://codex.wordpress.org/Function_Reference/get_objects_in_term)
Then in woocommerce/includes/widgets/class-wc-widget-layered-nav.php I changed line 258 to:
$count = sizeof( array_diff(array_intersect( $_products_in_term, WC()->query->filtered_product_ids) , $_SESSION['total_excluded'] ) );
In woocommerce/includes/widgets/class-wc-widget-price-filter.php the new lines 121, 136 are:
%1$s.ID IN (' . implode( ',', array_map( 'absint', array_diff(WC()->query->layered_nav_product_ids, $_SESSION['total_excluded'] ) ) ) . ')
In woocommerce/includes/widgets/class-wc-widget-price-filter.php the new lines 123, 138 are:
%1$s.post_parent IN (' . implode( ',', array_map( 'absint', array_diff(WC()->query->layered_nav_product_ids, $_SESSION['total_excluded'] ) ) ) . ')
Entirely Revised Please Reread
Hello,
The theme I am using displays the page's title as opposed to it's menu label in the breadcrumbs. I am trying to get the breadcrumbs to instead display the associated menu label if it is available and if not then default to the page_title.
I have come up with some code that I think is close. Line 4/// $menu_items = wp_get_nav_menu_items( $slug ); returns null and it should return the nav item that contains $slug of the current post. Obviously, there is something I do not understand.
What I am attempting to do is get the slug of the current post, then using the slug get the nav item post. Then extract the title of the nav item and use that in place of the page title in the breadcrumbs. If the page was not in the nav system then it should default to the page title, as might be the case for a ppc campaign landing page.
if ( is_page() && !$post->post_parent ) {
$title = null;
$slug = mpactMEDIA_get_the_slug( get_the_ID() );
$menu_items = wp_get_nav_menu_items( $slug );
//var_dump((array)$menu_items);
foreach ( (array)$menu_items as $key => $menu_item ) {
$title = $menu_item->post_title;
}
if ( $title ) { echo $delimiter . ' ' . $before . $title . $after; }
else { echo $delimiter . ' ' . $before . get_the_title() . $after; }
}
I'm my functions.php file I have the following function
function mpactMEDIA_get_the_slug( $id=null ){
if( empty($id) ) global $post;
if( empty($post) ) return '';
$id = $post->ID;
endif;
$slug = basename( get_permalink($id) );
return $slug;
}
Thank you in advance,
Tim
I read the question a few times, I got here searching for an answer, ended up making my own.
function get_menu_label_by_post_id($post_id, $menu) {
$menu_title = '';
$nav = wp_get_nav_menu_items($menu);
foreach ( $nav as $item ) {
if ( $post_id == $item->object_id ) {
$menu_title = $item->post_title;
break;
}
}
return ($menu_title !== '') ? $menu_title : get_the_title($post_id);
}
Example usage:
echo get_menu_label_by_post_id($post->ID, 'Primary Nav');
This will return what the menu label is if it finds it, otherwise just the title of the post ID.
Check the documentation for wp_get_nav_menu_items. It doesn't take a page slug as a parameter at all.
If you want to list child pages of a given page, use wp_list_pages and pass a child_of parameter to it.
Also, as a side note, if you know the $post and want the slug, it's just $post->post_name
I installed WooCommerce Custom Order Data PlugIn to create a custom field after checkout is completed. In a custom plugin I use the woocomerce_thankyou-hook to collect some data from the order and save it as a string to $order->custom->officer_text.
I need to print that custom data to the admin-new-order-mail, but I don't know how to do that.
echo $order->custom->officer_text
in admin-new-order-mail.php doesn't work.
I can print_r the data on the thank you-page, so I know, it's there. But no luck in the email-template.
How do I get it to work?
Edit:
I forgot to post the code of my custom plugin.
if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) {
global $woocommerce;
// Action after order is submitted
add_action('woocommerce_thankyou', 'woocommerce_officer_data');
// function to populate a custom field in $order
function woocommerce_officer_data($order_id) {
$order = new WC_Order( $order_id );
// create custom field
WC_CustomOrderData::extend($order);
$order->custom->officer_text = '';
$officer = '';
// get date and format
$date = DateTime::createFromFormat('Y-m-d H:i:s', $order->order_date);
$orderdate = $date->format('d.m.Y');
$ordertime = $date->format('H:i:s');
$officer .= '##Officer-START##<br>Datum:' . $orderdate . '<br>Zeit:' . $ordertime . '<br>';
$officer .= $order_id . '|' . $order_id . '|' . $order->billing_first_name . '|' . $order->billing_last_name . '|';
$officer .= $order->billing_country . '|' . $order->billing_postcode . '|' . $order->billing_city . '|' ;
$officer .= $order->shipping_address_1 . '|' . $order->billing_email . '|' . $order->billing_phone . '|' ;
$order->custom->officer_text = $officer;
$order->custom->save();
echo $order->custom->officer_text;
}
}
The field is printed right after the ul.order_details.bacs_details
But if I print_r($order) on thankyou.php, the custom data is not there, .
print_r($order->custom) in the plugin gives me this:
WC_CustomOrderData Object
(
[order_id:WC_CustomOrderData:private] => 241
[fields:WC_CustomOrderData:private] => Array
(
[officer_text] => ##Officer-START##
Datum:09.10.2013
Zeit:12:00:38
241|241|Peter|Petersen|DE|11111|Xtown|Ystreet 53|foo#example.de||01xx 654 xxx xx|
)
)
I'm happy, I got so far, because I'm not a real coder, but I have no idea, how to control the output of my first little plugin. So, if someone could show me a 'best practise' solution, it would be great.
For anyone searching in the future, this gist will print certain meta keys in any email template that features the woocommerce_email_order_meta hook.
_my_field_1 and _my_field_2 are the meta keys for the Order's custom data that you are trying to display. I am not familiar with the Custom Order Data plugin, but the meta key for the OP may be _officer_text. In my example, I will use the meta key _some_field.
/**
* Add the field to order emails
**/
add_filter('woocommerce_email_order_meta_keys', 'my_custom_checkout_field_order_meta_keys');
function my_custom_checkout_field_order_meta_keys( $keys ) {
$keys['Some Field'] = '_some_field;
return $keys;
}
For versions 2.3 and newer of WooCommerce:
// WooCommerce 2.3+
function kia_email_order_meta_fields( $fields, $sent_to_admin, $order ) {
$fields['some_field'] = array(
'label' => __( 'Some field' ),
'value' => get_post_meta( $order->id, '_some_field', true );
);
return $fields;
}
add_filter('woocommerce_email_order_meta_fields', 'kia_email_order_meta_keys', 10, 3 )
;